Summary
Two subscription providers are named after their internals, not after what the user pays for: openai-codex (a ChatGPT Plus/Pro subscription) and claude-sdk-oauth (a Claude Pro/Max subscription). Users cannot tell them apart from the metered API-key lanes openai and anthropic, which is a recurring source of confusion.
Rename them to chatgpt-subscription and anthropic-subscription, across every surface a user reads or types, without regressing anyone who is already logged in.
Expected (ideal state)
An existing user upgrades and: stays logged in; keeps their default model, favorites, thinking levels and service tiers; resumes old sessions on the same model; keeps hand-edited models.json overrides working; sees the new names everywhere; and if they type an old id, gets an error that names the new one.
Scope
Renamed: provider id, display name, the claudeSdkOauthProvider settings key, the per-account directory, all user-facing strings, and (separately committed) internal symbols, files and the extension directory.
NOT renamed: the api id openai-codex-responses; CLAUDE_CODE_OAUTH_TOKEN*; the API-key providers openai/anthropic; the npm package @anthropic-ai/claude-agent-sdk; and seven persisted tokens (session binding entry + its sidecar filename, tool-watch type, affinity key, managed sentinel, compact entry type, compact-boundary diagnostic).
Defects found while planning that a naive rename would ship silently
- The managed sentinel is derived, not literal.
managedSentinelMaterial(providerId) returns \${providerId}-managed` (packages/ai/src/auth/pool/slots.ts:384) and repairPoisonedPoolSlotscalls it with the auth.json top-level key. Moving that key makes pool repair stop matching stored sentinels, so a pooled user gets a slot that can never authenticate and is hidden fromlistAccounts. isManagedSentinelSlot` must accept both spellings.
PROVIDER_PRECEDENCE lists the old id first. packages/coding-agent/src/core/retry-fallback/expansion.ts declares ["claude-sdk-oauth","anthropic","kimi-coding"] above a comment stating absent providers sort alphabetically last. A rename that misses this table drops the subscription lane behind the metered anthropic lane.
- Provider id, api id and baseUrl are one constant for the Anthropic lane (
claude-sdk-oauth/index.ts), and prompt-cache-ttl.ts:358 switches on that api id — so renaming the provider silently renames the wire dialect. The api constant must be split first.
- Session JSONL is already truncate-rewritten by senpi (
session-manager.ts:1145), so normalized ids will reach disk through the existing path; that is expected, not a violation.
Acceptance criteria
- Legacy credentials, settings, overrides and sessions all resolve under the new ids, proven by fixture tests AND a real-CLI run on a seeded long-time-user profile.
- Rung ORDER is preserved wherever the subscription lane was deliberately placed ahead of a metered lane.
- No user-facing string contains a legacy id, enforced by a guard test with an explicit allowlist for the frozen tokens.
- A typed legacy id fails with a message naming the new id; config written by an earlier version never hard-errors.
Plan
Decision-complete plan with 23 implementation todos and 4 final verifiers is held locally; evidence held locally.
Summary
Two subscription providers are named after their internals, not after what the user pays for:
openai-codex(a ChatGPT Plus/Pro subscription) andclaude-sdk-oauth(a Claude Pro/Max subscription). Users cannot tell them apart from the metered API-key lanesopenaiandanthropic, which is a recurring source of confusion.Rename them to
chatgpt-subscriptionandanthropic-subscription, across every surface a user reads or types, without regressing anyone who is already logged in.Expected (ideal state)
An existing user upgrades and: stays logged in; keeps their default model, favorites, thinking levels and service tiers; resumes old sessions on the same model; keeps hand-edited
models.jsonoverrides working; sees the new names everywhere; and if they type an old id, gets an error that names the new one.Scope
Renamed: provider id, display name, the
claudeSdkOauthProvidersettings key, the per-account directory, all user-facing strings, and (separately committed) internal symbols, files and the extension directory.NOT renamed: the api id
openai-codex-responses;CLAUDE_CODE_OAUTH_TOKEN*; the API-key providersopenai/anthropic; the npm package@anthropic-ai/claude-agent-sdk; and seven persisted tokens (session binding entry + its sidecar filename, tool-watch type, affinity key, managed sentinel, compact entry type, compact-boundary diagnostic).Defects found while planning that a naive rename would ship silently
managedSentinelMaterial(providerId)returns\${providerId}-managed`(packages/ai/src/auth/pool/slots.ts:384) andrepairPoisonedPoolSlotscalls it with the auth.json top-level key. Moving that key makes pool repair stop matching stored sentinels, so a pooled user gets a slot that can never authenticate and is hidden fromlistAccounts.isManagedSentinelSlot` must accept both spellings.PROVIDER_PRECEDENCElists the old id first.packages/coding-agent/src/core/retry-fallback/expansion.tsdeclares["claude-sdk-oauth","anthropic","kimi-coding"]above a comment stating absent providers sort alphabetically last. A rename that misses this table drops the subscription lane behind the meteredanthropiclane.claude-sdk-oauth/index.ts), andprompt-cache-ttl.ts:358switches on that api id — so renaming the provider silently renames the wire dialect. The api constant must be split first.session-manager.ts:1145), so normalized ids will reach disk through the existing path; that is expected, not a violation.Acceptance criteria
Plan
Decision-complete plan with 23 implementation todos and 4 final verifiers is held locally; evidence held locally.