docs(claude-code): document oauthToken config and the macOS SDK bug
After investigating, the @anthropic-ai/claude-agent-sdk has a macOS- specific upstream bug that breaks subscription auth: the SDK isolates CLAUDE_CONFIG_DIR per invocation and tries to copy ~/.claude/.credentials.json, which doesn't exist on macOS (creds live in the Keychain). The spawned CLI then misclassifies the OAuth token as an API key and bills against API credits. Changes: - ClaudeCodeConfig.oauthToken: new optional config field that exports CLAUDE_CODE_OAUTH_TOKEN before invoking the SDK. Wired up and ready for when the upstream bug is fixed; currently affected by it on macOS. - README, JSDoc: clearly document the limitation. API-key mode works reliably; subscription mode is broken on macOS pending upstream fix. - billing_error message: explain the bug and recommend ClaudeProvider + ANTHROPIC_API_KEY as the workaround so users can self-diagnose. - examples/claude-code.ts: read CLAUDE_CODE_OAUTH_TOKEN from env so the smoke test attempts the subscription path when configured. No code changes silently in flight — when the SDK fixes the Keychain handling, subscribers will Just Work without any code changes here.
This commit is contained in:
39
README.md
39
README.md
@@ -52,27 +52,45 @@ const claude = new ClaudeProvider({
|
||||
});
|
||||
```
|
||||
|
||||
### Claude Code (subscription via local CLI)
|
||||
### Claude Code (via local CLI)
|
||||
|
||||
`ClaudeCodeProvider` wraps `@anthropic-ai/claude-agent-sdk`, which authenticates through the local `claude` CLI. This is the supported path for **Claude Pro / Max subscribers** who don't have a console API key.
|
||||
`ClaudeCodeProvider` wraps `@anthropic-ai/claude-agent-sdk`, which spawns the local `claude` CLI under the hood.
|
||||
|
||||
**Setup:** install the CLI and run `claude login` once. No API key required.
|
||||
> **Honest status:** the **API-key mode** (Mode B below) works reliably. The **subscription mode** (Mode A) is currently broken on macOS due to an upstream bug in `@anthropic-ai/claude-agent-sdk` — the SDK isolates `CLAUDE_CONFIG_DIR` per invocation and tries to copy a `~/.claude/.credentials.json` file that doesn't exist on macOS (Claude Code stores credentials in the Keychain). The provider misidentifies the OAuth token and bills it as an API key, so subscribers without API credits hit "Credit balance is too low".
|
||||
>
|
||||
> If you have a Pro/Max subscription and need programmatic access today: use the direct [`ClaudeProvider`](#claude-anthropic-api) with an API key, or wait for the upstream SDK fix. The `oauthToken` field is wired up and ready for when Anthropic fixes the Keychain handling.
|
||||
|
||||
**Mode A — Claude Pro/Max subscription** *(see status note above)*:
|
||||
|
||||
```bash
|
||||
# One-time: install the CLI, then mint a long-lived OAuth token.
|
||||
# `claude login` alone is NOT enough — Anthropic gates SDK use behind setup-token.
|
||||
claude setup-token
|
||||
```
|
||||
|
||||
```typescript
|
||||
import { ClaudeCodeProvider } from 'simple-ai-provider';
|
||||
|
||||
const claude = new ClaudeCodeProvider({}); // uses local credentials
|
||||
await claude.initialize();
|
||||
|
||||
const response = await claude.complete({
|
||||
messages: [{ role: 'user', content: 'Hello!' }]
|
||||
const claude = new ClaudeCodeProvider({
|
||||
oauthToken: process.env.CLAUDE_CODE_OAUTH_TOKEN // from `claude setup-token`
|
||||
});
|
||||
```
|
||||
|
||||
You can still pass `apiKey` to override (it's set as `ANTHROPIC_API_KEY` for the SDK). Optional config:
|
||||
**Mode B — Console API key** (billed per-token, works reliably):
|
||||
|
||||
```typescript
|
||||
const claude = new ClaudeCodeProvider({
|
||||
apiKey: process.env.ANTHROPIC_API_KEY
|
||||
});
|
||||
```
|
||||
|
||||
If both are present, `oauthToken` wins. Either field can also be picked up from the environment (`CLAUDE_CODE_OAUTH_TOKEN` / `ANTHROPIC_API_KEY`) without being passed explicitly.
|
||||
|
||||
Optional config:
|
||||
|
||||
```typescript
|
||||
new ClaudeCodeProvider({
|
||||
apiKey: '...',
|
||||
defaultModel: 'sonnet', // 'sonnet' | 'opus' | 'haiku' | 'inherit' | full model ID
|
||||
maxTurns: 1, // 1 for plain completion; raise for agent/tool loops
|
||||
allowedTools: [], // tool names to enable (default: none)
|
||||
@@ -80,10 +98,11 @@ new ClaudeCodeProvider({
|
||||
});
|
||||
```
|
||||
|
||||
**Trade-offs to know:**
|
||||
**Trade-offs even when it works:**
|
||||
- Requires `claude` CLI installed on the host. Not ideal for typical server deployments.
|
||||
- Higher latency than the direct API (spawns a CLI process per request).
|
||||
- Streaming yields text as the SDK emits successive assistant messages, not token-by-token deltas.
|
||||
- If you have an API key, [`ClaudeProvider`](#claude-anthropic-api) is the simpler, faster choice.
|
||||
|
||||
### OpenAI
|
||||
|
||||
|
||||
Reference in New Issue
Block a user