Multi-account, multi-LLM, one shared context — from a single machine.
$ CLAUDE_CONFIG_DIR=~/.claude-ac1 claude & $ OPENCODE_CONFIG_DIR=~/.config/opencode-ac2 opencode & # two identities, one machine, one shared context
~/.claude-ac1→~/.claude-ac2→~/.claude
Multi-account, multi-provider, one environment variable.
CLAUDE_CONFIG_DIR
·
settings.json
·
X_ prefix
Claude Code stores everything — auth, settings, session history, projects, plugins — under one config root, normally ~/.claude. Pointing CLAUDE_CONFIG_DIR at a different directory gives that invocation its own complete, independent root. Not an overlay on the default — a separate identity.
CLAUDE_CONFIG_DIR=~/.claude-ac1 claude # account 1: own auth/session/settings CLAUDE_CONFIG_DIR=~/.claude-ac2 claude # account 2: own auth/session/settings claude # default ~/.claude, untouched by either
Each config dir starts blank. You opt back in to sharing by symlinking the stable, personal pieces — and leave the per-identity pieces real.
| link Symlinked (shared across accounts) | lock Real / isolated (per account) |
|---|---|
| CLAUDE.md global instructions | projects/ chat history, session logs |
| agents/, commands/ subagents, slash commands | settings.json, .credentials.json |
| docs/, skills/, rules/ | plugins/ marketplaces, installed plugins |
# 1. create the new identity's root mkdir ~/.claude-ac1 # 2. link the shared pieces back to the default setup for s in CLAUDE.md agents commands docs skills rules; do ln -s "$HOME/.claude/$s" "$HOME/.claude-ac1/$s" done # 3. credentials/settings/projects/plugins stay real (absent) # — created on first launch
zsh, for s in $LIST does not word-split a space-separated string (it makes one broken, space-named link); bash does. Iterate a literal list or a real array, and you are safe in both.
A launcher alias per account means you never type the env var. But aliases only load from your interactive shell's rc file — and which file that is depends on your shell.
| Shell | rc file | reload an open tab |
|---|---|---|
| zsh (macOS default) | ~/.zshrc | source ~/.zshrc |
| bash (Linux; macOS legacy) | ~/.bashrc — check ~/.bash_profile too (login shells) | source ~/.bashrc |
| fish | ~/.config/fish/config.fish | automatic |
# one block per account, in the rc file for YOUR shell alias ac1claude='CLAUDE_CONFIG_DIR=~/.claude-ac1 claude' alias ac1claude-d='CLAUDE_CONFIG_DIR=~/.claude-ac1 claude --dangerously-skip-permissions' alias ac1claude-dr='CLAUDE_CONFIG_DIR=~/.claude-ac1 claude --dangerously-skip-permissions --resume'
echo $SHELL, then edit the matching rc file. New terminal tabs pick aliases up automatically; already-open tabs need a source first.
ac1claude # launch with the ac1 config dir /login # browser opens — sign in with that account
Repeat once per account. The auth token is saved inside that config dir and persists after — no repeated sign-ins.
/status shows which config dir and account are live. Essential when several tabs run different aliases.CLAUDE_CONFIG_DIR was active at launch. Two accounts in the same project folder write to different history directories — same working dir, different past, by design.The credential lives inside the config dir, so each account authenticates differently:
| Method | How | Use when |
|---|---|---|
| Subscription (OAuth) | claude /login | your monthly plan |
| API key (PAYG) | ANTHROPIC_API_KEY in the dir's settings.json env | usage-based billing |
| Bedrock / Vertex | CLAUDE_CODE_USE_BEDROCK=1 / …_VERTEX=1 | AWS / GCP shop |
| Anthropic-compatible LLM (GLM…) | ANTHROPIC_BASE_URL + ANTHROPIC_AUTH_TOKEN + ANTHROPIC_DEFAULT_*_MODEL | cheaper / residency / fallback |
| apiKeyHelper | script emitting a rotating key | short-lived / SSO keys |
// ~/.claude-ac1/settings.json ~/.claude-ac2/settings.json { "env": { { "env": { "ANTHROPIC_API_KEY": "sk-ant-…" "CLAUDE_CODE_USE_BEDROCK": "1" } } } }
Claude Code speaks the Anthropic API — any provider that speaks it back drops in. These env vars redirect the harness, tiers remapped:
| Env var | Does | GLM (Z.ai) |
|---|---|---|
| ANTHROPIC_BASE_URL | provider's Anthropic-compatible endpoint | https://api.z.ai/api/anthropic |
| ANTHROPIC_AUTH_TOKEN | Authorization: Bearer (3rd-party) | your Z.ai / BigModel key |
| ANTHROPIC_DEFAULT_{HAIKU,SONNET,OPUS}_MODEL | tier → model | glm-4.5-air / glm-5.1 / glm-5.1 |
AUTH_TOKEN (Bearer) for GLM — API_KEY (x-api-key) is direct-Anthropic only.Keep every provider's vars in global settings.json; prefix the inactive set with X_ so Claude Code ignores them. Activate one per project in .claude/settings.local.json (gitignored, overrides global) — GLM here, Anthropic login next repo, Bedrock in a third.
// prefix = INERT (global) · drop X_ = LIVE (project-local, gitignored) { "env": { "X_ANTHROPIC_BASE_URL": "https://api.z.ai/api/anthropic", "X_ANTHROPIC_AUTH_TOKEN": "…" } }
The open counterpart — 75+ providers, one UI, switchable mid-session.
Claude Code is one vendor — predictable, polished, capped on heavy days. OpenCode is the open-source counterpart: one UI over 75+ providers, switchable mid-session.
| Tool | Access | The tradeoff |
|---|---|---|
| Claude Code | One vendor | Out-of-the-box quality; capped; locked-in |
| OpenCode | 75+ providers, switch mid-session | One UI, any vendor's pricing underneath; you wire the keys |
| OpenRouter | 300+ models, one key | Cross-vendor arbitrage; proxy hop |
| Local (Ollama / LM Studio) | Whatever your hardware holds | $0/token — but cost shifts to GPU/RAM, not removed |
Claude has CLAUDE_CONFIG_DIR; OpenCode matches it — one env var for the file, one for the dir:
alias oc1='OPENCODE_CONFIG=~/.config/opencode-ac1/opencode.jsonc \ OPENCODE_CONFIG_DIR=~/.config/opencode-ac1 opencode' alias oc2='OPENCODE_CONFIG=~/.config/opencode-ac2/opencode.jsonc \ OPENCODE_CONFIG_DIR=~/.config/opencode-ac2 opencode'
| Env var | Swaps |
|---|---|
| OPENCODE_CONFIG | the config file — model, provider, instructions |
| OPENCODE_CONFIG_DIR | the config dir — agents/commands/plugins (layered over global) |
| {env:KEY} | per-account API keys, set per alias |
opencode auth login), so these swap config, not auth. For per-account keys, reference {env:AC1_…_API_KEY} per alias — or move the whole global dir via XDG_CONFIG_HOME (auth included), at the cost of relocating every XDG-aware tool.provider is a map, not a single choice — predefine Zen and GLM in one file, switch by changing model (or /connect / /models). No re-auth each time.
// opencode.json — Zen (built-in) + your GLM, one active { "model": "zai/glm-4.6", // ← flip to "opencode/gpt-5.5" for Zen "provider": { "zai": { "npm": "@ai-sdk/openai-compatible", // protocol adapter — built-ins (Zen) need only a key "options": { "baseURL": "https://open.bigmodel.cn/api/paas/v4/", "apiKey": "{env:ZAI_API_KEY}" }, "models": { "glm-4.6": { "name": "GLM-4.6" } } } // "opencode" (Zen) is built-in — added by /connect, billed per request } }
zai block, export ZAI_API_KEY=…, set "model": "zai/glm-4.6".You already wrote your standards once — in CLAUDE.md and rules/. OpenCode should read the same files, not a hand-maintained copy. Its config takes an instructions array of paths and globs, loaded at every session start:
// ~/.config/opencode/opencode.jsonc { "$schema": "https://opencode.ai/config.json", "instructions": [ "~/.claude/CLAUDE.md", "$HOME/.claude/rules/*.md" ] }
$HOME-absolute globs over ~+wildcard, which some loaders mishandle.OpenCode reads Claude-compatible locations on purpose, so most of your setup crosses over with zero config:
| Claude source | How OpenCode gets it | Cost |
|---|---|---|
| CLAUDE.md, rules/*.md | instructions[] glob, always-on | check_circleparity |
| skills/*/SKILL.md | auto-discovered — ~/.claude/skills/ + .claude/skills/, loaded on-demand via the native skill tool | check_circlelazy, no tax |
| agents/, commands/ | not read — OpenCode uses ~/.config/opencode/agents/, .opencode/agents/ | cancelrewrite |
.claude/skills/*/SKILL.md (project, up to the git root) and ~/.claude/skills/*/SKILL.md (global), and exposes each through its skill tool — invoked lazily, exactly like Claude Code. Your whole skills folder works in both tools, unchanged. Keep each SKILL.md's frontmatter valid (name matching its directory, a description), and nothing else is required.agents/ and commands/ live in different directories under a different schema. Recreate the few you depend on in OpenCode's agents/ format — or skip them; the built-in agents cover most cases.Run inside a project and OpenCode auto-discovers a fixed set of filenames, traversing up from the working directory. Everything else is invisible without a glob.
| File | Auto-picked? | Note |
|---|---|---|
| Repo AGENTS.md (cwd + ancestors) | check_circleyes | Primary. First match wins. |
| Repo CLAUDE.md | warningfallback only | Loaded only if no AGENTS.md — it shadows CLAUDE.md. |
| Global instructions[] (your rules) | check_circleyes | every repo, always |
| Repo .claude/rules/*.md, .cursor/rules | cancelno | needs a per-repo glob |
| Nested subdir AGENTS.md | cancelno | only via packages/*/AGENTS.md glob, or when cwd is inside it |
AGENTS.md shadows repo CLAUDE.md. A repo with both will drop its CLAUDE.md from OpenCode's view. Repos carrying project rules in .claude/rules/ or .cursor/rules/ are blind to OpenCode until you add the glob.One pattern, three scales — identity is a directory; the credential lives inside it.
The same harness shape repeats. Change the directory, change the identity — whether that identity is an account or a provider:
| Scale | Env var | What each dir holds |
|---|---|---|
| Multi Claude account | CLAUDE_CONFIG_DIR | own settings.json (key/provider in env), projects/, plugins/ |
| Multi OpenCode account | OPENCODE_CONFIG + OPENCODE_CONFIG_DIR | own opencode.json, agents/, commands/ |
| Multi provider (either tool) | one dir, a provider map | Claude: X_-prefixed vars, one active per project · OpenCode: many provider entries, one model active |
X_ prefix, OpenCode via the provider map. Different syntax, identical invariant.CLAUDE_CONFIG_DIR); symlink the shared six (CLAUDE.md, agents, commands, docs, skills, rules)./login once, verify with /status.settings.json env — API key, Bedrock, Vertex, or GLM endpoint; keep inactive providers X_-prefixed, activate per project in settings.local.json.OPENCODE_CONFIG / OPENCODE_CONFIG_DIR per account; point instructions at the same CLAUDE.md + rules/*.md.provider map — Zen (opencode/<model>) and custom GLM; switch by flipping model or /connect; keys via {env:…}.agents//commands/ need an OpenCode-format rewrite.| → Space PgDn | Next slide |
| ← PgUp | Previous slide |
| Home | First slide |
| End | Last slide |
| 1–9 | Quick jump to slide N (single digit) |
| G then number + Enter | Jump to slide N (1–21) |
| F or Cmd+Enter | Toggle fullscreen |
| Esc | Exit fullscreen / close help |
| S | Toggle speaker notes |
| B | Blank screen (blackout) |
| ? | Toggle this help |
| Click right half | Next slide |
| Click left half | Previous slide |
| Swipe (touch) | Next / previous |