@askalf/dario 3.4.0 → 3.4.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +158 -139
- package/dist/cc-oauth-detect.d.ts +30 -14
- package/dist/cc-oauth-detect.js +62 -72
- package/dist/cc-template-data.json +1 -1
- package/dist/cc-template.d.ts +4 -4
- package/dist/cc-template.js +66 -31
- package/dist/cli.js +19 -5
- package/dist/proxy.d.ts +1 -1
- package/dist/proxy.js +72 -292
- package/package.json +4 -2
package/README.md
CHANGED
|
@@ -2,7 +2,9 @@
|
|
|
2
2
|
<h1 align="center">dario</h1>
|
|
3
3
|
<p align="center"><strong>Use your Claude subscription as an API. The only proxy that bills correctly.</strong></p>
|
|
4
4
|
<p align="center">
|
|
5
|
-
No API key needed. Your Claude Max/Pro subscription becomes a local API endpoint<br/>
|
|
5
|
+
No API key needed. Your Claude Max/Pro subscription becomes a local API endpoint<br/>
|
|
6
|
+
that any tool, SDK, or framework can use. Template replay makes every request<br/>
|
|
7
|
+
indistinguishable from real Claude Code — so your Max plan limits actually work.
|
|
6
8
|
</p>
|
|
7
9
|
</p>
|
|
8
10
|
|
|
@@ -17,8 +19,8 @@
|
|
|
17
19
|
<p align="center">
|
|
18
20
|
<a href="#quick-start">Quick Start</a> •
|
|
19
21
|
<a href="#openai-compatibility">OpenAI Compat</a> •
|
|
20
|
-
<a href="#cli-backend">CLI Backend</a> •
|
|
21
22
|
<a href="#usage-examples">Examples</a> •
|
|
23
|
+
<a href="#askalf">askalf</a> •
|
|
22
24
|
<a href="#trust--transparency">Trust</a> •
|
|
23
25
|
<a href="#faq">FAQ</a>
|
|
24
26
|
</p>
|
|
@@ -33,7 +35,9 @@ export ANTHROPIC_BASE_URL=http://localhost:3456 # or OPENAI_BASE_URL=http://lo
|
|
|
33
35
|
export ANTHROPIC_API_KEY=dario # or OPENAI_API_KEY=dario
|
|
34
36
|
```
|
|
35
37
|
|
|
36
|
-
Opus, Sonnet, Haiku — all models, streaming, tool use. **Zero dependencies.** ~2,
|
|
38
|
+
Opus, Sonnet, Haiku — all models, streaming, tool use. **Zero dependencies.** ~2,000 lines of TypeScript. Works with Cursor, Continue, Aider, LiteLLM, Hermes, OpenClaw, or any tool that speaks the Anthropic or OpenAI API. Auto-launches under [Bun](https://bun.sh) when available for TLS fingerprint fidelity. **Auto-detects OAuth config from your installed CC binary** so dario stays in sync forever — Anthropic can rotate client IDs and dario picks them up on the next run.
|
|
39
|
+
|
|
40
|
+
dario is built and maintained by [askalf](https://askalf.org) — the open-source foundation of the askalf agent platform. If you need more than a proxy, [see below](#askalf).
|
|
37
41
|
|
|
38
42
|
<table>
|
|
39
43
|
<tr>
|
|
@@ -44,7 +48,7 @@ Opus, Sonnet, Haiku — all models, streaming, tool use. **Zero dependencies.**
|
|
|
44
48
|
|
|
45
49
|
**Grok** (xAI)
|
|
46
50
|
|
|
47
|
-
*"Dario works great and is safe. Fully functional with OpenClaw / Hermes. Gives you Opus
|
|
51
|
+
*"Dario works great and is safe. Fully functional with OpenClaw / Hermes. Gives you Opus, Sonnet & Haiku using your existing Claude Max/Pro sub. No extra API key or billing needed. Streaming + tools work perfectly. 100% open-source, runs locally only, proper OAuth (PKCE), no telemetry. Highly recommended if you want a clean local proxy."*
|
|
48
52
|
|
|
49
53
|
</td>
|
|
50
54
|
<td width="33%" valign="top">
|
|
@@ -74,15 +78,13 @@ Opus, Sonnet, Haiku — all models, streaming, tool use. **Zero dependencies.**
|
|
|
74
78
|
</tr>
|
|
75
79
|
</table>
|
|
76
80
|
|
|
77
|
-
> **Need more than a proxy?** Dario solves the API access problem. If you need a full agent fleet — desktop control, browser automation, scheduling, custom tools, persistent memory — check out the [askalf platform](https://askalf.org). Same team, different execution model that solves the proxy ceiling entirely.
|
|
78
|
-
|
|
79
81
|
---
|
|
80
82
|
|
|
81
83
|
## Why dario
|
|
82
84
|
|
|
83
85
|
Most Claude subscription proxies have a critical billing problem: **Anthropic classifies their requests as third-party and routes all usage to Extra Usage billing** — even when you have Max plan limits available. You're paying for your subscription twice.
|
|
84
86
|
|
|
85
|
-
dario is the only proxy that solves this. Instead of transforming your requests signal by signal, dario uses **template replay** — it replaces the entire request with Claude Code's exact template
|
|
87
|
+
dario is the only proxy that solves this. Instead of transforming your requests signal by signal, dario uses **template replay** — it replaces the entire request with Claude Code's exact template. 25 tool definitions, 25KB system prompt, exact field order, exact beta headers, exact metadata structure. Only your conversation content is preserved. When Bun is installed, dario auto-relaunches under Bun for TLS fingerprint fidelity matching CC's runtime. Anthropic's classifier sees a genuine Claude Code request because it IS one.
|
|
86
88
|
|
|
87
89
|
| | dario | Other proxies |
|
|
88
90
|
|---|---|---|
|
|
@@ -95,15 +97,14 @@ dario is the only proxy that solves this. Instead of transforming your requests
|
|
|
95
97
|
<details>
|
|
96
98
|
<summary><strong>vs competitors</strong></summary>
|
|
97
99
|
|
|
98
|
-
| Feature | dario | Meridian
|
|
100
|
+
| Feature | dario | Meridian | CLIProxyAPI |
|
|
99
101
|
|---------|-------|---------|------------|
|
|
100
|
-
| Template replay (undetectable) | **Yes** | No |
|
|
102
|
+
| Template replay (undetectable) | **Yes** | No | No |
|
|
101
103
|
| Direct OAuth (streaming, tools) | **Yes** | Yes (SDK-based) | No |
|
|
102
|
-
| CLI fallback (rate limit bypass) | **Yes** | No | Yes (only mode) |
|
|
103
104
|
| OpenAI API compat | **Yes** | Yes | Yes |
|
|
104
105
|
| Orchestration sanitization | **Yes** | Yes | No |
|
|
105
106
|
| Token anomaly detection | **Yes** | Yes | No |
|
|
106
|
-
| Codebase size | ~2,
|
|
107
|
+
| Codebase size | ~2,000 lines | ~9,000 lines | Platform |
|
|
107
108
|
| Dependencies | 0 | Many | Many |
|
|
108
109
|
| Setup | 2 commands | Config + build | Config + dashboard |
|
|
109
110
|
|
|
@@ -113,15 +114,15 @@ dario is the only proxy that solves this. Instead of transforming your requests
|
|
|
113
114
|
|
|
114
115
|
You pay $100-200/mo for Claude Max or Pro. But that subscription only works on claude.ai and Claude Code. If you want to use Claude with **any other tool** — Cursor, Continue, Aider, your own scripts — you need a separate API key with separate billing.
|
|
115
116
|
|
|
116
|
-
**
|
|
117
|
+
**dario fixes this.** It creates a local proxy that translates API key auth into your subscription's OAuth tokens. Your subscription handles the billing. No API key needed.
|
|
117
118
|
|
|
118
|
-
**
|
|
119
|
+
**Note:** Claude subscriptions have [usage limits](https://support.claude.com/en/articles/11647753-how-do-usage-and-length-limits-work) that reset on rolling 5-hour and 7-day windows. You can check your utilization via Claude Code's `/usage` command or the [statusline](https://code.claude.com/docs/en/statusline).
|
|
119
120
|
|
|
120
121
|
## Quick Start
|
|
121
122
|
|
|
122
123
|
### Prerequisites
|
|
123
124
|
|
|
124
|
-
[Claude Code](https://docs.anthropic.com/en/docs/claude-code/overview) installed and logged in (recommended). Dario detects your existing Claude Code credentials automatically.
|
|
125
|
+
[Claude Code](https://docs.anthropic.com/en/docs/claude-code/overview) installed and logged in (recommended). Dario detects your existing Claude Code credentials automatically and also auto-extracts the current OAuth client config from the installed CC binary so dario stays in sync with whatever CC version you have, even when Anthropic rotates client IDs.
|
|
125
126
|
|
|
126
127
|
If Claude Code isn't installed, dario runs its own OAuth flow — opens your browser, you authorize, done.
|
|
127
128
|
|
|
@@ -180,46 +181,13 @@ continue # in VS Code, set base URL in config
|
|
|
180
181
|
python my_script.py
|
|
181
182
|
```
|
|
182
183
|
|
|
183
|
-
## CLI Backend
|
|
184
|
-
|
|
185
|
-
If you're getting rate limited on Opus or Sonnet, use `--cli` mode. This routes requests through the Claude Code binary instead of hitting the API directly. Claude Code has priority routing that continues working even when direct API calls return 429.
|
|
186
|
-
|
|
187
|
-
```bash
|
|
188
|
-
dario proxy --cli # Opus works even when rate limited
|
|
189
|
-
dario proxy --cli --model=opus # Force Opus + CLI backend
|
|
190
|
-
```
|
|
191
|
-
|
|
192
|
-
```
|
|
193
|
-
dario — http://localhost:3456
|
|
194
|
-
|
|
195
|
-
Your Claude subscription is now an API.
|
|
196
|
-
|
|
197
|
-
Usage:
|
|
198
|
-
ANTHROPIC_BASE_URL=http://localhost:3456
|
|
199
|
-
ANTHROPIC_API_KEY=dario
|
|
200
|
-
|
|
201
|
-
Backend: Claude CLI (bypasses rate limits)
|
|
202
|
-
Model: claude-opus-4-6 (all requests)
|
|
203
|
-
```
|
|
204
|
-
|
|
205
|
-
**Trade-offs vs direct API mode:**
|
|
206
|
-
|
|
207
|
-
| | Direct API (default) | CLI Backend (`--cli`) | Passthrough (`--passthrough`) |
|
|
208
|
-
|---|---|---|---|
|
|
209
|
-
| Streaming | Native SSE | SSE (converted from JSON) | Native SSE |
|
|
210
|
-
| Tool use | Yes | No | Yes |
|
|
211
|
-
| Thinking/billing injection | Yes (Claude-optimized) | N/A | No (OAuth swap only) |
|
|
212
|
-
| Latency | Low | Higher (process spawn) | Low |
|
|
213
|
-
| Rate limits | Priority routing | Not affected | Standard (no priority) |
|
|
214
|
-
| Opus when throttled | Auto CLI fallback | **Always works** | May return 429 |
|
|
215
|
-
|
|
216
184
|
## Passthrough Mode
|
|
217
185
|
|
|
218
|
-
For tools that need exact Anthropic protocol fidelity with zero modification, use `--passthrough
|
|
186
|
+
For tools that need exact Anthropic protocol fidelity with zero modification, use `--passthrough` (alias: `--thin`). This does OAuth swap only — no billing tag, no template replay, no device identity, no extra beta flags. Note: most tools (including Hermes and OpenClaw) work better through default mode, which handles billing classification automatically.
|
|
219
187
|
|
|
220
188
|
```bash
|
|
221
189
|
dario proxy --passthrough # Thin proxy, zero injection
|
|
222
|
-
dario proxy --
|
|
190
|
+
dario proxy --thin --model=opus # Thin proxy + model override
|
|
223
191
|
```
|
|
224
192
|
|
|
225
193
|
## Model Selection
|
|
@@ -235,12 +203,6 @@ dario proxy # Passthrough (client decides)
|
|
|
235
203
|
|
|
236
204
|
Full model IDs also work: `--model=claude-opus-4-6`
|
|
237
205
|
|
|
238
|
-
Combine with `--cli` for rate-limit-proof Opus:
|
|
239
|
-
|
|
240
|
-
```bash
|
|
241
|
-
dario proxy --cli --model=opus
|
|
242
|
-
```
|
|
243
|
-
|
|
244
206
|
## OpenAI Compatibility
|
|
245
207
|
|
|
246
208
|
Dario implements `/v1/chat/completions` — any tool built for the OpenAI API works with your Claude subscription. No code changes needed.
|
|
@@ -344,8 +306,6 @@ model:
|
|
|
344
306
|
default: claude-opus-4-6
|
|
345
307
|
```
|
|
346
308
|
|
|
347
|
-
Then run `hermes` normally — it routes through dario using your Claude subscription.
|
|
348
|
-
|
|
349
309
|
### OpenClaw
|
|
350
310
|
|
|
351
311
|
Add to your `openclaw.json` models config:
|
|
@@ -384,52 +344,81 @@ Add to your `openclaw.json` models config:
|
|
|
384
344
|
|
|
385
345
|
**Note:** Use `http://127.0.0.1:3456` without `/v1` — OpenClaw adds the path itself.
|
|
386
346
|
|
|
347
|
+
---
|
|
348
|
+
|
|
387
349
|
## How It Works
|
|
388
350
|
|
|
389
351
|
### Direct API Mode (default) — Template Replay
|
|
390
352
|
|
|
391
353
|
```
|
|
392
|
-
|
|
393
|
-
│ Your App
|
|
394
|
-
│
|
|
395
|
-
│ sends
|
|
396
|
-
│ its own
|
|
397
|
-
│ tools &
|
|
398
|
-
│ params
|
|
399
|
-
|
|
354
|
+
┌───────────┐ ┌─────────────────────┐ ┌──────────────────┐
|
|
355
|
+
│ Your App │ ──> │ dario (proxy) │ ──> │ api.anthropic.com│
|
|
356
|
+
│ │ │ localhost:3456 │ │ │
|
|
357
|
+
│ sends │ │ │ │ sees a genuine │
|
|
358
|
+
│ its own │ │ replaces request │ │ Claude Code │
|
|
359
|
+
│ tools & │ │ with CC template │ │ request │
|
|
360
|
+
│ params │ │ keeps only content │ │ │
|
|
361
|
+
└───────────┘ └─────────────────────┘ └──────────────────┘
|
|
400
362
|
```
|
|
401
363
|
|
|
402
364
|
Your app sends whatever it wants — any tools, any parameters. dario replaces the entire request with Claude Code's template and injects only your conversation content. The upstream sees CC's exact tool definitions, field structure, and parameters.
|
|
403
365
|
|
|
404
|
-
###
|
|
366
|
+
### Passthrough Mode (`--passthrough`)
|
|
405
367
|
|
|
406
368
|
```
|
|
407
|
-
|
|
408
|
-
│ Your App
|
|
409
|
-
│
|
|
410
|
-
│ sends
|
|
411
|
-
│ API
|
|
412
|
-
│ request
|
|
413
|
-
|
|
369
|
+
┌───────────┐ ┌─────────────────┐ ┌──────────────────┐
|
|
370
|
+
│ Your App │ ──> │ dario (proxy) │ ──> │ api.anthropic.com│
|
|
371
|
+
│ │ │ localhost:3456 │ │ │
|
|
372
|
+
│ sends │ │ swaps API key │ │ sees valid │
|
|
373
|
+
│ API │ │ for OAuth │ │ OAuth bearer │
|
|
374
|
+
│ request │ │ nothing else │ │ token │
|
|
375
|
+
└───────────┘ └─────────────────┘ └──────────────────┘
|
|
414
376
|
```
|
|
415
377
|
|
|
416
|
-
###
|
|
378
|
+
### What dario actually sends upstream
|
|
379
|
+
|
|
380
|
+
In direct mode, every request dario sends to Anthropic is a genuine Claude Code request. Key fields injected or enforced:
|
|
417
381
|
|
|
382
|
+
**Billing tag** — reconstructed using Claude Code's own algorithm extracted from the CC binary:
|
|
418
383
|
```
|
|
419
|
-
|
|
420
|
-
│ Your App │ ──> │ dario (proxy) │ ──> │ api.anthropic.com│
|
|
421
|
-
│ │ │ localhost:3456 │ │ │
|
|
422
|
-
│ sends │ │ swaps API key │ │ sees valid │
|
|
423
|
-
│ API │ │ for OAuth │ │ OAuth bearer │
|
|
424
|
-
│ request │ │ nothing else │ │ token │
|
|
425
|
-
└──────────┘ └─────────────────┘ └──────────────────┘
|
|
384
|
+
x-anthropic-billing-header: cc_version=<version>.<build_tag>; cc_entrypoint=cli; cch=<5-char-hex>;
|
|
426
385
|
```
|
|
386
|
+
The build tag is `SHA-256(seed + chars[4,7,20] of user message + version).slice(0,3)`. The `cch` is a fresh random 5-char hex per request. Both were extracted via MITM capture.
|
|
427
387
|
|
|
428
|
-
|
|
388
|
+
**Beta set** — exactly 8 betas from CC, in CC's order:
|
|
389
|
+
```
|
|
390
|
+
claude-code-20250219, oauth-2025-04-20, context-1m-2025-08-07,
|
|
391
|
+
interleaved-thinking-2025-05-14, context-management-2025-06-27,
|
|
392
|
+
prompt-caching-scope-2026-01-05, advisor-tool-2026-03-01, effort-2025-11-24
|
|
393
|
+
```
|
|
394
|
+
|
|
395
|
+
**Request headers** — CC's exact Stainless SDK headers, including `x-stainless-runtime-version: v24.3.0` (the Node.js compat version CC reports when running on Bun), `x-app: cli`, `user-agent: claude-cli/<version>`, `anthropic-dangerous-direct-browser-access: true`.
|
|
396
|
+
|
|
397
|
+
**Upstream URL** — `api.anthropic.com/v1/messages?beta=true`, matching CC's own request format.
|
|
398
|
+
|
|
399
|
+
**Device identity** — `metadata.user_id` loaded from `~/.claude/.claude.json`. Without this, Anthropic classifies the request as third-party and routes it to Extra Usage billing instead of the Max plan allocation.
|
|
400
|
+
|
|
401
|
+
**Session ID** — rotates per request via `x-claude-code-session-id`. A persistent session ID across many rapid requests is a behavioral detection signal; CC `--print` creates a new session each invocation.
|
|
402
|
+
|
|
403
|
+
**Rate governor** — 500ms minimum between requests (configurable via `DARIO_MIN_INTERVAL_MS`). Configurable for agent workloads that need tighter pacing.
|
|
404
|
+
|
|
405
|
+
### OAuth Config Auto-Detection
|
|
429
406
|
|
|
430
|
-
|
|
407
|
+
Anthropic periodically rotates the OAuth `client_id`, authorize URL, token URL, and scopes that Claude Code uses. Historically this caused `"Invalid client id"` errors until a new dario release shipped.
|
|
431
408
|
|
|
432
|
-
|
|
409
|
+
Dario scans the installed CC binary at startup and extracts the current config directly:
|
|
410
|
+
|
|
411
|
+
- **Anchor**: `OAUTH_FILE_SUFFIX:"-local-oauth"` — the config block CC uses for clients that run their own localhost callback.
|
|
412
|
+
- **Extracted**: `CLIENT_ID`, `CLAUDE_AI_AUTHORIZE_URL`, `TOKEN_URL`, and the full `user:*` scope string.
|
|
413
|
+
- **Cached**: Results stored at `~/.dario/cc-oauth-cache.json` keyed by binary fingerprint (first 64KB sha256 + size + mtime). Cold scan ~500ms, cache hit ~5ms. Re-scans only when CC is upgraded.
|
|
414
|
+
- **Fallback**: If CC is not installed or scanning fails, dario uses known-good hardcoded values. No user action needed.
|
|
415
|
+
- **Override**: Set `DARIO_CC_PATH=/path/to/claude` to point dario at a non-standard CC binary location.
|
|
416
|
+
|
|
417
|
+
CC ships **two** OAuth client configurations in one binary — a `-local-oauth` flow (localhost callback) and a platform-hosted flow (`platform.claude.com/oauth/code/callback`). Dario must use the former. The scanner anchors specifically on the local block.
|
|
418
|
+
|
|
419
|
+
End-to-end verification lives at [`test/oauth-detector.mjs`](test/oauth-detector.mjs).
|
|
420
|
+
|
|
421
|
+
---
|
|
433
422
|
|
|
434
423
|
## Commands
|
|
435
424
|
|
|
@@ -446,49 +435,45 @@ Your app sends whatever it wants — any tools, any parameters. dario replaces t
|
|
|
446
435
|
|
|
447
436
|
| Flag/Env | Description | Default |
|
|
448
437
|
|----------|-------------|---------|
|
|
449
|
-
| `--
|
|
450
|
-
| `--
|
|
438
|
+
| `--passthrough` / `--thin` | Thin proxy — OAuth swap only, no injection | off |
|
|
439
|
+
| `--preserve-tools` / `--keep-tools` | Keep client tool schemas instead of remapping to CC tools | off |
|
|
451
440
|
| `--model=MODEL` | Force a model (`opus`, `sonnet`, `haiku`, or full ID) | passthrough |
|
|
452
441
|
| `--port=PORT` | Port to listen on | `3456` |
|
|
453
442
|
| `--verbose` / `-v` | Log every request | off |
|
|
454
|
-
| `DARIO_API_KEY` | If set, all endpoints (except `/health`) require matching `x-api-key`
|
|
443
|
+
| `DARIO_API_KEY` | If set, all endpoints (except `/health`) require matching `x-api-key` or `Authorization: Bearer` | unset (open) |
|
|
455
444
|
| `DARIO_NO_BUN` | Disable automatic Bun relaunch (stay on Node.js) | unset |
|
|
456
445
|
| `DARIO_MIN_INTERVAL_MS` | Minimum ms between requests (rate governor) | `500` |
|
|
446
|
+
| `DARIO_CC_PATH` | Override path to Claude Code binary for OAuth detection | auto-detect |
|
|
457
447
|
|
|
458
448
|
## Supported Features
|
|
459
449
|
|
|
460
450
|
### Direct API Mode
|
|
461
451
|
- All Claude models (Opus 4.6, Sonnet 4.6, Haiku 4.5) + 1M extended context aliases (`opus1m`, `sonnet1m`)
|
|
462
|
-
- **Template replay**
|
|
463
|
-
-
|
|
464
|
-
- **
|
|
465
|
-
- **
|
|
466
|
-
- **
|
|
467
|
-
- **
|
|
468
|
-
- **
|
|
469
|
-
-
|
|
470
|
-
-
|
|
471
|
-
-
|
|
472
|
-
-
|
|
473
|
-
-
|
|
474
|
-
-
|
|
475
|
-
- **
|
|
476
|
-
- **
|
|
477
|
-
-
|
|
478
|
-
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
- All Claude models — including Opus when rate limited
|
|
482
|
-
- Streaming via SSE conversion (client sends `stream: true`, CLI JSON response is converted to Anthropic or OpenAI SSE events)
|
|
483
|
-
- OpenAI compatibility (translates OpenAI → Anthropic before CLI, Anthropic → OpenAI after)
|
|
484
|
-
- System prompts and multi-turn conversations (via context injection)
|
|
485
|
-
- Not affected by API rate limits
|
|
452
|
+
- **Template replay** — replaces the entire request with Claude Code's exact template. 25 tool definitions, 25KB system prompt, exact body key order, exact beta headers (model-conditional), exact metadata structure. Client tools are mapped to CC equivalents and reverse-mapped in responses. Template data stored as JSON for easy updates.
|
|
453
|
+
- **`--preserve-tools` mode** — opt-out of CC tool schema replacement for agent frameworks that rely on their own custom tool definitions. Default mode still remaps for maximum detection resistance.
|
|
454
|
+
- **OAuth auto-detect** — scans the installed CC binary for OAuth config at startup. Stays in sync with whatever CC version you have; falls back to known-good hardcoded values if no binary is found. Override with `DARIO_CC_PATH`.
|
|
455
|
+
- **Bun auto-relaunch** — auto-detects Bun and relaunches under it for TLS fingerprint fidelity. CC runs on Bun; Node.js has a different TLS fingerprint visible at the network level.
|
|
456
|
+
- **Session ID rotation** — each request gets a fresh session ID via `x-claude-code-session-id`, matching CC behavior.
|
|
457
|
+
- **Rate governor** — configurable minimum interval between requests via `DARIO_MIN_INTERVAL_MS`.
|
|
458
|
+
- **Enriched 429 errors** — rate limit errors include utilization %, limiting window, and reset time instead of Anthropic's default `"Error"` message.
|
|
459
|
+
- **Auto-retry on long-context errors** — when Anthropic returns 400 or 429 with `"long context beta is not yet available"` or `"Extra usage is required"`, dario transparently retries without the `context-1m-2025-08-07` beta flag.
|
|
460
|
+
- **OpenAI-compatible** (`/v1/chat/completions`) — works with any OpenAI SDK or tool.
|
|
461
|
+
- Streaming and non-streaming (both Anthropic and OpenAI SSE formats, including tool_use streaming).
|
|
462
|
+
- Tool use / function calling.
|
|
463
|
+
- System prompts and multi-turn conversations.
|
|
464
|
+
- Prompt caching and extended thinking.
|
|
465
|
+
- **Billable beta filtering** — strips `extended-cache-ttl` from client betas (the only beta requiring Extra Usage enabled on the account).
|
|
466
|
+
- **Beta deduplication** — client-provided betas are deduplicated against the base set before appending.
|
|
467
|
+
- **Orchestration tag sanitization** — strips agent-injected XML (`<system-reminder>`, `<env>`, `<task_metadata>`, etc.) before forwarding.
|
|
468
|
+
- **Token anomaly detection** — warns on context spike (>60% input growth) or output explosion (>2x previous).
|
|
469
|
+
- Concurrency control (max 10 concurrent upstream requests).
|
|
470
|
+
- CORS enabled (works from browser apps on localhost).
|
|
486
471
|
|
|
487
472
|
### Passthrough Mode
|
|
488
|
-
- All Claude models with native streaming and tool use
|
|
489
|
-
- OAuth token swap only — no billing tag,
|
|
490
|
-
- Minimal beta flags (`oauth-2025-04-20` + client betas only)
|
|
491
|
-
- For tools that need exact Anthropic protocol fidelity with zero modification
|
|
473
|
+
- All Claude models with native streaming and tool use.
|
|
474
|
+
- OAuth token swap only — no billing tag, no template injection, no device identity.
|
|
475
|
+
- Minimal beta flags (`oauth-2025-04-20` + client betas only).
|
|
476
|
+
- For tools that need exact Anthropic protocol fidelity with zero modification.
|
|
492
477
|
|
|
493
478
|
## Endpoints
|
|
494
479
|
|
|
@@ -521,17 +506,45 @@ curl http://localhost:3456/health
|
|
|
521
506
|
|---------|---------------------|
|
|
522
507
|
| Credential storage | Reads from Claude Code (`~/.claude/.credentials.json`) or its own store (`~/.dario/credentials.json`) with `0600` permissions |
|
|
523
508
|
| OAuth flow | PKCE (Proof Key for Code Exchange) — no client secret needed |
|
|
524
|
-
|
|
|
525
|
-
|
|
|
526
|
-
|
|
|
527
|
-
|
|
|
528
|
-
|
|
|
529
|
-
|
|
|
509
|
+
| OAuth config source | Auto-detected from local CC binary at runtime; cached at `~/.dario/cc-oauth-cache.json`. Detector reads binary in read-only mode, never modifies it. |
|
|
510
|
+
| Token exposure | Tokens never logged; redacted from all error messages. |
|
|
511
|
+
| Network binding | Binds exclusively to `127.0.0.1`. Upstream traffic goes only to `api.anthropic.com` over HTTPS. |
|
|
512
|
+
| Auth timing | `timingSafeEqual` used for `DARIO_API_KEY` comparison. |
|
|
513
|
+
| SSRF protection | Only `/v1/messages` and `/v1/complete` are proxied upstream — hardcoded allowlist. |
|
|
514
|
+
| Body size | 10MB hard cap per request. 30s read timeout prevents slow-loris. |
|
|
515
|
+
| Token refresh | Auto-refreshes 30 minutes before expiry. Refresh tokens rotate on each use. Mutex prevents concurrent refresh races. |
|
|
516
|
+
| Telemetry | None. Zero analytics, tracking, or data collection of any kind. |
|
|
517
|
+
|
|
518
|
+
---
|
|
519
|
+
|
|
520
|
+
## askalf
|
|
521
|
+
|
|
522
|
+
dario solves the API access problem — your $200/mo subscription, usable everywhere, billed correctly.
|
|
523
|
+
|
|
524
|
+
But a proxy has a ceiling. Every request still runs on your single account, with your subscription's rate limits, on your machine. When you need to scale beyond that — multiple accounts, persistent browser sessions, desktop control, scheduled workflows, a fleet of agents that can run while you sleep — that's what [askalf](https://askalf.org) is built for.
|
|
525
|
+
|
|
526
|
+
**askalf** is the agent platform built on top of the same OAuth and billing infrastructure that powers dario:
|
|
527
|
+
|
|
528
|
+
| | dario | askalf |
|
|
529
|
+
|---|---|---|
|
|
530
|
+
| **What it is** | Local proxy, single account | Hosted agent fleet, multi-account |
|
|
531
|
+
| **Rate limits** | Your subscription's limits | Distributed across fleet, near-zero 429s |
|
|
532
|
+
| **Browser / desktop** | No | Yes — full computer use |
|
|
533
|
+
| **Scheduling** | No | Yes — cron, webhooks, triggers |
|
|
534
|
+
| **Persistent memory** | No | Yes — per-agent memory and context |
|
|
535
|
+
| **Custom tools** | Via `--preserve-tools` | Native MCP tool server |
|
|
536
|
+
| **Setup** | 2 commands | Waitlist → dashboard |
|
|
537
|
+
|
|
538
|
+
If you're running multi-agent workflows, hitting rate limits on Claude Max, or want agents that run 24/7 without babysitting, **[join the waitlist at askalf.org](https://askalf.org)**.
|
|
539
|
+
|
|
540
|
+
dario will always be open-source and free. askalf is the hosted tier for teams who need more.
|
|
541
|
+
|
|
542
|
+
---
|
|
530
543
|
|
|
531
544
|
## FAQ
|
|
532
545
|
|
|
533
546
|
**Does this violate Anthropic's terms of service?**
|
|
534
|
-
Dario uses your existing Claude Code credentials with the same OAuth tokens. It authenticates you as you, with your subscription, through Anthropic's official API.
|
|
547
|
+
Dario uses your existing Claude Code credentials with the same OAuth tokens. It authenticates you as you, with your subscription, through Anthropic's official API.
|
|
535
548
|
|
|
536
549
|
**What subscription plans work?**
|
|
537
550
|
Claude Max and Claude Pro. Any plan that lets you use Claude Code.
|
|
@@ -540,7 +553,7 @@ Claude Max and Claude Pro. Any plan that lets you use Claude Code.
|
|
|
540
553
|
Should work if your plan includes Claude Code access. Not tested yet — please open an issue with results.
|
|
541
554
|
|
|
542
555
|
**Do I need Claude Code installed?**
|
|
543
|
-
Recommended but not required. If Claude Code is installed and logged in, `dario login` picks up your credentials automatically. Without Claude Code, dario runs its own OAuth flow to authenticate directly.
|
|
556
|
+
Recommended but not required. If Claude Code is installed and logged in, `dario login` picks up your credentials automatically. Without Claude Code, dario runs its own OAuth flow to authenticate directly.
|
|
544
557
|
|
|
545
558
|
**First time setup — account priming**
|
|
546
559
|
If dario is the first thing you use with a new Claude account, run a few real Claude Code commands first to establish a session baseline:
|
|
@@ -557,14 +570,19 @@ Optional but recommended. If [Bun](https://bun.sh) is installed, dario auto-rela
|
|
|
557
570
|
**What happens when my token expires?**
|
|
558
571
|
Dario auto-refreshes tokens 30 minutes before expiry. You should never see an auth error in normal use. If something goes wrong, `dario refresh` forces an immediate refresh.
|
|
559
572
|
|
|
560
|
-
**
|
|
561
|
-
|
|
573
|
+
**What happens when Anthropic rotates the OAuth client_id or URL?**
|
|
574
|
+
Dario auto-detects OAuth config from your installed Claude Code binary. When CC ships a new version with rotated values, dario picks them up on the next startup — no dario release needed. The detector is cached at `~/.dario/cc-oauth-cache.json` and only re-scans when the binary fingerprint changes. If CC isn't installed, dario falls back to known-good hardcoded values.
|
|
575
|
+
|
|
576
|
+
**I'm hitting rate limits. What do I do?**
|
|
577
|
+
Claude subscriptions have rolling 5-hour and 7-day usage windows. Check your utilization with Claude Code's `/usage` command or the [statusline](https://code.claude.com/docs/en/statusline). Rate limit errors from dario include utilization percentages and reset times so you can see exactly when capacity returns.
|
|
578
|
+
|
|
579
|
+
If you're running a multi-agent workload and consistently hitting limits, [askalf](https://askalf.org) distributes load across multiple accounts automatically.
|
|
562
580
|
|
|
563
581
|
**What are the usage limits?**
|
|
564
|
-
Claude subscriptions have rolling 5-hour and 7-day usage windows shared across claude.ai and Claude Code. See [Anthropic's docs](https://support.claude.com/en/articles/11647753-how-do-usage-and-length-limits-work) for details.
|
|
582
|
+
Claude subscriptions have rolling 5-hour and 7-day usage windows shared across claude.ai and Claude Code. See [Anthropic's docs](https://support.claude.com/en/articles/11647753-how-do-usage-and-length-limits-work) for details.
|
|
565
583
|
|
|
566
584
|
**Can I run this on a server?**
|
|
567
|
-
Dario binds to localhost by default. For server use,
|
|
585
|
+
Dario binds to localhost by default. For server use, handle the initial login on a machine with a browser, then copy `~/.claude/.credentials.json` (or `~/.dario/credentials.json`) to your server. Auto-refresh will keep it alive from there.
|
|
568
586
|
|
|
569
587
|
**Why "dario"?**
|
|
570
588
|
Named after [Dario Amodei](https://en.wikipedia.org/wiki/Dario_Amodei), CEO of Anthropic.
|
|
@@ -579,12 +597,12 @@ import { startProxy, getAccessToken, getStatus } from "@askalf/dario";
|
|
|
579
597
|
// Start the proxy programmatically
|
|
580
598
|
await startProxy({ port: 3456, verbose: true });
|
|
581
599
|
|
|
582
|
-
// CLI backend mode
|
|
583
|
-
await startProxy({ port: 3456, cliBackend: true, model: "opus" });
|
|
584
|
-
|
|
585
600
|
// Passthrough mode (OAuth swap only, no injection)
|
|
586
601
|
await startProxy({ port: 3456, passthrough: true });
|
|
587
602
|
|
|
603
|
+
// Preserve-tools mode (keep client tool schemas)
|
|
604
|
+
await startProxy({ port: 3456, preserveTools: true });
|
|
605
|
+
|
|
588
606
|
// Or just get a raw access token
|
|
589
607
|
const token = await getAccessToken();
|
|
590
608
|
|
|
@@ -599,7 +617,7 @@ Dario handles your OAuth tokens. Here's why you can trust it:
|
|
|
599
617
|
|
|
600
618
|
| Signal | Status |
|
|
601
619
|
|--------|--------|
|
|
602
|
-
| **Source code** | ~2,
|
|
620
|
+
| **Source code** | ~2,000 lines of TypeScript — small enough to audit in one sitting |
|
|
603
621
|
| **Dependencies** | 0 runtime dependencies. Verify: `npm ls --production` |
|
|
604
622
|
| **npm provenance** | Every release is [SLSA attested](https://www.npmjs.com/package/@askalf/dario) via GitHub Actions |
|
|
605
623
|
| **Security scanning** | [CodeQL](https://github.com/askalf/dario/actions/workflows/codeql.yml) runs on every push and weekly |
|
|
@@ -625,21 +643,22 @@ cd $(npm root -g)/@askalf/dario && npm ls --production
|
|
|
625
643
|
|-------|------|
|
|
626
644
|
| v3.0 Template Replay — why we stopped matching signals | [Discussion 14](https://github.com/askalf/dario/discussions/14) |
|
|
627
645
|
| Claude Code defaults are detection signals, not optimizations | [Discussion 13](https://github.com/askalf/dario/discussions/13) |
|
|
628
|
-
| Why Opus
|
|
646
|
+
| Why Opus feels worse through other proxies and how to fix it | [Discussion 9](https://github.com/askalf/dario/discussions/9) |
|
|
629
647
|
| Billing tag algorithm and fingerprint analysis | [Discussion 8](https://github.com/askalf/dario/discussions/8) |
|
|
630
648
|
| Rate limit header analysis | [Discussion 1](https://github.com/askalf/dario/discussions/1) |
|
|
631
649
|
|
|
632
650
|
## Contributing
|
|
633
651
|
|
|
634
|
-
PRs welcome. The codebase is ~2,
|
|
652
|
+
PRs welcome. The codebase is ~2,000 lines of TypeScript across 7 files:
|
|
635
653
|
|
|
636
654
|
| File | Purpose |
|
|
637
655
|
|------|---------|
|
|
638
|
-
| `src/proxy.ts` | HTTP proxy server,
|
|
639
|
-
| `src/cc-template.ts` |
|
|
640
|
-
| `src/cc-template-data.json` |
|
|
641
|
-
| `src/oauth.ts` |
|
|
642
|
-
| `src/
|
|
656
|
+
| `src/proxy.ts` | HTTP proxy server, rate governor, billing tag, response forwarding |
|
|
657
|
+
| `src/cc-template.ts` | Template engine, tool mapping, orchestration sanitization |
|
|
658
|
+
| `src/cc-template-data.json` | CC request template data (25 tools, 25KB system prompt) |
|
|
659
|
+
| `src/cc-oauth-detect.ts` | Auto-detect OAuth config from the installed CC binary |
|
|
660
|
+
| `src/oauth.ts` | Token storage, PKCE flow, auto-refresh, credential detection |
|
|
661
|
+
| `src/cli.ts` | CLI entry point, command routing, Bun auto-relaunch |
|
|
643
662
|
| `src/index.ts` | Library exports |
|
|
644
663
|
|
|
645
664
|
```bash
|
|
@@ -654,7 +673,7 @@ npm run dev # runs with tsx (no build needed)
|
|
|
654
673
|
| Who | Contributions |
|
|
655
674
|
|-----|---------------|
|
|
656
675
|
| [@GodsBoy](https://github.com/GodsBoy) | Proxy authentication, token redaction, error sanitization ([#2](https://github.com/askalf/dario/pull/2)) |
|
|
657
|
-
| [@belangertrading](https://github.com/belangertrading) | Billing classification investigation ([#4](https://github.com/askalf/dario/issues/4)),
|
|
676
|
+
| [@belangertrading](https://github.com/belangertrading) | Billing classification investigation ([#4](https://github.com/askalf/dario/issues/4)), billing reclassification root cause ([#7](https://github.com/askalf/dario/issues/7)) |
|
|
658
677
|
|
|
659
678
|
## License
|
|
660
679
|
|
|
@@ -5,20 +5,32 @@
|
|
|
5
5
|
* (client_id, authorize URL, token URL, scopes). Eliminates the need to
|
|
6
6
|
* hardcode values that Anthropic rotates between CC releases.
|
|
7
7
|
*
|
|
8
|
-
* CC ships
|
|
8
|
+
* CC ships three OAuth config factories in one binary (dev/staging/prod),
|
|
9
|
+
* selected at runtime by an environment switch that is hardcoded to "prod"
|
|
10
|
+
* in shipped builds. Only the PROD block is live; "local" and "staging"
|
|
11
|
+
* are dead code paths.
|
|
9
12
|
*
|
|
10
|
-
*
|
|
11
|
-
*
|
|
12
|
-
*
|
|
13
|
+
* PROD block (the one we want):
|
|
14
|
+
* BASE_API_URL: "https://api.anthropic.com"
|
|
15
|
+
* CLAUDE_AI_AUTHORIZE_URL: "https://claude.com/cai/oauth/authorize"
|
|
16
|
+
* TOKEN_URL: "https://platform.claude.com/v1/oauth/token"
|
|
17
|
+
* CLIENT_ID: "9d1c250a-e61b-44d9-88ed-5944d1962f5e"
|
|
18
|
+
* OAUTH_FILE_SUFFIX: ""
|
|
13
19
|
*
|
|
14
|
-
*
|
|
15
|
-
*
|
|
16
|
-
*
|
|
20
|
+
* LOCAL block (dead code in shipped builds — CC pointing at localhost:8000
|
|
21
|
+
* etc. as its own dev stack, NOT about "client uses a localhost callback"):
|
|
22
|
+
* BASE_API_URL: "http://localhost:8000"
|
|
23
|
+
* CLIENT_ID: "22422756-60c9-4084-8eb7-27705fd5cf9a"
|
|
24
|
+
* OAUTH_FILE_SUFFIX: "-local-oauth"
|
|
17
25
|
*
|
|
18
|
-
*
|
|
26
|
+
* Dario uses CC's own automatic OAuth flow — the prod client is registered
|
|
27
|
+
* with `http://localhost:${port}/callback` exactly as dario sends. (The
|
|
28
|
+
* "MANUAL_REDIRECT_URL" on platform.claude.com is only used when dario's
|
|
29
|
+
* local HTTP server can't bind a port; dario never hits that path.)
|
|
19
30
|
*
|
|
20
|
-
* Results are cached per-binary-hash at ~/.dario/cc-oauth-cache.json so
|
|
21
|
-
* startup only re-scans when the user upgrades Claude Code.
|
|
31
|
+
* Results are cached per-binary-hash at ~/.dario/cc-oauth-cache-v2.json so
|
|
32
|
+
* startup only re-scans when the user upgrades Claude Code. The -v2 suffix
|
|
33
|
+
* invalidates the v3.4.0-v3.4.2 caches that held the wrong (dev) client_id.
|
|
22
34
|
*/
|
|
23
35
|
export interface DetectedOAuthConfig {
|
|
24
36
|
clientId: string;
|
|
@@ -30,10 +42,14 @@ export interface DetectedOAuthConfig {
|
|
|
30
42
|
ccHash?: string;
|
|
31
43
|
}
|
|
32
44
|
/**
|
|
33
|
-
* Scan binary bytes for the
|
|
34
|
-
*
|
|
35
|
-
*
|
|
36
|
-
*
|
|
45
|
+
* Scan binary bytes for the PROD OAuth config block.
|
|
46
|
+
*
|
|
47
|
+
* Anchors on `BASE_API_URL:"https://api.anthropic.com"` — this literal
|
|
48
|
+
* only appears inside the prod config object (`nh$`). The LOCAL-dev block
|
|
49
|
+
* uses `http://localhost:8000` for the same key, and there's no staging
|
|
50
|
+
* block present in shipped builds. Once we find the anchor, the CLIENT_ID,
|
|
51
|
+
* CLAUDE_AI_AUTHORIZE_URL, TOKEN_URL, and scopes all live within a ~1.5KB
|
|
52
|
+
* window after it.
|
|
37
53
|
*/
|
|
38
54
|
export declare function scanBinaryForOAuthConfig(buf: Buffer): Omit<DetectedOAuthConfig, 'source' | 'ccPath' | 'ccHash'> | null;
|
|
39
55
|
/**
|