1实现原理 · 为什么它能做到
用 CLAUDE_CONFIG_DIR 做进程级隔离:每个 provider 一个 ~/.claude-profiles/<name>/ 目录、一份独立 .claude.json(凭证与会话历史),共享目录(skills/projects/hooks/agents/plugins 内容)symlink 回 ~/.claude,实现‘多窗口同时跑不同 provider 且配置不串’。
The result: you can open one terminal with Kimi, another with DeepSeek, another with Anthropic — each running as a fully independent Claude Code process, without configuration bleed.
settings.json 层做‘从默认 profile 收敛’:sync-profile-settings.py 注册为 SessionStart hook,把默认 profile 的 settings.json 各键复制进每个第三方 profile(保留 model/advisorModel 等身份键与 provider 路由 env 不覆盖),解决第三方窗口 hook/marketplace/env 漂移。
Two denylists define the identity boundary — these are NEVER synced:
.claude.json 行为键层做 allowlist 收敛 + 状态键三分类防护:workflowSizeGuideline 等少量行为键同步,state/credential/identity 键(oauthAccount/userID/token/secret…)永不同步,其余灰键只报告不自动写——防把一份 profile 的会话状态/账号身份抹到别的 profile。
State keys (is_state_key(): prefixes/substrings/exact names) — per- profile runtime state, caches, counters, migration flags, identity and credentials. NEVER synced
插件状态特殊处理:known_marketplaces.json 必须 per-profile(Claude 用 path.resolve() 校验 installLocation、不解析 symlink,共享一份会让其它 profile 报 corrupted installLocation),claude-plugins-sync.py 重建每个 profile 的 per-profile 结构并镜像 enabledPlugins。
Each profile runs with its own CLAUDE_CONFIG_DIR, so `c` is a DIFFERENT literal string per profile
maintainer 专用本地源码同步:sync-local-skill-sources.py 把本地 skill 源仓库以 symlink 接进 Claude plugin cache 与 Codex ~/.agents/skills、~/.codex/skills,默认 dry-run、--apply 才改;用 O_NOFOLLOW dirfd、renameat2/renameatx_np 独占改名、时间戳备份防并发与目录竞态。
Real files/directories and third-party links are never deleted or automatically moved.
上下文窗口配置做成决策规则:真实 ~1M 才用字面量 [1m] 后缀(Claude Code 匹配该字面量),已知小窗口用显式 CLAUDE_CODE_MAX_CONTEXT_TOKENS/AUTO_COMPACT,未验证不猜;deepseek/glm 模板双写是刻意保留。
Claude Code matches this literal string, not a made-up marker like `[1million]` or `[max]`.
部署纪律:脚本用 symlink 部署而非 cp(防双向往漂移——修复躺在仓库 26 天、清理代码只进部署副本的真实事故),并提供 setup.sh 安装器与 claude-profiles-init/doctor/rm 运维命令族。
# Symlink rather than copy.
2核心能力
3外部依赖
| 类型 | 依赖 |
|---|---|
| cli | claude(官方 CLI,按 profile 启动) |
| cli | python3 |
| cli | uv(仅 daemon --install 时 uv python install 3.12 取托管运行时) |
| cli | launchctl(macOS LaunchAgent 安装/启动) |
| network | provider API 端点(经 claude CLI 转发;模板列出 base URL 需用户核实) |
4风险提醒 风险提醒:橙色 · 评估后使用
- 把 API 密钥明文复制进多个 settings 文件 — 每加一个 provider 就在 ~/.claude/settings/<name>.json 落一份明文 token;SKILL 明示与 Claude Code 同模型,但副本增多扩大泄露面(备份/同步/共享目录时易被带出)
- 本地源仓库被当作可信激活源 — 源码同步把本地仓库 symlink 成已激活技能/插件;若源仓库含被篡改的 hook/skill,所有 profile 一起中招(同等于供应链信任本地目录)
- 窗口期一致性问题 — enabledPlugins/行为键传播有秒级-会话级延迟与竞争窗口(SKILL 自述传播需 relaunch 或秒级 watcher);并发写 settings 理论上可互相覆盖(有锁但窗口存在)
- 安装面广、常驻组件多 — SessionStart hook + 可选 LaunchAgent watcher + shell 别名注入 .zshrc/.bashrc;卸载不彻底会残留自愈 hook 继续改写 settings
- 强依赖 Claude Code 内部行为(path.resolve 语义、[1m] 字面量、config-dir-local 判定) — 官方版本升级可能改变这些机制使脚本假设失效(SKILL 自身以‘实测日期’标明脆弱点)
5第二遍独立确认
- [ok] 脚本零网络外发 — 全部脚本无 urllib/requests/socket;grep 到的 https 仅 setup.sh echo 链接与模板/文档里的 provider base URL
- [ok] 凭证键不被同步(防串 profile) — STATE_EXACT 含 projects/oauthAccount/userID 等;STATE_SUBSTR 匹配 token/secret/credential/apikey;ENV_KEY_DENYLIST 拦 ANTHROPIC_* 与隔离旗标;灰键仅报告
- [ok] converger 方向单向(默认→第三方) — docstring:'every key present in main's settings.json overwrites the profile's, except denylisted ones';顶层 profile-only 键保留
- [ok] 删除/修复路径受控 — claude-profile-rm:意外真实文件即 ABORT + y/N 确认;init --repair 把 real dir 归档为 .pre-symlink-bak-<ts> 再 symlink,不直接删
- [ok] 源码同步竞态防护真实存在 — O_NOFOLLOW 打开每个路径组件、libc renameat2/renameatx_np 独占改名、失败 exclusive_rename 回滚、KEEP_JSON_BACKUPS=20
- [ok] ‘claude-profiles-doctor 报 real dir’等能力声明有脚本支撑 — doctor 遍历 profile 目录对比 symlink 与 real dir('WARN: <name> is a real directory (expected symlink...)')
6结论
1c1947b7efbf6091…d5c4678cb5