HARNESS · DECK
Notes: off
01 / 21  ·  TALK
// SESSION_LOG --identity=harness

Many Accounts,
Many Providers,
One Harness.

Multi-account, multi-LLM, one shared context — from a single machine.

Presented by   Mir Mursalin Ankur
Lead Software Engineer @ Nerddevs Ltd
BASH · ~/session
$ CLAUDE_CONFIG_DIR=~/.claude-ac1 claude &
      $ OPENCODE_CONFIG_DIR=~/.config/opencode-ac2 opencode &
      # two identities, one machine, one shared context
Diagram: two terminal identities, ac1 and ac2, each with their own config directory and provider, both reading the same shared CLAUDE.md and rules files
Two CLI tools run this show: Claude Code first, then OpenCode as the open counterpart. One account and one provider are rarely enough anymore — subscription caps throttle you on busy days, and a single LLM vendor is one outage or price hike away from blocking you. The fix is not another browser tab — it is more identities and more providers, all running the same shared context, side by side.
MANY · ACCOUNTS · PROVIDERS · HARNESS 01 / 21
02 / 21  ·  THE PROBLEM

One Account, One Provider —
Not Enough Anymore.

  • Subscription limits throttle you. Rate limits, 5-hour usage windows, and weekly caps bite on the days you code hardest.
  • Token and context caps. One account's quota is one ceiling; when it hits the wall, work stalls until it resets.
  • One vendor is a single point of failure. An outage, a price hike, a data-residency rule — and you're blocked. Multi-provider (Anthropic, GLM, Bedrock, local) keeps you moving.
  • The naive fix — log out, log in — throws away session history, settings, and auth every time.
lightbulb
THE REAL SHIFT
Stop treating "account" or "provider" as a login state. Treat each as a directory. Swap the directory, swap the identity — same harness, same shared context, without ever signing out.
~/.claude-ac1~/.claude-ac2~/.claude
MANY · ACCOUNTS · PROVIDERS · HARNESS 02 / 21
SECTION /01 OF /03
PART 01 / 03

Claude Code.

Multi-account, multi-provider, one environment variable.

CLAUDE_CONFIG_DIR · settings.json · X_ prefix
MANY · ACCOUNTS · PROVIDERS · HARNESS 03 / 21
04 / 21  ·  MENTAL MODEL

The Config Root IS the Identity.

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.

bolt
Same binary. Same machine. Same working directory. Three identities, decided at launch by one environment variable.
BASH · mental-model.sh
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
3 lines · 3 identities · 1 binary
MANY · ACCOUNTS · PROVIDERS · HARNESS 04 / 21
05 / 21  ·  WHAT TRAVELS

Isolation Is Total by Default.

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
balance
THE PRINCIPLE
Share the setup (one set of rules everyone runs), isolate the identity (auth, history, plugin state never bleed between accounts).
MANY · ACCOUNTS · PROVIDERS · HARNESS 05 / 21
06 / 21  ·  PROVISIONING

Symlink the Setup, Isolate the Identity.

BASH · provision.sh
# 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
warning
THE CON — AND IT BIT ME ONCE
Shells differ. In 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.
info
Don't drop account-only files into a symlinked dir — they land in the shared target and leak to every account. Keep per-account extensions in an unlinked subfolder.
MANY · ACCOUNTS · PROVIDERS · HARNESS 06 / 21
07 / 21  ·  SHELL ALIASES

Aliases Live Where Your Shell Lives.

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
BASH · ~/.zshrc
# 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'
tips_and_updates
Find yours: echo $SHELL, then edit the matching rc file. New terminal tabs pick aliases up automatically; already-open tabs need a source first.
MANY · ACCOUNTS · PROVIDERS · HARNESS 07 / 21
08 / 21  ·  FIRST RUN

Log In Once, Then Trust the Directory.

BASH
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.

badge
VERIFY MID-SESSION
/status shows which config dir and account are live. Essential when several tabs run different aliases.
history
WHERE LOGS LAND
Whichever 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.
MANY · ACCOUNTS · PROVIDERS · HARNESS 08 / 21
09 / 21  ·  AUTH PATHS

Login, API Key, or Cloud — One Identity, Many Auth Paths.

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
JSONC
// ~/.claude-ac1/settings.json        ~/.claude-ac2/settings.json
    { "env": {                            { "env": {
      "ANTHROPIC_API_KEY": "sk-ant-…"        "CLAUDE_CODE_USE_BEDROCK": "1"
    } }                                    } }
key
The env block is the lever — auth travels with the identity, no secrets in your shell.
Precedence (high → low):  managedCLI argslocal settings.local.json (yours, gitignored) → project settings.json (team) → user global. Higher scope wins.
MANY · ACCOUNTS · PROVIDERS · HARNESS 09 / 21
10 / 21  ·  GLM REDIRECT

Point the Harness at GLM.

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
priority_high
AUTH TOKEN vs API KEY
Use AUTH_TOKEN (Bearer) for GLM — API_KEY (x-api-key) is direct-Anthropic only.
MANY · ACCOUNTS · PROVIDERS · HARNESS 10 / 21
11 / 21  ·  PROVIDER TOGGLE

The X_ Prefix Toggle.

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.

JSONC
// prefix = INERT (global) · drop X_ = LIVE (project-local, gitignored)
    {
      "env": {
        "X_ANTHROPIC_BASE_URL":   "https://api.z.ai/api/anthropic",
        "X_ANTHROPIC_AUTH_TOKEN": "…"
      }
    }
swap_horiz
No re-login, no re-key. OpenCode does the same natively with a provider map → Slide 13.
MANY · ACCOUNTS · PROVIDERS · HARNESS 11 / 21
12 / 21  ·  SECTION
PART 02 / 03

OpenCode.

The open counterpart — 75+ providers, one UI, switchable mid-session.

OPENCODE_CONFIG · OPENCODE_CONFIG_DIR · provider map
MANY · ACCOUNTS · PROVIDERS · HARNESS 12 / 21
13 / 21  ·  TOOL COMPARISON

OpenCode Alongside Claude Code.

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
tune
Pick the tool for the constraint that binds: data residency → local · flexibility → OpenCode/OpenRouter · out-of-the-box quality → Claude Code.
MANY · ACCOUNTS · PROVIDERS · HARNESS 13 / 21
14 / 21  ·  OPENCODE IDENTITY

OPENCODE_CONFIG_DIR — OpenCode's Multi-Account Lever.

Claude has CLAUDE_CONFIG_DIR; OpenCode matches it — one env var for the file, one for the dir:

BASH
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
warning_amber
DIFFERENCE FROM CLAUDE
OpenCode stores auth globally (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.
MANY · ACCOUNTS · PROVIDERS · HARNESS 14 / 21
15 / 21 · PROVIDER MAP

Keep Zen and GLM — Switch by Flipping a Default.

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.

JSONC
// 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
      }
    }
bolt
ZEN → GLM RECIPE
Add the zai block, export ZAI_API_KEY=…, set "model": "zai/glm-4.6".
MANY · ACCOUNTS · PROVIDERS · HARNESS 15 / 21
16 / 21 · SHARED CONTEXT

Share Context, Don't Duplicate It.

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:

JSONC
// ~/.config/opencode/opencode.jsonc
    {
      "$schema": "https://opencode.ai/config.json",
      "instructions": [
        "~/.claude/CLAUDE.md",
        "$HOME/.claude/rules/*.md"
      ]
    }
tips_and_updates
GLOB SAFETY
Edit the rules once; both tools inherit. Tools resolve paths themselves (no shell), so prefer $HOME-absolute globs over ~+wildcard, which some loaders mishandle.
MANY · ACCOUNTS · PROVIDERS · HARNESS 16 / 21
17 / 21 · WHAT PORTS

Skills Auto-Port. Agents Don't.

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
SKILLS ARE THE QUIET WIN
OpenCode walks .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.
build
The only real porting work: custom 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.
MANY · ACCOUNTS · PROVIDERS · HARNESS 17 / 21
18 / 21 · REPO CONVENTIONS

Which Repo Rules Auto-Load — and Which Don't.

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
warning
THE GOTCHA
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.
MANY · ACCOUNTS · PROVIDERS · HARNESS 18 / 21
19 / 21 · CHAPTER
PART 03 / 03

Synthesis.

One pattern, three scales — identity is a directory; the credential lives inside it.

directory · env var · credential
MANY · ACCOUNTS · PROVIDERS · HARNESS 19 / 21
20 / 21 · THE UNIFYING PATTERN

A Directory, an Env Var, a Credential — At Every Scale.

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
THE UNIFYING IDEA
Identity is a directory; the credential lives inside it. Run one account or twenty, one provider or seven — the pattern doesn't change, only the count does. That's what makes it scriptable: an alias is a directory pointer, a credential is a file inside, a provider is one line flipped.
sync_alt
Both tools keep every option preconfigured and swap which is live — Claude via the X_ prefix, OpenCode via the provider map. Different syntax, identical invariant.
MANY · ACCOUNTS · PROVIDERS · HARNESS 20 / 21
21 / 21 · CHECKLIST

Tune For Your Stack.

terminal Claude Code
  • check_circleOne config dir per account (CLAUDE_CONFIG_DIR); symlink the shared six (CLAUDE.md, agents, commands, docs, skills, rules).
  • check_circleKeep credentials/settings/projects/plugins real per account; aliases in your shell's rc file; /login once, verify with /status.
  • check_circleAuth per account in its settings.json env — API key, Bedrock, Vertex, or GLM endpoint; keep inactive providers X_-prefixed, activate per project in settings.local.json.
hub OpenCode
  • check_circleOPENCODE_CONFIG / OPENCODE_CONFIG_DIR per account; point instructions at the same CLAUDE.md + rules/*.md.
  • check_circlePredefine providers in one provider map — Zen (opencode/<model>) and custom GLM; switch by flipping model or /connect; keys via {env:…}.
compare_arrows Cross-tool
  • check_circleSkills auto-port (zero config); agents//commands/ need an OpenCode-format rewrite.
  • check_circleOne source of truth, edited once, inherited everywhere.
IDENTITY IS A DIRECTORY · THE CREDENTIAL LIVES INSIDE IT
MANY · ACCOUNTS · PROVIDERS · HARNESS 21 / 21
01 / 21
navigate  ·  F fullscreen  ·  S notes  ·  ? help  ·  G go to
Go to Enter
// KEYBOARD SHORTCUTS

Deck Controls

Space PgDnNext slide
PgUpPrevious slide
HomeFirst slide
EndLast slide
19Quick jump to slide N (single digit)
G then number + EnterJump to slide N (1–21)
F or Cmd+EnterToggle fullscreen
EscExit fullscreen / close help
SToggle speaker notes
BBlank screen (blackout)
?Toggle this help
Click right halfNext slide
Click left halfPrevious slide
Swipe (touch)Next / previous
Press ? or Esc to close