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外部依赖
| Kind | Dependency / Endpoint |
|---|---|
| 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管控建议与判定依据
- scripts/: 执行本地脚本或命令: scripts/setup.sh
- 网络端点: 声明外部网络访问: (SKILL 流程中的用户动作)claude CLI 经各 provider 端点/网关出网;daemon --install 时 uv python
- 本地工作目录: 文件读写与工件输出: ~/.claude-profiles/<name>/ 结构(.claude.json、symlink 目录)
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…