Which Claude account a worker bills — oauthToken (k8rhz)
CLAUDECODEOAUTHTOKEN is a long-lived subscription credential that decides WHICH SEAT a claude worker bills. It used to reach every spawned worker by plain inheritance: T603's least-privilege env
CLAUDE_CODE_OAUTH_TOKEN is a long-lived subscription credential that decides WHICH SEAT a claude
worker bills. It used to reach every spawned worker by plain inheritance: T603's least-privilege env
scoping only recognized *_API_KEY / *_TOKEN_KEY names, and this one is neither, so the account a
fan-out wave spent was whichever the launching shell happened to export — invisibly, and differently
depending on how the session was started.
It is now credential-shaped (isProviderCredentialEnvKey also matches *_OAUTH_TOKEN) and is NOT
on the claude allowlist, so buildScopedChildEnv strips it from every spawned worker. With no
token in the child env the worker falls back to the keychain login — the same account claude uses
interactively. To pin a specific seat, pass it explicitly:
import { makeClaudeAdapter } from './src/adapters/CliAgentAdapter.ts';
// no oauthToken: the worker sees no token at all and uses the keychain login
const defaultWorker = makeClaudeAdapter({ model: 'claude-sonnet-5' });
// explicit seat: injected via envSet, applied AFTER the credential strip
const pinnedWorker = makeClaudeAdapter({
model: 'claude-sonnet-5',
oauthToken: process.env['MY_SECOND_SEAT_TOKEN'] ?? '',
});The scoping is covered with no network call by:
npm run selftest:claude-oauth-token-scopingKnown limitations and deferred work:
- There is deliberately no env default. Reading
CLAUDE_CODE_OAUTH_TOKENfromprocess.envinside the factory would re-create the ambient inheritance this change removes, one layer up. The caller names the seat or the worker uses the keychain. - One seat per dispatch is still all the fleet can pick.
oauthTokenis the seam only; selecting a different account per worker across one fan-out iskgjhf, and what a seat looks like when its quota runs out has not been measured (kzdc7). - The
--bgworker is out of reach of this scoping. Aclaude --bgjob is owned by the CLI's daemon, so it inherits the DAEMON's environment rather than the one Cyberine builds — the same reason that path refuses to run at all when a metered key is reachable (assertMeteredEnvReachable). Its account is decided by the daemon's own environment. aider/qwen/crushstill inherit it, along with every other provider credential: their credential cannot be determined from the command alone, so they keep full inheritance by T603's directive (breaking a worker's auth is worse than an over-broad env). Unchanged here, and asserted by the smoke so it stays a known gap rather than an accident.
Where a worker's CLAUDE_CODE_* settings came from — toolingSnapshot.workerEnv (kg4pt)
A spawned claude worker inherits the orchestrator's environment verbatim apart from provider credentials (buildScopedChildEnv). A Claude Code session exports its settings.json env block, so a...
Background fleet worker — claude --bg (k56eq)
The default claude build worker is an opaque claude -p child: nothing can open it, steer it, or outlive the orchestrator that spawned it. CYBERINECLAUDEWORKERMODE=bg swaps that ONE worker for a...