把 Claude Code 从「会写代码的聊天框」改造成你专属的工程运行时。
Day 3 讲过 harness 是 LLM 的 OS——Claude Code 就是当前公开 SOTA 的 coding harness。但 90% 的人只用它最表层的「对话+改文件」,把一个可编程平台当成了高级补全。这一期不讲「Claude Code 是什么」,而讲怎么把它的配置面全部打开:CLAUDE.md 的分层 memory 是每轮都计费的 token 预算,不是 README;subagent 的真正价值是 context 隔离而非「多个助手」;slash command 已经并入 skills,长流程可以做到「按需加载、零常驻成本」;而 claude -p 把整个 harness 变成一个能塞进 CI 与 cron 的 unix 工具,MCP 再把外部系统接成原生 tool。学会这四层,你的 Claude Code 和默认状态完全是两种生产力。
很多人把 CLAUDE.md 当成项目 README 来写,塞进整套架构文档、风格指南、历史决策。这是反模式:CLAUDE.md 在每次会话启动时整体注入上下文并持续占用,写得越长,一是吃掉你的有效 context,二是稀释 adherence——指令多到一定密度,模型反而开始漏执行。Anthropic 官方建议单个 CLAUDE.md 控制在 200 行以内,只放「高频、跨任务、稳定」的事实与约束。
Claude Code 的 memory 是一个四层 hierarchy,启动时按优先级合并:(1) 企业 / 受管策略层;(2) 项目层 ./CLAUDE.md 或 .claude/CLAUDE.md(随 git 共享给团队);(3) 项目本地 CLAUDE.local.md(gitignore,放个人偏好);(4) 用户层 ~/.claude/CLAUDE.md(跨所有项目)。大 monorepo 还能在子目录放各自的 CLAUDE.md,进入该目录时才加载——这是大 repo 控制 context 的关键手段:让上下文随工作区域按需出现,而不是把整个仓库的规则一次性堆在根部。
@import 语法(@docs/style.md)能把外部文件拉进来,但要记住一个反直觉点:import 是 inline 展开,不省 token——被引文件内容照样计入活动窗口。import 的价值是组织复用,不是压缩。真正省 context 的是把「流程」挪进按需加载的 skill(见 §3),而不是 import 进常驻的 CLAUDE.md。
一份「好」的根 CLAUDE.md:短、是约束不是叙述、把长内容推给 skill:
# CLAUDE.md — 只放高频稳定的事实与红线
## 命令
- 测试:pnpm test(改完必跑) 构建:pnpm build
- 不要用 npm / yarn,本仓库统一 pnpm
## 风格红线
- TS strict,禁止 any;新代码必须带单测
- API 层错误一律走 Result<T>,不要 throw
## 仓库地图
- 业务逻辑 packages/core,HTTP 在 packages/api
- 复杂发布流程见 /release(skill,按需加载,不在这里展开)
用 /memory 命令可随时在会话内编辑各层 CLAUDE.md,也能查看 Claude 根据你的纠正自动记下的 auto memory。规则:事实放 CLAUDE.md(常驻),流程放 skill(按需)。
@import 能省 token——它只是 inline 展开,被引内容照样全额计费。(3)大 monorepo 只用根 CLAUDE.md,结果根文件越长越笨;应该下沉到子目录按需加载。
Day 3 提过 subagent 是「独立 context window 的子进程」,这里讲它的工程判据。subagent 是放在 .claude/agents/*.md(项目级,团队共享)或 ~/.claude/agents/*.md(用户级)的 markdown 文件,每个拥有自己的 system prompt、工具权限、甚至自己的模型。用 /agents 命令可交互式创建。
它最有价值的用途只有一个母题:隔离会产生大量输出的操作。跑全套测试、读几千行日志、抓一篇长文档——这些动作会吐出海量 token,如果在主对话里做,主 context 立刻被噪声污染到不可用。把它丢给 subagent:冗长输出留在 subagent 的独立 context 里,只有提炼后的结论返回主线。这本质上是用「一次性的隔离上下文」换主线的清洁度——和 §1 的 token 经济学是同一套逻辑。
反过来,subagent 不适合需要共享主线全局状态的任务。因为子 agent 看不到主对话的上下文(这正是隔离的代价),你得在它的 prompt 里重新喂足背景,否则它在信息真空里工作。Cognition 在 Don't Build Multi-Agents 里反复警告的「context 在 agent 间漂移」就是这个坑——隔离是双刃剑。
一个高频好用的 subagent:用独立 context 跑测试并只回摘要,主线不被几千行测试输出淹没。
# .claude/agents/test-runner.md
---
name: test-runner
description: 跑测试套件并诊断失败。当用户改完代码要验证时主动使用。
tools: Bash, Read, Grep
model: haiku # 噪声活用便宜模型,省钱见 Day 16
---
你是测试诊断专家。执行步骤:
1. 运行 `pnpm test`,完整捕获输出(输出会很长,这没关系——它留在你的 context 里)。
2. 只在失败时:定位失败用例、读相关源文件、给出根因假设。
3. 返回主线的只有一段结构化摘要:
{ passed: N, failed: M, failures: [{test, file:line, 根因假设}] }
不要把原始测试日志返回主线。
关键在最后一句和 model: haiku:subagent 是「把脏活外包」的机制,外包的目的是主线只收干净的结论,顺便用便宜模型省 token。
description 写得含糊,导致 Claude 在不该用时调用它。
2026 年的一个重要变化:custom slash command 已经合并进 skills。.claude/commands/deploy.md 和 .claude/skills/deploy/SKILL.md 都会生成 /deploy,行为一致;老的 commands/ 文件继续可用。skill 的额外能力是:可带支撑文件目录、用 frontmatter 控制「谁来触发」、以及让 Claude 在相关时自动加载。
真正的工程意义在 context 经济学:和 CLAUDE.md 不同,skill 的正文只在被调用时才载入。所以那些「长但低频」的多步流程(发布、迁移、合规检查清单)——放进 CLAUDE.md 会白白常驻吃预算,放进 skill 则平时零成本、用到才展开。这是 §1「事实放 memory、流程放 skill」那条规则的底层机制。
frontmatter 关键字段:description(决定 Claude 何时自动调用)、allowed-tools(限制该流程能用的工具)、以及正文里的 $ARGUMENTS 占位符(接收 /命令 后面的参数)。你还能控制它是只能手动 /触发,还是允许 Claude 自主调用。
一个把团队提交规范固化下来的 /commit skill——以后不用每次复述 conventional commits 规则:
# .claude/skills/commit/SKILL.md
---
description: 按团队规范生成并执行一次 git 提交
allowed-tools: Bash(git add:*), Bash(git commit:*), Bash(git diff:*), Bash(git status:*)
---
为当前改动创建一次提交:
1. 跑 `git status` 和 `git diff` 看清改了什么。
2. 按 Conventional Commits 写 message:type(scope): summary
type ∈ feat|fix|refactor|docs|test|chore
3. 若用户传了参数,把它作为 scope 提示:$ARGUMENTS
4. 暂存相关文件并提交。不要提交未经审阅的无关改动。
调用 /commit api 就会以 api 为 scope 提示走完整套流程。注意 allowed-tools 把这个 skill 能碰的命令收窄到 git 子集——即使流程跑飞也碰不到 rm 或 push。
description 雷同,Claude 自动调用时选错——和 Day 4 的 tool selection 退化同源,宁可精而正交。(3)忘了设 allowed-tools,一个本该只读的 skill 拿到了写权限。
claude -p 把整个 harness 变成一个可脚本化的 unix 工具;MCP 再把外部系统接成原生 tool——两者合起来才是「自动化」。Headless 模式:claude -p "<prompt>" 不开交互 UI,执行完把结果打到 stdout 然后退出。配合几个 flag 就能进 CI / cron:--output-format json 给机器可读输出(含 token 与 cost)、--allowedTools 预授权工具免询问、无人值守时 --dangerously-skip-permissions 全程不拦。退出码可用于 pipeline 判断成败。典型场景:CI 里自动修 lint、批量改一类文件、夜间跑回归。
MCP(Model Context Protocol):把 GitHub、数据库、Notion、内部 API 等外部系统接成 Claude 能直接调的 tool。claude mcp add --transport http <name> <url> 接远程 server,--transport stdio ... -- <cmd> 接本地进程。配置可落到 .mcp.json 随仓库共享给整个团队。MCP 是 Day 18 的正题,这里只看它和 headless 的合体威力。
合起来:在 CI 里跑 claude -p + GitHub MCP server,Claude 就能读 PR diff、跑测试、把 review 评论发回 PR——一条全自动的工程流水线。但自动化的边界就是权限:headless 越省心,安全责任越重。
# CI 里让 Claude 审一个 PR:headless + GitHub MCP
claude mcp add --transport http github https://api.githubcopilot.com/mcp/ \
--header "Authorization: Bearer $GH_TOKEN"
claude -p "审阅 PR #$PR_NUM:读 diff,跑 pnpm test,
发现 bug 就在对应行留 inline 评论;通过就批准。" \
--allowedTools "Bash(pnpm test:*)" "mcp__github__*" "Read" "Grep" \
--output-format json > review.json
# 用退出码 + json 里的字段决定 CI 是否放行
test $? -eq 0 || exit 1
注意 --allowedTools 是白名单:只放 pnpm test、GitHub MCP、只读工具——没给的工具一律询问,而 headless 下「询问」=阻塞失败,等于硬性禁止。这是无人值守下唯一可靠的权限护栏。
--dangerously-skip-permissions——这是 prompt injection 的头号入口,恶意 diff 能诱导 Claude 跑任意命令(Day 24 详谈)。无人值守必须配死白名单 + 沙箱。(2)接一堆 MCP server 图全——工具数量爆炸会触发 selection 退化(Day 4),且每个 server 的 schema 都吃 context。(3)headless 跑长任务不设超时与 max-turns,死循环烧 token。
挑一个你常用的中型仓库,半小时把四层配置一次性铺好,体会默认 Claude Code 和「工程化」Claude Code 的差距:
test-runner,model: haiku,只回结构化摘要。对比主线 context 干净了多少。allowed-tools 收窄权限。验证它们平时不占 context、/触发才加载。claude -p "总结本周 merged PR" --output-format json。看 json 里的 token / cost——这就是把它放进 cron 的成本基线。.claude/settings.json 里 deny 掉 rm -rf / 强制 push / --no-verify(Day 3 的配置)。任何 headless 自动化都跑在这道护栏内。铺完你会有一个直觉:Claude Code 的能力上限不在模型,在你把多少工程纪律固化进了配置面。同一个模型,配置过和没配置过,是两种生产力。
.claude/agents/*.md),核心价值是隔离噪声、只回摘要。SKILL.md)。已合并 custom slash command,body 用到才载入。/命令 后参数的占位符。claude -p 非交互运行:执行完打到 stdout 退出,可进 CI / cron。