claude-switch-models-setup — скилл для Claude Code: обзор и установка
Скилл настраивает изолированные профили для одновременной работы с разными моделями (Kimi, DeepSeek, Anthropic) в отдельных окнах терминала. Он предотвращает рассинхронизацию настроек и хуков.
npx skills add daymade/claude-code-skills --skill claude-switch-models-setup -a claude-codeЧто делает claude-switch-models-setup
Скилл организует структуру каталогов ~/.claude-profiles/<name>/, изолируя файл состояния .claude.json для каждого провайдера (Kimi, DeepSeek, MiniMax, GLM, StepFun, Anthropic). Проекты, хуки, агенты и скиллы символически связываются с общей папкой ~/.claude/, поэтому их не нужно копировать вручную.
Для синхронизации параметров запускается скрипт sync-profile-settings.py в виде хука SessionStart. Он переносит настройки из settings.json основного профиля во все остальные, исключая ключи идентификации модели и переменные окружения конкретных провайдеров. Скрипт claude-plugins-sync.py отдельно обслуживает плагины, сохраняя для каждого профиля собственный known_marketplaces.json.
Скрипт проверяет параметры перед записью и создаёт резервные копии. Если основной файл конфигурации повреждён, синхронизация прерывается без очистки профилей. Это важно учесть заранее: для изоляции провайдеров сессии обязательно запускаются через CLAUDE_CONFIG_DIR.
Какие задачи решает
- запускать Claude Code с разными моделями в параллельных терминалах
- предотвратить расхождение настроек и хуков между профилями
- изолировать учётные данные и историю сессий сторонних провайдеров
- сохранить единую базу скиллов и агентов для всех моделей
Примеры запросов агенту
- Настрой отдельные профили Claude Code для Kimi и DeepSeek с общей папкой скиллов.
- Проверь расхождение настроек между профилями в
~/.claude-profilesс помощьюsync-profile-settings.py --check. - Синхронизируй включённые плагины и хуки из основного профиля во все сторонние конфигурации.
Как установить claude-switch-models-setup
1Через Skills CLI (Vercel)
npx skills add daymade/claude-code-skills --skill claude-switch-models-setup -a claude-code2Вручную: положить файлы
~/.claude/skills/claude-switch-models-setup/SKILL.mdПапка скилла целиком; для одного проекта — .claude/skills/claude-switch-models-setup/
1Через Skills CLI (Vercel)
npx skills add daymade/claude-code-skills --skill claude-switch-models-setup -a codex2Вручную: положить файлы
.agents/skills/claude-switch-models-setup/SKILL.mdДля всех проектов — ~/.agents/skills/
1Через Skills CLI (Vercel)
npx skills add daymade/claude-code-skills --skill claude-switch-models-setup -a cursor2Вручную: положить файлы
.cursor/skills/claude-switch-models-setup/SKILL.mdCursor читает и .agents/skills/, и .claude/skills/
1GitHub CLI
gh skill install daymade/claude-code-skills claude-switch-models-setup2Вручную: положить файлы
.github/skills/claude-switch-models-setup/SKILL.md1Через Skills CLI (Vercel)
npx skills add daymade/claude-code-skills --skill claude-switch-models-setup -a gemini-cli2Командой платформы
gemini skills install https://github.com/daymade/claude-code-skills --path daymade-claude-code/claude-switch-models-setupВручную: положить файлы
.devin/skills/claude-switch-models-setup/SKILL.mdСтарый путь .windsurf/skills/ тоже читается
Через Skills CLI (Vercel)
npx skills add daymade/claude-code-skills --skill claude-switch-models-setup -a opencodeClaude.ai
Упакуйте папку в zip и загрузите в Settings → Capabilities → Skills
По шагам, с командами для каждой платформы: Как установить скилл в Claude Code: пять способов
Вопросы о claude-switch-models-setup
Как установить claude-switch-models-setup в Claude Code?
Выполните команду npx skills add daymade/claude-code-skills --skill claude-switch-models-setup -a claude-code. Файлы скилла будут размещены в ~/.claude/skills/claude-switch-models-setup/SKILL.md.
Зачем нужен скилл claude-switch-models-setup?
Он изолирует учётные записи и контекст моделей вроде Kimi или DeepSeek в каталоге ~/.claude-profiles/, сохраняя при этом общие скиллы и хуки из основной директории ~/.claude/.
Как скилл предотвращает рассинхронизацию настроек?
Скрипт sync-profile-settings.py запускается при старте сессии и копирует ключи из основного settings.json, не затрагивая параметры маршрутизации моделей и переменные окружения провайдеров.
Исходный текст
SKILL.md · MIT
---
name: claude-switch-models-setup
disable-model-invocation: true
description: >-
Isolates profiles for multi-provider setup and switching models in separate
terminal windows (Kimi, MiniMax, DeepSeek, GLM, StepFun, Anthropic).
Use for provider switching, csk/csd/csg aliases,
CLAUDE_CONFIG_DIR, ~/.claude-profiles, profile drift (missing skills/hooks, symlinks,
settings), context-window setup ([1m], CLAUDE_CODE_MAX_CONTEXT_TOKENS), or reducing
startup context from preloaded MCP tool schemas.
---
# Claude Code Profiles and Local Skill Activation
## Overview
This skill creates an isolated-but-shared profile system for Claude Code CLI. Each profile gets its own `.claude.json` state file (provider credentials and session history) while sharing skills, projects, hook scripts, agents, and installed plugin state across all profiles — and converging each profile's `settings.json` (hook registration, marketplaces, env feature flags, permissions, preferences) plus the **behavior slice of its `.claude.json`** (e.g. `workflowSizeGuideline`) from the default profile, so the only intended difference between profiles is the model/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.
For reducing fixed startup context from preloaded MCP tool schemas, read
[references/mcp-startup-context.md](references/mcp-startup-context.md). It owns
same-mode measurement, active-profile discovery, provider compatibility checks,
reversible server suppression, and fresh-process acceptance.
## How It Works
- `CLAUDE_CONFIG_DIR` tells Claude Code CLI which directory to use as its config root.
- Each profile lives in `~/.claude-profiles/<name>/` with an isolated `.claude.json`.
- Content directories (`skills/`, `projects/`, `hooks/`, `agents/`, `settings/`) are symlinked back to the main `~/.claude/` directory so you only maintain one copy. Note this shares hook **scripts**, not hook **registration** — registration lives in each profile's own `settings.json` (next bullet).
- **Config layer — `settings.json`:** each profile has its own `settings.json` (Claude Code treats it as config-dir-local), so everything stored there — hook registration, `extraKnownMarketplaces`, `enabledPlugins`, `env` feature flags, `permissions`, behavior preferences — silently drifts the moment it changes in the default profile (measured 2026-07-18: 9/9 real profiles had zero hook registrations). `sync-profile-settings.py` is the converger: registered as a SessionStart hook, it copies every key from the default profile's `settings.json` into **every** profile's, except identity keys (top-level `model` and `advisorModel` — the latter is Anthropic-model routing a third-party endpoint can't serve; and env vars that carry provider routing or Anthropic-native isolation — `ANTHROPIC_*`, `CLAUDE_CODE_SUBAGENT_MODEL`, `ENABLE_TOOL_SEARCH`, `DISABLE_GROWTHBOOK/TELEMETRY/AUTOUPDATER` — which the provider settings file deliberately sets differently). Within `env`, convergence is two-way for non-identity keys: main's keys overwrite the profile's, and a non-identity key main no longer carries is **deleted** from the profile and reported (identity keys are exempt — main never carries them, so their absence is not deletion evidence). Profile-only **top-level** keys are preserved; nested collections inside a key main also has (e.g. `permissions.allow`, `enabledPlugins`) converge wholesale to main's value, and any profile-only nested entries dropped that way are listed (count on write, detail under `--check`) so the loss is visible rather than silent. This is what makes "everything except the model works in every profile" actually hold.
- **Scope is every profile, in every invocation.** No argument-free, `--all`, or `--check` run ever covers a subset: all of `~/.claude-profiles/*` plus `$CLAUDE_CONFIG_DIR`, every time. A run prints one line **per profile it actually changed** and nothing when there is no drift — so drift shows up in the session-start output instead of hiding, and a silent session start means converged. A `$CLAUDE_CONFIG_DIR` that is unset, empty, or not a profile directory is skipped, never created.
- **Exit codes:** the argument-free run exits 0 unconditionally — it is a session-start hook and never blocks a session, including when a main file is corrupt (it warns, converges nothing, and exits 0, because a corrupt main reads as empty and converging toward empty would strip hooks from every profile). `--check` exits 1 on drift and 2 on a corrupt main file or a profile it could not read; `--all` writes and exits 2 on those same two failures — the difference between them is that `--check` writes nothing, not which failures return 2. `--check --all` is the same audit as `--check`. One unreadable profile is reported and skipped — it never cancels convergence for the others.
- **State layer — `.claude.json` behavior keys:** `settings.json` is not the only per-profile config file. Claude Code also keeps a per-profile state file (the main profile's is `~/.claude.json`; each third-party profile's is `<profile>/.claude.json` — asymmetric paths, verified on disk), and a few **behavior** settings live only there (`workflowSizeGuideline`, notification/UI preferences). On 2026-08-17 `workflowSizeGuideline: small` existed only on the main profile and 10/11 third-party profiles had no copy — a Kimi session fanned one Dynamic Workflow out to 30+ agents with no size guidance in its system prompt. The same converger therefore also syncs an **allowlist of behavior keys** into each profile's `.claude.json`. The safety mechanism is a three-way classifier in the script, not a hand-maintained key list: allowlisted behavior keys sync; state/cache/counter/migration/credential keys (matched by name patterns) are never touched; anything unknown-and-different is **reported — one line per drifted key per run, until a human classifies it** (the tripwire that surfaces the next behavior key the day it appears). Writes are backup + atomic-replace; measured safe against a live harness rewriting the file (a marker key survived 30+ minutes of an active session). Applies next session — the harness reads this file at startup.
- **Exception — `plugins/`:** marketplace content and install state are shared, but each profile keeps its **own** `known_marketplaces.json`. Claude validates a marketplace's `installLocation` with `path.resolve()` (which does NOT resolve symlinks), so a single shared file would make every non-writing profile report "corrupted installLocation". `claude-plugins-sync.py` builds and maintains this per-profile structure.
- `claude-plugins-sync.py` also mirrors `enabledPlugins` from the default `~/.claude/settings.json` into each profile's `settings.json` (sharing cache files is not enough; Claude Code treats "enabled" state as config-dir-local). It runs at profile launch and reactively — the LaunchAgent in the next bullet re-runs it on every write to the default profile's `settings.json`, so `claude plugin enable`/`disable --scope user` typically propagates to every profile within seconds without a relaunch (verified 2026-08-22). The mirror **adopts first**: enabledPlugins keys that exist only in some profile's settings.json (the way `claude plugin install` writes them) are written back into the default profile before mirroring — consistent values only; cross-profile conflicts stay per-profile behind a standing warning instead of being silently overwritten. The SessionStart converger above covers the same key as part of its whole-settings sync; `claude-plugins-sync.py` remains the owner of the per-profile `known_marketplaces.json` structure. `skill-install-audit.py` reconciles the registry / installed / enabled / Codex-manifest / `~/.agents/skills` layers read-only, plus the daemon's pinned runtime version and whether the checkouts it judged everything against are themselves behind. `prune-source-sync-backups.py` removes only the `.source-sync-backups/` buckets git can reproduce; a bucket holding even one blob no repository has is reported and left alone.
- Local source sync keeps approved source-backed routes aligned for each host.
Before selecting or repairing entries, read the
[host-specific activation contract](references/local-source-sync-architecture.md#host-specific-user-skill-activation).
It owns the manifest fields, marketplace expansion, Claude plugin/direct-link
distinction, unresolved-name handling, collision safety, and legacy compatibility.
Source registration alone does not choose activation policy; do not hand-create
links or repurpose the manifest to manage third-party inventory.
- Sync scripts use a shared cross-process lock. This is required because users often open several provider windows from tmux or multiple terminals at once; concurrent launches must serialize marketplace/cache rewrites while still allowing all profiles to start.
- For the full local-source architecture, read `references/local-source-sync-architecture.md` before changing these scripts.
- For Skill authoring in an approved independent Fleet clone, use the
[leased-authoring owner procedure](references/local-source-sync-architecture.md#leased-fleet-authoring-clones).
- Provider routing is done via `~/.claude/settings/<name>.json`, which sets `ANTHROPIC_MODEL`, `ANTHROPIC_BASE_URL`, and `ANTHROPIC_AUTH_TOKEN` for that window. **That file is a full settings file rather than an env file, and it is the one layer the converger never touches** — `claude-profile` launches with `claude --settings ~/.claude/settings/<name>.json`, while the converger only ever writes `<profile>/settings.json`. So anything that has to be per-profile *and* has to survive every session start belongs here; put it in the profile's own `settings.json` and the next convergence takes it back. This includes per-profile `permissions.deny`, such as denying `WebSearch` and `WebFetch`.
- **Per-profile thinking effort lives in that provider file too.** The default profile sets effort per Anthropic model via `modelSettings` in `~/.claude/settings.json`; a third-party profile that needs a *different* effort pins `CLAUDE_CODE_EFFORT_LEVEL` (e.g. `"max"`) in its `~/.claude/settings/<name>.json` env instead. The provider file is the only layer that can hold that pin: put it in the profile's own `settings.json` env and the converger deletes it at the next session start (a non-identity env key the default profile doesn't carry is deletion-propagated away); put it in the default profile's env and it applies there *and* converges into every third-party profile's `settings.json` — usually wrong, because weaker third-party models benefit from forced max effort exactly when the default flagship no longer does (verified end-to-end 2026-10-06: a session launched via `claude-profile` reads the pinned value back from its own environment).
- **Credentials ride in that same file, so anything scripting a profile has to pass `--settings` as well.** `CLAUDE_CONFIG_DIR=<profile> claude -p ...` on its own answers `Not logged in · Please run /login`, because the token lives in the provider file and nothing else loads it. The message names login; the cause is the missing flag.
- The converger has no single-profile mode: every invocation covers all of `~/.claude-profiles/*` plus `$CLAUDE_CONFIG_DIR`, and no flag narrows that. To converge one profile on demand, point `CLAUDE_PROFILES_ROOT` at a directory holding only it, or run `--check` and read the per-profile lines. The default profile's own files are the source and are never written.
### ⚠️ Never run the converger against a synthetic main
Scope is every profile — all of `~/.claude-profiles/*` plus `$CLAUDE_CONFIG_DIR`
— and the source of truth is `CLAUDE_MAIN_CONFIG_DIR`. Point that at a throwaway
directory while `CLAUDE_PROFILES_ROOT` or `$CLAUDE_CONFIG_DIR` still reaches a
**real** profile, and the run converges that real profile toward the synthetic
main: its whole `hooks` object is replaced by whatever the fake main holds, and
its `env` gains the fake main's keys. **Every guard registered in that profile
stops firing.** The output does name `hooks` among the keys it synced and, when
the overwrite drops profile-only entries, reports how many — but nothing in it
says guards stopped firing, so it reads as the converger doing its job. A
synthetic main is safe only when the profiles root and `$CLAUDE_CONFIG_DIR` are
synthetic and disposable too.
Before running it by hand, check both halves of the scope:
```bash
echo "MAIN=$CLAUDE_MAIN_CONFIG_DIR ROOT=$CLAUDE_PROFILES_ROOT ACTIVE=$CLAUDE_CONFIG_DIR"
```
An unset `CLAUDE_PROFILES_ROOT` is **not** a green light — it defaults to the
real `~/.claude-profiles`, so every real profile converges. Stop unless both
`CLAUDE_PROFILES_ROOT` and `$CLAUDE_CONFIG_DIR` are synthetic and disposable.
Test fixtures must build the subprocess environment from a scrubbed base instead
of inheriting the live one — a shell profile sets these variables, and `unset`
inside a script does not reliably reach a child process:
```bash
env -u CLAUDE_CONFIG_DIR -u CLAUDE_MAIN_CONFIG_DIR -u CLAUDE_PROFILES_ROOT …
```
Decide whether a run wrote anything mechanically, not by eye. Record the target
profile's `settings.json` size before the run and compare after. `.sync-backup`
is written with `shutil.copy2`, which preserves the source mtime, so **an old
backup timestamp does not prove nothing was written** — compare size and bytes.
If a real profile did get written, restore from that profile's own backup and
verify byte-for-byte:
```bash
cp -p <profile>/settings.json.sync-backup <profile>/settings.json
```
Check size, JSON validity, top-level key count, `hooks` length, unexpected `env`
keys, and sandbox signatures such as `/bin/true`. Then scan the other profiles:
scope is all of them, so one run can hit several.
## One-Click Setup Workflow
When the user says something like "set up Claude Code profiles" or "I want to use Kimi and DeepSeek in different windows":
1. **Check prerequisites**
- `claude` CLI is installed: `which claude`
- Shell is zsh or bash: detect via `$SHELL`
- `python3` is available
2. **Install the profile manager scripts — symlink them, do not copy**
On a machine that has this repo checked out (the maintainer case), run the
bundled installer:
```bash
<absolute-path-to-this-repo>/daymade-claude-code/claude-switch-models-setup/scripts/setup.sh
```
`scripts/setup.sh` is the single source for the exact deployment set. It links
each helper into `~/.config/claude-switch-models-setup/` and seeds the activation
manifest only when it does not already exist. Do not maintain another helper list
here. No `chmod` step is needed: the deployment is by symlink, and the source
files retain their committed modes.
Recorder files are deployed without enabling the optional wrapper. Existing
ordinary recorder copies must be compared and preserved before setup replaces
them with links; pinned deployments follow the “advance the pin” procedure.
**Why symlinks and not `cp`:** `~/.config/…` is what actually runs — the
LaunchAgent and `claude-profile` invoke scripts by that path — while this
repo holds their source. Copies drift, and nothing about a deployed copy
looks different from its source. A link prevents independent edits and
source updates from silently diverging, *for as long as it stays a
link* — an atomic-save editor, an `rsync` or a stray `cp` turns one back into
a real file without saying so, which is why this is worth re-checking rather
than declaring solved. It also lets `sync-local-skill-sources.py` locate its
own source repo by resolving its own path, instead of falling back to
guessing.
Worth re-checking how? Any periodic check works; there is none bundled with
this skill. One line, run wherever you keep such things:
```bash
for f in ~/.config/claude-switch-models-setup/*.py ~/.config/claude-switch-models-setup/*.sh; do
[ -L "$f" ] && [ -e "$f" ] || echo "not a live link: $f"
done
```
If one has become a real file, **move it aside before re-linking** — it may
hold edits that exist nowhere else, which is the whole problem being
described: `mv "$f" "$f.local-edits" && ln -sf <source> "$f"`, then diff.
On a machine **without** the repo, copy the scripts listed by the installer out of this skill
bundle instead — and accept that repo fixes will not reach it until you copy
again.
On a machine whose LaunchAgent runs the **pinned plugin copy** (the maintainer
layout described in [local-source-sync-architecture.md](references/local-source-sync-architecture.md)),
these same links point at that copy's version directory under `.../plugins/cache/...`,
not at the checkout, and move only when the pin is advanced
([troubleshooting.md](references/troubleshooting.md), "advance the pin"). The
installer refuses to relink such a machine to the checkout
(`CSMS_SETUP_RELINK_TO_CHECKOUT=1` overrides), because the daemon and
`claude-profile` would then follow whatever branch the checkout sits on. The
live-link check above applies to both layouts.
3. **Add shell integration**
- Source the profile manager in `~/.zshrc` or `~/.bashrc`
- Add aliases: `csk`, `csd`, `csg`
- Add any further per-account/per-plan variant alias by hand if needed —
the script's help text only lists the base examples above; variants like
`cssplan`/`cssp` are hand-added, not generated
- Tell the user to run `source ~/.zshrc` (or open a new terminal)
4. **Generate provider settings files**
- For each provider the user wants, create `~/.claude/settings/<provider>.json`
- Use the templates in `assets/templates/` as a starting point
- Prompt the user for their API key and base URL; **never hardcode defaults**
- Set the context window correctly for this specific provider — `[1m]` suffix vs explicit `CLAUDE_CODE_MAX_CONTEXT_TOKENS`/`CLAUDE_CODE_AUTO_COMPACT_WINDOW`, see "Configuring Context Window Size" below. Do this explicitly for every new profile rather than copying whatever the nearest template happens to already have — the nearest template not needing it is not evidence that this one doesn't either.
- Include the required isolation flags:
- `CLAUDE_CODE_SUBAGENT_MODEL` (same as `ANTHROPIC_MODEL`)
- `ENABLE_TOOL_SEARCH: "false"`
- `DISABLE_GROWTHBOOK: "1"`
- `DISABLE_TELEMETRY: "1"`
- `DISABLE_AUTOUPDATER: "1"`
- Optionally pin `CLAUDE_CODE_EFFORT_LEVEL` (e.g. `"max"`) when this provider's model benefits from a forced thinking effort different from the default profile's. It belongs in this provider file — never in the profile's `settings.json` env, where the converger deletes it (see "Per-profile thinking effort" under How It Works).
5. **Initialize profile directories**
- Run `claude-profiles-init`
- This creates `~/.claude-profiles/<provider>/` with isolated `.claude.json` and symlinks
- On maintainer machines, this also repairs local source symlinks before syncing plugin metadata
**Statusline wiring:** `claude-profiles-init` auto-detects a statusline script from
`~/.claude/settings.json` or `~/.claude/statusline.sh` and injects it into each new
profile. If neither is present, profiles will work but without a status bar. **It is
the AI's job** to decide whether the user needs a statusline, install the
`statusline-generator` skill if appropriate, and run its installer — not the profile
setup script. Do not hardcode dependency installs into shell scripts.
6. **Register the settings converger**
- Add the converger as a SessionStart hook in the **default** profile's `~/.claude/settings.json` `hooks.SessionStart` list, using an absolute direct-Python command such as `'/absolute/path/to/python3' '/absolute/path/to/sync-profile-settings.py'`. Do not register the `.py` file by shebang or through a package manager: this hook exists to repair every profile and must not wait on a shared environment/cache lock. Register it **without arguments** — the argument-free call is the session-start mode, which converges every profile and never blocks the session. Do not add `--all` to the hook command: `--all` is the human mode and exits 2 on a corrupt main file or a profile it could not read, which would block session start.
- Run the initial alignment: `python3 ~/.config/claude-switch-models-setup/sync-profile-settings.py --all`
- From then on every profile converges its `settings.json` and the behavior slice of its `.claude.json` from the default profile at each session start, whoever starts it (changes apply next session). The default profile's own files are the SSOT and are never written. Audit without writing: `--check` (or `--check --all`, the same audit).
7. **Verify isolation**
- Run `claude-profiles-doctor`
- Confirm each profile directory has `.claude.json` and valid symlinks
8. **Select local source Skills for Codex and Claude**
- Skip this for normal students or users who do not edit the skill source repos
- Read the [host-specific activation contract](references/local-source-sync-architecture.md#host-specific-user-skill-activation), then edit the machine's activation manifest for the requested hosts. Use its compatibility rules only for consumers that still retain a legacy path.
- Preview with `python3 ~/.config/claude-switch-models-setup/sync-local-skill-sources.py`, read every affected path, then apply with `python3 ~/.config/claude-switch-models-setup/sync-local-skill-sources.py --apply`.
- On a maintainer macOS machine, run `~/.config/claude-switch-models-setup/sync-local-skill-sources-daemon.sh --install`
- This watches the activation manifest, default Claude install state, and local marketplace manifests, then repairs derived state after selection, install/uninstall, or plugin topology changes
9. **Show the user how to launch**
- `csk` → Kimi window
- `csd` → DeepSeek window
- `csg` → GLM window
- `claude` (no alias) → default Anthropic profile
- Optional: hand-add per-account/per-plan variant aliases yourself —
`claude-profiles.sh` does not generate them. StepFun is the running
example: its subscription plan only answers at a dedicated plan base URL
(`https://api.stepfun.com/step_plan`, single model), while pay-as-you-go
goes through the provider's standard endpoint or whatever gateway fronts
it — same provider, two billing modes, so they live as two profiles with
two aliases (always ask for the exact base URLs):
```bash
alias cssplan='claude-profile step-plan --dangerously-skip-permissions'
alias cssp='claude-profile step-pay --dangerously-skip-permissions'
```
## Commands
After setup, the user can run:
```bash
claude-profiles-init # Re-scan settings/*.json, create missing profiles;
# reports symlink drift (real dirs that should be symlinks).
# Add --repair to archive drift and replace with symlinks.
claude-profile <name> # Launch a specific profile
claude-profiles-ls # List profiles
claude-profiles-doctor # Check symlink health
claude-profile-rm <name> # Remove a profile's isolation directory
python3 ~/.config/claude-switch-models-setup/claude-plugins-sync.py
# Repair per-profile plugin structure and enabledPlugins
python3 ~/.config/claude-switch-models-setup/sync-profile-settings.py --all
# Converge every profile from the default profile:
# settings.json (hooks, marketplaces, env flags,
# permissions, preferences) + .claude.json behavior
# keys (workflowSizeGuideline etc.). Session start
# already does this for all profiles; run --all to
# apply a manual settings edit immediately.
# --check audits the same scope without writing
python3 ~/.config/claude-switch-models-setup/sync-local-skill-sources.py
# Maintainers: preview host selections and affected paths
python3 ~/.config/claude-switch-models-setup/sync-local-skill-sources.py --apply
# Apply the inspected Codex, Claude, and explicit
# legacy compatibility changes
~/.config/claude-switch-models-setup/sync-local-skill-sources-daemon.sh --install
# Maintainers: install automatic macOS watcher
```
These are not day-to-day commands. Edits to activated canonical sources are live through symlinks. The one-shot commands are for repair, bootstrap, or non-macOS environments without the LaunchAgent watcher.
## Provider Templates
Use the provider templates in [`assets/templates/`](assets/templates/). Read the
chosen file for its model, endpoint, context settings, and thinking behavior;
do not infer those values from a hand-maintained template summary.
Every template uses the `<API_KEY>` placeholder. Templates for configurable gateways also use `<BASE_URL>`; the MiniMax templates pin the documented regional endpoint. Ask the user for every real placeholder value; do not guess or reuse values from the current machine unless the user explicitly provides them.
MiniMax-M3 supports adaptive or disabled thinking; keep `ANTHROPIC_REASONING_MODEL`
on the same model. MiniMax-M2.7 thinking is always on; do not claim a
template-level disable path. Read model and context values from the chosen template.
## Configuring Context Window Size
Every provider template sets the model's context window one of two ways — get this wrong and Claude Code doesn't know how much context the model can actually hold. Undershoot and it compacts (summarizes, drops old detail) far earlier than the provider actually requires; overshoot and it won't compact until the real limit is already blown past.
The full client-side mechanism of the `[1m]` marker — what it strips off the model
field, what it adds to the `anthropic-beta` header, and why a missing `[1m]` does
*not* mean the provider can't hold a big prompt — is documented in
`references/context-window-config.md`. Reach for it when a context number looks
wrong, not at template-writing time.
### Decision rule
When writing a new provider's `settings/<name>.json`, pick based on the provider's real, verified context window — not the model's marketing name, and not by copying whatever the nearest template happens to do:
| Provider's real context window | What to set | Example template |
|---|---|---|
| ~1M tokens, explicitly confirmed (not assumed from the model's tier/name) | `[1m]` suffix on every `ANTHROPIC_MODEL` / `ANTHROPIC_DEFAULT_*_MODEL` / `CLAUDE_CODE_SUBAGENT_MODEL` value. Must be the exact 4 characters `[1m]` — Claude Code matches this literal string, not a made-up marker like `[1million]` or `[max]`. | `kimi.json` |
| A known, smaller size (e.g. 200K) | Explicit `CLAUDE_CODE_MAX_CONTEXT_TOKENS` and/or `CLAUDE_CODE_AUTO_COMPACT_WINDOW` set to the real number — no `[1m]`. | `kimi-highspeed.json` |
| Unknown / not yet verified | Don't guess, and don't copy another provider's number just because a template needs *something* there. Ask the user to check the provider's own docs/console first. An unverified `[1m]` or an unverified large `CLAUDE_CODE_AUTO_COMPACT_WINDOW` just moves the failure from "compacts too early" to "doesn't compact until well past the real limit" — worse, because it's silent until a request actually fails. |
When a template supplies both a context marker and an explicit limit, retain
both unless their precedence has been verified. Read the actual values from
the selected template rather than maintaining a model summary here.
For checking provider model identity and whether an environment variable changes
the request sent over the wire, read `references/context-window-config.md`.
**Important:** The exact endpoint depends on whether the user is calling the provider directly or through a compatibility gateway (e.g., OpenRouter). Always ask.
## Shared vs. Isolated
| Data | Location | Shared? |
|------|----------|---------|
| Session history | `~/.claude-profiles/<name>/.claude.json` | **Isolated per profile** |
| Auth tokens/cache | `~/.claude-profiles/<name>/.claude.json` | **Isolated per profile** |
| Account + MCP OAuth tokens | macOS Keychain, entry named from the config dir | **Isolated by default**; set `CLAUDE_SECURESTORAGE_CONFIG_DIR=""` to make every profile share one entry, so an MCP server authorized once is connected everywhere — see [credential-storage.md](references/credential-storage.md) |
| Skills | `~/.claude/skills/` | Shared via symlink |
| Plugin content | `~/.claude/plugins/marketplaces`, `cache`, `data`, ... | Shared via symlink |
| Plugin install registry | `~/.claude/plugins/installed_plugins.json` | Shared via symlink |
| Enabled plugin map | `~/.claude/settings.json` -> `<profile>/settings.json` | Converged by `sync-profile-settings.py` (also mirrored by `claude-plugins-sync.py`) |
| Plugin marketplace index | `<profile>/plugins/known_marketplaces.json` | **Per-profile** (installLocation is config-dir-specific; can't be shared) |
| Projects/memory | `~/.claude/projects/`, `~/.claude/memory/` | Shared via symlink |
| Hook scripts | `~/.claude/hooks/`, `~/.claude/commands/` | Shared via symlink (scripts only — NOT registration) |
| `settings.json` config: hook registration, marketplaces, env flags, permissions, preferences | `<profile>/settings.json` | **Converged from default profile into every profile** by `sync-profile-settings.py` at session start (identity keys like `model` and provider-routing/isolation env vars are never synced) |
| `...
© daymade · MIT · daymade/claude-code-skills