主题
字号
Chapter 03 / 06 ≈ 32 min
第三章

进阶武器库

五件套 + Agent SDK。前两章讲的是「怎么和 Claude Code 对话」;这一章讲的是「怎么让它越用越懂你」。学完你会从「能用」跨到「会架构它」。

先把五件套摆一起看

到第二章为止,你已经会用 Claude Code 完成单次任务了。但每开一次新会话,它都是「刚上班的新人」——不知道你项目的规矩、不知道你喜欢的风格、不知道上次做到哪里。

进阶的五件套就是用来解决「怎么让它越用越顺手」这件事的。每一件都在回答一个不同的问题:

名字回答的问题比喻生效时机
CLAUDE.md我的项目有什么规矩?员工手册每次会话启动
Skills有什么「招式」可以按需调用?武功秘籍/xxx 或自然语言触发时
Hooks某些时刻自动发生什么?红外感应器事件触发(如 PreToolUse)
Subagents能不能派几个人同时干活?分身主 Claude 自己决定派出去时
MCP怎么连外部服务(GitHub、Slack)?对外接线板服务器启动时连上,之后常驻

加上 Agent SDK(第 3.7 节),你就能把 Claude 作为一个库嵌进自己的 Python / TypeScript 程序里——彻底摆脱「必须有个终端坐在前面」的限制。下面一个一个拆开讲。

CLAUDE.md — 员工手册

CLAUDE.md 是一个普通的 Markdown 文件,放在项目的根目录。每次 Claude Code 在这个项目里启动,它都会自动读这个文件,把内容作为「永久指令」加进上下文。每一轮对话它都带着这份手册。

你在里面写什么?写那些每次都要告诉它、但每次都懒得重复的东西。

# 我的项目

包管理器用 pnpm,不要用 npm/yarn。
测试用 vitest,测试文件和源文件放一起,命名 *.test.ts。
所有 API 响应用 zod 校验,不要用手写的类型守卫。

## 常用命令
- 启动:pnpm dev
- 测试:pnpm test
- 类型检查:pnpm tsc
- 构建:pnpm build

## 风格
- 使用 2 空格缩进
- 导出用 named export,不用 default export
- 错误信息写中文,代码注释写英文

## 不要做
- 不要加任何 any 类型
- 不要写 if/else 嵌套超过 3 层,拆函数
- 不要动 src/legacy/ 下的文件,那是遗产代码
- 不要 @ts-ignore 绕过类型错误,测试失败要修代码不要改测试

一键生成

不用从零写,打 /init,Claude 会自己扫项目、读 package.json、看目录结构,生成一份初版 CLAUDE.md。你再改几笔就行。

分层:CLAUDE.md 的四种放法

CLAUDE.md 可以放在多个地方,作用域不一样,层层叠加:

位置作用域会被 git 提交吗
~/.claude/CLAUDE.md你所有项目(个人偏好)不会
./CLAUDE.md当前项目(团队共享)
./CLAUDE.local.md当前项目(只给你自己)不会(自动加到 .gitignore)
./src/subdir/CLAUDE.md子目录会,只在读这个目录下的文件时生效

这个分层设计很聪明:「所有 Go 项目都用 gofumpt 格式化」~/.claude/「这个项目的 API 必须先过 zod」 放项目根;「我这台机器上 Python 解释器在 /opt/…」.local.md。各司其职,不串味。

写好 CLAUDE.md 的几个经验

不要把 CLAUDE.md 写成小说

每一句都占你的上下文预算。写 300 行的背景介绍、商业逻辑考虑——不如抽成项目文档,CLAUDE.md 里只留「规则」和「命令」这两类硬货。

auto memory:CLAUDE.md 之外的另一层记忆

Claude Code 还维护一套自动记忆系统,存在 ~/.claude/projects/<proj-hash>/memory/。它会从你的历史交互中提炼三类信息:

每条存成一个单独的 md 文件,配一份索引 MEMORY.md/memory 命令打开这个目录的可视化面板。和 CLAUDE.md 的区别:CLAUDE.md 是你主动写的规则,auto memory 是 Claude 自己记的观察——你可以删、可以改,但不用每次亲自写。

Skills — 武功秘籍

CLAUDE.md 是「常驻背景」,每次都加载。但有些指令很复杂、又不是每次都用——比如「发布一个新版本」的完整流程,可能要跑七八步命令、检查十几个条件。把这些全塞进 CLAUDE.md,每次会话都占上下文,不划算。

Skill 就是为这种情况设计的:一段「按需召唤」的指令包。你想用的时候打 /skill-name,或者用自然语言描述需求触发它;不用的时候它就安静地待在文件系统里,不占空间。

一个最小 Skill

新建 ~/.claude/skills/summarize-changes/SKILL.md

---
description: 总结我未提交的改动,并点出潜在风险
allowed-tools: Bash(git *) Read
---

## 当前未提交的改动
!`git diff HEAD`

## 任务

用 2-3 个要点总结上面的 diff,然后列出你注意到的任何风险:
- 缺少错误处理
- 有硬编码的值
- 测试需要更新但还没更新
- 有 console.log 或调试代码忘了删

如果 diff 是空的,就说"没有未提交的改动",然后停。

保存完,在 Claude Code 里输入 /summarize-changes,它就跑这个流程。注意文件顶部的 !`git diff HEAD`——那个反引号 + 感叹号不是装饰,是告诉 Claude Code「加载 Skill 之前,先把这条命令跑一遍,把结果注入进来」。动态内容就这么来的。

SKILL.md 的完整 frontmatter

description
一句话描述,用于 Claude 自己判断「这个任务要不要召唤这个 skill」。写得越具体,误触发越少。
allowed-tools
这个 skill 能用的工具集合。例:Bash(git *) Read Grep。不写 = 继承会话权限。
model
指定这次用哪个模型。某些 skill 只做格式化,配 model: haiku 能省钱。
context
main(默认,在当前会话跑)或 fork(开子会话跑,结果汇报回来——不污染主上下文)。
name
可选。不写就用目录名。

参数和占位符

你可以让 skill 接参数:

---
description: 给一个分支名,把它 rebase 到 main 上
---

## 任务
把分支 $1 rebase 到 main。如果有冲突,逐个分析、给出解决建议,不要自作主张解决。

完整参数:$ARGUMENTS

使用时:/my-rebase feature-auth——$1 会被替换成 feature-auth$ARGUMENTS 保存完整参数串。

Skill 和斜杠命令的关系

你在第二章里见到的 /review/security-review/simplify/less-permission-prompts——它们都是 Anthropic 官方内置的 Skill。不神秘,你也能自己写。内置 skill 只是目录在 Claude Code 自己的安装路径下。

Skill 几个实战模板

把这些当样板改,很快能凑出一套自己的 Skill 库:

Hooks — 红外感应器

Skills 是「你主动喊它来」。Hooks 相反——它们在特定事件发生时自动触发,不需要你喊。

你可以把 Hook 理解成「事件监听器」。Claude Code 在生命周期里会发出各种事件,你可以绑脚本到这些事件上,系统自动帮你跑。

完整的事件清单

事件什么时候触发能阻止这次操作吗
SessionStart会话启动时不能
SessionEnd会话完全结束不能
UserPromptSubmit你按下回车把消息发出去之前
PreToolUseClaude 要调用一个工具之前
PostToolUse工具调用成功之后不能(但可改输出)
PostToolUseFailure工具调用失败时不能
PermissionRequest权限弹窗要显示之前
StopClaude 说「我做完了」要结束时能(可强制继续)
PreCompact上下文压缩前不能
SubagentStart / SubagentStop子代理启停不能
WorktreeCreate / WorktreeRemoveworktree 创建/销毁不能

四种 hook 处理器

一个具体例子:禁止跑 rm -rf

.claude/settings.json

{
  "hooks": {
    "PreToolUse": [
      {
        "matcher": "Bash",
        "hooks": [
          {
            "type": "command",
            "if": "Bash(rm -rf *)",
            "command": "${CLAUDE_PROJECT_DIR}/.claude/hooks/block-rm.sh"
          }
        ]
      }
    ]
  }
}

然后 .claude/hooks/block-rm.sh

#!/bin/bash
echo "Nope." >&2
exit 2   # 退出码 2 表示阻止这次工具调用

退出码约定:0 放行、2 阻止、其他按一般错误处理。从此 Claude 再想跑 rm -rf,钩子直接挡掉。

实用 hook 套路

写完即格式化
PostToolUse 钩 Edit / Write,改完自动跑 prettier --write / gofumpt -w
保护敏感文件
PreToolUse 拦截对 .envcredentials.json*.pem 的写操作。
做完响一声
Stop 事件调 notify-send / osascript / PowerShell Toast。长任务跑着你去干别的,做完提醒你。
自动注入上下文
UserPromptSubmit 里,把当前 git 分支、最近一次 commit hash 注到请求前——Claude 永远知道你在哪。
提交前强制 lint
PreToolUse 钩 Bash(git commit *),先跑 pnpm lint,挂了 exit 2 阻止提交。

Hook 是有执行代价的

钩子在每次匹配事件时都会跑。别在高频事件(PreToolUse / PostToolUse)上绑慢脚本——每次多 2 秒,一小时跑下来整个会话会发粘。慢脚本放 Stop 或单独的 cron。

Subagents — 分身

有时候你会遇到这种场景:主任务正在进行,中间卡了一个「先调研一下这个库怎么用」的子任务。让主 Claude 自己去调研?它会读一堆文档、主对话上下文被灌满。让你手动开一个新会话?麻烦。

Subagent就是主 Claude 派出去的「分身」。主 Claude 说:「去,帮我调研一下 Drizzle 怎么建 migration,结果回来告诉我。」分身在独立上下文里跑,读完十几个文档、写完一份报告,把总结返回主会话。主会话只看到那份简洁的总结。

内置几种 Subagent

Explore只读探索。适合「找 X 在哪」「搜用过 Y 的地方」。用 Haiku 跑省钱。
Plan做设计方案,和 /plan 是一对。
general-purpose什么都能干的通用分身。
claude-code-guide专门回答 Claude Code / SDK / API 问题。

/agents 命令打开面板,看当前运行的子代理和可用代理库。

自己写一个

新建 .claude/agents/my-researcher/AGENT.md

---
name: my-researcher
description: 深度研究一个特定主题,读大量文档/代码,生成详细报告。用于需要读很多东西才能回答的问题。
tools: Glob Grep Read WebFetch WebSearch
model: sonnet
---

你是一个技术研究员。给你一个主题:

1. 用 Glob/Grep 找出项目里所有和这个主题相关的文件
2. 读透它们,必要时上网搜外部资料
3. 生成一份结构化报告:背景 / 现状 / 选项 / 建议

不修改任何文件。报告要能让没看过代码的人看懂。

主 Claude 看到这个 agent 的 description,在合适的场景里自己决定派出去。或者你直接说「用 my-researcher 帮我研究 X」。

并行的力量

多个 subagent 可以并行跑。主 Claude 同时派三个分身查三件事,总耗时是最慢那个的时间。这是 Claude Code 做大任务时「变快」的主要手段。

> 我要调研三件事(可以并行):
> 1. 我们项目里所有用到 WebSocket 的地方
> 2. Node 22 在 Docker Alpine 上的已知坑
> 3. Redis 7.4 新增的命令对我们 cache 层有哪些影响
> 做完汇总成一份报告。

心智模型

Claude Code 本身是一个 agent。Subagent 是 agent 套 agent。一个管理者把子任务分给几个下属,下属只汇报结论,不带回所有原材料——和真实世界的团队一样。

MCP — 对外接线板

到目前为止,Claude Code 的工具都是「本地」的:读本地文件、跑本地命令。但现实工作里你常常要碰外部系统——GitHub issue、Slack 消息、Notion、Jira、线上数据库……

MCP(Model Context Protocol)是一个标准化的办法:把「第三方服务」封装成 Claude 能直接调用的工具集。你不用关心协议细节,只要知道:有一堆现成的 MCP 服务器,连进来以后 Claude 就多一批新工具。

连一个 GitHub MCP 服务器

在项目根的 .mcp.json

{
  "mcpServers": {
    "github": {
      "command": "npx",
      "args": ["@anthropic-ai/github-mcp"],
      "env": {
        "GITHUB_TOKEN": "${GITHUB_TOKEN}"
      }
    }
  }
}

重启 Claude Code,现在你可以说:

> 帮我看看 #42 这个 issue,然后开一个 PR 修它

Claude 调用 MCP 工具读 issue 原文、理解需求,按正常流程改代码、最后调 MCP 工具开 PR。全程你不用离开终端。

常见的 MCP 服务器

githubIssues、PR、Actions、代码搜索、review。
slack读频道、发消息、搜历史。
postgres / mysql跑 SQL、看 schema、生成迁移。
puppeteer开浏览器点按钮,自动化 E2E。
linear / notion / jira项目管理工具接入。
sentry读 issue、堆栈、事件频率。

三种传输方式

stdio
最常见。Claude Code 启动服务器进程,用标准输入输出通信。
SSE
流式 HTTP。适合远程 MCP,有流式返回。
HTTP
普通请求-响应式。适合简单的远程服务。
$ claude mcp add github npx @anthropic-ai/github-mcp
$ claude mcp add --transport sse remote-tool https://api.example.com/mcp
$ claude mcp add --transport http my-api https://api.example.com/mcp

MCP 权限要上心

MCP 工具一旦连上就是一等公民,和本地工具同级。一个能发 Slack 消息的 MCP,意味着 Claude 理论上能替你发消息。在 permissions 里明确允许/禁止:

{
  "permissions": {
    "allow": ["mcp__github__*"],
    "deny":  ["mcp__slack__send_message", "mcp__postgres__execute_write"]
  }
}

Agent SDK — 把 Claude 嵌进你自己的程序

前六节都在讲「在终端里怎么用好 Claude Code」。第七节讲一个完全不同的方向:把 Claude 作为一个库嵌进你自己写的 Python / TypeScript 程序里。这就是 Agent SDK。

SDK 给你和 Claude Code 同一个 agent 引擎,但你自己决定「在什么环境下跑、接什么工具、吃什么 prompt」。核心类是 query(TS)或 ClaudeSDKClient(Python):

from claude_agent_sdk import query, ClaudeAgentOptions

options = ClaudeAgentOptions(
    system_prompt="你是一个代码审查者。只看安全问题。",
    allowed_tools=["Read", "Grep", "Glob"],
    permission_mode="plan",
    max_turns=10,
    model="claude-opus-4-7",
)

async for msg in query(
    prompt="审一下 src/auth/ 下所有文件,找 SQL 注入和鉴权 bypass。",
    options=options,
):
    print(msg)

值得记的特性:

一个实际场景

你想做一个「新同事入职 checklist 机器人」:拿到同事的 GitHub 用户名,自动查他们最近 5 个 PR、生成技能画像、给 onboarding 路径。这种事情交互式跑也行,但你希望它长期挂在公司内网的 web 服务后面——SDK 就是这个场景。

from fastapi import FastAPI
from claude_agent_sdk import query, ClaudeAgentOptions

app = FastAPI()

@app.post("/onboard/{username}")
async def onboard(username: str):
    prompt = f"查看 GitHub 用户 {username} 最近 5 个 PR,生成技能画像和 onboarding 路径。"
    result = []
    async for msg in query(
        prompt=prompt,
        options=ClaudeAgentOptions(
            allowed_tools=["WebFetch", "Bash(gh pr *)"],
            max_turns=6,
            max_budget_usd=0.30,
        ),
    ):
        result.append(msg)
    return {"report": result}

该不该学 SDK

大一大二如果你只是用 Claude 帮自己写作业、做项目——前六节够了。SDK 是给「想把 Claude 变成自己产品里一部分」的人准备的。等你真的有 idea 了,回来看这一节即可。

组合拳:一个成熟项目的 Claude Code 配置

想象你在一个中等规模的项目里工作几个月了。你的 Claude Code 设置可能长这样:

~/.claude/
├── CLAUDE.md                   # 个人偏好:包管理器、命名风格...
├── skills/
│   ├── commit/                 # 我自己写的智能提交流程
│   └── my-pr-review/           # 我喜欢的 PR 审查清单
├── agents/
│   └── researcher/             # 个人研究员
├── memory/                     # 自动记忆
│   ├── MEMORY.md
│   └── *.md
└── keybindings.json            # 自定义快捷键

my-project/
├── CLAUDE.md                   # 团队规范:架构、禁区、测试要求
├── CLAUDE.local.md             # 我这台机器的特殊路径 (.gitignore)
├── .mcp.json                   # MCP 服务器配置
└── .claude/
    ├── settings.json           # Hook + 权限 + 策略
    ├── agents/
    │   └── migration-bot/      # 项目共享的数据库迁移代理
    ├── hooks/
    │   ├── block-env.sh
    │   ├── auto-format.sh
    │   └── notify-done.sh
    ├── skills/
    │   ├── deploy/             # 团队发布流程
    │   └── hotfix/             # 紧急修复流程
    └── plans/                  # 历史 /plan 产出归档

这时候你的 Claude Code 已经「长」出一个完整的工作台:

五件套不是「非学不可」——一个大一学生完全可以只用 claude + 自然语言跑很多东西。但当你发现自己每天都在告诉 Claude 同样的事,就是引入这些的信号。它们是你用得越久越值得投资的东西

建议的学习顺序

CLAUDE.md 开始——收益最大、成本最低。然后写 2–3 个你天天用的 Skills。权限弹窗多到烦了,配 permissions 白名单。再久一点,写一两个 HookSubagentsMCP 是锦上添花,不急。SDK 等你有真实产品需求再学。