Skip to content

[Bugfix #985] consult -m claude: authenticate against subscription, not metered API#986

Merged
waleedkadous merged 7 commits into
mainfrom
builder/bugfix-985
Jun 4, 2026
Merged

[Bugfix #985] consult -m claude: authenticate against subscription, not metered API#986
waleedkadous merged 7 commits into
mainfrom
builder/bugfix-985

Conversation

@waleedkadous
Copy link
Copy Markdown
Contributor

@waleedkadous waleedkadous commented Jun 4, 2026

Fixes #985

Problem

consult -m claude runs CMAP/review traffic on the metered Opus API instead of the Claude subscription. runClaudeConsultation() built the Agent SDK subprocess env by copying all of process.env, including ANTHROPIC_API_KEY/ANTHROPIC_AUTH_TOKEN. The Agent SDK prioritizes the API key over CLAUDE_CODE_OAUTH_TOKEN, so the subprocess silently authenticated as a metered key rather than the subscription. Reported by an external adopter (~$150/day on a heavy dev day).

Fix

Scoped to consult's Claude subprocess env only (packages/codev/src/commands/consult/index.ts):

  • Extracted env-building into a pure, exported helper buildClaudeConsultEnv(processEnv).
  • When CLAUDE_CODE_OAUTH_TOKEN is set, delete ANTHROPIC_API_KEY and ANTHROPIC_AUTH_TOKEN from the local env copy — never from global process.env. Other callers that need the API key (persona, dev:local) are unaffected.
  • When CLAUDE_CODE_OAUTH_TOKEN is not set, behavior is unchanged (fall back to the API key) so CI / key-only environments still authenticate.

Test

__tests__/claude-auth-env.test.ts (4 cases):

  • OAuth token set → API/auth tokens stripped, OAuth token + unrelated vars preserved.
  • No OAuth token → API key preserved (CI / key-only).
  • Source process.env is never mutated (deletion scoped to the copy).
  • Undefined values dropped while copying.

Verification: consult suite 79/79 pass, tsc --noEmit clean.

Effect & caveat

CMAP/review traffic runs on the Claude subscription instead of the metered Opus API — material saving (~$150/day reported on a heavy day).

Caveat (documented in consult.md, not a blocker): dedicated Agent-SDK subscription credit starts 2026-06-15; before then, subscription auth draws from the interactive Max quota.

Scope / notes

Isolated change in consult/index.ts (Claude-path env) + regression test + doc note. area/consult. Distinct from the Gemini auth work (#778) — this is the Claude lane.

Adjacent and intentionally out of scope: line ~519 hardcodes model: 'claude-opus-4-6'. Noted, not touched.

…scription

Strip ANTHROPIC_API_KEY/ANTHROPIC_AUTH_TOKEN from the Claude Agent SDK
subprocess env when CLAUDE_CODE_OAUTH_TOKEN is present, so consult
authenticates against the Claude subscription rather than the metered
Opus API. The SDK prioritizes ANTHROPIC_API_KEY over the OAuth token,
which silently routed CMAP/review traffic to the metered API.

- Extract env-building into pure exported helper buildClaudeConsultEnv()
- Deletion scoped to the local subprocess env copy, never process.env,
  so other callers (persona, dev:local) are unaffected
- Preserve the API key when no OAuth token is set (CI / key-only envs)
- Regression test covering both auth paths + no-mutation invariant
- Doc note in consult.md incl. 2026-06-15 subscription-credit caveat
@waleedkadous waleedkadous merged commit 7a6d334 into main Jun 4, 2026
6 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

consult -m claude bills metered Opus API instead of the Claude subscription (ANTHROPIC_API_KEY shadows CLAUDE_CODE_OAUTH_TOKEN)

1 participant