@askalf/dario 5.4.16 → 5.4.19
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/dist/cc-template.d.ts +11 -0
- package/dist/cc-template.js +68 -0
- package/dist/live-fingerprint.d.ts +0 -6
- package/dist/live-fingerprint.js +0 -8
- package/dist/proxy.js +26 -3
- package/dist/version.d.ts +0 -2
- package/dist/version.js +0 -4
- package/docs/admin-api.md +154 -0
- package/docs/commands.md +77 -0
- package/docs/configuration.md +109 -0
- package/docs/docker.md +233 -0
- package/docs/drift-monitor.md +290 -0
- package/docs/faq.md +145 -0
- package/docs/integrations/agent-compat.md +269 -0
- package/docs/integrations/compat-matrix.md +51 -0
- package/docs/integrations/hands-walkthrough.md +295 -0
- package/docs/integrations/openclaw-walkthrough.md +248 -0
- package/docs/integrations/openhands-walkthrough.md +255 -0
- package/docs/mcp-server.md +22 -0
- package/docs/multi-account-pool.md +68 -0
- package/docs/research/system-prompt-classifier-study.md +288 -0
- package/docs/returning.md +94 -0
- package/docs/sub-agent.md +13 -0
- package/docs/system-prompt.md +107 -0
- package/docs/usage.md +123 -0
- package/docs/vpn-routing.md +108 -0
- package/docs/why-now-2026-06.md +93 -0
- package/docs/wire-fidelity.md +16 -0
- package/package.json +4 -2
package/docs/faq.md
ADDED
|
@@ -0,0 +1,145 @@
|
|
|
1
|
+
# FAQ
|
|
2
|
+
|
|
3
|
+
**Does this violate Anthropic's terms of service?**
|
|
4
|
+
Mechanically: dario's Claude backend 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. Whether any particular use complies with Anthropic's current terms of service is between you and Anthropic — consult their terms and your own subscription agreement. This project is an independent, unofficial, third-party tool and does not provide legal advice. See [DISCLAIMER.md](../DISCLAIMER.md).
|
|
5
|
+
|
|
6
|
+
**What subscription plans work on the Claude backend?**
|
|
7
|
+
Any plan whose account currently has Claude Code access — Max has it unconditionally; Pro has it as of this writing but that's an upstream decision that has moved once already (see next entry). If `claude /login` on your account works and `claude -p "hi"` returns a response on subscription billing, dario's Claude backend will work too. If Anthropic removes Claude Code from your plan tier, dario's Claude backend stops working on that account — there is nothing dario can do at the client side to change that. Swap to a plan with Claude Code access, or use an OpenAI-compat backend instead.
|
|
8
|
+
|
|
9
|
+
**Is it true Anthropic removed Claude Code from Pro plans?**
|
|
10
|
+
On 2026-04-21 Anthropic temporarily removed Claude Code from new Pro signups, per [wheresyoured.at](https://www.wheresyoured.at/news-anthropic-removes-pro-cc/). Existing Pro users reportedly kept access; Anthropic's Head of Growth characterized it as "a small test of 2% of new prosumer signups," and the change was reversed at an unknown time. If you are a Pro user and dario's Claude backend stops billing against your subscription without warning, this is the class of thing to check — run `claude -p "hi"` directly and see whether Anthropic itself routes you to subscription billing. If they don't, dario can't either. The practical mitigation on dario's side is [multi-account pool mode](./multi-account-pool.md) — having a backup account on a plan Anthropic hasn't moved the goalposts on, so a single plan-tier change doesn't take all your traffic down at once.
|
|
11
|
+
|
|
12
|
+
**Does it work with Team / Enterprise?**
|
|
13
|
+
Yes — tested and confirmed working as long as your plan includes Claude Code access.
|
|
14
|
+
|
|
15
|
+
**Anthropic announced that `claude -p` and Agent SDK usage would move to a separate credit pool on 2026-06-15. Did that break dario's Claude backend?**
|
|
16
|
+
No — and the split itself was **paused before it took effect**. Anthropic announced it 2026-05-13, scheduled it for 2026-06-15, then paused it before that date; the Help Center now states Agent-SDK and `claude -p` usage continue drawing from your existing subscription pool unchanged, with a promise of advance notice before any revised version. So today `claude -p` and the Agent SDK still bill subscription whether or not you use dario.
|
|
17
|
+
|
|
18
|
+
dario is built to hold either way. The Claude backend sends every request as **interactive Claude Code** wire-shape — full template replay of headers, body key order, TLS ClientHello, session-id lifecycle, inter-request timing. The upstream billing classifier sees an interactive CC session regardless of which local tool (claude -p subprocess, Agent SDK app, Cline, Aider, your own scripts) originated the call. That's the entire point of the wire-fidelity work in [`wire-fidelity.md`](./wire-fidelity.md), and it predates the announcement.
|
|
19
|
+
|
|
20
|
+
What that means in practice:
|
|
21
|
+
|
|
22
|
+
- Workloads that route through dario bill against your **subscription pool** (Pro $20, Max 5x $100, Max 20x $200) — the same today as before the announcement, and the same if a revised split ships later.
|
|
23
|
+
- If the split does return, workloads that bypass dario and call `claude -p` directly would count against the **separate credit pool** (a fixed monthly grant rather than the rolling subscription bucket — and once exhausted, metered API pricing). Right now, paused, they bill subscription like everything else.
|
|
24
|
+
- Workloads that use the Agent SDK with API keys are unaffected either way (already metered API).
|
|
25
|
+
|
|
26
|
+
Two questions to verify at any time — and the exact check to run the day a revived split lands:
|
|
27
|
+
|
|
28
|
+
1. **Is dario's traffic still landing in the subscription bucket?** Run `claude -p "hi"` directly (no dario), check `representative-claim` and related rate-limit headers — that tells you the bucket Anthropic put the direct call in. Then run the same prompt through dario and check the same headers. Both should show a subscription bucket (`five_hour` / `seven_day`). If dario's path ever shows an agent-credit or `overage` bucket, file an issue — that's the drift the live template extractor, the [drift detector](./../scripts/capture-full-body.mjs), and the daily billing-classifier canary exist to catch (the canary runs this exact check automatically and opens an issue on a bad bucket).
|
|
29
|
+
2. **Did Anthropic tighten OAuth-token classification?** If access-token bearer alone ever signals "non-interactive," dario would have to add session affinity or a re-auth dance. The same rate-limit-header diagnostic surfaces it. None of this is observed today.
|
|
30
|
+
|
|
31
|
+
No config change is needed on the user side, split or no split — same install, same `localhost:3456`, same `ANTHROPIC_BASE_URL=http://localhost:3456` env var.
|
|
32
|
+
|
|
33
|
+
**Do I need Claude Code installed?**
|
|
34
|
+
Recommended for the Claude backend, not strictly required. With CC installed, `dario login` picks up your credentials automatically, and the live template extractor reads your CC binary on every startup so the template stays current. Without CC, dario runs its own OAuth flow and falls back to the bundled template snapshot (scrubbed of host context at bake time as of v3.21). Drift detection warns you if your installed CC doesn't match the captured template, so upgrade windows don't silently ship stale templates.
|
|
35
|
+
|
|
36
|
+
**Do I need Bun?**
|
|
37
|
+
Optional, strongly recommended for Claude-backend requests. Dario auto-relaunches under Bun when available so the TLS ClientHello matches CC's runtime. Without Bun, dario runs on Node.js and works fine — the TLS ClientHello is the only observable difference. As of v3.23, `dario doctor` surfaces the mismatch explicitly and `--strict-tls` refuses to start proxy mode until it's resolved.
|
|
38
|
+
|
|
39
|
+
**Can I use dario without a Claude subscription?**
|
|
40
|
+
Yes. Skip `dario login`, just run `dario backend add openai --key=...` (or any OpenAI-compat URL) and `dario proxy`. Claude-backend requests will return an authentication error; OpenAI-compat requests will work normally. Dario becomes a local OpenAI-compat router with no Claude involvement.
|
|
41
|
+
|
|
42
|
+
**Can I route non-OpenAI providers through dario?**
|
|
43
|
+
Yes — anything that speaks the OpenAI Chat Completions API. Groq, OpenRouter, LiteLLM, vLLM, Ollama's openai-compat mode, your own vLLM server, any hosted inference endpoint that exposes `/v1/chat/completions`. Just `dario backend add <name> --key=... --base-url=...`.
|
|
44
|
+
|
|
45
|
+
**My subscription usage through dario is higher than running Claude Code directly. Why?**
|
|
46
|
+
Two things drive this, and neither is proxy overhead — on the genuine-Claude-Code path dario forwards your request verbatim (system prompt + tools), adding only a ~20-token billing tag. First, the dominant cost on any cold turn is your **own** system prompt: agent harnesses (OpenClaw, context-mode, custom frameworks) can inject 100K+ tokens of instructions, and dario relays them byte-for-byte, so they cost the same sent direct. Second is the **prompt-cache TTL**. Anthropic caches your system+tools prefix so repeat turns read it warm instead of rebuilding — but the default lifetime is **5 minutes**. Interactive Claude Code on a subscription requests a **1-hour** TTL (`cache_control:{"type":"ephemeral","ttl":"1h"}` plus the `extended-cache-ttl-2025-04-11` beta); many SDK/agent harnesses only send the bare 5-minute stamp. dario mirrors exactly what your client sends — so if your harness sends 5m and you leave gaps longer than 5 minutes between messages, the prefix expires and is re-created every time. (Quick check: two messages **30 seconds** apart should be cheap; two messages **6 minutes** apart on a 5-minute stamp both pay full creation — that gap is the cost, not dario.)
|
|
47
|
+
|
|
48
|
+
Fixes, cheapest first:
|
|
49
|
+
- Keep turns within 5 minutes where you can — the prefix stays cached.
|
|
50
|
+
- Trim the injected system prompt; it's the biggest line item on every cold turn.
|
|
51
|
+
- Have your harness emit the 1-hour stamp + the `extended-cache-ttl-2025-04-11` beta — dario mirrors it and the prefix survives idle gaps.
|
|
52
|
+
- If the harness can't, set **`DARIO_CACHE_TTL_1H=1`**: dario forces the 1-hour TTL (and adds the enabling beta) on every request. Tradeoff — 1-hour cache *writes* bill ~2× the 5-minute rate, so it only wins when your idle gaps routinely exceed 5 minutes; on rapid back-to-back turns it costs more. `DARIO_CACHE_TTL_5M=1` forces the opposite (always 5m). Background: [#678](https://github.com/askalf/dario/issues/678).
|
|
53
|
+
|
|
54
|
+
**Delivering the env var:** it has to reach dario's own process. Running directly, prefix it — `DARIO_CACHE_TTL_1H=1 dario proxy …`. In **Docker / Compose**, put it in the container's `environment:` (or `env_file:`) — a value only in a host `.env` that the compose file doesn't pass through never reaches the process, and the flag is silently a no-op. Confirm it landed with `docker exec <container> printenv DARIO_CACHE_TTL_1H` (expect `1`).
|
|
55
|
+
|
|
56
|
+
**Something's wrong. Where do I start?**
|
|
57
|
+
`dario doctor`. One command, one aggregated report — dario version, Node, platform, runtime/TLS classification, CC binary compat, template source + age + drift, OAuth status, pool state, backends, sub-agent install state, home dir. Exit code 1 if any check fails. Paste the output when you file an issue. (If you're inside Claude Code, `dario subagent install` once and then ask CC to "use the dario sub-agent to run doctor" — same output, no context switch.)
|
|
58
|
+
|
|
59
|
+
**OpenClaw returns 401 after I set `DARIO_API_KEY` (or upgrade past v3.30.6).**
|
|
60
|
+
If you run `dario proxy --host=0.0.0.0` (non-loopback), dario requires `DARIO_API_KEY` to be set so it's not an open subscription relay. OpenClaw 2026.2.17+ prefers `~/.openclaw/agents/main/agent/auth-profiles.json` over `openclaw.json`'s `apiKey` field or the `ANTHROPIC_API_KEY` env var — so if you have a stale Anthropic token in `auth-profiles.json` from an earlier setup, OpenClaw sends *that* token instead of `dario`, and dario rejects the request with `Authorization present but value mismatch` (visible under `dario proxy -v`, added in v3.31.2).
|
|
61
|
+
|
|
62
|
+
Three fixes, in order of simplicity:
|
|
63
|
+
|
|
64
|
+
1. **Use loopback.** `dario proxy --host=127.0.0.1` — auth only enforced on non-loopback binds, no `DARIO_API_KEY` required, no OpenClaw changes. Best if you don't actually need LAN reach to dario.
|
|
65
|
+
2. **Delete the Anthropic auth profile.** Remove the `"anthropic:default"` entry from `~/.openclaw/agents/main/agent/auth-profiles.json`. OpenClaw then falls back through the config chain and picks up `ANTHROPIC_API_KEY=dario` from the env. Confirmed working by [@tetsuco in #97](https://github.com/askalf/dario/issues/97).
|
|
66
|
+
3. **Overwrite the auth profile.** `openclaw models auth paste-token --provider anthropic` and paste `dario`. Replaces whatever key was in there — keep a backup if you use it elsewhere.
|
|
67
|
+
|
|
68
|
+
Diagnose with `dario proxy -v` — the reject log (v3.31.2+) reports header-name only (never the value, since it may be a real credential you mistyped) and tells you which of the three configs is actually being hit.
|
|
69
|
+
|
|
70
|
+
**Claude Code's WebFetch fails on every domain with "Unable to verify if domain … is safe to fetch."**
|
|
71
|
+
Not a dario issue — dario is not in this code path, and no dario configuration can affect it. Before fetching a URL, Claude Code runs a domain-safety preflight: a direct call to `https://api.anthropic.com/api/web/domain_info?domain=…` (older builds used `claude.ai`, which the error text still names). That URL is absolute, so it ignores `ANTHROPIC_BASE_URL` entirely — the preflight never reaches dario, and only the real fetch happens after it passes. The error means the preflight *request itself* failed to complete, not that the domain is blocklisted — common in proxy setups, headless/CI boxes, and networks where that direct call can't succeed.
|
|
72
|
+
|
|
73
|
+
Fix: skip the preflight. Add to `~/.claude/settings.json` (or the project's `.claude/settings.json`) and restart Claude Code:
|
|
74
|
+
|
|
75
|
+
```json
|
|
76
|
+
{ "skipWebFetchPreflight": true }
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
The setting is Claude Code's own, meant for "enterprise environments with restrictive security policies"; with it set, WebFetch skips the domain check and fetches directly. Granting `Bash(curl:*)` so CC falls back to curl works too. Background: [#822](https://github.com/askalf/dario/issues/822).
|
|
80
|
+
|
|
81
|
+
**My RDP / RemotePC session randomly drops while claude is working. Logs say `error 121` / `0x80070079` / "ERROR_SEM_TIMEOUT". Network is otherwise fine — other devices don't drop, gateway pings are clean.**
|
|
82
|
+
Cause: heavy claude tool work bursts CPU on a small machine, the kernel network IO threads can't get scheduled, the RDP socket write times out, your session drops. The drops are real but the network path is not — they're caused by CPU starvation above the NIC layer, which is why every adapter (Ethernet, Wi-Fi, USB Wi-Fi) drops the same way. Confirmed pattern when running claude on a 4-core / 4-thread CPU you're RDP'd into.
|
|
83
|
+
|
|
84
|
+
Two fixes, in order of progressively-stronger:
|
|
85
|
+
|
|
86
|
+
1. **Lower claude's scheduling priority so the kernel can preempt it for network IO.** On Windows, launch it below-normal — `start /belownormal /b claude` (cmd), or set it after spawn with `(Get-Process claude).PriorityClass = 'BelowNormal'` (or Process Lasso for permanence). Same throughput when nothing else needs CPU. Escalate to `Idle` priority if drops continue — claude then only runs when nothing else is ready (~5-10% slower agent loops in practice). *(Before v5.0, `dario shim --priority=below-normal -- claude` did this for you; shim was removed in v5.0 — set the priority via the OS instead.)*
|
|
87
|
+
2. **Reserve a CPU core for the OS.** On Windows, `(Get-Process claude).ProcessorAffinity = 0x07` reserves logical CPU 3 (mask covers cores 0-2). Set after spawn or via Process Lasso for permanence. On a 4-core/4-thread machine, this guarantees the kernel always has a free core for network IO no matter what claude does.
|
|
88
|
+
|
|
89
|
+
If drops continue past all three: the underlying cause is hardware capacity. The same workload on a modern 8C/16T machine will not exhibit this. Move the heavy claude session off the RDP host, or upgrade the host.
|
|
90
|
+
|
|
91
|
+
**What happens when Anthropic rotates the OAuth config?**
|
|
92
|
+
Dario auto-detects OAuth config from the installed Claude Code binary. When CC ships a new version with rotated values, dario picks them up on the next run. Cache at `~/.dario/cc-oauth-cache-v6.json`, keyed by the CC binary fingerprint. The cache path version bumps each time the canonical OAuth config shape changes so stale caches regenerate automatically on upgrade — v3 → v4 in v3.19.4 (scope-list flip CC v2.1.104 → v2.1.107), v4 → v5 in v3.31.3 (authorize URL `claude.com/cai/` → `claude.ai/` host normalization), v5 → v6 in v3.31.4 (6-scope restore after CC v2.1.116).
|
|
93
|
+
|
|
94
|
+
If Anthropic rotates the values before the detector is updated, you can temporarily override any field with env vars (`DARIO_OAUTH_CLIENT_ID`, `DARIO_OAUTH_AUTHORIZE_URL`, `DARIO_OAUTH_TOKEN_URL`, `DARIO_OAUTH_SCOPES`) or by writing `~/.dario/oauth-config.override.json`:
|
|
95
|
+
|
|
96
|
+
```json
|
|
97
|
+
{
|
|
98
|
+
"clientId": "...",
|
|
99
|
+
"authorizeUrl": "https://claude.com/cai/oauth/authorize",
|
|
100
|
+
"tokenUrl": "https://platform.claude.com/v1/oauth/token",
|
|
101
|
+
"scopes": "user:profile user:inference user:sessions:claude_code user:mcp_servers user:file_upload"
|
|
102
|
+
}
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
Env vars win over the file. Set `DARIO_OAUTH_DISABLE_OVERRIDE=1` to force pure auto-detection.
|
|
106
|
+
|
|
107
|
+
**What happens when Anthropic changes the CC request template?**
|
|
108
|
+
Dario extracts the live request template from your installed Claude Code binary on startup — the system prompt, tool schemas, user-agent, beta flags, header insertion order, static header values, and top-level request-body key order — and uses those to replay requests instead of a version pinned into dario itself. When CC ships a new version with a tweaked template, the next `dario proxy` run picks it up automatically. Drift detection forces a refresh when the installed CC version changes under dario, and the nightly `cc-drift-watch` workflow catches upstream rotations (client_id, URLs, tool set, version) the day they ship on npm.
|
|
109
|
+
|
|
110
|
+
**Why does `dario accounts list` show an account called `login` I never added?**
|
|
111
|
+
That's your `dario login` credentials, materialized into the pool automatically. As of v5.0 the account pool is dario's one credential model, so a plain `dario login` is a **pool of one** stored as `~/.dario/accounts/login.json` under the reserved `login` alias — the back-fill runs on `dario login` itself and again on `dario proxy` startup. Your original `~/.dario/credentials.json` is untouched (the copy is one-way), so `dario accounts remove login` is safe if you don't want it pooled — the next `dario login` / `dario proxy` just re-materializes it. See [The account pool](./multi-account-pool.md) for the full picture.
|
|
112
|
+
|
|
113
|
+
**First time setup on a fresh Claude account.**
|
|
114
|
+
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:
|
|
115
|
+
```bash
|
|
116
|
+
claude --print "hello"
|
|
117
|
+
claude --print "hello"
|
|
118
|
+
```
|
|
119
|
+
This establishes a session baseline. Without priming, brand-new accounts occasionally see billing classification issues on first use.
|
|
120
|
+
|
|
121
|
+
**I'm hitting rate limits on the Claude backend. What do I do?**
|
|
122
|
+
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). For multi-agent workloads, add more accounts and let pool mode distribute the load: `dario accounts add <alias>`. Session stickiness keeps long conversations pinned to one account so the prompt cache isn't destroyed by rotation.
|
|
123
|
+
|
|
124
|
+
**I'm seeing `representative-claim: seven_day` in my rate-limit headers instead of `five_hour`. Am I being downgraded to API billing?**
|
|
125
|
+
|
|
126
|
+
**No.** You're still on subscription billing. Both `five_hour` and `seven_day` are the same subscription billing mode — two different accounting buckets inside it.
|
|
127
|
+
|
|
128
|
+
| Claim | What it means |
|
|
129
|
+
|---|---|
|
|
130
|
+
| `five_hour` | You're well inside your 5-hour window; billing against the short-term bucket. |
|
|
131
|
+
| `seven_day` | You've exhausted (or come close to exhausting) the 5-hour window for this rolling cycle, so Anthropic is charging this request against the 7-day bucket. **Still subscription billing. Still your plan.** Not API pricing, not overage. |
|
|
132
|
+
| `overage` | Both subscription windows are effectively exhausted. *This* is where per-token Extra Usage charges kick in — if you've enabled Extra Usage on the account. If not, you get 429'd instead. |
|
|
133
|
+
|
|
134
|
+
Seeing `seven_day` is a healthy state. Your Max plan is doing exactly what it's supposed to do: letting you keep working past short bursts of heavy use by absorbing them into the larger 7-day bucket. When your 5-hour window rolls forward enough, the claim on new requests will go back to `five_hour` on its own. If the 7-day bucket is painful, add more Claude subscriptions to the pool — each account has its own independent 5h/7d windows, and pool mode routes each request to the account with the most headroom.
|
|
135
|
+
|
|
136
|
+
Standalone writeup: [Discussion #1 — full rate-limit-header breakdown](https://github.com/askalf/dario/discussions/1).
|
|
137
|
+
|
|
138
|
+
**My multi-agent workload is getting reclassified to overage even though dario mirrors the CC wire shape per request. Why?**
|
|
139
|
+
Reclassification at high agent volume is not a per-request problem. The upstream billing logic takes cumulative per-OAuth-session aggregates into account — token throughput, conversation depth, streaming duration, inter-arrival timing, thinking-block volume. Dario's Claude backend can make each individual request match Claude Code and still hit this wall on a long-running agent session. Thorough diagnostic work was contributed by [@belangertrading](https://github.com/belangertrading) in [#23](https://github.com/askalf/dario/issues/23). The practical answer at the dario layer is **pool mode** — distribute load across multiple subscriptions so no single account accumulates signal along any single dimension. See [Multi-account pool mode](./multi-account-pool.md). The v3.22 – v3.28 wire-fidelity track (pacing, stream-drain, session-id lifecycle) also narrows the cumulative signal on a single account — see [Wire-fidelity axes](./wire-fidelity.md).
|
|
140
|
+
|
|
141
|
+
**My proxy is on Node, not Bun. What's the actual risk?**
|
|
142
|
+
Node uses OpenSSL, Bun uses BoringSSL — the TLS ClientHello differs enough to yield a distinct JA3/JA4 hash. The upstream service can see the hash. Whether any routing decisions depend on it today is not published; making the axis visible is the v3.23 contribution. If certainty matters to you, install Bun (dario auto-relaunches under it) or run `dario proxy --strict-tls` to fail loud. If it doesn't, the warning is ignorable — dario still works, the TLS ClientHello is just the one observable axis left.
|
|
143
|
+
|
|
144
|
+
**Why "dario"?**
|
|
145
|
+
It's a name, not an acronym. Don't overthink it.
|
|
@@ -0,0 +1,269 @@
|
|
|
1
|
+
# Agent compatibility
|
|
2
|
+
|
|
3
|
+
Dario's built-in `TOOL_MAP` carries **66 schema-verified entries** covering the tool schemas of every major coding agent. On the Claude backend, tool calls translate to CC's native `Bash / Read / Write / Edit / Glob / Grep / WebSearch / WebFetch` on the outbound path (so the request stays on the subscription wire shape) and rebuild to your agent's exact expected shape on the inbound path (so your validator is happy). No flag required.
|
|
4
|
+
|
|
5
|
+
For a one-page status table of every tool dario supports — working / inferred / untested — see [`compat-matrix.md`](./compat-matrix.md). This page covers per-tool setup; the matrix covers "does it work?" at a glance.
|
|
6
|
+
|
|
7
|
+
| Agent | Covered tool names (subset) |
|
|
8
|
+
|---|---|
|
|
9
|
+
| Claude Code / Claude Agent SDK | default — CC / SDK tools (same schema as of CC v2.1.114 / `@anthropic-ai/claude-agent-sdk@0.2.x`) |
|
|
10
|
+
| Cline / Roo Code / Kilo Code | `execute_command`, `write_to_file`, `replace_in_file`, `apply_diff`, `list_files`, `search_files`, `read_file` |
|
|
11
|
+
| Cursor | `run_terminal_cmd`, `edit_file`, `search_replace`, `codebase_search`, `grep_search`, `file_search`, `list_dir`, `read_file` (`target_file`) |
|
|
12
|
+
| Windsurf | `run_command`, `view_file`, `write_to_file`, `replace_file_content`, `find_by_name`, `grep_search`, `list_dir`, `search_web`, `read_url_content` |
|
|
13
|
+
| Continue.dev | `builtin_run_terminal_command`, `builtin_read_file`, `builtin_create_new_file`, `builtin_edit_existing_file`, `builtin_file_glob_search`, `builtin_grep_search`, `builtin_ls` |
|
|
14
|
+
| GitHub Copilot | `run_in_terminal`, `insert_edit_into_file`, `semantic_search`, `codebase_search`, `list_dir`, `fetch_webpage` |
|
|
15
|
+
| OpenHands | `execute_bash`, `str_replace_editor` |
|
|
16
|
+
| OpenClaw | `exec`, `process`, `web_search`, `web_fetch`, `browser`, `message` |
|
|
17
|
+
| hands ([askalf/hands](https://github.com/askalf/hands)) | Anthropic beta computer-use tools (`computer`, `bash`, `str_replace_based_edit_tool`) — auto-preserved via system-prompt identity match (v3.33.0) |
|
|
18
|
+
| Hermes Agent (Nous Research) | `terminal`, `process`, `read_file`, `write_file`, `patch`, `search_files`, `web_search`, `web_extract`, `todo` mapped directly. Hermes-specific tools (`browser_*`, `vision_analyze`, `image_generate`, `skill_*`, `memory`, `session_search`, `cronjob`, `send_message`, `ha_*`, `mixture_of_agents`, `delegate_task`, `execute_code`, `text_to_speech`) have no CC equivalent and auto-preserve through the identity detector. Also consider `--max-tokens=client` so Hermes's 64k/128k per-model caps survive dario's outbound pin. |
|
|
19
|
+
|
|
20
|
+
Text-tool clients (Cline / Kilo Code / Roo Code and forks) are auto-detected via system-prompt identity markers and automatically flipped into preserve-tools mode, because mixing CC's `tools` array with their XML protocol makes the model emit `<function_calls><invoke>` that their parsers can't read. The same identity path also catches `hands` (askalf's computer-use agent) — its tool names overlap with `TOOL_MAP` but its schemas diverge, so identity match → preserve-tools is the only correct routing. If you run dario specifically for wire-level fidelity and would rather pick `--preserve-tools` yourself, `--no-auto-detect` (v3.20.1, aka `--no-auto-preserve`) disables the heuristic — explicit operator choice then wins.
|
|
21
|
+
|
|
22
|
+
Beyond the identity path, dario falls back to a **structural** check: when a request carries 3+ tools and ≥80% of them aren't in `TOOL_MAP`, that's a custom client whose tool surface has effectively no overlap with CC's, and round-robin remap onto CC fallback slots silently corrupts the calls. The structural fallback flips those requests to preserve-tools too, with `client: 'unknown-non-cc'` in the request log. This catches in-house agents and OpenClaw derivatives that we haven't added an explicit pattern for, without needing per-client maintenance. `--no-auto-detect` disables both paths.
|
|
23
|
+
|
|
24
|
+
Platform-scoped CC natives (`PowerShell`, `Glob`, `Grep` — win32-only in CC's own tool list) map by the **client's** declaration, not the proxy host's platform (v4.8.136): a win32 CC client through a Linux-hosted dario gets their canonical definitions instead of having them dropped from the advertised array.
|
|
25
|
+
|
|
26
|
+
MCP tools take a third path: anything named `mcp__<server>__<tool>` is neither remapped nor flipped to preserve — it forwards **verbatim** and its calls flow back untouched (v4.8.135). That's what real CC does with session-attached MCP servers; their schemas are operator-supplied and have no canonical template entry, so passthrough *is* the CC wire shape. Before this, a CC session with an MCP server attached had its `mcp__*` surface dropped from the advertised array and its history references round-robined onto fallback slots (`tool substitution: 28/52 client tools not in TOOL_MAP` in the live log), and two or three attached servers were enough to trip the 80% structural threshold on their own. MCP names no longer count toward that threshold.
|
|
27
|
+
|
|
28
|
+
If your agent's tool names aren't pre-mapped and its tools carry fields CC's schema doesn't have, there are two escape hatches: **`--preserve-tools`** (forward your schema verbatim, lose the CC wire shape) or **`--hybrid-tools`** (keep the CC wire shape, fill request-context fields from headers). See [Custom tool schemas](#custom-tool-schemas).
|
|
29
|
+
|
|
30
|
+
The OpenAI-compat backend forwards tool definitions byte-for-byte and doesn't need any of this.
|
|
31
|
+
|
|
32
|
+
## Per-tool setup
|
|
33
|
+
|
|
34
|
+
### Cursor
|
|
35
|
+
|
|
36
|
+
> **⚠️ Architectural mismatch (read this before configuring)**
|
|
37
|
+
>
|
|
38
|
+
> Cursor's BYOK is **backend-mediated**, not client-side. When you set "Override OpenAI Base URL" in Cursor, the Electron app sends that URL up to Cursor's own backend (`api2.cursor.sh`), and **Cursor's servers** make the outbound LLM call — not your machine. Their backend has an SSRF (Server-Side Request Forgery) guard that rejects RFC1918 + loopback addresses by design, so `http://localhost:3456` is structurally unreachable. The error surfaces as either `Provider returned error: Access to private networks is forbidden` (older form) or `{"error":{"type":"client","reason":"ssrf_blocked","message":"connection to private IP is blocked"}}` (current form).
|
|
39
|
+
>
|
|
40
|
+
> Confirmed by Cursor staff in their own words across multiple forum threads — Colin, Feb 9 2026: *"we have SSRF (Server-Side Request Forgery) protection that blocks connections to private/internal IP ranges"* ([thread](https://forum.cursor.com/t/cannot-connect-to-self-hosted-llm)); Dean Rie, Jan 20 2026: *"BYOK API keys work through Cursor's backend. All requests go through our servers"* ([thread](https://forum.cursor.com/t/use-on-prem-model/149334)). No fix ETA. dario#190 + every other local-proxy project (e.g. [mergd/ccproxy](https://github.com/mergd/ccproxy)) hits the same wall.
|
|
41
|
+
>
|
|
42
|
+
> **The simple path:** if you want a frictionless setup, use Claude Code, Continue.dev, OpenHands, Aider, Cline, or Zed instead (sections below). Those clients make the outbound call from your machine, so `http://localhost:3456` Just Works — no tunnel required.
|
|
43
|
+
>
|
|
44
|
+
> **The Cursor path:** expose dario behind a public HTTPS tunnel (cloudflared, ngrok, etc.) so Cursor's backend can reach it. Walkthrough below.
|
|
45
|
+
|
|
46
|
+
#### 1. Expose dario via a public HTTPS tunnel
|
|
47
|
+
|
|
48
|
+
In two terminals:
|
|
49
|
+
|
|
50
|
+
```bash
|
|
51
|
+
# Terminal 1 — dario as usual
|
|
52
|
+
dario proxy --verbose
|
|
53
|
+
|
|
54
|
+
# Terminal 2 — cloudflared quick tunnel (free, no signup)
|
|
55
|
+
cloudflared tunnel --url http://localhost:3456
|
|
56
|
+
# → prints something like https://random-words-here.trycloudflare.com
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
Copy the `https://...trycloudflare.com` URL — you'll paste it into Cursor next.
|
|
60
|
+
|
|
61
|
+
> **🔐 The tunnel URL is a credential.** `.trycloudflare.com` URLs are unauthenticated by default — anyone who learns the URL can spend your Claude subscription against it. Random subdomains keep casual exposure low-risk, but **don't paste it publicly, and kill the tunnel when you're done.** For anything beyond a quick test:
|
|
62
|
+
> - ngrok with `--basic-auth` or a reserved domain + auth, or
|
|
63
|
+
> - Named cloudflared tunnels behind [Cloudflare Access](https://developers.cloudflare.com/cloudflare-one/applications/configure-apps/self-hosted-public-app/) policies, or
|
|
64
|
+
> - dario behind your own VPS reverse proxy with TLS + auth.
|
|
65
|
+
|
|
66
|
+
#### 2. Configure Cursor
|
|
67
|
+
|
|
68
|
+
**Cmd/Ctrl + ,** → **Models**. Under the **OpenAI API Key** section:
|
|
69
|
+
|
|
70
|
+
- Check **Override OpenAI Base URL**: `https://random-words-here.trycloudflare.com/v1` *(your tunnel URL + `/v1`; the checkbox must be enabled, not just the field populated)*
|
|
71
|
+
- API key: `dario`
|
|
72
|
+
- *(Recent Cursor versions removed the explicit "Verify" button — the green toggle on its own is sufficient.)*
|
|
73
|
+
|
|
74
|
+
#### 3. Add models — use `anthropic:` (not `claude:`) to keep tool-format intact
|
|
75
|
+
|
|
76
|
+
Two name gotchas to dodge in this step. Both are about Cursor's behavior, not dario's.
|
|
77
|
+
|
|
78
|
+
**Gotcha A — built-in name collision.** Cursor recognizes any model name it ships natively (e.g., `claude-opus-4-7`, `claude-sonnet-4-6`, `claude-haiku-4-5`, `gpt-5`, `gpt-4o`). Add one of those raw and Cursor pops a *"this model is already available as Opus 4.7"* toast and silently routes it through **its own** Anthropic gateway — billing your Cursor API credits, never reaching the override URL. The Override OpenAI Base URL only takes effect for model names Cursor does **not** recognize as built-ins.
|
|
79
|
+
|
|
80
|
+
**Gotcha B — Anthropic-format-switcher (matters for Agent mode).** Cursor inspects the model-name string and switches its outbound tool-call format based on substring match. From Cursor staff Dean Rie: *"When Cursor sees a model name like `claude-*`, it switches to a Claude-specific tool-calling format, which isn't compatible with OpenAI-compatible API endpoints"* ([forum thread](https://forum.cursor.com/t/using-byok-in-agent-mode-with-claude-opus-4-5-not-apply-to-file/148018)). So `claude:claude-opus-4-7` (or any name containing `claude-`) makes Cursor send Anthropic-shape tool blocks to the OpenAI-compat `/v1/chat/completions` endpoint — dario's OpenAI-compat handler can't parse those, the model receives a confused tool surface, and you get text-form tool calls in the response instead of structured edits. dario#190 is the canonical case.
|
|
81
|
+
|
|
82
|
+
Use the [provider prefix](./usage.md#provider-prefix) form that dodges **both** gotchas:
|
|
83
|
+
|
|
84
|
+
- **Claude** — `anthropic:opus`, `anthropic:sonnet`, `anthropic:haiku` (or full IDs: `anthropic:claude-opus-5` / `anthropic:claude-sonnet-5` / `anthropic:claude-haiku-4-5`). The `anthropic:` prefix routes through dario's Claude backend identically to `claude:`, but the visible model name doesn't contain the `claude-` substring, so Cursor ships OpenAI-shape `tool_calls` and dario's translator handles them cleanly.
|
|
85
|
+
- **OpenAI** *(if you've run `dario backend add openai --key=sk-...`)* — `openai:gpt-4o`, `openai:gpt-5`, `openai:o1`, etc. The `openai:` prefix dodges Cursor's `gpt-*` collision the same way.
|
|
86
|
+
- **Other OpenAI-compat backends** *(Groq, OpenRouter, local LiteLLM, Ollama, etc.)* — `groq:llama-3.3-70b`, `openrouter:moonshotai/kimi-k2`, `local:qwen-coder-32b`, etc.
|
|
87
|
+
|
|
88
|
+
dario v3.36+ resolves `anthropic:fable`/`opus`/`sonnet`/`haiku` (and `fable1m`/`opus1m`/`sonnet1m`) shortcuts to canonical Anthropic model IDs at request time. Older dario versions (≤ v3.35) need the full canonical form: `anthropic:claude-opus-4-7` etc.
|
|
89
|
+
|
|
90
|
+
> **Older docs / muscle memory note:** earlier versions of this guide recommended the `claude:` prefix. That works fine on tool-less Chat (Gotcha B doesn't fire when no tools are sent) but breaks Agent mode. Prefer `anthropic:` going forward — it's drop-in compatible with every dario version that supports `claude:`.
|
|
91
|
+
|
|
92
|
+
Select one of the registered models in Cursor's model picker.
|
|
93
|
+
|
|
94
|
+
#### 4. Use **Agent mode**, not Chat — Chat doesn't pass tools to BYOK models
|
|
95
|
+
|
|
96
|
+
Cursor's surfaces handle tools differently:
|
|
97
|
+
|
|
98
|
+
| Surface | Shortcut | Tools forwarded to BYOK? |
|
|
99
|
+
|---|---|---|
|
|
100
|
+
| Chat (right-pane chat tab) | — | No — chat-only, no `tools` array sent |
|
|
101
|
+
| Agent / Composer (Cmd-I) | **Cmd-I** (Mac) / **Ctrl-I** (Windows/Linux) | **Yes** — full `tools` array sent in OpenAI function-calling format |
|
|
102
|
+
| Tab Apply (autocomplete) | — | First-party model, BYOK ignored |
|
|
103
|
+
| Cmd-K (inline) | Cmd-K / Ctrl-K | Variable; uses its own model selection |
|
|
104
|
+
|
|
105
|
+
If you point dario at the **Chat** surface, the request body has no `tools` array, but dario still replays Claude Code's full system prompt (which tells the model "you have Bash/Read/Write/Edit/Grep/Glob…") — the model improvises by narrating tool calls in plain text. Same root cause as the *"system instructs me to default to no comments…"* leak: the model is decision-narrating because the wire shape it expected (full agent harness) doesn't match what arrived (plain chat with no tools).
|
|
106
|
+
|
|
107
|
+
**For agent-style work, open Cmd-I / Ctrl-I (Agent / Composer pane), not the Chat tab.** Pick one of the `anthropic:*` models in the picker and send your request. dario's logs should show the request/response cycle for each tool call, with `tool_use` blocks translated to OpenAI `tool_calls` on the way back to Cursor.
|
|
108
|
+
|
|
109
|
+
#### 5. Verify
|
|
110
|
+
|
|
111
|
+
With `dario proxy --verbose` running, send a test message in Cursor's **Agent** pane. You should see:
|
|
112
|
+
|
|
113
|
+
- A `provider prefix: anthropic:opus → claude backend with model claude-opus-5` line in dario's logs
|
|
114
|
+
- One or more `POST /v1/chat/completions` lines per turn (one per tool round-trip)
|
|
115
|
+
- An incremented request count in `dario doctor --usage`
|
|
116
|
+
|
|
117
|
+
If dario's logs stay silent and `Usage 5h (all)` stays at `0.0%`, the request never reached the tunnel. Three likely causes:
|
|
118
|
+
|
|
119
|
+
- **`Access to private networks is forbidden` / `ssrf_blocked` error in Cursor** — you pasted the `localhost:3456` URL, not the tunnel URL. Check step 2.
|
|
120
|
+
- **Cursor's name-collision toast fired** — the model name you added matches a Cursor built-in (Gotcha A). Use the `anthropic:` form (step 3).
|
|
121
|
+
- **You're testing in Chat, not Agent** — open Cmd-I / Ctrl-I and test there (step 4).
|
|
122
|
+
|
|
123
|
+
If logs show traffic but the model emits text-form tool calls (`Tool: Read\n{"file_path":...}`) instead of structured calls, you're hitting Gotcha B — your model name still contains `claude-`. Switch to `anthropic:opus` etc. (step 3).
|
|
124
|
+
|
|
125
|
+
**Why no "Override Anthropic Base URL"?** Cursor doesn't have one. There's a [year-old open feature request](https://forum.cursor.com/t/missing-anthropic-base-url-override-in-cursor-byok/158805) and no plans to ship it. Routing Claude through dario is only possible via the OpenAI-compat path with a prefixed model name as above.
|
|
126
|
+
|
|
127
|
+
### Continue.dev
|
|
128
|
+
|
|
129
|
+
In `~/.continue/config.yaml` (or the Continue settings UI, which edits the same file):
|
|
130
|
+
|
|
131
|
+
```yaml
|
|
132
|
+
models:
|
|
133
|
+
- name: Claude Sonnet (dario)
|
|
134
|
+
provider: anthropic
|
|
135
|
+
model: claude-sonnet-5
|
|
136
|
+
apiBase: http://localhost:3456
|
|
137
|
+
apiKey: dario
|
|
138
|
+
- name: Claude Opus (dario)
|
|
139
|
+
provider: anthropic
|
|
140
|
+
model: claude-opus-5
|
|
141
|
+
apiBase: http://localhost:3456
|
|
142
|
+
apiKey: dario
|
|
143
|
+
```
|
|
144
|
+
|
|
145
|
+
`provider: anthropic` + `apiBase: http://localhost:3456` points Continue's Anthropic SDK path at dario instead of `api.anthropic.com`. dario runs the full Claude Code wire replay on the outbound path.
|
|
146
|
+
|
|
147
|
+
### Aider
|
|
148
|
+
|
|
149
|
+
```bash
|
|
150
|
+
export ANTHROPIC_BASE_URL=http://localhost:3456
|
|
151
|
+
export ANTHROPIC_API_KEY=dario
|
|
152
|
+
aider --model sonnet
|
|
153
|
+
```
|
|
154
|
+
|
|
155
|
+
Aider's Anthropic path honors `ANTHROPIC_BASE_URL` directly. `--model opus`, `--model haiku`, or any explicit `claude-*` model name works.
|
|
156
|
+
|
|
157
|
+
### Cline / Roo Code / Kilo Code
|
|
158
|
+
|
|
159
|
+
Cline and its forks use a UI-based "API Provider" dropdown. Pick **Anthropic** as the provider and fill in:
|
|
160
|
+
|
|
161
|
+
- **API Key**: `dario`
|
|
162
|
+
- **Anthropic Base URL**: `http://localhost:3456`
|
|
163
|
+
- **Model**: `claude-sonnet-5` / `claude-opus-5` / `claude-haiku-4-5`
|
|
164
|
+
|
|
165
|
+
Cline's tool-invocation protocol is XML-based (`<execute_command>`, `<write_to_file>`, etc.), not Anthropic's tool-use format. Dario auto-detects Cline-family clients via system-prompt identity markers and flips into preserve-tools mode automatically — Cline's own tool schema passes through, your commands route back to Cline's parser. No flag required. Override: `--no-auto-detect` if you'd rather force the CC wire shape and deal with the parser mismatch yourself.
|
|
166
|
+
|
|
167
|
+
### Zed
|
|
168
|
+
|
|
169
|
+
Zed's Anthropic provider config (`~/.config/zed/settings.json` or Cmd/Ctrl+,):
|
|
170
|
+
|
|
171
|
+
```json
|
|
172
|
+
{
|
|
173
|
+
"language_models": {
|
|
174
|
+
"anthropic": {
|
|
175
|
+
"api_url": "http://localhost:3456",
|
|
176
|
+
"version": "2023-06-01"
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
```
|
|
181
|
+
|
|
182
|
+
Set the `ANTHROPIC_API_KEY` env var to `dario` before launching Zed. Model picker then shows Claude models routed through your subscription.
|
|
183
|
+
|
|
184
|
+
### OpenHands
|
|
185
|
+
|
|
186
|
+
```bash
|
|
187
|
+
export LLM_BASE_URL=http://localhost:3456
|
|
188
|
+
export LLM_API_KEY=dario
|
|
189
|
+
export LLM_MODEL=anthropic/claude-sonnet-4-6
|
|
190
|
+
openhands --task "task description"
|
|
191
|
+
```
|
|
192
|
+
|
|
193
|
+
Prefix the model with `anthropic/` so LiteLLM (OpenHands' inner routing layer) knows to hit the Anthropic path, which dario is now fronting.
|
|
194
|
+
|
|
195
|
+
For a full end-to-end walkthrough — install, battletested model picks, subscription-billing verification, retries, multi-account pool, and the gotchas that bite first-time users — see [`openhands-walkthrough.md`](./openhands-walkthrough.md).
|
|
196
|
+
|
|
197
|
+
### OpenClaw
|
|
198
|
+
|
|
199
|
+
```bash
|
|
200
|
+
export ANTHROPIC_BASE_URL=http://localhost:3456
|
|
201
|
+
export ANTHROPIC_API_KEY=dario
|
|
202
|
+
openclaw "task description"
|
|
203
|
+
```
|
|
204
|
+
|
|
205
|
+
OpenClaw uses the standard `ANTHROPIC_BASE_URL` and `ANTHROPIC_API_KEY` env vars. Dario's structural-fallback tool detection auto-translates OpenClaw's `exec` / `process` / `web_search` / `web_fetch` / `browser` / `message` tools to CC's canonical set — no flag required.
|
|
206
|
+
|
|
207
|
+
**Heads up:** OpenClaw 2026.2.17+ reads `~/.openclaw/agents/main/agent/auth-profiles.json` before checking env vars, so a stale Anthropic key in that file silently overrides `ANTHROPIC_API_KEY=dario`. If you see 401s, see the [auth-profiles entry in faq.md](./faq.md#openclaw-returns-401-after-i-set-dario_api_key-or-upgrade-past-v3306). Dario's default template-replay mode also strips the `openclaw.inbound_meta.v1` classifier-trigger string from your local git context at the proxy boundary, so subscription billing is preserved on OpenClaw-namespaced projects without you doing anything.
|
|
208
|
+
|
|
209
|
+
For a full end-to-end walkthrough — auth-profiles handling, classifier-filter protection, subscription-billing verification, multi-account pool, and the gotchas that bite first-time users — see [`openclaw-walkthrough.md`](./openclaw-walkthrough.md).
|
|
210
|
+
|
|
211
|
+
### hands
|
|
212
|
+
|
|
213
|
+
[hands](https://github.com/askalf/hands) is a sister project to dario — a local computer-use agent that drives your OS through its native shell instead of a screenshot loop. Two modes: Claude Login (uses the `claude` CLI directly, no dario required) and SDK mode (audit-logged, supports `--dry-run`, routes through dario for $0 per task).
|
|
214
|
+
|
|
215
|
+
```bash
|
|
216
|
+
# SDK mode — env vars route the Anthropic SDK through dario
|
|
217
|
+
export ANTHROPIC_BASE_URL=http://localhost:3456
|
|
218
|
+
export ANTHROPIC_API_KEY=dario
|
|
219
|
+
|
|
220
|
+
dario proxy --verbose &
|
|
221
|
+
hands auth # pick "API Key", paste: dario
|
|
222
|
+
hands run "open notepad and type hello world"
|
|
223
|
+
```
|
|
224
|
+
|
|
225
|
+
Dario v3.33.0+ auto-detects hands via system-prompt identity match and **preserves the Anthropic computer-use beta tools** (`computer`, `bash`, `str_replace_based_edit_tool`) instead of remapping them. No flag required — the `anthropic-beta: computer-use-*` header survives the proxy and the wire shape stays subscription-eligible.
|
|
226
|
+
|
|
227
|
+
For the full end-to-end walkthrough — both auth modes, audit log, dry-run patterns, voice mode, multi-account pool, and the gotchas that bite first-time users — see [`hands-walkthrough.md`](./hands-walkthrough.md).
|
|
228
|
+
|
|
229
|
+
### Everything else
|
|
230
|
+
|
|
231
|
+
If your tool isn't listed, check whether it reads `OPENAI_BASE_URL` / `ANTHROPIC_BASE_URL` from the environment. Most do. For tools that don't, look in their settings for "Base URL" / "API URL" / "Endpoint" / "OpenAI-compatible endpoint" — all of those map to dario's `http://localhost:3456` (Anthropic-protocol) or `http://localhost:3456/v1` (OpenAI-protocol). If the tool only accepts `https://`, you'll need a loopback TLS shim (out of scope here — open an issue if you need one for a specific tool).
|
|
232
|
+
|
|
233
|
+
## Custom tool schemas
|
|
234
|
+
|
|
235
|
+
By default, on the Claude backend, dario replaces your client's tool definitions with the real Claude Code tools (`Bash`, `Read`, `Write`, `Edit`, `Grep`, `Glob`, `WebSearch`, `WebFetch`) and translates parameters back and forth. That's what keeps the request on the CC wire shape, which is what keeps the session on subscription billing instead of per-token API pricing. For the agents listed in the table above, the translation is pre-mapped and runs automatically — nothing to configure.
|
|
236
|
+
|
|
237
|
+
The trade-off shows up when you're running something that *isn't* in the pre-mapped list and whose tools carry fields CC's schema doesn't have — a `sessionId`, a custom request id, a channel-bound context token, a `confidence` score the model is supposed to emit. Those fields don't survive the round trip.
|
|
238
|
+
|
|
239
|
+
Symptom: your tool calls come back looking stripped-down, or your runtime complains about a required field being absent *only when routed through dario's Claude backend*.
|
|
240
|
+
|
|
241
|
+
Fix: run dario with `--preserve-tools`. That skips the CC tool remap entirely, passes your client's tool definitions through to the model unchanged, and lets the model populate every field your schema expects.
|
|
242
|
+
|
|
243
|
+
```bash
|
|
244
|
+
dario proxy --preserve-tools
|
|
245
|
+
```
|
|
246
|
+
|
|
247
|
+
The cost: requests no longer look like CC on the wire, so the subscription-billing wire shape is gone. On a subscription plan, that means the request may be counted against your API usage rather than your subscription quota. Hybrid tool mode below is the compromise that keeps both.
|
|
248
|
+
|
|
249
|
+
The OpenAI-compat backend is unaffected — it forwards tool definitions byte-for-byte and doesn't need this flag.
|
|
250
|
+
|
|
251
|
+
## Hybrid tool mode
|
|
252
|
+
|
|
253
|
+
For the very common case where the "missing" fields on your client's tool are **request context** — `sessionId`, `requestId`, `channelId`, `userId`, `timestamp` — dario can remap to CC tools *and* inject those values on the reverse path. The CC wire shape stays intact, the model still sees only CC's tools (so subscription billing still routes), and your validator still sees the fields it requires because dario fills them from request headers on the way back.
|
|
254
|
+
|
|
255
|
+
```bash
|
|
256
|
+
dario proxy --hybrid-tools
|
|
257
|
+
```
|
|
258
|
+
|
|
259
|
+
**How it works.** On each request, dario builds a `RequestContext` from headers (`x-session-id`, `x-request-id`, `x-channel-id`, `x-user-id`) plus its own generated ids and the current timestamp. After `translateBack` produces the client-shaped tool call on the response path, any field declared on the client's tool schema whose name matches a known context field (`sessionId`/`session_id`, `requestId`/`request_id`, `channelId`/`channel_id`, `userId`/`user_id`, `timestamp`/`created_at`/`createdAt`) and isn't already populated gets filled from the context. Fields the model genuinely populated are never overwritten.
|
|
260
|
+
|
|
261
|
+
**When to use which flag:**
|
|
262
|
+
|
|
263
|
+
| Your situation | Flag | Why |
|
|
264
|
+
|---|---|---|
|
|
265
|
+
| Your agent is listed in the table at the top | *(neither)* | Pre-mapped in `TOOL_MAP`; the default path already handles it. |
|
|
266
|
+
| Your custom fields are request context (session/request/channel/user ids, timestamps) | `--hybrid-tools` | Keeps the CC wire shape *and* your validator is satisfied. |
|
|
267
|
+
| Your custom fields need the model's reasoning (e.g. `confidence`, `reasoning_trace`, `tool_selection_rationale`) | `--preserve-tools` | The model has to see the real schema to populate these. Accept the CC-wire-shape loss. |
|
|
268
|
+
| Your client's tools are already a subset of CC's `Bash/Read/Write/Edit/Grep/Glob/WebSearch/WebFetch` | *(neither)* | Default mode works as-is. |
|
|
269
|
+
| You're on a text-tool client (Cline / Kilo Code / Roo Code) and want to override the auto-detect | `--no-auto-detect` (plus `--preserve-tools` or not, your call) | Operator choice outranks the heuristic. |
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
# Compatibility matrix
|
|
2
|
+
|
|
3
|
+
One-page status table per tool. The setup details for each row live in [`agent-compat.md`](./agent-compat.md) and the per-tool walkthroughs (`hands-walkthrough.md`, `openhands-walkthrough.md`, `openclaw-walkthrough.md`); this page is just "does it work?" with an honest cell per tool.
|
|
4
|
+
|
|
5
|
+
Status legend:
|
|
6
|
+
|
|
7
|
+
- **✅ Working** — code path exercised, walkthrough or per-tool docs exist, no known dario-side gaps.
|
|
8
|
+
- **⚪ Inferred** — uses a generic protocol path (Anthropic SDK or OpenAI-compat passthrough) that dario handles correctly, but no tool-specific test exists. Should work; report if not.
|
|
9
|
+
- **🟡 Untested** — listed in the README's "every tool that honors those env vars" sentence, but no walkthrough, no per-tool docs, and no smoke test.
|
|
10
|
+
|
|
11
|
+
| Tool | Protocol | Routes via | Status | Setup |
|
|
12
|
+
|---|---|---|---|---|
|
|
13
|
+
| **Claude Code** | Anthropic Messages | Claude backend | ✅ Working | Default — what dario was built around. `dario login`, `dario proxy`, no per-tool config. |
|
|
14
|
+
| **Cursor** (BYOK Custom OpenAI) | Anthropic Messages | Claude backend | ✅ Working | Cloudflared tunnel + `anthropic:` model prefix + Agent mode. Long form: [`agent-compat.md#cursor`](./agent-compat.md#cursor). |
|
|
15
|
+
| **Continue.dev** | Anthropic / OpenAI | Either | ✅ Working | [`agent-compat.md#continuedev`](./agent-compat.md#continuedev) |
|
|
16
|
+
| **Aider** | Anthropic / OpenAI | Either | ✅ Working | [`agent-compat.md#aider`](./agent-compat.md#aider) |
|
|
17
|
+
| **Cline / Roo Code / Kilo Code** | Anthropic (text-tool) | Claude backend | ✅ Working | Auto-flips into preserve-tools mode via system-prompt identity markers. [`agent-compat.md#cline--roo-code--kilo-code`](./agent-compat.md#cline--roo-code--kilo-code) |
|
|
18
|
+
| **Zed** | Anthropic | Claude backend | ✅ Working | [`agent-compat.md#zed`](./agent-compat.md#zed) |
|
|
19
|
+
| **OpenHands** | Anthropic | Claude backend | ✅ Working | Full walkthrough: [`openhands-walkthrough.md`](./openhands-walkthrough.md) |
|
|
20
|
+
| **OpenClaw** | Anthropic | Claude backend | ✅ Working | Full walkthrough: [`openclaw-walkthrough.md`](./openclaw-walkthrough.md). Identity-detected for preserve-tools. |
|
|
21
|
+
| **hands** | Anthropic | Claude backend | ✅ Working | Full walkthrough: [`hands-walkthrough.md`](./hands-walkthrough.md). Identity-detected. |
|
|
22
|
+
| **CC sub-agents** | Anthropic | Claude backend | ✅ Working | `dario subagent install` registers a CC sub-agent that exposes `dario doctor` and other read-only diagnostics inside any CC session. [`sub-agent.md`](./sub-agent.md) |
|
|
23
|
+
| **Claude Agent SDK** | Anthropic | Claude backend | ✅ Working | `baseURL: 'http://localhost:3456'` on the `Anthropic` client. SDK examples in [`usage.md`](./usage.md). |
|
|
24
|
+
| **MCP clients (any)** | MCP / JSON-RPC | dario as MCP server | ✅ Working | `dario mcp` exposes dario as a read-only MCP server. [`mcp-server.md`](./mcp-server.md) |
|
|
25
|
+
| **Codex CLI** | OpenAI | OpenAI-compat backend | ⚪ Inferred | `dario backend add openai --key=...` then point Codex CLI at `OPENAI_BASE_URL=http://localhost:3456/v1`. The OpenAI backend is a byte-for-byte passthrough (verified by `test/openai-backend-passthrough.mjs`); no Codex-specific code path exists or is needed. |
|
|
26
|
+
| **Hermes** | Anthropic | Claude backend | ⚪ Inferred | Identity-detected by name in CC's identity markers; routes through the standard preserve-tools path. No dedicated walkthrough yet. |
|
|
27
|
+
| **Windsurf** | Anthropic | Claude backend | 🟡 Untested | Listed in README — uses Anthropic-shape requests, should pass through dario's Claude backend. No dedicated walkthrough or smoke test. Open an issue with `dario doctor` output if it doesn't work. |
|
|
28
|
+
| **Claude Desktop** | Anthropic | Claude backend | 🟡 Untested | Generic Anthropic SDK consumer; should work via the same path Claude Code uses. No dedicated walkthrough. |
|
|
29
|
+
| **GitHub Copilot** | Proprietary | n/a | 🟡 Not applicable | Copilot's BYOK paths are surface-specific (Copilot Chat in VS Code, GitHub.com, etc.) and don't expose a generic OpenAI/Anthropic base-URL override. Listed in README for completeness; no dario integration is currently possible without a vendor-side change. |
|
|
30
|
+
|
|
31
|
+
## What "Inferred" means in practice
|
|
32
|
+
|
|
33
|
+
For ⚪ Inferred entries, the underlying protocol path is identical to a tested one — the generic OpenAI-compat passthrough (`forwardToOpenAI` in [`src/openai-backend.ts`](../src/openai-backend.ts), exercised by `test/openai-backend-passthrough.mjs`) or the standard Anthropic backend path. There's no tool-specific code to break; the dario-side risk is "did the upstream provider rotate something we cared about", which `cc-drift-watch.yml` catches on the Claude side and which OpenAI-compat clients self-detect by speaking the protocol they speak.
|
|
34
|
+
|
|
35
|
+
If an Inferred entry doesn't work for you, the failure is almost always upstream (provider rate-limit shape, model deprecation, custom header the tool sends that we don't forward). Open an issue with `dario doctor` output and we'll either fix it (if it's dario) or document the workaround (if it's the tool).
|
|
36
|
+
|
|
37
|
+
## What's missing from this page
|
|
38
|
+
|
|
39
|
+
- A "tested at version vX.Y.Z" column — the matrix is moment-in-time, not historical.
|
|
40
|
+
- Performance characteristics (latency, throughput) — see the per-tool walkthroughs.
|
|
41
|
+
- Per-tool feature matrices (does Cursor's BYOK pass `tools`? does Cline's text-tool mode survive `--system-prompt=partial`? etc) — those live in the long-form docs.
|
|
42
|
+
|
|
43
|
+
## Adding a tool to this matrix
|
|
44
|
+
|
|
45
|
+
Honest framing for new entries:
|
|
46
|
+
|
|
47
|
+
- **✅ Working** requires either (a) a checked-in walkthrough doc, or (b) a smoke test that exercises the tool's request shape end-to-end.
|
|
48
|
+
- **⚪ Inferred** is the right cell for "uses a generic protocol path I can point to in code, but I haven't run the actual tool through dario."
|
|
49
|
+
- **🟡 Untested** is the right cell for "mentioned in README, but I have no evidence either way."
|
|
50
|
+
|
|
51
|
+
Don't promote ⚪ → ✅ without a walkthrough or test landing. Don't promote 🟡 → ⚪ without at least pointing at the code path you're claiming covers it.
|