Claude Code 写得越快,越要把错误控制在可回滚范围内
如果只给 Claude Code 一句“帮我修一下”它需要自己猜范围、根因、完成标准和哪些动作可以做。猜对了速度很快其中一个假设错了后面的动作仍可能顺着错误方向继续推进。拿一个很常见的小任务来说修复“刷新 Token 偶发失败”。看起来只需要改认证模块Claude Code 为了复现问题可能会读取环境配置、运行脚本。等它开始调整公开响应或访问外部服务任务边界已经悄悄变了。每一步单独看都挺合理。连在一起风险就变了测试即使全绿也未必覆盖真实登录链路代码即使能撤销脚本写过的数据库和远端系统也未必能退回来。我现在看这类任务通常先问两个问题如果判断错了这次改动会走多远它最后拿什么证明自己做对了模型会犯错人也会。工程上能提前做好的是别让一次错误走得太远。我会把改动停在计划和验证两个节点上。远端与生产动作另设闸门。这样Claude Code 的结果才有机会从“它说做完了”变成团队可以接收的改动。Claude Code 更新很快。文中的命令、模式和版本限制按 2026 年 7 月 13 日的官方文档核对实际使用时还是要以最新文档为准。一个小 Bug怎么变成可提交的改动还是回到“刷新 Token 偶发失败”这个任务。如果只给 Claude Code 一句“帮我修一下”它需要自己猜范围、根因、完成标准和哪些动作可以做。猜对了速度很快其中一个假设错了后面的动作仍可能顺着错误方向继续推进。我会先把任务拆成几个状态状态这一步做什么结果先停在哪里调查只读检查src/auth与tests/auth说明复现路径和计划一份待确认的 Plan修改只改约定目录push 和公开接口变更需要确认Worktree 里的候选 Diff运行命令在 Sandbox 中执行凭据与无关路径不可访问受限环境里的执行结果验收失败用例、单测、lint 和真实刷新流程都能复核一份证据报告提交人看重点 Diff再决定 commit、PR、merge 与发布可审查、可撤回的变更这样做并不新鲜。发布要留灰度代码要进版本控制本来就是为了让错误有边界。Coding Agent 带来的变化是执行速度更快、能碰到的工具更多中间状态也更容易被跳过。CLAUDE.md写得再认真也挡不住一个已经获准执行的危险命令。Sandbox 配得再严如果任务没有验收标准Agent 仍可能在隔离环境里交出错误结果。测试全绿也不代表它没有顺手改到不该改的目录。麻烦往往出在中间状态被跳过模型刚提出想法工具已经执行测试还没跑任务已经被标成完成代码可以撤销数据库和外部系统却已经写入。每一步先停在哪里最好在任务开始前就说清楚。上一层证据不足改动就先停在原地。把这条链路放在一起看大致是五道关口一次改动从任务范围、动作闸门、执行边界和验证证据进入可提交状态CLAUDEmd只负责减少猜测CLAUDE.md是 Agent 进入仓库时最先看到的项目说明。它很有用也经常被写得太重。它适合记录代码里不容易直接读出来的约定技术栈版本、目录边界、常用测试命令、公开接口能不能改、哪些失败需要停下来汇报。例如- Work only in src/auth and tests/auth. - Do not change public API contracts without approval. - Run pnpm test auth and pnpm lint before reporting completion. - Stop after the same verification failure occurs twice and report the blocker.这几行解决的都是具体问题范围容易扩大测试命令可能猜错同一处失败也不该一直重试。官方当前建议每份CLAUDE.md尽量控制在 200 行以内。文件越长占用的上下文越多规则遵守度也可能下降。我的筛选方式很简单删掉这一行Claude 下次会不会更容易犯错如果不会通常没必要把它留在常驻上下文里。更大的项目可以把规则放进.claude/rules/再用路径匹配按需加载。认证、数据库迁移、前端和测试各自维护少量规则比把所有要求堆进一个总文件更容易长期维护。CLAUDE.md终究只是上下文。它可能含糊也可能在长会话里被其他信息冲淡。聊天中临时说的“不要 push”经过上下文压缩后还可能丢失。所以我只把项目背景和工作约定放在这里。密钥、生产访问和远端写入要交给权限与隔离机制处理。权限和 Hook 拦的是动作Claude Code 当前的权限规则由执行层处理不靠模型自己记住。deny → ask → allow的顺序很明确先看是否禁止再看是否需要确认最后才看能否直接运行。一个宽泛的 deny不会被更具体的 allow 覆盖。在CLAUDE.md中写“不要读取.env”只能影响 Claude 的选择。把路径写进 deny 规则工具调用时才会被拦住。Hook 处理更具体的运行时规则。PreToolUse可以在执行前阻断动作或要求确认PostToolUse适合记录和检查动作已经发生无法靠它撤销。Hook 也不能绕过已有 deny 去放宽权限。权限规则也有边界。Read、Editdeny 能覆盖 Claude Code 的内置文件工具也能覆盖一部分被识别的文件命令。可如果 Agent 启动 Python 或 Node 进程让脚本自己打开文件文件工具权限就不再是完整的 OS 级边界。命令规则也有同样的问题。Bash(rm -rf *)可以拦住匹配形式却拦不住脚本封装后的等价动作。到了高风险路径permissions、Hook 和 Sandbox 得配合使用最后一道仍然是人审。Auto Mode 也适合放在这个位置理解。它用独立分类器逐动作判断风险可以减少频繁确认带来的疲劳。官方同时写得很克制Auto Mode 不能保证安全。我对它的长期稳定性还没有足够多的跨项目样本。日常低风险任务可以用它改善节奏涉及生产、密钥、远端写入和基础设施时我仍更倾向于显式 deny、ask、Sandbox 与人工审批。Worktree 隔离改动Sandbox 管住进程Worktree 和 Sandbox 经常一起出现也最容易被混成一件事。Git Worktree 给每个会话一份独立目录和分支主要解决并行修改互相覆盖的问题。一个 Agent 改认证另一个 Agent 修支付文件不会踩到一起主工作区也能保持干净。可以这样启动一个独立会话claude --worktree auth-refresh但 Worktree 仍然共享仓库历史和远端也不会自动隔离主机上的 SSH Key、云凭据和网络。官方支持用.worktreeinclude把.env、本地配置复制进新 Worktree这对开发很方便也可能扩大凭据暴露面。简单说Worktree 避免文件互相覆盖Sandbox 限制进程能访问什么。两者放到同一张图里边界会更清楚Worktree 与 Sandbox 的隔离对象、能力和边界对比Claude ode 的 Bash Sandbox 会借助 macOS Seatbelt或者 Linux、WSL2 上的 bubblewrap限制 Bash 命令及其子进程能读写哪些路径、访问哪些网络域名。它在 OS 层约束实际进程比根据命令名字猜风险更可靠。这里有个容易忽略的默认值Sandbox 默认限制工作目录之外的写入但读权限并不等于“只读当前项目”。官方文档明确提醒默认读取范围仍可能覆盖整台机器包括~/.aws/credentials和~/.ssh/。敏感文件与环境变量需要用sandbox.credentials或denyRead另外保护。内置 Bash Sandbox 主要覆盖 Bash 和子进程。Read、Edit、WebFetch 有各自的权限边界MCP Server 与 Hooks 还可能直接运行在宿主机上。网络白名单、Docker socket 和环境变量配得太松隔离效果也会打折。坦率说网络隔离这块我也不敢把话写满。官方当前文档专门提醒宽泛域名白名单、代理配置和宿主能力仍可能留下外传路径。如果任务要长时间无人值守或者要处理陌生仓库与外部输入我会换用 Sandbox Runtime、Dev Container、容器、VM或者 Claude Code on the web让整个进程都待在隔离环境里。内置 Bash Sandbox 更适合日常开发不能当成完整的会话隔离。“做完了”要拿证据说话Claude Code 创建者 Boris Cherny 在两次公开分享中都把验证放在很靠前的位置。他的使用体感是给 Claude 一条可以自己运行的反馈路径最终结果质量可能提升 2 到 3 倍。这个数字是个人经验不是通用基准。工程上的问题倒是很具体如果没有测试、构建或真实操作结果Agent 判断完成时主要依据仍是自己的解释。拿刷新 Token 这个任务来说我会把任务说明写成这样先只读调查不要修改文件。 目标定位刷新 Token 偶发失败的根因。 范围只调查 src/auth 和 tests/auth。 完成条件先补一个能稳定复现问题的失败用例再完成修复。 验证运行 pnpm test auth 和 pnpm lint启动本地服务走一遍真实登录刷新流程。 证据列出命令、退出码、改动文件、关键结果和仍未覆盖的风险。 停止同一错误连续出现两次或需要修改公开接口、数据库与范围外文件时停下来汇报。这段话没有什么提示词技巧只是把范围、完成条件、证据与停止点放在了一起。验证也不等于“跑过测试”。这类任务至少要看代码、行为和变更三层证据证据层刷新 Token 任务里的例子它能回答什么代码级失败用例由红变绿lint 退出码为 0修改有没有满足局部规则行为级本地服务完成一次真实登录与刷新关键链路是否真的工作变更级Diff 只落在约定目录公开契约没有变化有没有顺手改坏别处如果是前端任务行为级证据可能是浏览器操作与截图如果是性能问题可能是同口径基准如果是账单、迁移或数据修复还要对账数量、异常样本与回滚结果。最后让 Agent 用固定格式交接比一句“测试都通过了”更有用改动范围 验证命令与退出码 关键行为结果 Diff 中需要重点审查的文件 未覆盖风险 待人工确认的动作这个模板也方便后续接手。即使会话中断改了什么、测到哪里、还有什么没有确认仍然有记录可查。Checkpoint 只能撤销一部分变化Claude Code 的 Checkpoint 很方便。每次提示都会创建检查点可以用/rewind或双击 Esc 恢复对话、代码或者只恢复其中一部分。这个“撤销”有明确边界。它主要跟踪 Claude 内置文件编辑工具产生的变化。Bash 删除文件、脚本批量改写、外部服务更新、数据库写入以及其他并发会话造成的变化通常不在 Checkpoint 的恢复范围内。官方对它的定位很准确Checkpoint 是本地撤销Git 才是长期历史。任务风险一旦上升我会尽量从干净分支或 Worktree 开始把改动拆成小 commit并保留验证结果。push、merge、deploy 继续走确认碰到数据库和生产配置还要单独准备业务回滚。恢复能力最好在任务开始前就设计进去。这里要控制的不只是一次改多少文件还包括最小可审查、可验证、可独立撤回的改动单元有多大。等 Agent 已经改完几十个文件、跑过迁移、写过外部系统再讨论怎么退通常已经很被动了。三种能力同时出现风险会变Simon Willison 长期在追踪提示注入。他在解读 Meta 的Agents Rule of Two时提到一个很容易落到工程现场的框架。一次 Agent 会话里如果同时出现未可信输入、敏感数据和对外写操作我不会把它留在无人监督状态。提示注入目前还不能被可靠识别这三类能力一旦连起来模型的一次误判就可能越过代码库。三项能力一旦闭环风险就不再只是“模型会不会写错代码”Agents Rule of Two未可信输入、敏感数据和对外写操作形成完整风险链能力代码场景里的例子未可信输入陌生仓库 README、Issue、网页文档、依赖安装脚本、外部日志敏感数据私有源码、.env、云凭据、生产日志、客户数据改变状态或外联写文件、push、发 PR 评论、调用 MCP、部署、写数据库假设 Agent 正在审查一个陌生 GitHub 仓库同时能读取本机~/.ssh和云凭据还能自由访问网络或 push 代码。即使模型大部分时间表现正常这条链路的风险也已经太高。处理外部仓库时可以放进 VM 或云端环境不带私有凭据。修改内部代码时再限制网络出口和可写分支。到了发布环节我会换成干净上下文和固定制品并保留人工审批。Agents Rule of Two只是帮团队切开威胁模型。Meta 原文也明确说它不能替代最小权限和纵深防御。它给我的提醒是事故里常常找不到一个特别显眼的危险工具。几类普通能力放进同一会话碰巧就连成了完整路径。边界要跟任务风险一起变日常任务全部套上最高安全级别会很重权限一律放开又很难放心。我更习惯先看任务的副作用再决定护栏做到哪一层风险常见任务我通常怎么处理低文档、补单测、小范围只读分析限定目录允许固定测试命令结果留在本地中多文件 Bug、局部重构、依赖升级使用 Worktree 和 Sandbox保护凭据push 保持确认高数据迁移、生产配置、基础设施、客户数据放进容器或 VM使用临时凭据另备业务回滚风险等级不会只由任务名称决定。一个“只改文档”的任务如果文档来自不可信仓库同时会调用带生产凭据的 MCP它也可能从低风险变成高风险。我的判断主要看四件事数据是否敏感输入是否可信动作能否撤销会不会影响代码库之外的系统。风险越高隔离和人审就放得越靠前。从一个小任务开始如果团队刚开始用 Claude Code我不会急着设计一套庞大的 Agent 平台。先挑一个边界清楚、能自动验证、失败后容易撤销的任务把一条小链跑通。我通常先开一个独立 Worktreeclaude --worktree auth-refresh进入会话后运行/sandbox确认依赖、实际生效配置以及失败命令能否退回非沙箱执行。界面显示 enabled只能说明 Bash Sandbox 已开启不代表所有子系统都在隔离里。任务先从只读调查开始。Plan 里的范围、风险和验证命令确认后再进入修改。项目级配置可以从偏保守的版本起步。测试命令、敏感路径和 Token 名称要按项目调整其中sandbox.credentials要求 Claude Code v2.1.187 或更高版本{ permissions: { allow: [ Bash(pnpm test *), Bash(pnpm lint *) ], ask: [ Bash(git push *), Bash(gh pr merge *) ], deny: [ Read(//**/.env), Read(~/.ssh/**), Read(~/.aws/**), Bash(rm -rf *) ] }, sandbox: { enabled:true, failIfUnavailable:true, allowUnsandboxedCommands:false, credentials: { files: [ { path: ~/.aws, mode: deny }, { path: ~/.ssh, mode: deny } ], envVars: [ { name: GITHUB_TOKEN, mode: deny }, { name: NPM_TOKEN, mode: deny } ] } } }这份配置允许测试和 lint 直接运行push 与合并保持确认。列出的凭据不会进入沙箱子进程Sandbox 不可用时任务直接失败不会退回非沙箱执行。它只覆盖 Claude Code 的内置权限和 Bash Sandbox。MCP、浏览器以及外部系统有各自的授权边界还需要单独配置。Agent 交出证据报告后人再看重点 Diff、验证结果和未覆盖风险。到这里改动才适合进入 commit 或草稿 PR。这条小链稳定以后再扩大到多文件任务和长时间运行。无人值守放在最后考虑而且要换到完整进程隔离环境中使用临时凭据并保留人工合并。写在最后回到开头那个刷新 Token 的小修复我不会把信任压在 Claude Code 的一句“已经完成”上。更可靠的信号是改动仍在约定范围内验证结果可以复查远端动作没有绕过审批出错后也知道从哪里退。模型能力继续提高这些工程边界仍然不会过时。我目前更愿意把成熟的 Agent 工作流看成一个整理过的开发现场模型知道自己在改什么外部机制决定它能做什么团队根据证据决定是否接收。这样即使方向错了留下的也只是一份容易审查和撤回的小改动。