@askalf/dario 3.3.0 → 3.4.1
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 -137
- package/dist/cc-oauth-detect.d.ts +47 -0
- package/dist/cc-oauth-detect.js +232 -0
- package/dist/cc-template.d.ts +4 -4
- package/dist/cc-template.js +5 -5
- package/dist/cli.js +3 -5
- package/dist/oauth.js +21 -14
- package/dist/proxy.d.ts +0 -1
- package/dist/proxy.js +73 -296
- package/package.json +1 -1
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">
|
|
@@ -80,7 +84,7 @@ Opus, Sonnet, Haiku — all models, streaming, tool use. **Zero dependencies.**
|
|
|
80
84
|
|
|
81
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.
|
|
82
86
|
|
|
83
|
-
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.
|
|
84
88
|
|
|
85
89
|
| | dario | Other proxies |
|
|
86
90
|
|---|---|---|
|
|
@@ -93,15 +97,14 @@ dario is the only proxy that solves this. Instead of transforming your requests
|
|
|
93
97
|
<details>
|
|
94
98
|
<summary><strong>vs competitors</strong></summary>
|
|
95
99
|
|
|
96
|
-
| Feature | dario | Meridian
|
|
100
|
+
| Feature | dario | Meridian | CLIProxyAPI |
|
|
97
101
|
|---------|-------|---------|------------|
|
|
98
|
-
| Template replay (undetectable) | **Yes** | No |
|
|
102
|
+
| Template replay (undetectable) | **Yes** | No | No |
|
|
99
103
|
| Direct OAuth (streaming, tools) | **Yes** | Yes (SDK-based) | No |
|
|
100
|
-
| CLI fallback (rate limit bypass) | **Yes** | No | Yes (only mode) |
|
|
101
104
|
| OpenAI API compat | **Yes** | Yes | Yes |
|
|
102
105
|
| Orchestration sanitization | **Yes** | Yes | No |
|
|
103
106
|
| Token anomaly detection | **Yes** | Yes | No |
|
|
104
|
-
| Codebase size | ~2,
|
|
107
|
+
| Codebase size | ~2,000 lines | ~9,000 lines | Platform |
|
|
105
108
|
| Dependencies | 0 | Many | Many |
|
|
106
109
|
| Setup | 2 commands | Config + build | Config + dashboard |
|
|
107
110
|
|
|
@@ -111,15 +114,15 @@ dario is the only proxy that solves this. Instead of transforming your requests
|
|
|
111
114
|
|
|
112
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.
|
|
113
116
|
|
|
114
|
-
**
|
|
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.
|
|
115
118
|
|
|
116
|
-
**
|
|
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).
|
|
117
120
|
|
|
118
121
|
## Quick Start
|
|
119
122
|
|
|
120
123
|
### Prerequisites
|
|
121
124
|
|
|
122
|
-
[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.
|
|
123
126
|
|
|
124
127
|
If Claude Code isn't installed, dario runs its own OAuth flow — opens your browser, you authorize, done.
|
|
125
128
|
|
|
@@ -178,46 +181,13 @@ continue # in VS Code, set base URL in config
|
|
|
178
181
|
python my_script.py
|
|
179
182
|
```
|
|
180
183
|
|
|
181
|
-
## CLI Backend
|
|
182
|
-
|
|
183
|
-
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.
|
|
184
|
-
|
|
185
|
-
```bash
|
|
186
|
-
dario proxy --cli # Opus works even when rate limited
|
|
187
|
-
dario proxy --cli --model=opus # Force Opus + CLI backend
|
|
188
|
-
```
|
|
189
|
-
|
|
190
|
-
```
|
|
191
|
-
dario — http://localhost:3456
|
|
192
|
-
|
|
193
|
-
Your Claude subscription is now an API.
|
|
194
|
-
|
|
195
|
-
Usage:
|
|
196
|
-
ANTHROPIC_BASE_URL=http://localhost:3456
|
|
197
|
-
ANTHROPIC_API_KEY=dario
|
|
198
|
-
|
|
199
|
-
Backend: Claude CLI (bypasses rate limits)
|
|
200
|
-
Model: claude-opus-4-6 (all requests)
|
|
201
|
-
```
|
|
202
|
-
|
|
203
|
-
**Trade-offs vs direct API mode:**
|
|
204
|
-
|
|
205
|
-
| | Direct API (default) | CLI Backend (`--cli`) | Passthrough (`--passthrough`) |
|
|
206
|
-
|---|---|---|---|
|
|
207
|
-
| Streaming | Native SSE | SSE (converted from JSON) | Native SSE |
|
|
208
|
-
| Tool use | Yes | No | Yes |
|
|
209
|
-
| Thinking/billing injection | Yes (Claude-optimized) | N/A | No (OAuth swap only) |
|
|
210
|
-
| Latency | Low | Higher (process spawn) | Low |
|
|
211
|
-
| Rate limits | Priority routing | Not affected | Standard (no priority) |
|
|
212
|
-
| Opus when throttled | Auto CLI fallback | **Always works** | May return 429 |
|
|
213
|
-
|
|
214
184
|
## Passthrough Mode
|
|
215
185
|
|
|
216
|
-
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.
|
|
217
187
|
|
|
218
188
|
```bash
|
|
219
189
|
dario proxy --passthrough # Thin proxy, zero injection
|
|
220
|
-
dario proxy --
|
|
190
|
+
dario proxy --thin --model=opus # Thin proxy + model override
|
|
221
191
|
```
|
|
222
192
|
|
|
223
193
|
## Model Selection
|
|
@@ -233,12 +203,6 @@ dario proxy # Passthrough (client decides)
|
|
|
233
203
|
|
|
234
204
|
Full model IDs also work: `--model=claude-opus-4-6`
|
|
235
205
|
|
|
236
|
-
Combine with `--cli` for rate-limit-proof Opus:
|
|
237
|
-
|
|
238
|
-
```bash
|
|
239
|
-
dario proxy --cli --model=opus
|
|
240
|
-
```
|
|
241
|
-
|
|
242
206
|
## OpenAI Compatibility
|
|
243
207
|
|
|
244
208
|
Dario implements `/v1/chat/completions` — any tool built for the OpenAI API works with your Claude subscription. No code changes needed.
|
|
@@ -342,8 +306,6 @@ model:
|
|
|
342
306
|
default: claude-opus-4-6
|
|
343
307
|
```
|
|
344
308
|
|
|
345
|
-
Then run `hermes` normally — it routes through dario using your Claude subscription.
|
|
346
|
-
|
|
347
309
|
### OpenClaw
|
|
348
310
|
|
|
349
311
|
Add to your `openclaw.json` models config:
|
|
@@ -382,52 +344,81 @@ Add to your `openclaw.json` models config:
|
|
|
382
344
|
|
|
383
345
|
**Note:** Use `http://127.0.0.1:3456` without `/v1` — OpenClaw adds the path itself.
|
|
384
346
|
|
|
347
|
+
---
|
|
348
|
+
|
|
385
349
|
## How It Works
|
|
386
350
|
|
|
387
351
|
### Direct API Mode (default) — Template Replay
|
|
388
352
|
|
|
389
353
|
```
|
|
390
|
-
|
|
391
|
-
│ Your App
|
|
392
|
-
│
|
|
393
|
-
│ sends
|
|
394
|
-
│ its own
|
|
395
|
-
│ tools &
|
|
396
|
-
│ params
|
|
397
|
-
|
|
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
|
+
└───────────┘ └─────────────────────┘ └──────────────────┘
|
|
398
362
|
```
|
|
399
363
|
|
|
400
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.
|
|
401
365
|
|
|
402
|
-
###
|
|
366
|
+
### Passthrough Mode (`--passthrough`)
|
|
403
367
|
|
|
404
368
|
```
|
|
405
|
-
|
|
406
|
-
│ Your App
|
|
407
|
-
│
|
|
408
|
-
│ sends
|
|
409
|
-
│ API
|
|
410
|
-
│ request
|
|
411
|
-
|
|
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
|
+
└───────────┘ └─────────────────┘ └──────────────────┘
|
|
412
376
|
```
|
|
413
377
|
|
|
414
|
-
###
|
|
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:
|
|
415
381
|
|
|
382
|
+
**Billing tag** — reconstructed using Claude Code's own algorithm extracted from the CC binary:
|
|
416
383
|
```
|
|
417
|
-
|
|
418
|
-
│ Your App │ ──> │ dario (proxy) │ ──> │ api.anthropic.com│
|
|
419
|
-
│ │ │ localhost:3456 │ │ │
|
|
420
|
-
│ sends │ │ swaps API key │ │ sees valid │
|
|
421
|
-
│ API │ │ for OAuth │ │ OAuth bearer │
|
|
422
|
-
│ request │ │ nothing else │ │ token │
|
|
423
|
-
└──────────┘ └─────────────────┘ └──────────────────┘
|
|
384
|
+
x-anthropic-billing-header: cc_version=<version>.<build_tag>; cc_entrypoint=cli; cch=<5-char-hex>;
|
|
424
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.
|
|
425
387
|
|
|
426
|
-
|
|
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
|
|
427
406
|
|
|
428
|
-
|
|
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.
|
|
429
408
|
|
|
430
|
-
|
|
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
|
+
---
|
|
431
422
|
|
|
432
423
|
## Commands
|
|
433
424
|
|
|
@@ -444,49 +435,45 @@ Your app sends whatever it wants — any tools, any parameters. dario replaces t
|
|
|
444
435
|
|
|
445
436
|
| Flag/Env | Description | Default |
|
|
446
437
|
|----------|-------------|---------|
|
|
447
|
-
| `--
|
|
448
|
-
| `--
|
|
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 |
|
|
449
440
|
| `--model=MODEL` | Force a model (`opus`, `sonnet`, `haiku`, or full ID) | passthrough |
|
|
450
441
|
| `--port=PORT` | Port to listen on | `3456` |
|
|
451
442
|
| `--verbose` / `-v` | Log every request | off |
|
|
452
|
-
| `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) |
|
|
453
444
|
| `DARIO_NO_BUN` | Disable automatic Bun relaunch (stay on Node.js) | unset |
|
|
454
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 |
|
|
455
447
|
|
|
456
448
|
## Supported Features
|
|
457
449
|
|
|
458
450
|
### Direct API Mode
|
|
459
451
|
- All Claude models (Opus 4.6, Sonnet 4.6, Haiku 4.5) + 1M extended context aliases (`opus1m`, `sonnet1m`)
|
|
460
|
-
- **Template replay**
|
|
461
|
-
-
|
|
462
|
-
- **
|
|
463
|
-
- **
|
|
464
|
-
- **
|
|
465
|
-
- **
|
|
466
|
-
- **
|
|
467
|
-
-
|
|
468
|
-
-
|
|
469
|
-
-
|
|
470
|
-
-
|
|
471
|
-
-
|
|
472
|
-
-
|
|
473
|
-
- **
|
|
474
|
-
- **
|
|
475
|
-
-
|
|
476
|
-
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
- All Claude models — including Opus when rate limited
|
|
480
|
-
- Streaming via SSE conversion (client sends `stream: true`, CLI JSON response is converted to Anthropic or OpenAI SSE events)
|
|
481
|
-
- OpenAI compatibility (translates OpenAI → Anthropic before CLI, Anthropic → OpenAI after)
|
|
482
|
-
- System prompts and multi-turn conversations (via context injection)
|
|
483
|
-
- 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).
|
|
484
471
|
|
|
485
472
|
### Passthrough Mode
|
|
486
|
-
- All Claude models with native streaming and tool use
|
|
487
|
-
- OAuth token swap only — no billing tag,
|
|
488
|
-
- Minimal beta flags (`oauth-2025-04-20` + client betas only)
|
|
489
|
-
- 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.
|
|
490
477
|
|
|
491
478
|
## Endpoints
|
|
492
479
|
|
|
@@ -519,17 +506,45 @@ curl http://localhost:3456/health
|
|
|
519
506
|
|---------|---------------------|
|
|
520
507
|
| Credential storage | Reads from Claude Code (`~/.claude/.credentials.json`) or its own store (`~/.dario/credentials.json`) with `0600` permissions |
|
|
521
508
|
| OAuth flow | PKCE (Proof Key for Code Exchange) — no client secret needed |
|
|
522
|
-
|
|
|
523
|
-
|
|
|
524
|
-
|
|
|
525
|
-
|
|
|
526
|
-
|
|
|
527
|
-
|
|
|
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
|
+
---
|
|
528
543
|
|
|
529
544
|
## FAQ
|
|
530
545
|
|
|
531
546
|
**Does this violate Anthropic's terms of service?**
|
|
532
|
-
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.
|
|
533
548
|
|
|
534
549
|
**What subscription plans work?**
|
|
535
550
|
Claude Max and Claude Pro. Any plan that lets you use Claude Code.
|
|
@@ -538,7 +553,7 @@ Claude Max and Claude Pro. Any plan that lets you use Claude Code.
|
|
|
538
553
|
Should work if your plan includes Claude Code access. Not tested yet — please open an issue with results.
|
|
539
554
|
|
|
540
555
|
**Do I need Claude Code installed?**
|
|
541
|
-
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.
|
|
542
557
|
|
|
543
558
|
**First time setup — account priming**
|
|
544
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:
|
|
@@ -555,14 +570,19 @@ Optional but recommended. If [Bun](https://bun.sh) is installed, dario auto-rela
|
|
|
555
570
|
**What happens when my token expires?**
|
|
556
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.
|
|
557
572
|
|
|
558
|
-
**
|
|
559
|
-
|
|
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.
|
|
560
580
|
|
|
561
581
|
**What are the usage limits?**
|
|
562
|
-
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.
|
|
563
583
|
|
|
564
584
|
**Can I run this on a server?**
|
|
565
|
-
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.
|
|
566
586
|
|
|
567
587
|
**Why "dario"?**
|
|
568
588
|
Named after [Dario Amodei](https://en.wikipedia.org/wiki/Dario_Amodei), CEO of Anthropic.
|
|
@@ -577,12 +597,12 @@ import { startProxy, getAccessToken, getStatus } from "@askalf/dario";
|
|
|
577
597
|
// Start the proxy programmatically
|
|
578
598
|
await startProxy({ port: 3456, verbose: true });
|
|
579
599
|
|
|
580
|
-
// CLI backend mode
|
|
581
|
-
await startProxy({ port: 3456, cliBackend: true, model: "opus" });
|
|
582
|
-
|
|
583
600
|
// Passthrough mode (OAuth swap only, no injection)
|
|
584
601
|
await startProxy({ port: 3456, passthrough: true });
|
|
585
602
|
|
|
603
|
+
// Preserve-tools mode (keep client tool schemas)
|
|
604
|
+
await startProxy({ port: 3456, preserveTools: true });
|
|
605
|
+
|
|
586
606
|
// Or just get a raw access token
|
|
587
607
|
const token = await getAccessToken();
|
|
588
608
|
|
|
@@ -597,7 +617,7 @@ Dario handles your OAuth tokens. Here's why you can trust it:
|
|
|
597
617
|
|
|
598
618
|
| Signal | Status |
|
|
599
619
|
|--------|--------|
|
|
600
|
-
| **Source code** | ~2,
|
|
620
|
+
| **Source code** | ~2,000 lines of TypeScript — small enough to audit in one sitting |
|
|
601
621
|
| **Dependencies** | 0 runtime dependencies. Verify: `npm ls --production` |
|
|
602
622
|
| **npm provenance** | Every release is [SLSA attested](https://www.npmjs.com/package/@askalf/dario) via GitHub Actions |
|
|
603
623
|
| **Security scanning** | [CodeQL](https://github.com/askalf/dario/actions/workflows/codeql.yml) runs on every push and weekly |
|
|
@@ -623,21 +643,22 @@ cd $(npm root -g)/@askalf/dario && npm ls --production
|
|
|
623
643
|
|-------|------|
|
|
624
644
|
| v3.0 Template Replay — why we stopped matching signals | [Discussion 14](https://github.com/askalf/dario/discussions/14) |
|
|
625
645
|
| Claude Code defaults are detection signals, not optimizations | [Discussion 13](https://github.com/askalf/dario/discussions/13) |
|
|
626
|
-
| Why Opus
|
|
646
|
+
| Why Opus feels worse through other proxies and how to fix it | [Discussion 9](https://github.com/askalf/dario/discussions/9) |
|
|
627
647
|
| Billing tag algorithm and fingerprint analysis | [Discussion 8](https://github.com/askalf/dario/discussions/8) |
|
|
628
648
|
| Rate limit header analysis | [Discussion 1](https://github.com/askalf/dario/discussions/1) |
|
|
629
649
|
|
|
630
650
|
## Contributing
|
|
631
651
|
|
|
632
|
-
PRs welcome. The codebase is ~2,
|
|
652
|
+
PRs welcome. The codebase is ~2,000 lines of TypeScript across 7 files:
|
|
633
653
|
|
|
634
654
|
| File | Purpose |
|
|
635
655
|
|------|---------|
|
|
636
|
-
| `src/proxy.ts` | HTTP proxy server,
|
|
637
|
-
| `src/cc-template.ts` |
|
|
638
|
-
| `src/cc-template-data.json` |
|
|
639
|
-
| `src/oauth.ts` |
|
|
640
|
-
| `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 |
|
|
641
662
|
| `src/index.ts` | Library exports |
|
|
642
663
|
|
|
643
664
|
```bash
|
|
@@ -652,7 +673,7 @@ npm run dev # runs with tsx (no build needed)
|
|
|
652
673
|
| Who | Contributions |
|
|
653
674
|
|-----|---------------|
|
|
654
675
|
| [@GodsBoy](https://github.com/GodsBoy) | Proxy authentication, token redaction, error sanitization ([#2](https://github.com/askalf/dario/pull/2)) |
|
|
655
|
-
| [@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)) |
|
|
656
677
|
|
|
657
678
|
## License
|
|
658
679
|
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* CC OAuth Auto-Detection
|
|
3
|
+
*
|
|
4
|
+
* Scans the installed Claude Code binary to extract its OAuth configuration
|
|
5
|
+
* (client_id, authorize URL, token URL, scopes). Eliminates the need to
|
|
6
|
+
* hardcode values that Anthropic rotates between CC releases.
|
|
7
|
+
*
|
|
8
|
+
* CC ships two OAuth client configurations in one binary:
|
|
9
|
+
*
|
|
10
|
+
* 1. LOCAL flow — used when the OAuth client owns the callback
|
|
11
|
+
* (i.e. runs an HTTP server on localhost). This is what dario does.
|
|
12
|
+
* Identified by OAUTH_FILE_SUFFIX:"-local-oauth" next to the CLIENT_ID.
|
|
13
|
+
*
|
|
14
|
+
* 2. PLATFORM flow — used when the callback is hosted at
|
|
15
|
+
* platform.claude.com/oauth/code/callback. Different CLIENT_ID.
|
|
16
|
+
* Not applicable to dario.
|
|
17
|
+
*
|
|
18
|
+
* We scan for the LOCAL block and extract its config.
|
|
19
|
+
*
|
|
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.
|
|
22
|
+
*/
|
|
23
|
+
export interface DetectedOAuthConfig {
|
|
24
|
+
clientId: string;
|
|
25
|
+
authorizeUrl: string;
|
|
26
|
+
tokenUrl: string;
|
|
27
|
+
scopes: string;
|
|
28
|
+
source: 'detected' | 'cached' | 'fallback';
|
|
29
|
+
ccPath?: string;
|
|
30
|
+
ccHash?: string;
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* Scan binary bytes for the LOCAL-oauth OAuth block.
|
|
34
|
+
* Uses Buffer.indexOf to locate anchor strings, then slices a small
|
|
35
|
+
* window of context to run regexes on. This avoids converting the
|
|
36
|
+
* whole binary to a JS string.
|
|
37
|
+
*/
|
|
38
|
+
export declare function scanBinaryForOAuthConfig(buf: Buffer): Omit<DetectedOAuthConfig, 'source' | 'ccPath' | 'ccHash'> | null;
|
|
39
|
+
/**
|
|
40
|
+
* Get the OAuth config for dario to use. Scans the installed CC binary
|
|
41
|
+
* on first call, caches to disk, and memoizes in-process for subsequent
|
|
42
|
+
* calls. If no binary is found or scanning fails, falls back to the
|
|
43
|
+
* known-good v2.1.104 values.
|
|
44
|
+
*/
|
|
45
|
+
export declare function detectCCOAuthConfig(): Promise<DetectedOAuthConfig>;
|
|
46
|
+
/** Test-only: reset in-process memoization. */
|
|
47
|
+
export declare function _resetDetectorCache(): void;
|