选中 provider 后启动 claude 子进程的完整语义:env 引用解析、并集清理、注入规则、可执行文件查找、stdio 透传、信号转发、退出码传播与退出清理保证。
启动流程在"并集清理"之前 SHALL 先对父进程环境取一次快照(os.Environ())。对于选中 provider 的每一项 env value,若匹配 ^env:[A-Za-z_][A-Za-z0-9_]*$,SHALL 从该快照中查找同名变量:
claude、MUST NOT 对 env 做任何 mutation。解析完成后得到的"物化"env map 作为后续"并集清理 + 注入"的输入。解析到的值 MUST 不做任何 shell 扩展或二次引用解析(不支持链式 env:A → env:B)。
MY_KEY=sk-abc,provider foo.env.ANTHROPIC_API_KEY=env:MY_KEY,用户执行 cc-switch use fooclaude 收到 ANTHROPIC_API_KEY=sk-abcMY_KEY,provider foo.env.ANTHROPIC_API_KEY=env:MY_KEYANTHROPIC_API_KEY references env var MY_KEY which is not set;claude 未被启动ANTHROPIC_API_KEY,provider B 的 env.ANTHROPIC_API_KEY=env:ANTHROPIC_API_KEY,父 shell 已 export ANTHROPIC_API_KEY=sk-real,用户执行 cc-switch use Bclaude 正确收到 ANTHROPIC_API_KEY=sk-real(来自快照)A=env:B 与 B=plain,provider 的 value 为 env:Aenv:B(不继续解析 B)启动 claude 前,工具 SHALL 计算所有已配置 provider 的 env key 的并集(记为 K),并从即将传给子进程的环境中移除 K 中每一个 key。该清理 MUST 在注入选中 provider 的 env 之前完成。工具 MUST NOT 修改 cc-switch 自身进程的 os.Environ,也 MUST NOT 尝试修改父 shell 的环境。
ANTHROPIC_API_KEY=old 且该 key 出现在某个 provider 的 env 中,用户执行 cc-switch use foo(foo.env 不含 ANTHROPIC_API_KEY)claude 的环境中 ANTHROPIC_API_KEY 不存在(被清理、且 foo 未重新设置)HOME、PATH、LANG 等变量,它们不在任何 provider 的 env key 集合中claude 继承这些变量、值与父进程一致ANTHROPIC_API_KEY、provider B 的 env 含 ANTHROPIC_AUTH_TOKEN,用户 cc-switch use AANTHROPIC_AUTH_TOKEN 被清理(因其属于并集),同时 provider A 的 ANTHROPIC_API_KEY 被写入清理完成后,工具 SHALL 将选中 provider 的 env 中每一个 key=value 写入子进程环境。若 key 与清理后的继承环境中某个 key 同名,provider 的 value SHALL 胜出(注入覆盖)。Value MUST 原样传递,不做任何 shell 扩展或变量替换。
ANTHROPIC_MODEL=x,该 key 不在并集中但选中 provider 设置了 ANTHROPIC_MODEL=yANTHROPIC_MODEL=yANTHROPIC_BASE_URL=$HOME/api$HOME/api,不会被展开为用户 home 目录工具 SHALL 按以下顺序解析要执行的路径:
claude_path 已配置,使用之(支持 ~ 展开),并校验可执行位;exec.LookPath("claude")。
任一步找到且可执行即使用该路径;均失败时 SHALL 以非零退出码终止,并输出清晰错误(指出用户可执行 cc-switch config set claude-path <path> 来解决)。claude_path=~/.claude/local/claude 且该文件存在且有执行位claude_path 未配置且 PATH 中存在 claudeexec.LookPath 结果启动子进程claude_path 未配置且 PATH 中无 claudeclaude-path 的提示启动 claude 时,工具 SHALL 将 cc-switch 自身的 stdin / stdout / stderr 直接继承给子进程(cmd.Stdin/Stdout/Stderr = os.Stdin/Stdout/Stderr),不做任何缓冲或改写。
claude 运行期间敲入字符claude 即时读取,与直接运行 claude 行为一致claude 写入 stdoutclaude 完全一致,cc-switch 不添加前缀、颜色或时间戳cc-switch SHALL 捕获 SIGINT、SIGTERM、SIGHUP 并转发给子进程 claude;收到信号后 MUST NOT 立即退出,而是继续等待子进程自行收尾后读取其退出码。
claude 运行时按下 Ctrl+C(SIGINT)claude 收到 SIGINT,进入自己的取消流程;cc-switch 不立即退出cc-switch)cc-switch 向子进程转发 SIGHUP,等待其退出后再退出cc-switch SHALL 使用子进程 claude 的退出码作为自身退出码。若子进程因信号终止,cc-switch SHALL 退出码 128 + signum(符合 POSIX 约定)。若 cc-switch 自身在调用 claude 前失败(如配置错误、路径解析失败),退出码 SHALL 为非零且不是 0–125 范围内容易与 claude 混淆的值(使用 64、70 之类的约定值或 >= 1,在实现中固定)。
claude 以退出码 0 退出cc-switch 以退出码 0 退出claude 以退出码 42 退出cc-switch 以退出码 42 退出claude 被 SIGKILL(9)杀死cc-switch 以退出码 137(128+9)退出claude 子进程退出后,并集中的 env key MUST 不残留在任何与 cc-switch 运行相关的 shell 状态中。由于工具采用"构造子进程 Env 切片"的实现,子进程退出即意味着其私有环境被销毁,cc-switch 本身未修改过 os.Environ,父 shell 未受影响,该要求天然满足。工具 SHALL 在 --verbose 模式下打印一条 trace 日志确认"cleanup complete"。
cc-switch use foo 运行并退出后,回到 shell 执行 env | grep ANTHROPIC_foo 新引入的 env 变量(只保留用户自己 export 的那些)cc-switch -v use foo,claude 正常退出cleanup complete 或等价语义的 trace 行