:用 CLAUDE.md、Plan Mode、Hooks 与 Subagents 搭建可复用的项目级配置骨架)
1. 为什么零散技巧撑不起一个团队项目很多人用 Claude Code 的路径都差不多一开始靠/init生成一份 CLAUDE.md然后记住几个快捷键遇到复杂改动就切 Plan Mode偶尔配个 Hook 拦一下危险命令。单看每一步都没问题但真正进到多人协作的项目里问题会集中爆发——新人 clone 下来跑一遍发现 Claude 读到的项目约定和老人完全不一样同一个仓库里A 同学让 Claude 先出计划再动手B 同学直接让它改文件结果 diff 风格对不上更麻烦的是那些「口头约定」只存在于某次对话里会话一关就没了。这一篇要解决的就是这件事把 CLAUDE.md、Plan Mode、Hooks、Subagents 这四个能力从「个人技巧」升级成「项目级配置骨架」。骨架的意思是它不依赖某个人记性好而是写进仓库、跟着代码走、任何人拉下来都能复现同一套行为。CLAUDE.md 负责定义项目上下文Plan Mode 负责把任务拆解成可审阅的步骤Hooks 负责在关键节点挂上校验动作Subagents 负责把并行职责拆开。四者配合起来Claude Code 才从「一个聪明的补全工具」变成「团队工程规范的一部分」。下面我会给出可以直接复制的settings.json与 CLAUDE.md 骨架、Hooks 触发配置以及每一项的验证动作。你不需要一次全上可以按「先 CLAUDE.md、再 Plan Mode、然后 Hooks、最后 Subagents」的顺序逐步落地。2. 前置准备把模型接入和项目目录先理顺在动配置之前有两件事要先确认否则后面所有骨架都跑不起来。第一是模型接入。Claude Code 本身是客户端真正干活的是背后的模型服务。如果你用的是 TaoToken 这类兼容 Anthropic 接口的服务需要先在控制台拿到 API Key再把它配到环境变量里。这一步不做后面claude命令会直接报鉴权错误。第二是项目目录结构。Claude Code 读取配置有几个固定位置建议在项目根目录建一个.claude/文件夹把项目级配置都放进去your-project/ ├── .claude/ │ ├── settings.json # 项目级配置权限、Hooks、环境变量 │ ├── commands/ # 自定义斜杠命令 │ └── agents/ # Subagents 定义 ├── CLAUDE.md # 项目记忆构建/测试/约定 └── src/.claude/settings.json是项目级配置会跟着仓库走~/.claude/settings.json是用户级配置只影响你自己。团队规范要沉淀就写进项目级那份。拿 Key 和看接入文档的入口在这里先配好再往下控制台与 API Keyhttps://taotoken.net/console?utm_sourcetaotoken_aicg_blog_endutm_contentconsoleutm_campaignrewrite 接入文档https://taotoken.net/doc?utm_sourcetaotoken_aicg_blog_endutm_contentdocutm_campaignrewrite环境变量配置示例写进你的 shell 配置或 CI 的 secretexport ANTHROPIC_BASE_URLhttps://taotoken.net/api export ANTHROPIC_API_KEYsk-你的key配完执行claude --version能正常输出说明客户端没问题再随便问一句让它读个文件能返回内容就说明模型链路通了。3. CLAUDE.md 骨架把项目上下文写成可复现的记忆CLAUDE.md 是整个骨架的地基。它的作用是让 Claude 每次进入项目时不用你重复解释「用什么包管理器、测试怎么跑、目录怎么分」。/init可以自动生成初版但自动生成的往往太泛真正有价值的是你手动补进去的团队约定。一个可复用的 CLAUDE.md 骨架长这样# 项目订单服务order-service ## 技术栈 - 语言TypeScript 5.xNode 20 - 包管理器pnpm禁止使用 npm/yarn锁文件为 pnpm-lock.yaml - 框架Fastify Prisma - 测试Vitest覆盖率阈值 80% ## 常用命令 - 安装依赖pnpm install - 本地启动pnpm dev - 跑单测pnpm test - 跑单个文件pnpm test src/order/order.service.test.ts - 类型检查pnpm typecheck - Lint 并自动修复pnpm lint --fix ## 目录约定 - src/order/ 订单核心逻辑 - src/payment/ 支付适配层禁止直接引用 order 内部实现 - src/shared/ 跨模块工具改动需谨慎 - prisma/schema.prisma 数据模型唯一来源 ## 代码约定 - 所有对外接口必须有 zod schema 校验 - 错误统一抛 AppError禁止裸 throw new Error - 提交信息遵循 Conventional Commits ## 禁止事项 - 不要修改 prisma/migrations 下已存在的迁移文件 - 不要在 src/payment 里 import src/order 的内部模块 - 不要执行 pnpm publish 或任何发布命令这份文件的关键在于「具体」。写「用 pnpm」不够要写「禁止 npm/yarn锁文件是 pnpm-lock.yaml」写「注意目录」不够要写清楚哪个目录不能跨引用。Claude 读到的约束越明确跑偏的概率越低。维护习惯上我建议把「重复纠正」当成信号当你发现自己在对话里第二次说同一句话就把它写进 CLAUDE.md。比如你总在提醒「测试文件放同目录不要放tests」那就补一条目录约定。这样 CLAUDE.md 会随着项目演进越来越贴合实际。验证动作新开一个会话直接问「这个项目用什么包管理器跑测试」如果它答出 pnpm 和具体命令说明 CLAUDE.md 被正确加载了。4. Plan Mode先出方案再动手的落地方式Plan Mode 解决的是「改之前先想清楚」的问题。它进入只读状态Claude 会读代码、给方案但不直接改文件。对跨多文件的改动、或者你还没想好怎么拆的任务这一步能省掉大量返工。进入方式有两种会话里按ShiftTab切换或者启动时指定claude --permission-mode plan在 Plan Mode 下一个好的任务描述应该带上约束而不是只说「帮我重构订单模块」。比如在 Plan Mode 下分析把 src/order/order.service.ts 里的 支付调用抽到 src/payment 适配层。 约束 1. 不改变对外接口签名 2. 现有测试必须全部通过 3. 给出分步骤计划标注每步影响哪些文件 先只给计划不要改代码。Claude 会返回一份分步计划通常包含「读哪些文件、改哪些文件、每步验证方式」。这时候你要做的是审阅计划本身而不是急着让它执行。计划里如果有「直接删除旧函数」这种激进步骤就在这一步拦下来让它改成「保留旧函数并标记 deprecated下个版本再删」。计划确认后退出 Plan Mode 让它执行。执行过程中如果发现计划有偏差可以再切回 Plan Mode 重新规划。这个「规划—审阅—执行」的循环比直接让它改文件稳得多。验证动作故意给一个模糊任务看它是否在 Plan Mode 下拒绝直接改文件、只输出计划。如果它直接动手了检查是不是没真正进入 plan 模式。5. Hooks 配置在关键节点挂上自动校验Hooks 是把「规范」变成「强制」的关键。CLAUDE.md 是建议Hooks 是拦截。它能在工具调用前后、权限请求等事件触发脚本适合做代码风格校验、危险命令拦截、审计日志。配置写在.claude/settings.json里。下面是一份可直接复制的骨架{ hooks: { PreToolUse: [ { matcher: Bash, hooks: [ { type: command, command: python3 .claude/hooks/guard_bash.py } ] } ], PostToolUse: [ { matcher: Edit|Write, hooks: [ { type: command, command: pnpm lint --fix $CLAUDE_FILE_PATH } ] } ] } }PreToolUse在工具执行前触发适合拦截PostToolUse在执行后触发适合校验和修复。matcher匹配工具名Bash匹配所有 shell 命令Edit|Write匹配文件编辑。配套的拦截脚本.claude/hooks/guard_bash.py#!/usr/bin/env python3 import json import sys # 危险命令黑名单 BLOCKED [rm -rf /, pnpm publish, git push --force, DROP TABLE] def main(): payload json.load(sys.stdin) command payload.get(tool_input, {}).get(command, ) for pattern in BLOCKED: if pattern in command: # 退出码 2 表示阻止执行并把原因反馈给模型 print(f已拦截危险命令{pattern}, filesys.stderr) sys.exit(2) sys.exit(0) if __name__ __main__: main()这里有个关键点Hook 脚本退出码为 2 时Claude Code 会阻止这次工具调用并把 stderr 的内容反馈给模型让它知道为什么被拦。退出码 0 表示放行。这个机制让你能把「不要执行发布命令」从建议变成硬约束。PostToolUse里那个 lint 命令$CLAUDE_FILE_PATH是 Claude Code 传入的当前文件路径每次编辑后自动跑一次格式化能有效避免「Claude 写的代码风格和项目不一致」。验证动作在会话里让它执行git push --force如果被拦截并提示原因说明 PreToolUse 生效了随便改一个文件看是否自动触发了 lint。6. Subagents把并行职责拆开Subagents 适合大型任务。当一件事可以拆成「调查、实现、测试、文档」几条独立线索时让一个主代理串行做会很慢拆成子代理并行推进效率更高。在.claude/agents/下定义子代理每个是一个 Markdown 文件。比如一个专门做代码审查的子代理.claude/agents/reviewer.md--- name: reviewer description: 代码审查专用检查约定遵守情况 tools: Read, Grep, Glob --- 你是代码审查员。审查时重点检查 1. 是否违反 CLAUDE.md 中的目录约定 2. 对外接口是否有 zod 校验 3. 错误是否统一用 AppError 只报告问题不修改代码。输出格式文件路径 行号 问题描述。注意tools字段限制了它只能用只读工具这样审查代理不会误改代码。另一个做测试的子代理可以只给Read, Bash让它能跑测试但不能改源码。使用时在主会话里明确要求拆分这个重构任务拆成三条线并行 1. reviewer 子代理审查现有 order 模块的约定遵守情况 2. 主代理实现支付适配层抽取 3. 一个测试子代理补充适配层的单测 各自独立推进最后汇总。Subagents 的价值在于「职责隔离」审查的只读、实现的能写、测试的能跑权限边界清晰出问题也好定位。对跨模块排障尤其有用可以让不同子代理同时追不同的线索。验证动作定义好子代理后让它执行一个只读任务确认它没有修改任何文件再确认它的输出格式符合你在定义里写的要求。7. 本篇常见错排查CLAUDE.md 没生效先确认文件在项目根目录且文件名大小写正确是CLAUDE.md不是claude.md。如果用了 monorepo注意 Claude Code 读取的是当前工作目录的 CLAUDE.md子包里的需要单独放或在上层引用。Plan Mode 下还是改了文件检查是不是通过--permission-mode plan启动的或者ShiftTab是否真的切到了 plan 状态。有些版本里权限模式会被 settings.json 覆盖检查配置里有没有强制指定 permission mode。Hook 脚本不触发确认settings.json的 JSON 格式合法可以用python3 -m json.tool校验matcher的工具名拼写正确。脚本路径建议用相对项目根目录的路径并确认有执行权限。Hook 拦截后模型反复重试退出码 2 会把 stderr 反馈给模型如果反馈信息不够明确模型可能换个写法继续试。把拦截原因写清楚比如「禁止发布命令如需发布请人工执行」模型通常就会停止。Subagent 权限过大检查定义文件里的tools字段只读任务一定要限制成Read, Grep, Glob不要给Write或Bash。权限给多了隔离就失去意义。模型鉴权失败确认ANTHROPIC_BASE_URL和ANTHROPIC_API_KEY都配了且 Key 没有过期。如果用的是兼容接口注意 base URL 结尾不要多加/v1具体以接入文档为准。8. 把骨架沉淀成团队资产这套骨架真正发挥价值是在它进了仓库之后。CLAUDE.md、.claude/settings.json、Hooks 脚本、Subagents 定义全部跟着代码走新人 clone 下来就继承同一套行为。你不需要在群里发「记得用 pnpm」这种消息配置本身就是规范。落地节奏上建议分四步走先把 CLAUDE.md 写扎实这是投入产出比最高的一步然后团队统一用 Plan Mode 处理跨文件改动接着把最容易出错的环节做成 Hook比如危险命令拦截和编辑后 lint最后在大型任务里引入 Subagents 做职责拆分。每一步都能独立验证不用等全部配完才见效。如果你还在选模型接入方式或者想先把链路跑通再上配置可以从模型对话入口先试一轮确认返回质量符合预期再写进项目模型对话体验https://taotoken.net/?utm_sourcetaotoken_aicg_blog_endutm_contentmodel-chatutm_campaignrewrite 长期编码与 Agent 场景https://taotoken.net/coding-plan?utm_sourcetaotoken_aicg_blog_endutm_contentcoding-planutm_campaignrewrite配置这件事没有一步到位先把 CLAUDE.md 和 Plan Mode 用顺再逐步加 Hooks 和 Subagents比一次性堆满配置然后发现互相冲突要省心得多。