claude-switch-models-setup
Set up and maintain multiple isolated Claude Code CLI profiles so students and power users can run different LLM providers (Kimi K3, Kimi K2.7 highspeed, MiniMax M3, MiniMax M2.7, GLM, DeepSeek, StepFun, Anthropic) in separate terminal windows at the same time. Use this skill whenever the user asks about multi-provider Claude setup, multiple Claude Code windows, switching models or the csk/csd/csg aliases, CLAUDE_CONFIG_DIR, the ~/.claude-profiles directory, or running Kimi/MiniMax/GLM/DeepSeek/StepFun alongside Anthropic. It also owns profile-drift troubleshooting — a third-party profile missing skills/hooks/plugins the default profile has, claude-profiles-doctor reporting a real directory where a symlink belongs, or settings not converging — and per-provider context-window configuration (the [1m] marker or explicit CLAUDE_CODE_MAX_CONTEXT_TOKENS).
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…