@askalf/dario 3.4.5 → 3.4.6

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.
Files changed (2) hide show
  1. package/README.md +214 -474
  2. package/package.json +1 -1
package/README.md CHANGED
@@ -1,11 +1,6 @@
1
1
  <p align="center">
2
2
  <h1 align="center">dario</h1>
3
- <p align="center"><strong>Use your Claude subscription as an API. The only proxy that bills correctly.</strong></p>
4
- <p align="center">
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.
8
- </p>
3
+ <p align="center"><strong>Use your Claude subscription inside your local tools and scripts — without moving to API billing or rebuilding your workflow around a separate stack.</strong></p>
9
4
  </p>
10
5
 
11
6
  <p align="center">
@@ -18,220 +13,200 @@
18
13
 
19
14
  <p align="center">
20
15
  <a href="#quick-start">Quick Start</a> &bull;
21
- <a href="#openai-compatibility">OpenAI Compat</a> &bull;
22
- <a href="#usage-examples">Examples</a> &bull;
23
- <a href="#askalf">askalf</a> &bull;
16
+ <a href="#who-this-is-for">Who it's for</a> &bull;
17
+ <a href="#why-switch">Why switch</a> &bull;
18
+ <a href="#how-it-works">How it works</a> &bull;
19
+ <a href="#from-standalone-to-askalf">Standalone → askalf</a> &bull;
24
20
  <a href="#trust--transparency">Trust</a> &bull;
25
21
  <a href="#faq">FAQ</a>
26
22
  </p>
27
23
 
28
24
  ---
29
25
 
30
- ```bash
31
- npx @askalf/dario login # detects Claude Code credentials, starts proxy
26
+ ## What it is
32
27
 
33
- # now use it from anywhereAnthropic or OpenAI SDK
34
- export ANTHROPIC_BASE_URL=http://localhost:3456 # or OPENAI_BASE_URL=http://localhost:3456/v1
35
- export ANTHROPIC_API_KEY=dario # or OPENAI_API_KEY=dario
36
- ```
28
+ dario is a local process that turns your Claude Max or Pro subscription into an API endpoint that any tool on your machine can use. It talks to Anthropic the same way Claude Code does, so your subscription's rate limits are what you spend against not a separate API billing tier.
37
29
 
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.
30
+ Install it once, log in once (using your existing Claude Code credentials if you have them), and from that point on every tool that speaks the Anthropic API or the OpenAI chat completions API Cursor, Continue, Aider, LiteLLM, your own scripts, whatever — can reach Claude through `http://localhost:3456`.
39
31
 
40
- dario is the **per-request layer** one account, one workload, every request indistinguishable from CC on the wire. Session-level and account-level concerns (multi-account pooling, behavioral-classifier shaping, 24/7 fleets) live a layer above dario, in [askalf](https://askalf.org) [see below](#askalf). Both are built by the same team on the same OAuth and billing infrastructure.
32
+ **Standalone is the default.** You don't need an account anywhere, you don't need to wait for anything, and nothing phones home. Install and run.
41
33
 
42
- <table>
43
- <tr>
44
- <td colspan="3" align="center"><br/><strong>Independently reviewed by 3 competing AI companies</strong><br/><br/></td>
45
- </tr>
46
- <tr>
47
- <td width="33%" valign="top">
34
+ **Dario is also the local bridge for [askalf](https://askalf.org).** When your workload outgrows a single subscription — multi-account pooling, session shaping to stay under Anthropic's behavioral classifiers, 24/7 fleets, scheduled workflows — dario is the component that keeps running on your machine and connects to the askalf platform. Same install, same commands, extra capabilities unlocked when you link it. You don't have to use askalf to use dario today, and you won't have to change how you use dario when you join askalf later.
48
35
 
49
- **Grok** (xAI)
36
+ ---
50
37
 
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."*
38
+ ## Who this is for
52
39
 
53
- </td>
54
- <td width="33%" valign="top">
40
+ **Best fit:**
41
+ - Power users already paying for Claude Max or Pro who want Claude available inside their local stack — editors, terminals, scripts, internal tools — without moving to API billing.
42
+ - Small teams that work in terminals and IDEs, not in hosted agent stacks, and want Claude as a drop-in provider for whatever tools they already use.
43
+ - Anyone who wants Claude Code's billing behavior on their own requests, from their own code.
55
44
 
56
- **Copilot** (Microsoft)
45
+ **Not a fit:**
46
+ - You need vendor-managed production SLAs on every request. Use the Anthropic API directly.
47
+ - You need high-scale agent orchestration, multi-account pooling, or session-level classifier shaping. That's [askalf](https://askalf.org), which dario bridges into.
48
+ - You want a hosted chat UI. Use claude.ai.
57
49
 
58
- *"Verdict: Safe for local use — well-implemented with strong security practices. Minimal attack surface: zero runtime dependencies, PKCE OAuth, localhost-only binding, timing-safe auth, zero telemetry. The main risk vector is operator error rather than code defects."*
50
+ ---
59
51
 
60
- </td>
61
- <td width="33%" valign="top">
52
+ ## First use case
62
53
 
63
- **Gemini** (Google)
54
+ > Use Claude in your local automation and developer workflows the way you'd normally reach for an API — but backed by the subscription you already pay for.
64
55
 
65
- *"Highly recommended for personal, local development. Solves a massive pain point for developers by bridging Claude Max/Pro subscriptions with developer IDEs, saving substantial API costs. Modular & lean, modern PKCE auth, SSRF protection, mature CI/CD pipeline with CodeQL and npm provenance attestations."*
56
+ You install dario, point your existing tool at `http://localhost:3456`, and that tool now sees Claude. The tool doesn't know it's going through a proxy; from its perspective dario *is* the Anthropic API. Your subscription handles the billing. Your Max plan limits are what count against usage.
66
57
 
67
- </td>
68
- </tr>
69
- <tr>
70
- <td colspan="3" align="center"><br/><strong>In production</strong><br/><br/></td>
71
- </tr>
72
- <tr>
73
- <td colspan="3" valign="top">
58
+ Flow on a fresh machine:
74
59
 
75
- *"The 429s were driving us crazy running a multi-agent stack on Claude Max. You found the billing tag, fixed the checksum, reverse-engineered the per-request hash from the binary — running clean, zero reclassification."* — [@belangertrading](https://github.com/belangertrading), multi-agent stack on Claude Max
60
+ 1. `npm install -g @askalf/dario`
61
+ 2. `dario login` — detects your installed Claude Code credentials, or runs its own OAuth flow if you don't have CC installed
62
+ 3. `dario proxy` — starts the local server on port 3456
63
+ 4. Set two environment variables in the tool you already use:
64
+ ```bash
65
+ ANTHROPIC_BASE_URL=http://localhost:3456
66
+ ANTHROPIC_API_KEY=dario
67
+ ```
68
+ 5. That tool now uses your Claude subscription. Streaming works, tool use works, prompt caching works.
76
69
 
77
- </td>
78
- </tr>
79
- </table>
70
+ No separate API key. No Extra Usage charges. No rebuilding your workflow around a new provider.
80
71
 
81
72
  ---
82
73
 
83
- ## Why dario
84
-
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.
86
-
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.
88
-
89
- | | dario | Other proxies |
90
- |---|---|---|
91
- | **Approach** | Template replay — sends CC's actual request | Signal matching or none |
92
- | **Tools** | CC's exact tool definitions sent upstream | Client tools (detected) |
93
- | **Max plan limits** | Used correctly | Bypassed — billed separately |
94
- | **Detection resistance** | Undetectable at the per-request level without flagging CC itself | Detected by tool names, field order, effort level, etc. |
95
- | **Dependencies** | 0 | Many |
96
-
97
- <details>
98
- <summary><strong>vs competitors</strong></summary>
74
+ ## Why switch
99
75
 
100
- | Feature | dario | Meridian | CLIProxyAPI |
101
- |---------|-------|---------|------------|
102
- | Template replay (undetectable) | **Yes** | No | No |
103
- | Direct OAuth (streaming, tools) | **Yes** | Yes (SDK-based) | No |
104
- | OpenAI API compat | **Yes** | Yes | Yes |
105
- | Orchestration sanitization | **Yes** | Yes | No |
106
- | Token anomaly detection | **Yes** | Yes | No |
107
- | Codebase size | ~2,000 lines | ~9,000 lines | Platform |
108
- | Dependencies | 0 | Many | Many |
109
- | Setup | 2 commands | Config + build | Config + dashboard |
76
+ **Use dario if** you already pay for Claude Max or Pro and you want Claude inside the tools you already use, without paying API rates for every request or routing your work through a second hosted stack.
110
77
 
111
- </details>
78
+ **Use the Anthropic API directly if** you need platform-native primitives, vendor-managed production usage, high-scale control, or SLAs your subscription tier doesn't cover. Dario isn't trying to replace the API — it's trying to unlock the subscription you already bought.
112
79
 
113
- ## The Problem
80
+ **Use dario + askalf if** you're running multi-agent workloads, hitting session-level rate limits that a single account can't clear, or need a 24/7 fleet. Dario keeps running on your machine as the local bridge; askalf adds multi-account pooling, session shaping, and the platform pieces a single-subscription proxy can't deliver. See [below](#from-standalone-to-askalf).
114
81
 
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.
82
+ **Don't use dario if** you want a subprocess bridge that shells out to `claude --print` under the hood. Those tools (openclaw-claude-bridge and similar) work well for single-team single-machine workloads that can accept a one-subscription rate ceiling and a one-machine deployment. Dario is the API-path alternative, which trades that simplicity for pooling-friendly behavior on the wire. Different tradeoffs, different tool.
116
83
 
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.
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).
84
+ ---
120
85
 
121
86
  ## Quick Start
122
87
 
123
- ### Prerequisites
88
+ ```bash
89
+ # Install
90
+ npm install -g @askalf/dario
124
91
 
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.
92
+ # Log in (detects Claude Code credentials if installed)
93
+ dario login
126
94
 
127
- If Claude Code isn't installed, dario runs its own OAuth flow — opens your browser, you authorize, done.
95
+ # Start the proxy
96
+ dario proxy
128
97
 
129
- ### Install
98
+ # Anthropic SDK
99
+ export ANTHROPIC_BASE_URL=http://localhost:3456
100
+ export ANTHROPIC_API_KEY=dario
130
101
 
131
- ```bash
132
- npm install -g @askalf/dario
102
+ # or OpenAI-compatible tools
103
+ export OPENAI_BASE_URL=http://localhost:3456/v1
104
+ export OPENAI_API_KEY=dario
133
105
  ```
134
106
 
135
- Or use npx (no install needed):
107
+ Opus, Sonnet, Haiku — all models, streaming, tool use, prompt caching, extended thinking. **Zero runtime dependencies.** ~2,000 lines of TypeScript. Auto-launches under [Bun](https://bun.sh) when available for TLS fingerprint fidelity with Claude Code's runtime. **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.
136
108
 
137
- ```bash
138
- npx @askalf/dario login
139
- ```
109
+ ---
140
110
 
141
- ### Login
111
+ ## How It Works
142
112
 
143
- ```bash
144
- dario login
145
- ```
113
+ Dario has two modes: **direct API mode** (the default) and **passthrough mode** (`--passthrough`).
146
114
 
147
- - **With Claude Code installed:** Detects your credentials automatically and starts the proxy. No browser needed.
148
- - **Without Claude Code:** Opens your browser to Claude's OAuth page. Authorize, and dario captures the token automatically via a local callback server. Then run `dario proxy` to start the server.
115
+ ### Direct API Mode Template Replay
149
116
 
150
- ### Start the proxy
117
+ This is the mode you want for almost every case. Dario takes each request you send it and replaces it with a Claude Code request: same 25 tool definitions, same 25KB system prompt, same field order, same beta headers, same metadata structure, same device identity. Only your conversation content is preserved. Anthropic's classifier sees what looks like a Claude Code session because, from the wire up, it *is* one — and that's what keeps your usage on subscription billing instead of Extra Usage.
151
118
 
152
- ```bash
153
- dario proxy
154
119
  ```
155
-
120
+ ┌───────────┐ ┌─────────────────────┐ ┌──────────────────┐
121
+ │ Your App │ ──> │ dario (proxy) │ ──> │ api.anthropic.com│
122
+ │ │ │ localhost:3456 │ │ │
123
+ │ sends │ │ │ │ sees a genuine │
124
+ │ its own │ │ replaces request │ │ Claude Code │
125
+ │ tools & │ │ with CC template │ │ request │
126
+ │ params │ │ keeps only content │ │ │
127
+ └───────────┘ └─────────────────────┘ └──────────────────┘
156
128
  ```
157
- dario — http://localhost:3456
158
129
 
159
- Your Claude subscription is now an API.
130
+ The details that matter:
160
131
 
161
- Usage:
162
- ANTHROPIC_BASE_URL=http://localhost:3456
163
- ANTHROPIC_API_KEY=dario
132
+ - **Billing tag** reconstructed using CC's own algorithm extracted from the binary: `x-anthropic-billing-header: cc_version=<version>.<build_tag>; cc_entrypoint=cli; cch=<5-char-hex>;` where `build_tag = SHA-256(seed + chars[4,7,20] of user message + version).slice(0,3)`.
133
+ - **Beta set** — CC's exact beta list in CC's order, minus any beta that would require Extra Usage to be enabled on your account.
134
+ - **OAuth config** auto-detected from the installed CC binary at startup. When Anthropic rotates `client_id`, authorize URL, or scopes, dario picks up the new values on the next run without needing a new release. Falls back to hardcoded CC 2.1.104 prod values if CC isn't installed. Cache at `~/.dario/cc-oauth-cache-v3.json`, keyed by binary fingerprint.
135
+ - **Session ID** rotates per request via `x-claude-code-session-id`, matching how `claude --print` behaves. A persistent session ID across rapid requests is a behavioral signal.
136
+ - **Framework scrub** — framework identifiers and known fingerprint tokens (`OpenClaw`, `sessions_*` tool prefixes, orchestration tags, etc.) are stripped from both the system prompt and message content before the request goes upstream.
137
+ - **Bun auto-relaunch** — when Bun is installed, dario relaunches under it so its TLS fingerprint matches CC's runtime. Without Bun, dario runs on Node.js and works fine; the TLS fingerprint is the only difference.
164
138
 
165
- Auth: open (no DARIO_API_KEY set)
166
- OAuth: healthy (expires in 11h 42m)
167
- Model: passthrough (client decides)
168
- ```
139
+ ### Passthrough Mode `--passthrough`
169
140
 
170
- ### Use it
141
+ For tools that need exact Anthropic protocol fidelity with nothing injected. This mode does an OAuth token swap and nothing else: no billing tag, no template, no device identity.
171
142
 
172
143
  ```bash
173
- # Set these two env vars — every Anthropic SDK respects them
174
- export ANTHROPIC_BASE_URL=http://localhost:3456
175
- export ANTHROPIC_API_KEY=dario
176
-
177
- # Now any tool just works
178
- openclaw start
179
- aider --model claude-opus-4-6
180
- continue # in VS Code, set base URL in config
181
- python my_script.py
144
+ dario proxy --passthrough
182
145
  ```
183
146
 
184
- ## Passthrough Mode
147
+ Use it when the upstream tool already builds a Claude-Code-shaped request on its own and you just need the token auth.
185
148
 
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.
149
+ ### Detection scope
187
150
 
188
- ```bash
189
- dario proxy --passthrough # Thin proxy, zero injection
190
- dario proxy --thin --model=opus # Thin proxy + model override
191
- ```
151
+ Dario is a **per-request layer**. Every request it sends upstream is designed to be indistinguishable from a Claude Code request, and the per-request scrubbing hardened in v3.4.5 makes that meaningfully harder to fingerprint than it was when v3.0 first shipped. What dario cannot do at the per-request level is defend against Anthropic's session-level and account-level classifiers — those operate on cumulative per-OAuth behavioral aggregates (token throughput, conversation depth, streaming duration, inter-arrival timing) and no amount of per-request hardening reaches them. That's a different problem at a different layer, and it's [askalf](https://askalf.org)'s job rather than dario's. See the [FAQ entry](#faq) for the full explanation.
192
152
 
193
- ## Model Selection
153
+ ---
194
154
 
195
- Force a specific model for all requests — useful when your tool doesn't let you configure the model:
155
+ ## From standalone to askalf
196
156
 
197
- ```bash
198
- dario proxy --model=opus # Force Opus 4.6
199
- dario proxy --model=sonnet # Force Sonnet 4.6
200
- dario proxy --model=haiku # Force Haiku 4.5
201
- dario proxy # Passthrough (client decides)
202
- ```
157
+ Dario is fully useful on its own. You don't need an account, you don't need to wait for anything, and the standalone mode is and will remain the default.
203
158
 
204
- Full model IDs also work: `--model=claude-opus-4-6`
159
+ When your workload grows past what a single Claude subscription can hold, dario is also the local-edge component of the [askalf](https://askalf.org) platform. Same binary, same commands, same local proxy — linking to askalf adds what a per-request layer alone can't deliver:
205
160
 
206
- ## OpenAI Compatibility
161
+ | | dario standalone | dario + askalf |
162
+ |---|---|---|
163
+ | **Accounts** | 1 (yours) | Pool of 2–20+ |
164
+ | **Rate limits** | Your subscription's 5h / 7d windows | Distributed across the pool, near-zero 429s |
165
+ | **Session shaping** | Per-request scrub | Per-session cumulative tracking, rotation, classifier avoidance |
166
+ | **Browser / desktop control** | No | Yes — full computer use |
167
+ | **Scheduling** | No | Cron, webhooks, triggers |
168
+ | **Persistent memory** | No | Per-agent context and state |
169
+ | **Hosted dashboard** | No | Yes |
170
+ | **Local proxy component** | dario | dario |
207
171
 
208
- Dario implements `/v1/chat/completions` any tool built for the OpenAI API works with your Claude subscription. No code changes needed.
172
+ When the askalf bridge endpoint is live, a single command (`dario link`) will pair this local instance with your askalf account and the extra capabilities unlock in place. Until then, standalone is the only mode that runs — nothing to wait for to use dario as it is today.
209
173
 
210
- ```bash
211
- dario proxy --model=opus
174
+ **[Join the askalf waitlist →](https://askalf.org)**
212
175
 
213
- export OPENAI_BASE_URL=http://localhost:3456/v1
214
- export OPENAI_API_KEY=dario
176
+ Dario will always be open-source and free. askalf is the hosted tier for teams who need the layer above.
215
177
 
216
- # Cursor, Continue, LiteLLM, any OpenAI SDK — all work
217
- ```
178
+ ---
218
179
 
219
- Use `--model=opus` to force the model regardless of what the client sends. Or pass `claude-opus-4-6` as the model name directly — Claude model names work as-is.
180
+ ## Commands
220
181
 
221
- ## Usage Examples
182
+ | Command | Description |
183
+ |---------|-------------|
184
+ | `dario login` | Log in (detects CC credentials or runs its own OAuth flow) |
185
+ | `dario proxy` | Start the local API proxy on port 3456 |
186
+ | `dario status` | Show OAuth token health and expiry |
187
+ | `dario refresh` | Force an immediate token refresh |
188
+ | `dario logout` | Delete stored credentials |
189
+ | `dario help` | Full command reference |
222
190
 
223
- ### curl
191
+ ### Proxy options
224
192
 
225
- ```bash
226
- curl http://localhost:3456/v1/messages \
227
- -H "Content-Type: application/json" \
228
- -H "anthropic-version: 2023-06-01" \
229
- -d '{
230
- "model": "claude-opus-4-6",
231
- "max_tokens": 1024,
232
- "messages": [{"role": "user", "content": "Hello!"}]
233
- }'
234
- ```
193
+ | Flag / env | Description | Default |
194
+ |---|---|---|
195
+ | `--passthrough` / `--thin` | Thin proxy — OAuth swap only, no template injection | off |
196
+ | `--preserve-tools` / `--keep-tools` | Keep client tool schemas instead of remapping to CC tools | off |
197
+ | `--model=<name>` | Force a model (`opus`, `sonnet`, `haiku`, or full ID) | passthrough |
198
+ | `--port=<n>` | Port to listen on | `3456` |
199
+ | `--host=<addr>` / `DARIO_HOST` | Bind address. Use `0.0.0.0` for LAN, or a specific IP (e.g. a Tailscale interface). When non-loopback, also set `DARIO_API_KEY`. | `127.0.0.1` |
200
+ | `--verbose` / `-v` | Log every request | off |
201
+ | `DARIO_API_KEY` | If set, all endpoints (except `/health`) require a matching `x-api-key` or `Authorization: Bearer` header. Required when `--host` binds non-loopback. | unset (open) |
202
+ | `DARIO_CORS_ORIGIN` | Override the browser CORS `Access-Control-Allow-Origin`. Useful for browser clients reaching dario over a mesh network. | `http://localhost:${port}` |
203
+ | `DARIO_NO_BUN` | Disable automatic Bun relaunch | unset |
204
+ | `DARIO_MIN_INTERVAL_MS` | Minimum ms between requests (rate governor) | `500` |
205
+ | `DARIO_CC_PATH` | Override path to the Claude Code binary for OAuth detection | auto-detect |
206
+
207
+ ---
208
+
209
+ ## Usage
235
210
 
236
211
  ### Python
237
212
 
@@ -240,15 +215,15 @@ import anthropic
240
215
 
241
216
  client = anthropic.Anthropic(
242
217
  base_url="http://localhost:3456",
243
- api_key="dario"
218
+ api_key="dario",
244
219
  )
245
220
 
246
- message = client.messages.create(
221
+ msg = client.messages.create(
247
222
  model="claude-opus-4-6",
248
223
  max_tokens=1024,
249
- messages=[{"role": "user", "content": "Hello!"}]
224
+ messages=[{"role": "user", "content": "Hello!"}],
250
225
  )
251
- print(message.content[0].text)
226
+ print(msg.content[0].text)
252
227
  ```
253
228
 
254
229
  ### TypeScript / Node.js
@@ -261,222 +236,64 @@ const client = new Anthropic({
261
236
  apiKey: "dario",
262
237
  });
263
238
 
264
- const message = await client.messages.create({
239
+ const msg = await client.messages.create({
265
240
  model: "claude-opus-4-6",
266
241
  max_tokens: 1024,
267
242
  messages: [{ role: "user", content: "Hello!" }],
268
243
  });
269
244
  ```
270
245
 
271
- ### Streaming
246
+ ### OpenAI-compatible (Cursor, Continue, LiteLLM, Aider, …)
247
+
248
+ ```bash
249
+ export OPENAI_BASE_URL=http://localhost:3456/v1
250
+ export OPENAI_API_KEY=dario
251
+ ```
252
+
253
+ Any tool that accepts an OpenAI base URL works as-is. Claude model names pass through directly; GPT-style names (`gpt-4`, `gpt-5.4`, etc.) map to their closest Claude equivalents so tools with hardcoded OpenAI model lists work without code changes.
254
+
255
+ ### curl
272
256
 
273
257
  ```bash
274
258
  curl http://localhost:3456/v1/messages \
275
259
  -H "Content-Type: application/json" \
276
260
  -H "anthropic-version: 2023-06-01" \
277
- -d '{
278
- "model": "claude-opus-4-6",
279
- "max_tokens": 1024,
280
- "stream": true,
281
- "messages": [{"role": "user", "content": "Write a haiku about APIs"}]
282
- }'
261
+ -d '{"model":"claude-opus-4-6","max_tokens":1024,"messages":[{"role":"user","content":"Hello!"}]}'
283
262
  ```
284
263
 
285
- ### With Other Tools
286
-
287
- ```bash
288
- # Cursor / Continue / any OpenAI-compatible tool
289
- OPENAI_BASE_URL=http://localhost:3456/v1 OPENAI_API_KEY=dario cursor
264
+ ### Streaming, tool use, prompt caching, extended thinking
290
265
 
291
- # Aider
292
- ANTHROPIC_BASE_URL=http://localhost:3456 ANTHROPIC_API_KEY=dario aider --model claude-opus-4-6
266
+ All supported in both Anthropic and OpenAI SSE formats. Tool-use streaming emits `input_json_delta` events. Prompt caching works as-is. Extended thinking is routed through `reasoning_effort` in OpenAI format or the native `thinking` field in Anthropic format.
293
267
 
294
- # Any tool that uses ANTHROPIC_BASE_URL
295
- ANTHROPIC_BASE_URL=http://localhost:3456 ANTHROPIC_API_KEY=dario your-tool-here
296
- ```
268
+ ### Library mode
297
269
 
298
- ### Hermes
270
+ Dario is also importable:
299
271
 
300
- Add to `~/.hermes/config.yaml`:
272
+ ```typescript
273
+ import { startProxy, getAccessToken, getStatus } from "@askalf/dario";
301
274
 
302
- ```yaml
303
- model:
304
- base_url: "http://localhost:3456/v1"
305
- api_key: "dario"
306
- default: claude-opus-4-6
275
+ await startProxy({ port: 3456, verbose: true });
276
+ const token = await getAccessToken();
277
+ const status = await getStatus();
307
278
  ```
308
279
 
309
- ### OpenClaw
280
+ ### Health check
310
281
 
311
- Add to your `openclaw.json` models config:
282
+ ```bash
283
+ curl http://localhost:3456/health
284
+ ```
312
285
 
313
286
  ```json
314
287
  {
315
- "models": {
316
- "providers": {
317
- "anthropic": {
318
- "baseUrl": "http://127.0.0.1:3456",
319
- "apiKey": "dario",
320
- "api": "anthropic-messages",
321
- "models": [
322
- {
323
- "id": "claude-sonnet-4-6",
324
- "name": "claude-sonnet-4-6",
325
- "contextWindow": 1000000,
326
- "maxTokens": 64000,
327
- "input": ["text"],
328
- "reasoning": true
329
- },
330
- {
331
- "id": "claude-opus-4-6",
332
- "name": "claude-opus-4-6",
333
- "contextWindow": 1000000,
334
- "maxTokens": 64000,
335
- "input": ["text"],
336
- "reasoning": true
337
- }
338
- ]
339
- }
340
- }
341
- }
288
+ "status": "ok",
289
+ "oauth": "healthy",
290
+ "expiresIn": "11h 42m",
291
+ "requests": 47
342
292
  }
343
293
  ```
344
294
 
345
- **Note:** Use `http://127.0.0.1:3456` without `/v1` — OpenClaw adds the path itself.
346
-
347
295
  ---
348
296
 
349
- ## How It Works
350
-
351
- ### Direct API Mode (default) — Template Replay
352
-
353
- ```
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
- └───────────┘ └─────────────────────┘ └──────────────────┘
362
- ```
363
-
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.
365
-
366
- ### Passthrough Mode (`--passthrough`)
367
-
368
- ```
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
- └───────────┘ └─────────────────┘ └──────────────────┘
376
- ```
377
-
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:
381
-
382
- **Billing tag** — reconstructed using Claude Code's own algorithm extracted from the CC binary:
383
- ```
384
- x-anthropic-billing-header: cc_version=<version>.<build_tag>; cc_entrypoint=cli; cch=<5-char-hex>;
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.
387
-
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
406
-
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.
408
-
409
- Dario scans the installed CC binary at startup and extracts the current config directly:
410
-
411
- - **Anchor**: `BASE_API_URL:"https://api.anthropic.com"` — this literal appears only inside CC's live prod OAuth config block, so the scanner reliably lands in the right object even when the minifier reorders fields across CC releases.
412
- - **Extracted**: `CLIENT_ID`, `CLAUDE_AI_AUTHORIZE_URL`, `TOKEN_URL`, and the full `user:*` scope string. A defensive check rejects any scan result that matches a known-dead internal client_id.
413
- - **Cached**: Results stored at `~/.dario/cc-oauth-cache-v2.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 the CC 2.1.104 prod config values hardcoded in-tree. 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 three OAuth config factories (`local`, `staging`, `prod`) in one binary, selected at runtime by a function that is hardcoded to `prod` in shipped builds. Only the prod block is live; the other two are dead code paths CC uses when pointing at internal dev/staging infrastructure. The scanner targets the prod block specifically.
418
-
419
- End-to-end verification lives at [`test/oauth-detector.mjs`](test/oauth-detector.mjs).
420
-
421
- ---
422
-
423
- ## Commands
424
-
425
- | Command | Description |
426
- |---------|-------------|
427
- | `dario login` | Detect credentials and start proxy |
428
- | `dario proxy` | Start the local API proxy |
429
- | `dario status` | Check if your token is healthy |
430
- | `dario refresh` | Force an immediate token refresh |
431
- | `dario logout` | Delete stored credentials |
432
- | `dario help` | Show usage information |
433
-
434
- ### Proxy Options
435
-
436
- | Flag/Env | Description | Default |
437
- |----------|-------------|---------|
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 |
440
- | `--model=MODEL` | Force a model (`opus`, `sonnet`, `haiku`, or full ID) | passthrough |
441
- | `--port=PORT` | Port to listen on | `3456` |
442
- | `--host=ADDRESS` / `DARIO_HOST` | Bind address. Use `0.0.0.0` to accept LAN connections, or a specific IP to bind selectively (e.g. a Tailscale interface). When non-loopback, also set `DARIO_API_KEY`. | `127.0.0.1` |
443
- | `--verbose` / `-v` | Log every request | off |
444
- | `DARIO_API_KEY` | If set, all endpoints (except `/health`) require matching `x-api-key` or `Authorization: Bearer`. **Required** when `--host` binds to anything other than loopback. | unset (open) |
445
- | `DARIO_CORS_ORIGIN` | Override the browser CORS `Access-Control-Allow-Origin`. Useful for browser-based clients (open-webui, librechat) connecting over a mesh network. | `http://localhost:${port}` |
446
- | `DARIO_NO_BUN` | Disable automatic Bun relaunch (stay on Node.js) | unset |
447
- | `DARIO_MIN_INTERVAL_MS` | Minimum ms between requests (rate governor) | `500` |
448
- | `DARIO_CC_PATH` | Override path to Claude Code binary for OAuth detection | auto-detect |
449
-
450
- ## Supported Features
451
-
452
- ### Direct API Mode
453
- - All Claude models (Opus 4.6, Sonnet 4.6, Haiku 4.5) + 1M extended context aliases (`opus1m`, `sonnet1m`)
454
- - **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.
455
- - **`--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.
456
- - **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`.
457
- - **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.
458
- - **Session ID rotation** — each request gets a fresh session ID via `x-claude-code-session-id`, matching CC behavior.
459
- - **Rate governor** — configurable minimum interval between requests via `DARIO_MIN_INTERVAL_MS`.
460
- - **Enriched 429 errors** — rate limit errors include utilization %, limiting window, and reset time instead of Anthropic's default `"Error"` message.
461
- - **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.
462
- - **OpenAI-compatible** (`/v1/chat/completions`) — works with any OpenAI SDK or tool.
463
- - Streaming and non-streaming (both Anthropic and OpenAI SSE formats, including tool_use streaming).
464
- - Tool use / function calling.
465
- - System prompts and multi-turn conversations.
466
- - Prompt caching and extended thinking.
467
- - **Billable beta filtering** — strips `extended-cache-ttl` from client betas (the only beta requiring Extra Usage enabled on the account).
468
- - **Beta deduplication** — client-provided betas are deduplicated against the base set before appending.
469
- - **Orchestration tag sanitization** — strips agent-injected XML (`<system-reminder>`, `<env>`, `<task_metadata>`, etc.) before forwarding.
470
- - **Token anomaly detection** — warns on context spike (>60% input growth) or output explosion (>2x previous).
471
- - Concurrency control (max 10 concurrent upstream requests).
472
- - CORS enabled (works from browser apps on localhost).
473
-
474
- ### Passthrough Mode
475
- - All Claude models with native streaming and tool use.
476
- - OAuth token swap only — no billing tag, no template injection, no device identity.
477
- - Minimal beta flags (`oauth-2025-04-20` + client betas only).
478
- - For tools that need exact Anthropic protocol fidelity with zero modification.
479
-
480
297
  ## Endpoints
481
298
 
482
299
  | Path | Description |
@@ -487,182 +304,100 @@ End-to-end verification lives at [`test/oauth-detector.mjs`](test/oauth-detector
487
304
  | `GET /health` | Proxy health + OAuth status + request count |
488
305
  | `GET /status` | Detailed OAuth token status |
489
306
 
490
- ## Health Check
491
-
492
- ```bash
493
- curl http://localhost:3456/health
494
- ```
495
-
496
- ```json
497
- {
498
- "status": "ok",
499
- "oauth": "healthy",
500
- "expiresIn": "11h 42m",
501
- "requests": 47
502
- }
503
- ```
504
-
505
- ## Security
506
-
507
- | Concern | How dario handles it |
508
- |---------|---------------------|
509
- | Credential storage | Reads from Claude Code (`~/.claude/.credentials.json`) or its own store (`~/.dario/credentials.json`) with `0600` permissions |
510
- | OAuth flow | PKCE (Proof Key for Code Exchange) — no client secret needed |
511
- | OAuth config source | Auto-detected from local CC binary at runtime; cached at `~/.dario/cc-oauth-cache-v2.json`. Detector reads binary in read-only mode, never modifies it. |
512
- | Token exposure | Tokens never logged; redacted from all error messages. |
513
- | Network binding | Binds to `127.0.0.1` by default. Override with `--host` / `DARIO_HOST` for mesh/LAN use; dario refuses to treat non-loopback binds as safe and requires you to set `DARIO_API_KEY` to avoid an unauthenticated LAN-reachable proxy. Upstream traffic goes only to `api.anthropic.com` over HTTPS. |
514
- | Auth timing | `timingSafeEqual` used for `DARIO_API_KEY` comparison. |
515
- | SSRF protection | Only `/v1/messages` and `/v1/complete` are proxied upstream — hardcoded allowlist. |
516
- | Body size | 10MB hard cap per request. 30s read timeout prevents slow-loris. |
517
- | Token refresh | Auto-refreshes 30 minutes before expiry. Refresh tokens rotate on each use. Mutex prevents concurrent refresh races. |
518
- | Telemetry | None. Zero analytics, tracking, or data collection of any kind. |
519
-
520
307
  ---
521
308
 
522
- ## askalf
523
-
524
- **dario and askalf solve different layers of the same problem.**
525
-
526
- dario is the per-request layer: one account, one workload, every request on the wire indistinguishable from Claude Code. It's what you reach for when you want your Max/Pro subscription usable from any tool that speaks the Anthropic or OpenAI API. It does not pool accounts, shape sessions, distribute load, or care about cumulative behavioral signals — those are not per-request concerns, and solving them at the per-request layer is a category error.
309
+ ## Trust & Transparency
527
310
 
528
- **askalf** is the layer above that: multi-account pooling behind one endpoint, session and workload shaping to stay under Anthropic's session-level classifiers, persistent browser and desktop sessions, scheduling, and a hosted fleet that runs 24/7. Built on the same OAuth and billing infrastructure as dario.
311
+ Dario handles your OAuth tokens. Here's why you can trust it:
529
312
 
530
- | | dario | askalf |
531
- |---|---|---|
532
- | **What it is** | Local proxy, single account | Hosted agent fleet, multi-account |
533
- | **Rate limits** | Your subscription's limits | Distributed across fleet, near-zero 429s |
534
- | **Browser / desktop** | No | Yes full computer use |
535
- | **Scheduling** | No | Yes cron, webhooks, triggers |
536
- | **Persistent memory** | No | Yes per-agent memory and context |
537
- | **Custom tools** | Via `--preserve-tools` | Native MCP tool server |
538
- | **Setup** | 2 commands | Waitlist dashboard |
313
+ | Signal | Status |
314
+ |---|---|
315
+ | **Source code** | ~2,000 lines of TypeScript across 7 files small enough to audit in one sitting |
316
+ | **Dependencies** | 0 runtime dependencies. Verify: `npm ls --production` |
317
+ | **npm provenance** | Every release is [SLSA-attested](https://www.npmjs.com/package/@askalf/dario) via GitHub Actions |
318
+ | **Security scanning** | [CodeQL](https://github.com/askalf/dario/actions/workflows/codeql.yml) runs on every push and weekly |
319
+ | **Credential handling** | Tokens never logged, redacted from errors, stored with `0600` permissions |
320
+ | **OAuth flow** | PKCE (Proof Key for Code Exchange) no client secret |
321
+ | **Network scope** | Binds to `127.0.0.1` by default. `--host` allows LAN/mesh with `DARIO_API_KEY` gating. Upstream traffic goes only to `api.anthropic.com` over HTTPS |
322
+ | **SSRF protection** | Only `/v1/messages` and `/v1/complete` proxy upstream — hardcoded allowlist |
323
+ | **Telemetry** | None. Zero analytics, tracking, or data collection |
324
+ | **Audit trail** | [CHANGELOG.md](CHANGELOG.md) documents every release |
539
325
 
540
- 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)**.
326
+ Verify the npm tarball matches this repo:
541
327
 
542
- dario will always be open-source and free. askalf is the hosted tier for teams who need more.
328
+ ```bash
329
+ npm audit signatures
330
+ npm view @askalf/dario dist.integrity
331
+ cd $(npm root -g)/@askalf/dario && npm ls --production
332
+ ```
543
333
 
544
334
  ---
545
335
 
546
336
  ## FAQ
547
337
 
548
338
  **Does this violate Anthropic's terms of service?**
549
- 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.
339
+ Dario uses your existing Claude Code credentials with the same OAuth tokens CC uses. It authenticates you as you, with your subscription, through Anthropic's official API endpoints.
550
340
 
551
341
  **What subscription plans work?**
552
342
  Claude Max and Claude Pro. Any plan that lets you use Claude Code.
553
343
 
554
- **Does it work with Claude Team / Enterprise?**
555
- Should work if your plan includes Claude Code access. Not tested yet — please open an issue with results.
344
+ **Does it work with Team / Enterprise?**
345
+ Should work if your plan includes Claude Code access. Not widely tested yet — open an issue with results.
556
346
 
557
347
  **Do I need Claude Code installed?**
558
- 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.
348
+ Recommended, not required. With CC installed, `dario login` picks up your credentials automatically. Without CC, dario runs its own OAuth flow against Anthropic's authorize endpoint.
349
+
350
+ **Do I need Bun?**
351
+ Optional, recommended. Dario auto-relaunches under Bun when it's available so the TLS fingerprint matches CC's runtime. Without Bun, dario runs on Node.js and works fine; the TLS fingerprint is the only difference. Install: `curl -fsSL https://bun.sh/install | bash`.
559
352
 
560
- **First time setup account priming**
561
- 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:
353
+ **First time setup on a fresh account.**
354
+ If dario is the first thing you run against a brand-new Claude account, prime the account with a few real Claude Code commands first:
562
355
  ```bash
563
356
  claude --print "hello"
564
357
  claude --print "hello"
565
- claude --print "hello"
566
358
  ```
567
- This primes the account with legitimate Claude Code sessions. Then start dario normally. Without priming, new accounts may see billing classification issues on first use.
568
-
569
- **Do I need Bun installed?**
570
- Optional but recommended. If [Bun](https://bun.sh) is installed, dario auto-relaunches under it for TLS fingerprint fidelity with Claude Code's runtime. Without Bun, dario runs on Node.js and works fine — the TLS fingerprint is the only difference. Install Bun: `curl -fsSL https://bun.sh/install | bash`
359
+ This establishes a session baseline. Without priming, brand-new accounts occasionally see billing classification issues on first use.
571
360
 
572
361
  **What happens when my token expires?**
573
- 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.
362
+ Dario auto-refreshes tokens 30 minutes before expiry. `dario refresh` forces an immediate refresh if something goes wrong.
574
363
 
575
364
  **What happens when Anthropic rotates the OAuth client_id or URL?**
576
- 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-v2.json` and only re-scans when the binary fingerprint changes. If CC isn't installed, dario falls back to hardcoded CC 2.1.104 prod values.
365
+ 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 run — no dario release needed. Cache at `~/.dario/cc-oauth-cache-v3.json`, keyed by the CC binary fingerprint. If CC isn't installed, dario falls back to hardcoded CC 2.1.104 prod values.
577
366
 
578
367
  **I'm hitting rate limits. What do I do?**
579
- 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.
368
+ Claude subscriptions have rolling 5-hour and 7-day usage windows. Check utilization with Claude Code's `/usage` command or the [statusline](https://code.claude.com/docs/en/statusline). Dario's rate-limit errors include utilization percentages and reset times so you can see exactly when capacity returns.
580
369
 
581
370
  **My multi-agent workload is getting reclassified to overage even though dario template-replays per request. Why?**
582
- Because reclassification at high agent volume is not a per-request problem. Anthropic's classifier operates on cumulative per-OAuth-session behavioral aggregates — token throughput, conversation depth, streaming duration, inter-arrival timing, thinking-block volume. Dario can make each individual request indistinguishable from Claude Code and still hit this wall on a long-running agent session, because the wall isn't at the request level. Thorough diagnostic work on this was contributed by [@belangertrading](https://github.com/belangertrading) in [#23](https://github.com/askalf/dario/issues/23), including the per-request v3.4.3 hardening that landed as a result. For the session-layer shaping itself — multi-account pooling, session rotation, workload distribution that keeps any single account from concentrating the behavioral signal — that's what [askalf](https://askalf.org) is built for. Different layer, different tool.
583
-
584
- If you're running a multi-agent workload and consistently hitting limits, [askalf](https://askalf.org) distributes load across multiple accounts automatically.
585
-
586
- **What are the usage limits?**
587
- 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.
588
-
589
- **Can I run this on a server?**
590
- 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. If you want dario reachable from other machines on the same LAN or a Tailscale mesh, pass `--host=0.0.0.0` (or a specific interface IP) and set `DARIO_API_KEY` to gate access.
371
+ Because reclassification at high agent volume is not a per-request problem. Anthropic's classifier operates on cumulative per-OAuth-session behavioral aggregates — token throughput, conversation depth, streaming duration, inter-arrival timing, thinking-block volume. Dario can make each individual request indistinguishable from Claude Code and still hit this wall on a long-running agent session, because the wall isn't at the request level. Thorough diagnostic work on this was contributed by [@belangertrading](https://github.com/belangertrading) in [#23](https://github.com/askalf/dario/issues/23), including the per-request v3.4.3 and v3.4.5 hardening that landed as a result. For the session-layer shaping itself — multi-account pooling, session rotation, workload distribution that keeps any single account from concentrating the behavioral signal — that's what [askalf](https://askalf.org) is built for. Different layer, different tool.
591
372
 
592
373
  **Why "dario"?**
593
- Named after [Dario Amodei](https://en.wikipedia.org/wiki/Dario_Amodei), CEO of Anthropic.
594
-
595
- ## Programmatic API
596
-
597
- Use dario as a library in your own Node.js app:
598
-
599
- ```typescript
600
- import { startProxy, getAccessToken, getStatus } from "@askalf/dario";
601
-
602
- // Start the proxy programmatically
603
- await startProxy({ port: 3456, verbose: true });
604
-
605
- // Passthrough mode (OAuth swap only, no injection)
606
- await startProxy({ port: 3456, passthrough: true });
374
+ It's a name, not an acronym. Don't overthink it.
607
375
 
608
- // Preserve-tools mode (keep client tool schemas)
609
- await startProxy({ port: 3456, preserveTools: true });
610
-
611
- // Or just get a raw access token
612
- const token = await getAccessToken();
613
-
614
- // Check token health
615
- const status = await getStatus();
616
- console.log(status.expiresIn); // "11h 42m"
617
- ```
618
-
619
- ## Trust & Transparency
620
-
621
- Dario handles your OAuth tokens. Here's why you can trust it:
622
-
623
- | Signal | Status |
624
- |--------|--------|
625
- | **Source code** | ~2,000 lines of TypeScript — small enough to audit in one sitting |
626
- | **Dependencies** | 0 runtime dependencies. Verify: `npm ls --production` |
627
- | **npm provenance** | Every release is [SLSA attested](https://www.npmjs.com/package/@askalf/dario) via GitHub Actions |
628
- | **Security scanning** | [CodeQL](https://github.com/askalf/dario/actions/workflows/codeql.yml) runs on every push and weekly |
629
- | **Credential handling** | Tokens never logged, redacted from errors, stored with 0600 permissions |
630
- | **Network scope** | Binds to 127.0.0.1 by default; `--host` / `DARIO_HOST` allows LAN/mesh exposure with `DARIO_API_KEY` gating. Upstream traffic goes exclusively to `api.anthropic.com` over HTTPS |
631
- | **No telemetry** | Zero analytics, tracking, or data collection of any kind |
632
- | **Audit trail** | [CHANGELOG.md](CHANGELOG.md) documents every release |
633
- | **Branch protection** | CI must pass before merge. CODEOWNERS enforces review |
376
+ ---
634
377
 
635
- Verify the npm package matches this repo:
378
+ ## Technical Deep Dives
636
379
 
637
- ```bash
638
- # Check provenance attestation
639
- npm audit signatures 2>/dev/null; npm view @askalf/dario dist.integrity
380
+ Longer-form writing on how dario works and why it works that way:
640
381
 
641
- # Check dependency tree (should be minimal)
642
- cd $(npm root -g)/@askalf/dario && npm ls --production
643
- ```
382
+ - [v3.0 Template Replay why we stopped matching signals](https://github.com/askalf/dario/discussions/14)
383
+ - [Claude Code defaults are detection signals, not optimizations](https://github.com/askalf/dario/discussions/13)
384
+ - [Why Opus feels worse through other proxies and how to fix it](https://github.com/askalf/dario/discussions/9)
385
+ - [Billing tag algorithm and fingerprint analysis](https://github.com/askalf/dario/discussions/8)
386
+ - [Rate limit header analysis](https://github.com/askalf/dario/discussions/1)
644
387
 
645
- ## Technical Deep Dives
646
-
647
- | Topic | Link |
648
- |-------|------|
649
- | v3.0 Template Replay — why we stopped matching signals | [Discussion 14](https://github.com/askalf/dario/discussions/14) |
650
- | Claude Code defaults are detection signals, not optimizations | [Discussion 13](https://github.com/askalf/dario/discussions/13) |
651
- | Why Opus feels worse through other proxies and how to fix it | [Discussion 9](https://github.com/askalf/dario/discussions/9) |
652
- | Billing tag algorithm and fingerprint analysis | [Discussion 8](https://github.com/askalf/dario/discussions/8) |
653
- | Rate limit header analysis | [Discussion 1](https://github.com/askalf/dario/discussions/1) |
388
+ ---
654
389
 
655
390
  ## Contributing
656
391
 
657
392
  PRs welcome. The codebase is ~2,000 lines of TypeScript across 7 files:
658
393
 
659
394
  | File | Purpose |
660
- |------|---------|
395
+ |---|---|
661
396
  | `src/proxy.ts` | HTTP proxy server, rate governor, billing tag, response forwarding |
662
- | `src/cc-template.ts` | Template engine, tool mapping, orchestration sanitization |
397
+ | `src/cc-template.ts` | Template engine, tool mapping, orchestration & framework scrubbing |
663
398
  | `src/cc-template-data.json` | CC request template data (25 tools, 25KB system prompt) |
664
- | `src/cc-oauth-detect.ts` | Auto-detect OAuth config from the installed CC binary |
665
- | `src/oauth.ts` | Token storage, PKCE flow, auto-refresh, credential detection |
399
+ | `src/cc-oauth-detect.ts` | OAuth config auto-detection from the installed CC binary |
400
+ | `src/oauth.ts` | Token storage, PKCE flow, auto-refresh |
666
401
  | `src/cli.ts` | CLI entry point, command routing, Bun auto-relaunch |
667
402
  | `src/index.ts` | Library exports |
668
403
 
@@ -670,15 +405,20 @@ PRs welcome. The codebase is ~2,000 lines of TypeScript across 7 files:
670
405
  git clone https://github.com/askalf/dario
671
406
  cd dario
672
407
  npm install
673
- npm run dev # runs with tsx (no build needed)
408
+ npm run dev # runs with tsx, no build step
674
409
  ```
675
410
 
411
+ ---
412
+
676
413
  ## Contributors
677
414
 
678
415
  | Who | Contributions |
679
- |-----|---------------|
416
+ |---|---|
680
417
  | [@GodsBoy](https://github.com/GodsBoy) | Proxy authentication, token redaction, error sanitization ([#2](https://github.com/askalf/dario/pull/2)) |
681
418
  | [@belangertrading](https://github.com/belangertrading) | Billing classification investigation ([#4](https://github.com/askalf/dario/issues/4)), cache_control fingerprinting ([#6](https://github.com/askalf/dario/issues/6)), billing reclassification root cause ([#7](https://github.com/askalf/dario/issues/7)), OAuth client_id discovery ([#12](https://github.com/askalf/dario/issues/12)), multi-agent session-level billing analysis ([#23](https://github.com/askalf/dario/issues/23)) |
419
+ | [@nathan-widjaja](https://github.com/nathan-widjaja) | README positioning rewrite structure ([#21](https://github.com/askalf/dario/issues/21)) |
420
+
421
+ ---
682
422
 
683
423
  ## License
684
424
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@askalf/dario",
3
- "version": "3.4.5",
3
+ "version": "3.4.6",
4
4
  "description": "Use your Claude subscription as an API. No API key needed. Local proxy for Claude Max/Pro subscriptions.",
5
5
  "type": "module",
6
6
  "bin": {