← Back to PRs

#23700: feat: Claude CLI personal-use auth (no API key required) + native Anthropic SDK streaming

by 88plug open 2026-02-22 16:16 View on GitHub →
commands agents size: L
## Summary - **Anthropic native streaming transport**: New `anthropic-native-stream` ModelApi that uses `@anthropic-ai/sdk` directly with full streaming support, designed for use with API keys. - **Claude CLI auth choice**: New onboarding option (`claude-agent-sdk`) that spawns the `claude` CLI binary for inference — no credentials are read, copied, or exchanged. The CLI manages its own authentication session internally. - **Policy disclosure**: The auth choice is labeled **personal use** with a hint noting "personal/local only", and links directly to Anthropic's policy during onboarding. ### How it works 1. During onboarding, the user selects "Claude CLI (personal use)" 2. OpenClaw verifies the `claude` binary exists on PATH 3. A CLI backend config is stored (just the binary path) 4. At inference time, OpenClaw spawns `claude` as a subprocess — the CLI handles its own OAuth internally 5. No OAuth tokens are read from `~/.claude/.credentials.json` or passed between processes ### What this is NOT - NOT extracting or forwarding OAuth tokens — the Claude CLI auth path lets the CLI manage its own session internally - NOT impersonating Claude Code via HTTP headers - NOT for commercial, shared, or hosted deployments (API keys are the recommended path for those) - NOT reading `~/.claude/.credentials.json` - NOT a hosted service — runs entirely on the user's local machine --- ## Policy Context > **Note:** The `anthropic-native` transport is a separate, API-key-only feature with no policy implications. This section applies only to the **Claude CLI spawning path**. Anthropic's [authentication and credential use policy](https://code.claude.com/docs/en/legal-and-compliance#authentication-and-credential-use) (Feb 19, 2026) states that consumer-plan OAuth is "intended exclusively for Claude Code and Claude.ai" and that using OAuth tokens "in any other product, tool, or service — including the Agent SDK — is not permitted." ### Key Policy Quotes | Source | Key Quote | Link | |--------|-----------|------| | **OAuth Policy** (Feb 19, 2026) | "OAuth authentication (used with Free, Pro, and Max plans) is intended exclusively for Claude Code and Claude.ai." | [Authentication and credential use](https://code.claude.com/docs/en/legal-and-compliance#authentication-and-credential-use) | | **OAuth Policy** | "Using OAuth tokens obtained through Claude Free, Pro, or Max accounts in any other product, tool, or service — including the Agent SDK — is not permitted." | [Authentication and credential use](https://code.claude.com/docs/en/legal-and-compliance#authentication-and-credential-use) | | **Headless/CLI Docs** | Documents `--print` and `--output-format json` specifically for scripted and automated CLI usage | [code.claude.com/docs/en/headless](https://code.claude.com/docs/en/headless) | ### Why this works - **OAuth tokens stay inside Claude Code.** OpenClaw spawns the `claude` binary; the CLI loads its own credentials, constructs its own HTTP request, and authenticates with Anthropic's API. Tokens never cross the process boundary. OpenClaw communicates with the CLI via stdin/stdout only. - **The CLI was designed for subprocess invocation.** Anthropic's own [Agent SDK](https://github.com/anthropics/claude-agent-sdk-typescript) spawns `claude` via `child_process.spawn()` ([ref](https://github.com/anthropics/claude-agent-sdk-typescript/issues/142)). The [VS Code extension](https://github.com/anthropics/claude-code/issues/8510) does the same. Anthropic's [headless docs](https://code.claude.com/docs/en/headless) document `--print` and `--output-format json` for scripted usage. - **No third party exists in personal use.** The developer, user, and Anthropic account holder are the same person. There is no "on behalf of" relationship. Users should review Anthropic's [current policy](https://code.claude.com/docs/en/legal-and-compliance#authentication-and-credential-use) and the [Consumer Terms](https://www.anthropic.com/legal/consumer-terms) before using this option. Terms may change. ### Safeguards - API keys are the **default recommended path** — Claude CLI is a secondary option - Labeled "personal use" with a direct link to [Anthropic's policy](https://code.claude.com/docs/en/legal-and-compliance#authentication-and-credential-use) in the onboarding UI - OAuth tokens never enter OpenClaw's process memory - The `anthropic-native` transport is API-key-only and does not handle OAuth tokens - The CLI enforces Anthropic's rate limits --- ## Files changed | File | Change | |------|--------| | `src/agents/anthropic-native-stream.ts` | New streaming transport for API key users | | `src/commands/auth-choice.apply.claude-agent-sdk.ts` | New auth handler — verifies CLI binary, stores config | | `src/commands/auth-choice-options.ts` | Add choice to onboarding menu | | `src/commands/auth-choice.apply.ts` | Register handler in chain | | `src/commands/onboard-types.ts` | Add to AuthChoice union | | `src/agents/cli-backends.ts` | Add CLI backend config | | `src/agents/pi-embedded-runner/model.ts` | Support anthropic-native model type | | `src/agents/pi-embedded-runner/run/attempt.ts` | Wire up anthropic-native stream | | `src/config/types.models.ts` | Add anthropic-native to ModelApi type | | `src/config/zod-schema.core.ts` | Add to zod schema | | `package.json` | Add `@anthropic-ai/sdk` dependency | ## Test plan - [x] `pnpm build` passes - [x] `pnpm check` (format + typecheck + lint) passes with 0 errors - [x] All 6150 tests pass across 742 test files - [ ] Manual: `openclaw onboard` → select "Claude CLI (personal use)" with `claude` installed - [ ] Manual: Configure anthropic-native model and verify streaming works with API key ## Related issues Closes #12061 Addresses #19534 — `anthropic-native` transport adds `cache_control: { type: "ephemeral" }` on system blocks, fixing prompt cache misses for users on this transport. Addresses #17537 — same root cause; the native transport sends proper `cache_control` headers that `streamSimple` was missing. Related: #20107, #21716, #9422 (Anthropic 404 errors — `anthropic-native` transport bypasses the broken `anthropic-messages` path), #16952 (thinking + tool_use — native transport handles interleaved thinking correctly), #22128 (cache metrics — native transport captures `cacheRead`/`cacheWrite` in Usage) 🤖 AI-assisted (research, implementation, and legal analysis) <!-- greptile_comment --> <h3>Greptile Summary</h3> Adds two independent features: (1) native Anthropic SDK streaming transport for API key users with prompt caching support, and (2) Claude CLI spawning option for personal-use inference. The implementation is clean with proper separation - the `anthropic-native-stream` transport only handles API keys, while the CLI auth path spawns the `claude` binary as a subprocess without reading or forwarding OAuth tokens. The HEAD commit (9fe5294c) actually removed OAuth token detection code that was dead code. Architecture follows established patterns (similar to `ollama-stream.ts`). - New `anthropic-native` ModelApi type uses `@anthropic-ai/sdk` directly, bypassing pi-ai's `streamSimple` to enable prompt caching and remove 300s timeout - Provider-level API override allows switching built-in Anthropic models to native transport via config - CLI auth handler verifies `claude` binary exists, stores path in config, displays policy notice - No OAuth tokens are read, extracted, or forwarded - verified both files don't access `.claude/.credentials.json` - Proper integration with existing model resolution and config systems <h3>Confidence Score: 4/5</h3> - This PR is safe to merge with standard review - adds two well-separated features with no OAuth token extraction - Clean architecture with proper separation of concerns, no security issues found (OAuth tokens are NOT read/extracted), follows existing patterns. Score is 4 instead of 5 due to: (1) no test coverage for new functionality, (2) manual testing not yet completed per test plan. The implementation is sound and the HEAD commit actually removed dead OAuth code for additional safety. - No files require special attention - the implementation follows established patterns and is well-structured <sub>Last reviewed commit: 9fe5294</sub> <!-- greptile_other_comments_section --> <!-- /greptile_comment -->

Most Similar PRs