ARTICLE DETAIL

资讯详情

深耕网站视觉设计与运营推广的一线实战洞察。

Claude Code 进阶指南:权限、记忆与TDD工作流实战

Claude Code 进阶指南:权限、记忆与TDD工作流实战 从装好了到用顺手我的 Claude Code 进阶路线图先说清楚一个前提这篇是系列第二篇第一篇讲的是安装、账号、基础环境这些东西。如果你还在claude命令都敲不出来、报auth错误、或者是不知道怎么和 VS Code 里的终端配合建议先把第一篇翻出来把环境弄好再来往下看。今天要聊的是另一件事——Claude Code 装好之后的真实使用体验包括怎么管住它、怎么让它干活更稳、怎么把这东西真正接进自己的开发流里。Claude Code 这个东西表面上看就是一个跑在终端里的 AI 编程助手能读文件、改代码、执行命令、跑测试但如果你只是在终端里敲一句帮我加个登录接口然后看它噼里啪啦输出那你大概只用了它 10% 的能力。真正让它值回票价的地方是你能不能给它划清边界、立好规矩、设计好任务链路。这套东西玩明白了它就从一个高级自动补全变成了一个真正能托管中型任务的工程助理。这篇我不会写那种点击这里、输入那里的保姆级操作步骤——那些官方文档里都有。我重点拆的是三块权限模型怎么设计、记忆和上下文怎么喂、以及怎么把它嵌进你的 TDD 和 Git 工作流里。最后会复盘一个真实的多文件重构任务把整个链路从头到尾串一遍。中间会夹很多我实际踩过的坑以及现在我已经固化成肌肉记忆的用法。1. 权限模式不是摆设allow和deny背后的运行逻辑很多人的第一反应是Claude Code 让我做啥我就做啥它说改哪个文件就改哪个文件反正它会自己判断。大错特错。它本质上是一个需要持续决策的代理并不是一次性生成完就不管了。每一次它想读取、编辑文件或者执行 shell 命令都需要和你手里的权限系统打交道。说白了你要做的是当它的项目经理而不是观众。1.1 三种授权模式到底怎么选Claude Code 的权限机制核心是三种模式Allow、Deny、Skip。在交互界面里当 Claude Code 要执行一个操作时它通常会弹出选项模式行为适用场景Allow允许当前这次操作单次确认觉得这次操作没问题就选这个Allow Always记住规则后续同类操作不再询问高频且安全的操作比如编辑器保存、读取测试文件Deny拒绝当前操作明确告诉它这次不行Deny Always永久拒绝同类操作比如永远不想让它碰某个目录Skip跳过当前操作不执行暂时绕过比如这波先不改这个文件请注意这里的当前操作不是按文件来的而是按规则模式来匹配的。比如它要对src/api/client.ts执行Write操作你选了 Allow Always那么以后所有对src/api/下文件的写入请求可能都不再询问具体匹配粒度看你用的版本设置。所以Allow Always 一定要克制用我见过最惨烈的翻车现场就是有人对“所有文件写入”点了 Allow Always然后 Claude Code 在重构的时候把他的整个项目配置目录重写了一遍。1.2 先从默认拒绝开始我的建议是如果你刚开始用不要急着把权限全部放给 Claude Code 让它自由发挥。先把模式调成偏保守特别是在真实项目和共享代码库里。具体做法是编辑器和终端命令的权限可以给但要设范围。比如Write操作可以允许在项目目录内但临时目录、系统目录、home 目录下的.*rc文件这些最好显式 deny。执行命令的权限要看命令类型。像grep、ls、cat、find这种只读命令允许没问题git push、rm -rf、pnpm publish这类有副作用的一定要让它来问你。Bash(command)的授权优先级要低于文件操作因为执行命令一旦放出去就等于把机器交出去了。我自己初期犯过的错是在某个周末图省事把git reset --hard也放到了 Allow Always 里结果它在一段混乱的交互中把本地两天的工作全部回滚了。虽然用git reflog救了回来但从那以后我建立了底线任何不可逆操作必须手动确认。提示如果你不确定当前项目的权限设置状态可以敲/permissions查看当前的授权情况也可以随时在对话里用/permissions add allow Bash(git push:*)这种形式动态补充规则。先别急着做大范围授权宁可多敲几次确认也不要让它自由发挥。1.3 授权文件的位置和版本控制权限规则并不是存在某个记忆黑洞里的它是以文件形式存在的。一般来说全局配置在~/.claude/下面项目级别的配置在项目根目录的.claude/下面。你要关注的重点是这个权限配置有没有进 Git。如果你在团队里协作.claude/目录里的权限文件应该进仓库让其他人的体验一致但如果你放了一些和项目无关的全局配置比如全局 deny 了某个目录就不要拿到项目里来。我自己的习惯是项目级别的.claude/settings.json放和这个项目强相关的权限和元信息跟着仓库走。全局的~/.claude/CLAUDE.md放个人通用规范不进公司仓库。.claude/目录里有些自动生成的 session 记录和临时文件我会加进.gitignore避免污染。这一块信息很容易被忽略但它是后面所有工作流能不能安全跑起来的基础。把权限理解成给代理建护栏护栏立好了它才敢跑得快。2. 记忆与上下文工程CLAUDE.md 怎么写才不白写Claude Code 每一轮会话都是失忆的——准确说是它的上下文窗口有限每次开启新会话它不会天然记得你上个会话里交代的细节。它赖以记住你的项目偏好、背景信息、约定规范的核心文件是CLAUDE.md。这个文件写得好不好直接决定了它干的活是通用正确还是贴合本项目正确。2.1 CLAUDE.md 的分层结构正常情况下Claude Code 会依次读取几个层级的 CLAUDE.md系统级或个人级~/.claude/CLAUDE.md存放你对所有项目通用的偏好比如不要问我要做多么细节的确认除非是不可逆的操作或者优先使用 pnpm 而不是 npm。项目级项目根目录下的CLAUDE.md存放这个项目的技术栈、目录结构、构建命令、测试方式、编码规范等。如果有子目录级别的CLAUDE.md某些情况下也会被加载但我个人极少用这个层级因为容易让人迷惑。如果你将团队编码规范写进了根目录的CLAUDE.md它每次启动都会读取省得你每开一个会话都要把我们后端是 Go微服务划分是 xxx重新打一遍。2.2 写好 CLAUDE.md 的几个关键点很多人的 CLAUDE.md 写得太抽象比如# 项目规范 - 代码要整洁 - 性能要好 - 注释要清晰这种文件写了等于没写。因为整洁、好、清晰都是模糊概念Claude Code 不是你肚子里的蛔虫它需要的是可校验的规则和具体的上下文。我比较认可的结构是这样的# 项目支付网关后台 ## 技术栈 - 前端React 18 TypeScript Vite - 后端Node.js 20 Fastify Prisma - 数据库PostgreSQL 15 - 包管理器pnpm禁止使用 npm 或 yarn 生成 lockfile ## 常用命令 - 启动开发pnpm dev - 运行测试pnpm test -- --runInBand - 类型检查pnpm typecheck ## 目录结构 - src/api/路由与控制器层一个文件对应一个微服务路由模块 - src/service/业务逻辑层只允许被 controller 或 service 调用 - src/repository/数据库存取层禁止把 SQL 拼在 controller 里 ## 编码约定 - HTTP 接口统一走 RESTful 风格不要引入 GraphQL - 错误响应必须包含 code 字段格式{ code: PAYMENT_TIMEOUT, message: ... } - 所有金额字段一律使用 number 类型单位是分禁止使用浮点数直接存金额 - 组件使用函数组件和 hooks不使用 class 组件 - 提交信息使用 conventional commits 格式 ## 特别注意事项 - 这是一个支付项目任何涉及退款、打款、对账的逻辑改动必须是用户可手动确认的操作 - 禁止对生产数据库执行直接 UPDATE 或 DELETE需要操作时使用 migrations - 不要把本地 .env 文件的内容以任何形式打印到日志里注意几个点每一条规范都尽量是机器可以验证的比如使用 pnpm 禁止 npm、错误码必须包含code字段而不是代码风格保持统一。常用命令写清楚尤其测试命令因为 Claude Code 在改完代码后经常会自己跑测试验证如果测试命令是错的它很容易产生误判。标注出“不可逆操作”的雷区这比在权限配置文件里写 deny 规则更早一步能让 Claude Code 在动手之前就知道要小心。2.3 会话中的记忆补充/memory和--add-dir除了 CLAUDE.mdClaude Code 还支持在会话中动态添加 memory 或引用某些目录的内容。我现在比较喜欢用的一个方式是在启动项目任务前先不带任何要求运行一次claude --add-dir docs这样它会在开始工作之前先把docs目录中可能的需求文档、接口文档都读进上下文相当于给它做了一次新员工入职培训。如果你初始化项目时发现某个文件特别重要也可以在会话中用/memory把它追加进记忆。有一点要小心记忆和上下文不是越多越好。有一次我在一个大仓库的根目录运行 Claude Code它光是把各种 README、配置文件、类型声明读进上下文就已经占了不少窗口真正干活的时候反而变得迟缓。后来我养成了习惯——只在必要的时候用--add-dir或--include指定关键路径而不是让它把整个仓库都读一遍。提示CLAUDE.md 的更新应该是持续的。每次在会话中发现它重复犯同一个错误我都会把对应的规则写进 CLAUDE.md。比如有段时间它老想把所有的测试文件放到__tests__目录而我的项目约定是把测试文件放在src/目录下同名文件旁边。遇到第三次的时候我就没再忍直接写进了 CLAUDE.md后来基本没再犯过。3. 从 Read → Bash → Edit 的飞轮运转逻辑Claude Code 执行一个任务并不是一步到位的它的核心循环是不断重复读取相关信息 → 执行必要的核查命令 → 修改代码 → 运行测试/检查 → 再读取反馈。理解这个循环你才能真正驾驭它。3.1 一个真实的多文件重构任务复盘我举一个上周做的任务当例子。这个项目是一个内部工具的后端服务原来所有路由都堆在一个app.ts里大概有 1500 行。我需要把它按领域拆分成auth、billing、user三个模块同时不能改变任何外部 API 的行为。我的启动命令是这样的claude进入交互后第一句话我就抛出完整任务我要把 app.ts 里的路由拆分到 auth/billing/user 三个模块目录下。 拆分原则完全保持现有 HTTP 路径和响应格式不变不要修改业务逻辑。 拆分完成后运行 pnpm typecheck 和 pnpm test确保全部通过。 先给我一个拆分计划我确认后再动手。注意我最后一句——先给我一个拆分计划我确认后再动手。这句话非常关键。很多人一上来就让 Claude Code 直接搞它搞到一半你发现方向不对再打断它双方都难受。在让它花费大量 token 写代码之前先让它用最少的成本输出计划是一个非常划算的确认节点。它给出的计划大致是创建src/modules/auth/router.ts、billing、user等文件。逐个将app.ts中对应的路由 handler 移动过去。保留公共的 middleware 在src/middleware/中。最后用pnpm typecheck和pnpm test验证。我批准之后它开始进入循环。中间我能看到它反复调用命令读取 src/app.ts 的部分内容 执行 grep -n auth src/app.ts 编辑 src/modules/auth/router.ts 执行 npx tsc --noEmit我在旁边看着基本没有过多干预只在一个地方叫停了它——它想把app.ts里一个公共的errorHandler也挪到billing目录下理由是和计费错误相关。我立刻纠正这个中间件是全局的和某个业务模块没有归属关系留在src/middleware/就好。它马上调整没有继续自由发挥。3.2 给足约束条件比给它自由更重要通过这个案例我想强调一个核心体会给 Claude Code 的约束越明确它的产出越稳定。约束条件可以包括改动范围明确只能改哪些目录禁止动哪些目录。验证方式明确改完要跑什么命令才算完成。风格约束明确使用什么 API 风格、错误码格式、命名方式。不可逆操作明确禁止执行哪些命令。比如同样是对支付模块做改动我可能会说请修改 refund 接口让它支持部分退款。要求 1. 只修改 src/modules/refund/ 目录下的代码 2. 不改变其它模块以及数据库表结构 3. 参数校验规则和现有 refund.validation.ts 保持一致 4. 修改完运行 pnpm test -- refund所有测试必须通过。对比一下没有加这些约束的版本请帮我支持部分退款。——你不是在训练它你是在挖坑给自己跳。3.3 打断和纠错的时机判断和 Claude Code 协作的过程中它不可能永远是对的。重点是你什么时候打断它。我自己总结的经验如果它还在信息收集阶段比如读文件、搜索代码、查类型定义尽量不打断。让它把上下文铺开。如果它进入了大规模写入阶段但你发现它要从一个错误的方向前进立刻按 ESC或对应中断快捷键打断并把正确的方向丢给它。这时候越早纠正成本越低。如果它只是在小步执行命令、读取结果、修正代码不要频繁打断。它在等测试输出的时候耐心一点。如果它连续两次在同一个问题上犯错说明它缺少某个信息。这个时候不是继续纠正而是应该停下思考是我 CLAUDE.md 少了规则还是它没注意到某个上下文还是权限受限导致它看不到关键文件这个判断能力没有捷径只有多上手几次才能建立直觉。但有一个小技巧让 Claude Code 输出更多中间结论。在让它改代码之前先让把自己看到的项目结构、理解的业务规则说出来你检验一下基本能确认它是不是懂了。4. TDD 闭环把 Claude Code 写代码 变成 Claude Code 证明代码如果你只是让 Claude Code 写一段代码然后跑一下看有没有报错这其实是很弱的验证。尤其是后端业务代码编译通过只是及格线行为是否正确才是关键。所以我倾向于把它集成进 TDD 的闭环里。4.1 让 Claude Code 遵守 Red-Green-RefactorTDD 的流程是写一个失败的测试Red。写最少的代码让测试通过Green。重构并保持测试通过Refactor。Claude Code 完全可以按照这个顺序执行而且效果比我直接让它实现功能要好很多。因为测试就是一种精确的需求描述比你在对话里写限制条件还要精确。一个典型的对话模式是请按照 TDD 方式实现用户可以通过邮箱和密码注册这个功能。 步骤 1. 先为 POST /api/auth/register 写测试覆盖成功注册、邮箱重复、参数缺失三个场景。 2. 运行测试确认新测试失败此时报错信息应该能说明功能未实现。 3. 再编写实现代码使测试通过。 4. 重构任何你觉得需要优化的地方但要保证测试仍然通过。在 Claude Code 执行过程中它会自动运行测试并读取结果。这比我手动一行行看它的输出更可靠因为测试本身就是最终裁判。4.2 用测试结果驱动下一次对话我特别喜欢的一个用法是让 Claude Code 在完成修改之后不仅告诉我改完了还告诉我测试输出是什么。甚至我会直接命令它如果测试有失败不要尝试解释原因直接把失败信息贴出来我们逐条讨论。这能避免它陷入我知道哪里错了但不想承认的循环。我在实际使用中发现Claude Code 在处理编译错误时表现得挺好但处理测试断言错误时偶尔会自作聪明。比如测试期望某个响应码是400它返回了403它可能会给你解释因为权限校验的原因所以用了 403。这时如果你不看测试输出很容易被它带偏。但是只要你要求它把测试失败信息贴出来你就有了判断依据直接说按测试期望改成 400即可。4.3 一个值得一试的固定命令模板我用得最多的一个固定 prompt 模板是这样的请完成功能{功能描述} 要求 1. 先写自动化测试测试文件放在 {测试路径}覆盖 {具体场景成功/失败/边界}。 2. 运行 {测试命令}确认新测试失败。 3. 再实现功能使用项目现有代码风格和目录约定。 4. 反复运行 {测试命令} 直到全部通过。 5. 最后运行 {类型检查命令} 确保没有类型错误。 6. 不要执行任何不可逆的命令如 git push、数据库迁移等。这个模板我保存在一个文件里不同项目之间稍微修改路径和命令就能复用。它能保证有一个客观的完成标准测试通过。你能在关键节点Red 阶段观察它的行为。避免它跳过测试直接写实现。5. 把 Claude Code 接进现有工程链MCP、Git 与 Code ReviewClaude Code 不应该是一座孤岛它最大的价值在于能和你的整套工具链协同。这一节聊聊我试过的几个实际整合方式。5.1 用 MCP 扩展感知能力MCPModel Context Protocol是让 Claude Code 通过标准化的方式连接外部工具和数据源。我目前最常用的场景是连上自己的内部 API 文档、错误监控系统或者数据库结构预览。以连接一个 Postgres 数据库的 schema 为例合理配置 MCP 之后Claude Code 可以直接获取表结构和字段注释这样它写 SQL 或 ORM 查询的时候就不会瞎猜字段名。配置方法大致是在~/.claude.json或项目配置里声明 MCP server{ mcpServers: { project-db: { command: npx, args: [-y, modelcontextprotocol/server-postgres], env: { DATABASE_URL: postgresql://user:passlocalhost:5432/mydb } } } }然后在会话里使用工具调用就能直接查询数据库 schema 了。这里要提醒一句MCP 工具给了代理数据库访问能力等于扩大了攻击面。生产环境的信息、敏感 schema、或者线上库不建议通过 MCP 暴露给代理。我目前只让它连接本地开发库或沙箱环境。5.2 Git 工作流协作从 diff 到 commit messageClaude Code 改完代码之后你是否直接让它git push我的回答是尽量别。我的默认策略是让 Claude Code 专注在本地代码修改上commit 和 push 这种不可逆操作留在我的手上。常见的用法是让 Claude Code 完成代码修改。我不主动让它 commit。先执行git diff自己过一遍改动或者用 IDE 的 diff 视图看看它改了什么。确认无误后再让它生成 commit message或者我手动 commit。下面这个用法也很常用拿到 dif 之后把 diff 贴给它这是本次改动的 git diff请帮我写一个符合 conventional commits 格式的提交信息 diff内容这比我手动写 commit message 效率高得多而且格式稳定。但有一点要注意不要把整个 diff 都盲贴给 Claude Code如果改动量巨大就按文件拆分分批次生成提交信息否则容易产生笼统的描述。5.3 把它当 Code Review 的第一轮审阅员写完代码后我还会让 Claude Code 做一轮安全审查基本 prompt 是这样请以资深代码审查员的视角检查当前未提交的改动。重点检查 1. 是否存在 SQL 注入、路径穿越、敏感信息泄露等常见安全问题 2. 是否存在明显的高复杂度或重复代码 3. 异常处理是否合理错误响应是否符合项目约定错误码 消息 4. 是否有测试覆盖关键分支 5. 不需要修改代码只需输出问题清单和建议优先级。然后我会把git diff的内容贴给它。它会返回一份审查报告我再根据优先级决定是否让它在下一轮修改。用这个方案我能借助 Claude Code 的上下文理解能力在没有专门安全审查工具的情况下做一轮低成本 review。不过记住第一轮它在 code review 时的标准、洞察力和专注度是随着上下文和提示质量变化的。如果项目是关键性高可用系统人工的二次 review 仍然不可替代。6. 效率与成本控制避免最贵的四类错误Claude Code 用久了你会发现它有一套贵价错误清单。这些错误不是崩溃级别的 Bug而是慢慢消耗你时间、token 和耐心的暗坑。我逐个说说。6.1 上下文无限制膨胀每轮会话开始时Claude Code 会把 CLAUDE.md、最近会话内容、当前目录文件等塞进上下文。如果你不管它会越来越大导致响应变慢、认知混乱。解决办法给每个任务单独开启新会话不要在一个会话里连续处理多个不相关的任务。把已完成任务的总结写回 CLAUDE.md 或一个专门的docs/文件然后开新会话。如果发现它开始突然忘记前面说的东西检查是否上下文已经接近上限该考虑分拆任务了。6.2 让代理无条件重试有一次它连续改了三次还没过测试我硬是让它重试了四次期间 token 消耗像流水一样。后来我才习惯了一个原则连续两次失败后必须改变策略而不是继续加码重试。可能的策略调整包括缩小改动范围、换个实现方案、手动介入改某些关键文件或者把测试拆开跑。6.3 拒绝看输出全凭感觉有朋友和我说感觉 Claude Code 干得不错因为它的日志一直在滚看起来很忙。但一问它到底改了什么他却说不出所以然来。这种人实际上是把决策权完全交给了代理极容易出事。我的习惯是至少每 10~15 分钟跳出来看一眼当前状态问自己几个问题它正在改的文件是否是我预期的那些是否出现了计划外的顺手改动有没有执行我不允许的不可逆命令6.4 忽略--print等非交互模式的价值Claude Code 不仅可以交互式运行还支持一次性任务模式claude --print或-p适合做小范围的自动化操作。比如claude -p 把 src/utils/format.ts 中的所有 console.log 改成使用 pino 日志这种模式不需要你盯着屏幕适合在脚本或 CI 里调用。不过要注意的是非交互模式下权限决策会比较激进因为它无法实时等待你的确认。所以在非交互模式下运行时更要限制命令权限尤其是不可逆操作的权限。7. 学废了这些之后我的个人工作流长什么样最后分享一下我现在用 Claude Code 处理一个功能开发的完整流程你可以把它当成一套可复制的模板来用。第一步准备阶段。我把项目相关的背景、约定、命令写进 CLAUDE.md就像第2节说的那样。这一步看起来耗时实际上是性价比最高的投资——之后每次会话都能自动加载省的不是一点半点。第二步启动会话时把目标讲清楚。我会用这个骨架目标{要实现或修改的功能} 背景{上下文简述可以引用某个 issue 链接或文档路径} 范围{允许改动的目录} 验证{测试命令和类型检查命令} 提醒{不可逆操作切勿执行保留某些现有行为不变}第三步让它先输出方案。我不急着让立即开干而是先让它用一两段话描述自己的理解、准备改哪些文件、可能的风险。这个检查点通常能暴露不少误解。第四步开工。授权它读文件、跑命令但写操作一定要先看它准备改哪儿。较大规模的改动我会要求它分阶段来先做第 1 步跑完测试再继续第 2 步。第五步验收。拿到它的改动后我不会只看它说完成。我会自己跑测试、看git diff再让它做个 code review。确认无误后才 commit。这套流程跑顺之后我的产出速度提升确实明显而且质量很稳定。当然它不是一个能替代你思考和决策工具更像一个精力旺盛、知识面很广但需要你当项目经理的实习生。你给它的上下文和护栏越具体它的发挥就越接近一个中级工程师。有些朋友会问既然它这么强会不会以后我们这些写代码的没活干我的看法是Claude Code 这类工具淘汰的从来不是会写代码的人而是只会机械敲代码而不动脑的人。懂得如何拆任务、立规范、验收结果的开发者反而会因为能驾驭工具而走得更远。这也是我写这一系列文章的动力——不是去吹一个 AI 工具多神而是希望把自己摸出来的这套和代理协作的方法论传下去让后来者少踩几个坑。如果这篇对你有一点启发建议你按文章里的思路拿自己手头一个不紧急的模块练练手。先从把 CLAUDE.md 写好开始再走一遍 TDD 的流程你很快就会感受到差别——那不是省力一点点而是整个工作习惯都在发生变化。
返回列表