# Account roots are per-account, and continuity is junctioned, never linked

Status: accepted (2026-08-21)

Switching Anthropic accounts without logging out requires swapping `CLAUDE_CONFIG_DIR`:
Claude Code 2.1.239 holds exactly one account per config root, `/login` replaces it, and
`claude auth` offers only login/logout/status — measured, plus the published docs say the
same. So claude-spt gains **account roots**: adapter-owned config roots named after the
account they hold, selected by an **alt profile** that changes nothing but which root the
session launches against.

**One root per ACCOUNT, not per endpoint.** A per-endpoint root was the first design and is
rejected: credentials live in the root, so N endpoints would mean N logins of the same
account, which is disqualifying for the failover this feature exists to serve (run out of
tokens on one account, keep working on another). Per-endpoint separation of Claude Code's
own session state was the thing that layout bought, and it is not worth a login apiece —
per-endpoint memory and identity are spt's job at the mind layer, not the config root's.
Endpoints already share one root today.

**Continuity is shared by DIRECTORY JUNCTION into every account root** — `projects/`,
`todos/`, `file-history/`, `shell-snapshots/`, `session-env/`, one node-wide tree. This is
what lets a session started under one account be resumed under another, which is the whole
requirement: without a shared `projects/`, an account switch abandons the in-flight session,
because spt's resume passes `--resume <session_id>` and Claude Code reads that transcript
out of the active root.

**Credentials and `.claude.json` are REAL FILES in each root, never links.** Measured
2026-08-21: `.claude.json` is rewritten with a NEW FILE IDENTITY every ~15-25 seconds while
a session is live (eight consecutive samples, eight inodes, mtime advancing, size constant)
— it is written tmp-then-rename. A hard link or symlink at that path stops tracking on the
first rewrite and the two stores diverge SILENTLY from then on, which is worse than not
sharing at all: a token refresh would land in one store while the other rots. Junctions are
used for the directories because they are also the option that needs no elevation, where
file symlinks on Windows require Developer Mode — the failure mode ccs hits and papers over
with silent directory copies.

Refined at build time (2026-08-21), consistent with the rule above: `settings.json` is **copied**
into each account root, not linked. It is a file, so the elevation-free link form (a junction) does
not exist for it, and a hard link would sit in the same tmp-then-rename hazard class as
`.claude.json` — so a copy, taken once at init and honestly described as a snapshot, is the option
that cannot diverge silently. The authoring DIRECTORIES (`skills/`, `agents/`, `commands/`) are
junctioned from the primary root as planned.

Consequences taken deliberately: `history.jsonl` is a file, so it cannot join the shared
tree and stays per-account — an account switch does not carry prompt history, which is the
cheapest thing to lose. Every spawned role (session, resume, Psyche, echo-commune) moves
with the profile, since a failover that leaves the Psyche drawing on the exhausted account
is not a failover. The adapter seeds the root's trust store before launch, because trust is
per-config-root and an unseeded root does not fail — it HANGS on the dialog.

Rejected alternatives: copying credentials into per-endpoint roots and writing them back at
session end (two endpoints on one account clobber each other's refreshed token, silently —
the same divergence class the measurement just killed, with copies instead of links);
sharing `history.jsonl` by hard link (same rewrite hazard); and reproducing ccs's instance
manager, which maintains its roots on every launch and is the reason its launches are slow.
