From 0239e7d4739bd6e884d247fabe5788bffeb15a1f Mon Sep 17 00:00:00 2001 From: Eric Wang Date: Mon, 27 Jul 2026 09:30:05 -0700 Subject: [PATCH] Account identity for multi-account credential overlays MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit One ~/.claude used to imply one account; deva-style runners bind-mount a different .credentials.json per container over the same shared config home, and the account-scoped caches bled across accounts: B rendered A's 5h/7d bars whenever A fetched last, profile.cache stuck to the first account for 24h. Tokens rotate, so the credentials file cannot identify itself — the runner says who the session is. - STATUSLINE_ACCOUNT (explicit) or DEVA_AUTH_TAG (deva --auth-with) resolve to an account tag; sanitized before touching any path - user segment renders @tag chip; tag beats profile display name (two accounts can carry the same human name) - account state moves to accounts// under the shared statusline dir: same-account sessions share one fetch, different accounts stop clobbering each other; auth-default and explicit CLAUDE_DATA_DIR / CLAUDE_CACHE_DIR overrides change nothing - chip also renders for api-key/custom-endpoint sessions that skip the OAuth quota block — the sessions only a tag can tell apart - legacy-state migration never lands in a tagged account dir - tests: 3 unit + 6 integration; helpers unset host DEVA_AUTH_TAG so suites running inside tagged deva containers stay hermetic Co-Authored-By: Claude Fable 5 --- CHANGELOG.md | 22 ++++++++++ README.md | 2 + statusline.sh | 61 +++++++++++++++++++++++--- t/helpers.bash | 5 +++ t/statusline.bats | 106 ++++++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 189 insertions(+), 7 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index bb7107a..95b21f7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,27 @@ # Changelog +## Unreleased + +**New: account identity for multi-account credential overlays.** One +`~/.claude` used to imply one account; deva-style runners broke that by +bind-mounting a different `.credentials.json` per container over the same +shared config home. The "account-scoped" caches (`usage.cache`, +`profile.cache`, `usage.jsonl`) then bled across accounts: B rendered A's +5h/7d bars whenever A fetched last, and the profile stuck to whichever +account fetched first for 24h. The credentials file itself carries no +stable identity (tokens rotate), so the runner must say who the session +is: `STATUSLINE_ACCOUNT` (explicit) or `DEVA_AUTH_TAG` (set by deva from +`--auth-with`). When present, the user segment shows an `@tag` chip +(`[MAX|@work]`, tag beats the profile display name — two accounts can +carry the same human name) and account state moves to +`accounts//` under the shared statusline dir: same-account sessions +still share one fetch, different accounts stop clobbering each other. +`auth-default` (single-account) changes nothing; an explicit +`CLAUDE_DATA_DIR`/`CLAUDE_CACHE_DIR` override is respected verbatim; tags +are sanitized to a filesystem-safe charset before touching a path. The +chip also renders for API-key/custom-endpoint sessions, which skip the +OAuth quota block — exactly the sessions only a tag can tell apart. + ## v0.18.0 — 2026-07-15 — freeze-safe cache expiry deadline, 7d hybrid reset **Fix: the 7d pressure suffix no longer decays in a frozen frame.** The diff --git a/README.md b/README.md index 3ffd880..aa9d404 100644 --- a/README.md +++ b/README.md @@ -294,6 +294,8 @@ run. Setting only `CLAUDE_CACHE_DIR` keeps the legacy single-dir behavior. | `CLAUDE_7D_WORKDAYS` | unset | Skip weekends in the 7d pace deadline — quota you won't spend Sat/Sun no longer counts against runway (opt-in; the limit itself stays calendar-based) | | `CLAUDE_DATA_DIR` | `~/.claude/statusline` | Account-scoped cache + usage log location | | `CLAUDE_CACHE_DIR` | `$CLAUDE_DATA_DIR/sessions` | Per-session cache-health state | +| `STATUSLINE_ACCOUNT` | unset | Account label for multi-account setups: renders an `@label` chip and moves account caches to `accounts/