Skip to content

feat: add Claude subscription OAuth support#697

Merged
ericleepi314 merged 1 commit into
mainfrom
feat/claude-subscription-oauth
Jul 12, 2026
Merged

feat: add Claude subscription OAuth support#697
ericleepi314 merged 1 commit into
mainfrom
feat/claude-subscription-oauth

Conversation

@ericleepi314

Copy link
Copy Markdown
Collaborator

Summary

  • add Claude Pro/Max PKCE login with secure token persistence, refresh, status, and logout
  • route Anthropic through subscription Bearer auth with required request/tool adaptations while preserving API-key precedence
  • report subscription usage as zero metered API cost and document Anthropic support caveat

Test plan

  • .venv/bin/pytest -q tests/test_anthropic_subscription.py tests/entrypoints/test_startup_validation.py tests/test_providers.py tests/test_cost_tracker.py tests/test_headless_cli.py tests/test_init_integration.py (88 passed)
  • .venv/bin/pytest -q tests (2466 passed + 17 subtests before a pre-existing long-running async test was interrupted after 3m51s; no failures)
  • git diff --check
  • python -m compileall on changed Python modules

Note

Anthropic does not officially support using Claude Pro/Max subscriptions from third-party clients. The CLI displays this warning and requires explicit confirmation before OAuth login.

@ericleepi314 ericleepi314 merged commit 87f057b into main Jul 12, 2026
2 checks passed
@ericleepi314 ericleepi314 deleted the feat/claude-subscription-oauth branch July 12, 2026 17:15
ericleepi314 added a commit that referenced this pull request Jul 12, 2026
* feat: add OpenAI ChatGPT-subscription support (Sign in with ChatGPT)

Use OpenAI models via a ChatGPT Plus/Pro plan instead of metered API
billing — the mechanism OpenCode's openai plugin implements and the
Codex CLI's official OAuth app provides.

- src/auth/openai_subscription.py: authorization-code+PKCE against
  auth.openai.com with a localhost:1455 callback, device-code flow for
  headless boxes, import-from-Codex-CLI, form-urlencoded token exchange/
  refresh (lock + rotation-safe), JWT account-id extraction, 0600
  atomic credential store at ~/.clawcodex/openai-oauth.json.
- src/providers/openai_responses.py: Responses-API wire format —
  Anthropic-format messages → input items (function_call/
  function_call_output/reasoning replay with ids stripped, the Codex
  convention), flat function tools, SSE parsing, usage mapping with
  billing_mode=subscription (/bin/zsh cost via the #697 hook).
- OpenAIProvider: subscription mode (active when no API key + stored
  OAuth) streams from chatgpt.com/backend-api/codex/responses with
  ESC-abort worker/queue parity, 401→refresh-once retry, encrypted
  reasoning replayed across turns via raw_content_blocks passthrough.
- Foreign-provider strips: Chat-Completions converter, Anthropic and
  Minimax providers drop the passthrough blocks (mid-session /model
  switches); Gemini drops unknown blocks by construction.
- provider_has_credentials(): shared gate for startup validation and
  BOTH agent-server gates — also fixes #697's Claude subscription
  being rejected by the TUI session-init/set_provider api-key checks.
- Model configs for gpt-5.5/5.4/5.4-mini/5.3-codex-spark (272K/128K
  windows) + legacy gpt rows; subscription model list in login/picker.
- CLI: clawcodex login openai→subscription (browser/device-code/import),
  clawcodex logout openai, config status line.

Validated live against the ChatGPT backend: single-turn with custom
instructions+tools, multi-turn replay (with and without reasoning
items), headless -p runs incl. Bash tool loop, and the agent-server
gate in both directions.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* fix: critic fast-follows for ChatGPT subscription

- Abort-path test: ESC mid-stream raises AbortError and the guard's
  close-on-abort listener closes the httpx response (critic MAJOR).
- Honor /effort on the subscription path: the agent-server's
  _EffortProvider injects extra_body.reasoning_effort — map it to
  reasoning.effort with xhigh/max clamped to high (general gpt-5.x
  models advertise low/medium/high).
- Construct the provider from load_credentials() presence only —
  get_valid_credentials() could do a blocking 30s token refresh at
  startup / every model switch; the request path already refreshes.
- Warn at login when an exported OPENAI_API_KEY shadows the
  subscription.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
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.

1 participant