Claude Code 环境依赖清单(CC Environment Deps)
术-操作 · 术层 skill 全文
本页是 <code>rules/skills/bestpractice_cc_environment_deps.md</code> 的逐字投影(仅隐私清洗,零改写)。
时点提示:本页是仓内文件 rules/skills/bestpractice_cc_environment_deps.md 的逐字投影(仅做隐私清洗:仓库根绝对路径→相对路径、家目录→~/;除此零改写)。若源文件后续有修订,以仓内真源为准。
Claude Code 环境依赖清单(CC Environment Deps)
元数据
- 类型: BestPractice
- 适用场景: 设计任何涉及 Claude Code 运行环境的改动前必读
- 创建日期: 2026-04-18
- 来源: Git V2-01 blind spot 复盘、Level 0 Hotfix #3 追责
When to Use
设计以下任何一类改动之前,先把本文件从头到尾过一遍:
- Worktree 方案(新增/修改 session worktree、task worktree、cron worktree 的目录结构或启动路径)
- Sandbox 设计(改
tools/sandbox/lib/sandbox_env.sh、引入新的隔离维度、调整CLAUDE_CONFIG_DIR/ HOME 重定向策略) - Cron 封装(写新的定时任务 wrapper、改
periodic_jobs/下的 CC 子调用) - Hook 编写(写/改
tools/git/hooks/*、SessionStart/Stop/PostToolUse hook、git 原生 hook) - Provider 切换(接入新的 Anthropic-compatible 订阅代理、调整
tools/claude/*.shwrapper、改bin_paths.sh的 claude 解析链)
触发判断准则:一个改动是否涉及 CC 运行环境,等价于问这三件事:它会不会改 cwd?会不会改 env var?会不会改 ~/.claude/ 的读写路径?只要任一答案为是,就属于本文范围。
Prerequisites
- 熟悉
config/bin_paths.sh(CC 二进制解析链) - 熟悉
rules/git_safety.md§6(hook 路径)和 §8(Level 1 session 隔离) - 熟悉
tools/claude/PROVIDERS.md(provider wrapper 的 env pin 机制)
环境依赖项
CC 在启动和运行过程中读取一组环境量来定位配置、凭据、存储。任何改动如果意外改变了其中一项,轻则行为偏差,重则 --resume 整体失效或 auth 失败。下面按「作用 → 决定什么 → blast radius → 验证方式 → 已知陷阱」固化 8 个核心依赖项。
1. cwd(当前工作目录)
- 作用:CC 启动时计算
sessionStoragePortable.ts里的 slug,slug 决定 JSONL 写入[session-path]下哪个目录。slug 是 cwd 的纯函数,没有任何 env var 可以覆盖。 - 决定什么:整个 session 的聊天记录存储位置、
claude --resume的扫描范围、claude --continue的恢复目标。 - blast radius:改 cwd = 改 slug = 改存储目录。不同 cwd 启动的 session 互相看不到对方的 JSONL。如果 launcher 做了
cd <new_dir> && exec claude,用户在原 cwd 敲claude --resume会得到No conversation found,即使 JSONL 文件物理上还在。 - 验证方式:启动 claude 后立刻
ls -lt [session-path] | sed 's|/|-|g')/*.jsonl看是否有对应 slug 目录生成;换路径启动后回到原路径跑claude --resume验证能否恢复。 - 已知陷阱:V2-01 blind spot。
claude_launcher.sh原设计在 session worktree 里cd + exec claude,04-17 被用户报告 resume 失效。设计阶段的「现状事实清单」没有列出「cwd 决定 JSONL slug」这条事实,导致所有后续推理默认 cwd 不影响存储。Level 1 架构反转:cwd 恒定主目录,session 隔离走GIT_INDEX_FILE+refs/sessions/<id>。见config/build_logs/GIT_V2_REVIEW_AND_REDESIGN_20260417.md§3-4。
2. HOME
- 作用:决定
~/.claude/的默认根、macOS Keychain 访问路径、pip/npm 缓存位置、.gitconfig/.ssh/.zshrc初始化链的查找起点。 - 决定什么:所有相对 HOME 的系统资源:
~/.claude/settings.json、~/.claude/.credentials.json、[session-path]、~/Library/Keychains/里的 pycookiecheat 缓存、~/.cache/pip、~/.ssh/id_*。 - blast radius:重定向 HOME 后所有上述路径同时切换。CC 找不到原 credentials 就走未登录分支;Keychain 访问失败导致 pycookiecheat 拿不到 cookie;pip 和 npm 退化为全新缓存,每次重新下包;
.ssh/不见导致git push失败。 - 验证方式:改动前记录
env | grep HOME,改动后在子进程里echo $HOME核对;跑claude doctor看是否识别到主 credentials;跑一次git commit确认 author/email 正确。 - 已知陷阱:
sandbox_env_setup_full_home(tools/sandbox/lib/sandbox_env.sh)默认关闭就是因为 HOME 重定向的副作用链太长。脚本头部注释里列出了 5 条确定的副作用(zsh 初始化 / Keychain / pip 缓存 / npm / ssh key)。启用前必须显式SANDBOX_FULL_HOME=1或--full-homeflag。
3. CLAUDE_CONFIG_DIR
- 作用:覆盖
~/.claude/作为 CC 的配置根。CC 源码adhoc_jobs/claude_code_source/src/utils/auth.ts:1255-1300的getClaudeAIOAuthTokens明确通过此变量定位 credentials。 - 决定什么:
settings.json、.credentials.json、projects/子目录的读写路径。只覆盖 CC 自身的 config,不覆盖 HOME 的其他子路径(Keychain / pip / ssh 不受影响)。 - blast radius:设置后 CC 从新目录读配置,原
~/.claude/对当前进程不可见。子进程继承此变量,整棵进程树共用同一个隔离目录。 - 验证方式:设置后
env | grep CLAUDE_CONFIG_DIR,跑claude -p "echo test"确认能正常认证;比对<new_dir>/.credentials.json的 mtime 确认写入方向正确。 - 已知陷阱:Level 0 Hotfix #3。
sandbox_env_setup原实现只复制了settings.json和projects/下的小文件,漏了.credentials.json。结果 sandbox 内 spawn 的 background agent 读不到 OAuth token,批量authentication_failed。JSONL 时间线:17:02:10 启动 5 个 agent → 17:02:17 第一个 auth 失败。修复方案在同文件新增cp "${HOME}/.claude/.credentials.json" "${sandbox_claude_dir}/.credentials.json"。注意这只覆盖 OAuth 分支,macOS Keychain 绑定的ANTHROPIC_API_KEY不在 credentials.json 里,需 HOME 重定向 + Keychain bind-mount 才能隔离。
4. ANTHROPIC_BASE_URL / ANTHROPIC_AUTH_TOKEN
- 作用:把 CC 的请求指向非 Anthropic 原生端点(ZAI、Kimi 订阅代理)。
- 决定什么:整个 session 的 API 流量走向。未设置时走 Anthropic 原生(按量计费);设置后走代理(订阅配额)。
- blast radius:没在 wrapper 里 pin 住这两项,sub-agent 或内部 tool call 会穿透到原生 Anthropic,产生意料外的按量计费,或因代理未映射原生模型 ID 被拒。
- 验证方式:wrapper 启动后
env | grep ANTHROPIC_核对;跑一个简单claude -p "hello"看响应 header 或 latency 特征是否符合代理预期;在代理后台看调用日志是否有对应请求。 - 已知陷阱:
tools/claude/provider_common.sh的pin_fallback_models是唯一防穿透保险。新 provider 接入时如果忘了 source 这个文件,或者 pin 顺序搞错(ANTHROPIC_AUTH_TOKEN必须在 exec claude 之前 export),就会默默走原生。PROVIDERS.md 的「共享架构」第 2 条明确警告「不 pin 就会穿透到真 Anthropic」。
5. ANTHROPIC_DEFAULT_SONNET_MODEL / OPUS_MODEL / HAIKU_MODEL / SMALL_FAST_MODEL
- 作用:provider wrapper 用来把 CC 内部的 model 路由名(sonnet / opus / haiku / small-fast)映射到当前 provider 的具体 model ID。
- 决定什么:sub-agent 调用、内部 tool call、自动压缩(compact)等走哪个模型。CC 会把 haiku 子任务自动派发到
HAIKU_MODEL;sub-agent 不显式指定 model 时用SONNET_MODEL;SMALL_FAST_MODEL走压缩、日志抽取等轻量任务。 - blast radius:漏 pin 任何一项,该档位会穿透到 Anthropic 原生 model ID(如
claude-haiku-4-5),代理如果没做该 ID 的映射就会被拒,或落入代理的默认 fallback(可能是另一个模型,产生行为差异)。 - 验证方式:wrapper 启动后四项
env | grep ANTHROPIC_.*_MODEL全部有值;跑一个能触发 sub-agent 的 prompt,从日志确认实际下发的 model ID。 - 已知陷阱:PROVIDERS.md「共享架构」强调必须 pin 的是四项(sonnet / opus / haiku / small-fast),不是两三项。只 pin sonnet + opus 时 haiku 子任务和 compact 仍会穿透。接入新 provider 的 checklist 里这条是最容易忘的。
6. CLAUDE_BIN / PATH
- 作用:定位
claude二进制。CC 通过 nvm / mise / Homebrew / system 四条降级链解析。 - 决定什么:哪个版本的
claude被执行。Wrapper 脚本、hook 内 subprocess、cron job 共享同一个解析结果。 - blast radius:解析不一致时,同一仓库里不同入口跑出不同版本的 claude。cron 的 PATH 极简(
/usr/bin:/bin),没有 NVM_DIR,如果不走bin_paths.sh会直接command not found。 - 验证方式:source
config/bin_paths.sh后echo $CLAUDE_BIN确认路径;$CLAUDE_BIN --version确认版本;在 cron 环境(env -i /bin/bash -c '...')模拟跑一遍。 - 已知陷阱:
bin_paths.sh的降级链里有~/.nvm/versions/node/v*的直接 probe(见该文件第 31-38 行),就是为了兜住 cron 零 PATH 场景。任何新脚本如果自己which claude或硬编码路径,都会在 cron 或 hook 环境下失效。规则:通过source "$REPO_ROOT/config/bin_paths.sh"拿$CLAUDE_BIN,不自行解析。
7. Hook 注册位置(~/.claude/settings.json)
- 作用:CC 启动时读取
~/.claude/settings.json的hooks字段,按事件类型(SessionStart / PostToolUse / Stop 等)注册 hook command。文件里每条 hook 写死绝对路径。 - 决定什么:SessionStart 是否触发
session_start_hook.sh、PostToolUse 是否 staging、Stop 是否 commit。整个 session 隔离机制依赖这些 hook 正确注册。 - blast radius:如果 HOME 被重定向且没建
.claude/settings.json镜像,CC 在子进程里找不到 hooks 配置,所有 hook 静默失效,session index 不初始化,commit 不触发,JSONL 记录正常但 git 层无任何动作。用户不会看到错误,只会在事后发现refs/sessions/*是空的。 - 验证方式:
cat $CLAUDE_CONFIG_DIR/settings.json | jq .hooks确认 hooks 字段存在;启动 session 后检查~/.cache/context-infra/session_start_hook.log是否有新条目;故意敲一次 Write 工具,确认posttooluse_stage.log有记录。 - 已知陷阱:sandbox 全 HOME 重定向时,如果只 symlink
.claude/但不保证settings.json存在(比如主 HOME 没写过),hook 就全部失效。sandbox_env_setup的 settings.json 复制是基础前提,不能省。
8. Credentials(.credentials.json + macOS Keychain)
- 作用:存 OAuth token 和 API key。CC 认证有两条路径:OAuth token 走
~/.claude/.credentials.json(文件);某些ANTHROPIC_API_KEY走 macOS Keychain(系统服务)。 - 决定什么:CC 能否通过 Anthropic 认证、订阅代理的 auth token 是否可读、sub-agent spawn 时能否继承登录态。
- blast radius:credentials.json 没复制 → OAuth 失败;Keychain 访问被 HOME 重定向切断 → API key 读不到;sandbox 内
/login写入的新 token 在 worktree 销毁时一起消失,下次启动读不到。 - 验证方式:
claude doctor看认证状态;ls -la $CLAUDE_CONFIG_DIR/.credentials.json确认文件存在且非空;在 sandbox 里跑claude -p "test"确认无authentication_failed。 - 已知陷阱:Level 0 Hotfix #3 的另一面。
sandbox_env_setup的.credentials.json复制只覆盖 OAuth 分支。如果用户用 Keychain 绑定的 API key,必须等 Level 2 的完整 HOME 重定向 + Keychain bind-mount 方案。短期妥协:交互式 session 根本不进 sandbox 环境,sandbox 只用于后台任务。
设计 Checklist(改动前过一遍)
改动提交前,对 8 项依赖逐项确认:
| # | 依赖项 | 本改动是否影响 | 影响方式 | 验证手段 | 回滚路径 |
|---|---|---|---|---|---|
| 1 | cwd | ☐ | |||
| 2 | HOME | ☐ | |||
| 3 | CLAUDE_CONFIG_DIR | ☐ | |||
| 4 | ANTHROPIC_BASE_URL/AUTH_TOKEN | ☐ | |||
| 5 | ANTHROPIC_*_MODEL(四项) | ☐ | |||
| 6 | CLAUDE_BIN/PATH | ☐ | |||
| 7 | Hook 注册位置 | ☐ | |||
| 8 | Credentials | ☐ |
判断准则:只要勾了任一项,这个改动就要进设计文档的「环境依赖影响」段,并附上对应的测试用例。e2e 测试至少覆盖一次「启动 + resume 一个既存 session」的闭环,因为 resume 同时打在依赖 1(cwd)和依赖 8(credentials)上,是最便宜的综合验证。
反面案例
案例 1:V2-01 blind spot(2026-04-17)。设计 session_wrap.sh 的「前台 session 强制 worktree」时,claude_launcher.sh 在 session worktree 里做 cd + exec claude。设计文档 §3「现状事实清单」列了 7 条硬事实,无一提到「JSONL 按 cwd 分目录」。上线后用户 claude --resume 全部 No conversation found,JSONL 物理上存在但散落在 5 个 worktree slug 下。根因:设计阶段的事实清单没显式列出 CC 对 cwd 的存储依赖(本文依赖项 1)。修复走 Level 1 架构反转(git 层隔离,cwd 恒定)。详见 config/build_logs/GIT_V2_REVIEW_AND_REDESIGN_20260417.md 第 3-4 轮。
案例 2:Level 0 Hotfix #3(2026-04-17)。sandbox_env.sh 的 sandbox_env_setup 原实现切了 CLAUDE_CONFIG_DIR 但没复制 .credentials.json。sandbox 内 spawn 5 个 background agent,7 秒内全部 authentication_failed;主 session /login 把新 token 写到 sandbox 目录,worktree 销毁后 token 也消失。根因:CLAUDE_CONFIG_DIR 切换影响的不止是 settings.json(依赖项 3),credentials.json 也绑在这个目录里(依赖项 8)。修复是一行 cp .credentials.json 补丁。教训:CLAUDE_CONFIG_DIR 和 credentials 是同一个依赖簇,讨论任何一个都要把另一个也纳入。
与其他 Skill 的关系
rules/git_safety.md§8:Level 1 session 隔离的三件套(GIT_INDEX_FILE / commit-tree / refs/sessions)tools/claude/PROVIDERS.md:依赖 4、5 的权威文档rules/skills/claude_code_self_evoke_call_codex_loop.md:CC agent invocation 场景下这 8 项依赖的组合用法rules/skills/_archive_claudecode_harness_extension_guide_20260418.md:hook 系统的扩展方式,对应依赖 7