Skip to content

Show which credential a coding session actually used (subscription vs per-token API key) and what the engine really is #248

Description

@serge-ivo

The ask

A user must be able to see, for a running session, which credential the engine actually used
their Claude subscription, or an API key billed per token — and what the engine actually is (a
child process, not a tmux pane). Today both are unanswerable from the UI.

Credential: the setting is visible, the OUTCOME is not

lib/coding-engines.ts:96 defines four modes, chosen per engine preset:

mode what happens
auto stored claude setup-token if saved, else the machine's own login
machine inject nothing — whatever the runner machine has
subscription inject CLAUDE_CODE_OAUTH_TOKEN, and remove ANTHROPIC_API_KEY
api-key inject the vault provider key (per-token billing)

The console lets you pick one (EnginesModal.tsx:106-112, which even labels api-key
"per-token billing"). Nothing reports what was resolved. For auto and machine — the default
is auto — the answer is decided on the user's machine at spawn time and never travels back.

This has already gone wrong once, and the fix is documented in headless.ts:5:

a developer with ANTHROPIC_API_KEY in their shell handed it to every engine, and Claude Code
prefers an API key over the subscription token — so choosing "subscription" injected
CLAUDE_CODE_OAUTH_TOKEN and then silently lost, billing per token anyway.

That was fixed by letting an empty overlay value mean remove (mergeEnv). But the fix only
covers the two explicit modes. auto and machine still inherit the shell wholesale, so a
lingering ANTHROPIC_API_KEY silently bills per token with no signal anywhere — not in the
session view, not in diagnostics, not in Usage.

The money question ("am I burning API credits or using the subscription I already pay for?")
currently has no answer in the product.

Runtime: "is this tmux?"

Coder sessions have not used tmux since c94642f (2026-06-26) — they are child processes driven
over stream-json. But every session still records tmuxSession: "pags-claude-csess_…", diagnostics
still report pagsTmuxTotal, and there is still a "Kill tmux" control (#247). A user cannot tell
what their engine actually is, and the surface actively suggests the wrong answer.

Proposal

The runner already computes the final merged env, so it knows both answers at spawn time.

  • Report per session: authMode (the preset's setting) and authResolved — what the process
    actually got: subscription (OAuth token present, no API key), api-key (API key present), or
    machine-login (neither). Derive it from the merged env, never from the setting alone.
  • Report engineRuntime: "child-process" alongside it, so the tmux question is answerable rather
    than implied.
  • Surface both in the session header / diagnostics, and make a mismatch loud: preset says
    subscription but an ANTHROPIC_API_KEY survived into the env ⇒ warn, because that is the
    documented silent-billing case.
  • Never send the key or token itself — presence and mode only. This is a transparency feature,
    not a credential channel.
  • Worth a line in Usage too: the token/cost ledger is where someone goes when the bill surprises
    them, and it currently cannot distinguish engine-side API-key spend from platform BYOK spend.

Verification

  • A session started with a shell ANTHROPIC_API_KEY and preset auto reports
    authResolved: "api-key" and warns.
  • The same with preset subscription reports subscription and does not warn (the key is removed).
  • machine with no credentials reports machine-login.
  • No response on any surface contains the key or token value.

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions