云端 VM 改变了什么
VM 是一次性的,它能触及的东西不是。云端会话会在真实分支上 clone 你的仓库、commit,然后 push 回真实的远端。在那里对未提交的工作执行git reset --hard,损失的工作量和本地一模一样;git push --force 落在的也是队友会 pull 的分支。
凭据就在这些工作旁边。Anthropic 关于 Claude Code on the web 的文档这样描述 Anthropic 托管环境:“git credentials and signing keys stay outside the sandbox, and a proxy authenticates on the session’s behalf with scoped credentials”。你添加到云端环境的 API key 也按同样方式处理,“attached to matching requests after they leave the session”。这个设计让会话读不到密钥材料,切分是对的,但它并不阻止会话使用这份凭据。一个为基础设施工作准备的环境,可以带着有效身份执行 terraform destroy、aws s3 rm、gcloud projects delete 和 az group delete,而这正是官方规则库拦截的对象。
平台侧的防护同样是逐版本的验证结果,而不是长期保证,我们这边也一样。2026 年 4 月有人报告,在没有开启 unrestricted branch pushes 的情况下,一个计划中的云端任务仍然直接 push 到了 main,记录在 anthropics/claude-code#44949。
提交到仓库里的 deny 层会随着每一次 clone 进入会话,按项目策略设定的 preset 生效,不需要任何人在每个会话里额外做事。
Claude Code 云端会话与自托管环境
云端会话从仓库里读配置。同一页写得很直接:“To change settings for a cloud session, use environment variables or commit settings files to the repository”。hook 就配置在 settings 文件里,所以只要提交两样东西,云端会话就会执行你的策略。1
2
把 hook 装进会话
做法取决于环境有没有 setup script。在环境的 setup script 里,或者在自托管环境所依赖的镜像里,直接跑常规安装:带上目标 flag 后安装是非交互的,不需要终端确认,可以在无 TTY 的情况下完成。如果没有 setup script,就把 hook 条目本身作为
.claude/settings.json 提交:hook --coding-cli 是规范的 hook 入口,已安装的插件调用的也是它。这种形式每次工具调用都要付出一次 npx 启动的开销,因此环境有 setup script 时优先用 setup script。npx -y cc-safety-net@latest explain "git reset --hard",它不执行任何东西,只打印判定和给出判定的规则。输出的读法见 explain 追踪。
Amp Orb 线程
Amp 不需要按容器操作。在任何一台用amp login 登录过的机器上安装一次即可:
devcontainer 与容器镜像
自己构建的容器,把安装放在构建期。下面这个 Dockerfile 是可用的形态:- 必须有
git和ca-certificates。 Claude Code 的安装会添加插件 marketplace,这一步通过 HTTPS 执行 clone,而 slim 基础镜像两者都没有。 - 先装智能体 CLI。 安装程序调用的是智能体自己的插件命令,所以先装 CC Safety Net 再装智能体的构建会失败。
postCreateCommand:
postinstall 外面加的 process.env.CI 判断在这里不该出现。那个判断是为了在 CI 和容器里跳过一次白做的安装;而这里容器就是智能体运行的机器,安装正是目的本身。
仍然需要人批准的部分
装上防护可以自动化,上面的做法都是自动化的;放松防护不行。policy apply 在没有终端确认 diff 时会拒绝运行,来自智能体的调用会被直接拦截。这一点在云端 VM 和笔记本上完全一致,所以会话读到的 .cc-safety-net/policy.json 一定是人写下、评审者看过的文件,通常经过一个 pull request。会话里的智能体最多只能起草提案文件并用 policy check 验证。