@mrrlin-dev/external-agents 0.1.0
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/LICENSE +21 -0
- package/README.md +237 -0
- package/agents.yaml +357 -0
- package/cli.js +203 -0
- package/docs/adding-a-provider.md +139 -0
- package/lib/dispatch.js +380 -0
- package/lib/pick.js +52 -0
- package/lib/registry.js +29 -0
- package/lib/state.js +113 -0
- package/package.json +58 -0
- package/server.js +384 -0
- package/ui.js +449 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 mrrlin-dev
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,237 @@
|
|
|
1
|
+
# @mrrlin-dev/external-agents
|
|
2
|
+
|
|
3
|
+
**One MCP server for every LLM you talk to.**
|
|
4
|
+
|
|
5
|
+
`external-agents` is a small, opinionated MCP server + CLI that lets your primary coding agent (Claude Code, Codex, Cursor) route work to a pool of secondary LLMs — Gemini, DeepSeek, Grok, OpenRouter, local Ollama, and any CLI-agentic reviewer (cursor-agent, opencode) — through one clean surface, with per-provider auth, cooldowns, round-robin, escalation, and a local statistics dashboard.
|
|
6
|
+
|
|
7
|
+
> **Part of [mrrlin.com](https://mrrlin.com)** — the AI orchestration platform for developers. `external-agents` is the open-source layer we use internally to power multi-model consensus and cost-efficient atomic execution. Ships MIT so anyone can adopt it standalone.
|
|
8
|
+
|
|
9
|
+
---
|
|
10
|
+
|
|
11
|
+
## Why this exists
|
|
12
|
+
|
|
13
|
+
If you use more than one LLM in your workflow (and by now most people do), you've probably done at least one of these:
|
|
14
|
+
|
|
15
|
+
- Hand-rolled a shell script that alternates DeepSeek and Gemini for cheap tasks.
|
|
16
|
+
- Copy-pasted the same "review this diff" prompt into three CLIs to compare answers.
|
|
17
|
+
- Written a wrapper to detect a 429 and retry on a different provider.
|
|
18
|
+
- Kept a mental note of which providers are quota-exhausted today.
|
|
19
|
+
|
|
20
|
+
`external-agents` collapses all of that into **one tool with one config**:
|
|
21
|
+
|
|
22
|
+
- **Unified dispatch.** `dispatch(agent_id, prompt)` with default transport `generate_new` picks the next healthy provider by round-robin; N parallel `pick_agents` + `dispatch` calls (consumer-composed) fans out to N providers in parallel with cross-model diversity guaranteed.
|
|
23
|
+
- **State that heals itself.** Quota exhaustion is detected from live responses and rate-limit headers, cooldown lasts until the *provider's* reset time (not a made-up default), and healthy calls automatically clear stale cooldowns.
|
|
24
|
+
- **Auth surfaces you actually have.** Subscription CLI (Codex, Claude), env-var API keys via [`aider`](https://aider.chat) → direct-to-provider through LiteLLM (Gemini, DeepSeek, Grok, OpenRouter, and 100+ more), direct CLI (cursor-agent, opencode, ollama) — pick your credential path per entry, no forced OAuth, no gateway proxy.
|
|
25
|
+
- **Statistics that answer your questions.** How many dispatches went to Gemini this week? What did they cost? Which provider is failing the most? All in a local dashboard, no cloud required.
|
|
26
|
+
|
|
27
|
+
---
|
|
28
|
+
|
|
29
|
+
## Install
|
|
30
|
+
|
|
31
|
+
```bash
|
|
32
|
+
npm install -g @mrrlin-dev/external-agents
|
|
33
|
+
external-agents --version
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
Requires Node ≥ 20. Works on macOS and Linux. Windows via WSL.
|
|
37
|
+
|
|
38
|
+
---
|
|
39
|
+
|
|
40
|
+
## Two-minute quickstart
|
|
41
|
+
|
|
42
|
+
```bash
|
|
43
|
+
# 1. See what's available (starts with zero-config defaults)
|
|
44
|
+
external-agents status
|
|
45
|
+
|
|
46
|
+
# 2. Wire an API-key provider (e.g. DeepSeek — sets DEEPSEEK_API_KEY for aider)
|
|
47
|
+
external-agents auth deepseek
|
|
48
|
+
|
|
49
|
+
# 3. Dispatch something (auto-pick + run)
|
|
50
|
+
id=$(external-agents pick -n 1)
|
|
51
|
+
external-agents dispatch "$id" "Summarize this in one line: <paste any text>"
|
|
52
|
+
|
|
53
|
+
# 4. See what just happened
|
|
54
|
+
external-agents stats
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
Open the local dashboard with `external-agents ui` and you'll get a page like:
|
|
58
|
+
|
|
59
|
+

|
|
60
|
+
|
|
61
|
+
---
|
|
62
|
+
|
|
63
|
+
## Wire into your MCP client
|
|
64
|
+
|
|
65
|
+
Once installed, add one block to your MCP client config.
|
|
66
|
+
|
|
67
|
+
**Claude Code** (`~/.claude.json`):
|
|
68
|
+
```json
|
|
69
|
+
{
|
|
70
|
+
"mcpServers": {
|
|
71
|
+
"external-agents": {
|
|
72
|
+
"command": "external-agents",
|
|
73
|
+
"args": ["mcp", "serve"]
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
**Codex Code** (`~/.codex/config.toml`):
|
|
80
|
+
```toml
|
|
81
|
+
[mcp_servers.external-agents]
|
|
82
|
+
command = "external-agents"
|
|
83
|
+
args = ["mcp", "serve"]
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
**Cursor** — Settings → MCP → Add server → same command.
|
|
87
|
+
|
|
88
|
+
Your primary agent now has these low-level tools (build your own exec/review flows on top):
|
|
89
|
+
|
|
90
|
+
| Tool | What it does |
|
|
91
|
+
| --- | --- |
|
|
92
|
+
| `pick_agents` | Pick N distinct healthy candidates (round-robin, cooldown-aware). Optional `min_distinct_providers` for diverse fan-out. |
|
|
93
|
+
| `dispatch` | Run a specific agent with a prompt. `escalate_to_pro: true` retries on the same provider's strong tier. |
|
|
94
|
+
| `probe_agent` | Health-check one provider (cheap prompt). |
|
|
95
|
+
| `list_agents` | Registry with live state. |
|
|
96
|
+
| `get_state` | Full state file — for building your own dashboard. |
|
|
97
|
+
| `get_stats` | Aggregated dispatch metrics from local JSONL. |
|
|
98
|
+
| `set_credential` | Store a provider credential via the entry's auth surface. |
|
|
99
|
+
|
|
100
|
+
**Composition example** — build "review by a panel of 3 diverse providers" client-side:
|
|
101
|
+
```
|
|
102
|
+
ids = pick_agents({ n: 3, min_distinct_providers: 3, exclude_ids: [primary] })
|
|
103
|
+
outs = Promise.all(ids.map(id => dispatch({ agent_id: id, prompt })))
|
|
104
|
+
```
|
|
105
|
+
The package is deliberately unopinionated about *what* you compose. Mrrlin uses these primitives for its own `/consensus` gate and atomic-executor loop; your workflow probably has its own vocabulary — that's the whole point.
|
|
106
|
+
|
|
107
|
+
---
|
|
108
|
+
|
|
109
|
+
## Supported providers (v0.1.0)
|
|
110
|
+
|
|
111
|
+
### Free tier — no card required to get started
|
|
112
|
+
|
|
113
|
+
Most of the pool runs on generous free tiers. **20 agents across 8 providers, 17 of which cost $0** when the request is on the provider's free plan (all get their own quota bucket, so round-robin dramatically extends what you can do without paying).
|
|
114
|
+
|
|
115
|
+
| Provider | Models | Free tier |
|
|
116
|
+
| --- | --- | --- |
|
|
117
|
+
| **Google Gemini** (via AI Studio) | 3.5-flash-lite, 3.1-flash-lite, 3.6-flash, 3.5-flash, 3-flash-preview, 3/3.1-pro-preview | ✅ generous per-model quotas |
|
|
118
|
+
| **Groq** ⚡ | llama-3.3-70b-versatile, deepseek-r1-distill-llama-70b | ✅ 30 rpm — fastest inference on the market (~500-800 tok/s) |
|
|
119
|
+
| **OpenRouter** 🌐 | 50+ models tagged `:free` (deepseek-r1, qwen-coder-32b, llama-3.3-70b, ...) | ✅ 20 rpd free without card |
|
|
120
|
+
| **Cerebras** ⚡⚡ | llama3.3-70b, qwen-3-coder-480b | ✅ 30 rpm — ~2000 tok/s (fastest on the planet) |
|
|
121
|
+
| **Z.ai** (GLM) | glm-4.7-flash | ✅ free API tier |
|
|
122
|
+
| **Ollama Cloud** | gpt-oss:20b-cloud, gpt-oss:120b-cloud | ✅ free with Ollama account |
|
|
123
|
+
|
|
124
|
+
### Paid tier / per-token
|
|
125
|
+
|
|
126
|
+
| Provider | Models | Notes |
|
|
127
|
+
| --- | --- | --- |
|
|
128
|
+
| **DeepSeek** (direct API) | deepseek-chat (Flash), deepseek-reasoner | Very cheap per-token; not on free tier but often <$1/day for atomic-task workloads |
|
|
129
|
+
| **Codex** (subscription) | gpt-5.2-codex (primary orchestrator) | Uses your Codex Code subscription; not an API key |
|
|
130
|
+
|
|
131
|
+
### Direct-CLI agentic (repo-aware reviewers)
|
|
132
|
+
|
|
133
|
+
- cursor-agent, opencode, Ollama (local, no quota)
|
|
134
|
+
|
|
135
|
+
Missing a provider? Adding one is a ~15-line YAML addition — see [docs/adding-a-provider.md](docs/adding-a-provider.md). aider (our downstream) supports 100+ providers via LiteLLM.
|
|
136
|
+
|
|
137
|
+
---
|
|
138
|
+
|
|
139
|
+
## Config reference
|
|
140
|
+
|
|
141
|
+
Registry file at `~/.config/external-agents/agents.yaml`:
|
|
142
|
+
|
|
143
|
+
```yaml
|
|
144
|
+
runtime:
|
|
145
|
+
primary_agent: codex # ignored when there's no orchestrator concept
|
|
146
|
+
review_diversity:
|
|
147
|
+
min_distinct_providers: 3
|
|
148
|
+
max_rounds_default: 3
|
|
149
|
+
|
|
150
|
+
telemetry_sink: # optional: pipe events to your own endpoint
|
|
151
|
+
url: https://your-backend.example/telemetry
|
|
152
|
+
headers:
|
|
153
|
+
Authorization: "Bearer {ENV_TOKEN}"
|
|
154
|
+
batch_size: 50
|
|
155
|
+
|
|
156
|
+
agents:
|
|
157
|
+
aider-gemini-flash:
|
|
158
|
+
provider: google
|
|
159
|
+
model: gemini-3-flash-preview
|
|
160
|
+
tier: weak
|
|
161
|
+
auth: "env:GEMINI_API_KEY"
|
|
162
|
+
transports:
|
|
163
|
+
generate_new:
|
|
164
|
+
url: "https://generativelanguage.googleapis.com/v1beta/openai/chat/completions"
|
|
165
|
+
env: GEMINI_API_KEY
|
|
166
|
+
model: gemini-3-flash-preview
|
|
167
|
+
edit_exists: "aider --model gemini/gemini-3-flash-preview"
|
|
168
|
+
# ... more entries
|
|
169
|
+
```
|
|
170
|
+
|
|
171
|
+
Full schema documented in [docs/registry-schema.md](docs/registry-schema.md).
|
|
172
|
+
|
|
173
|
+
---
|
|
174
|
+
|
|
175
|
+
## Local UI
|
|
176
|
+
|
|
177
|
+
Run `external-agents ui` and a page opens on `http://127.0.0.1:port`. Loopback only — never exposed to the network. Shows:
|
|
178
|
+
|
|
179
|
+
**💰 "Unlock more free voices" banner at the top** — as long as you have any free-tier provider that hasn't been wired up yet (no env var set), the UI shows a golden banner urging you to sign up. One row per provider with: what it gives you ("Groq: ~500-800 tok/s — fastest on the market"), the exact env var name to set, and a green "Get free key ↗" link to the signup page. **Signup is usually 60 seconds and doesn't ask for a card.** Once you add the key and restart your MCP client, that provider drops from the banner and joins the pool.
|
|
180
|
+
|
|
181
|
+
|
|
182
|
+
- Every registry entry with a live status badge
|
|
183
|
+
- **Per-row Usage link** — for each provider that publishes one (Gemini / DeepSeek / OpenAI / Z.ai / Ollama Cloud / ...), a small `↗ usage` link opens the provider's own dashboard so you never have to guess where your billing lives
|
|
184
|
+
- Install / auth / verify buttons per state
|
|
185
|
+
- **"Missing your model?" panel** — a two-input form (model name + optional docs URL) at the bottom of the table. Submit records your suggestion locally (JSONL). If you're running inside mrrlin, the same submit is intercepted and filed as an actionable task in your inbox
|
|
186
|
+
- Statistics tab: dispatches, costs, success rate, per-agent timing
|
|
187
|
+
- Config editor with schema validation
|
|
188
|
+
|
|
189
|
+
Everything the UI does is also available in the CLI — the UI is a convenience, not a requirement.
|
|
190
|
+
|
|
191
|
+
---
|
|
192
|
+
|
|
193
|
+
## FAQ
|
|
194
|
+
|
|
195
|
+
**Do you send my API keys anywhere?**
|
|
196
|
+
No. API-key credentials live in env vars only (read by aider at spawn time). Subscription tokens live where the subscription CLI keeps them (`codex login`, `claude login`, ...). `external-agents` never persists or transmits your credentials.
|
|
197
|
+
|
|
198
|
+
**Do you phone home?**
|
|
199
|
+
Not by default. Telemetry writes to a local JSONL file. If you configure `telemetry_sink` in your registry, events go to *your* endpoint — no default sink.
|
|
200
|
+
|
|
201
|
+
**Is Mrrlin required?**
|
|
202
|
+
No. `external-agents` is standalone. Mrrlin uses it internally, but the package works for anyone building a multi-model workflow.
|
|
203
|
+
|
|
204
|
+
**Can I use this with just a subscription (no API keys)?**
|
|
205
|
+
Yes — Codex subscription with `--model` overrides gives you access to cheaper models on the same plan. Same story with Claude when v0.2 lands. Zero API-key setup for those cases.
|
|
206
|
+
|
|
207
|
+
**How do you avoid rate-limit surprises?**
|
|
208
|
+
Every real call updates state from response headers and error signals. Cooldown honors the provider's own reset time (parsed from `x-ratelimit-reset-*`, `Retry-After`, and error bodies). If Google says "resets in 42h", we wait 42h — not a 1h default.
|
|
209
|
+
|
|
210
|
+
**Why `aider` for API-key providers?**
|
|
211
|
+
[aider](https://aider.chat) is a mature (4-year) agentic CLI that talks to 100+ providers directly through [LiteLLM](https://litellm.ai) — no gateway proxy. Every provider is just an env var (`GEMINI_API_KEY`, `DEEPSEEK_API_KEY`, `ANTHROPIC_API_KEY`, ...) and a `--model {provider}/{id}` flag. We layer state / round-robin / cooldown on top instead of writing our own provider client for every LLM ourselves.
|
|
212
|
+
|
|
213
|
+
---
|
|
214
|
+
|
|
215
|
+
## Contributing
|
|
216
|
+
|
|
217
|
+
Contributions welcome. See [CONTRIBUTING.md](CONTRIBUTING.md).
|
|
218
|
+
|
|
219
|
+
We use MIT + DCO (sign-off in commits), no CLA. Bug reports and provider additions are especially appreciated.
|
|
220
|
+
|
|
221
|
+
---
|
|
222
|
+
|
|
223
|
+
## License
|
|
224
|
+
|
|
225
|
+
MIT. See [LICENSE](LICENSE).
|
|
226
|
+
|
|
227
|
+
---
|
|
228
|
+
|
|
229
|
+
## About Mrrlin
|
|
230
|
+
|
|
231
|
+
`external-agents` is one piece of [**Mrrlin**](https://mrrlin.com) — an AI orchestration platform for solo developers and small teams. Mrrlin uses this package internally to power its multi-model consensus gate and cost-efficient atomic executor, and layers on top of it a Director agent that decides what work to route where.
|
|
232
|
+
|
|
233
|
+
If you like `external-agents`, you'll probably like the rest of Mrrlin.
|
|
234
|
+
|
|
235
|
+
---
|
|
236
|
+
|
|
237
|
+
|
package/agents.yaml
ADDED
|
@@ -0,0 +1,357 @@
|
|
|
1
|
+
# External-agents registry v1 (see ADR 0021 in mrrlin repo).
|
|
2
|
+
#
|
|
3
|
+
# ONE entry per (provider, model). An entry may declare BOTH transports —
|
|
4
|
+
# named after WHAT they do reliably (action-oriented):
|
|
5
|
+
# transports.generate_new — native fetch → OpenAI-compat /chat/completions.
|
|
6
|
+
# Dispatcher writes the response content to workdir/generated.md. Ideal
|
|
7
|
+
# for "produce the contents of this file from spec". Preferred by default.
|
|
8
|
+
# transports.edit_exists — spawns aider (or another agentic CLI). Used when
|
|
9
|
+
# the caller explicitly requests transport="edit_exists" (iterative edits,
|
|
10
|
+
# multi-file, tool use — aider's core strength).
|
|
11
|
+
# When both are present, `runAny` picks `generate_new` unless overridden.
|
|
12
|
+
#
|
|
13
|
+
# Auth surfaces (2, merged from previous 3):
|
|
14
|
+
# env:VAR — external-agents reads the value from process.env.VAR
|
|
15
|
+
# cli:tool — the named CLI owns its own credential store (subscription
|
|
16
|
+
# token, cookie, OAuth session; whatever `<tool> login` writes)
|
|
17
|
+
#
|
|
18
|
+
# Tags are opaque strings. UI styles `free` as a green $0 badge.
|
|
19
|
+
# Env overrides live under `env:` (values may be "@file:~/path" refs).
|
|
20
|
+
schema_version: 1
|
|
21
|
+
agents:
|
|
22
|
+
|
|
23
|
+
# ============ Google Gemini (AI Studio) ============
|
|
24
|
+
- id: gemini-3.5-flash-lite
|
|
25
|
+
provider: google
|
|
26
|
+
model: gemini-3.5-flash-lite
|
|
27
|
+
quota_scope: per_model
|
|
28
|
+
tier: weak
|
|
29
|
+
tags: [quick, cheap, free]
|
|
30
|
+
auth: "env:GEMINI_API_KEY"
|
|
31
|
+
preference_order: 5
|
|
32
|
+
usage_url: "https://aistudio.google.com/usage"
|
|
33
|
+
transports:
|
|
34
|
+
generate_new:
|
|
35
|
+
url: "https://generativelanguage.googleapis.com/v1beta/openai/chat/completions"
|
|
36
|
+
env: GEMINI_API_KEY
|
|
37
|
+
model: gemini-3.5-flash-lite
|
|
38
|
+
edit_exists: "aider --model gemini/gemini-3.5-flash-lite"
|
|
39
|
+
|
|
40
|
+
- id: gemini-3.1-flash-lite
|
|
41
|
+
provider: google
|
|
42
|
+
model: gemini-3.1-flash-lite
|
|
43
|
+
quota_scope: per_model
|
|
44
|
+
tier: weak
|
|
45
|
+
tags: [quick, cheap, free]
|
|
46
|
+
auth: "env:GEMINI_API_KEY"
|
|
47
|
+
preference_order: 5
|
|
48
|
+
usage_url: "https://aistudio.google.com/usage"
|
|
49
|
+
transports:
|
|
50
|
+
generate_new:
|
|
51
|
+
url: "https://generativelanguage.googleapis.com/v1beta/openai/chat/completions"
|
|
52
|
+
env: GEMINI_API_KEY
|
|
53
|
+
model: gemini-3.1-flash-lite
|
|
54
|
+
edit_exists: "aider --model gemini/gemini-3.1-flash-lite"
|
|
55
|
+
|
|
56
|
+
- id: gemini-3.6-flash
|
|
57
|
+
provider: google
|
|
58
|
+
model: gemini-3.6-flash
|
|
59
|
+
quota_scope: per_model
|
|
60
|
+
tier: weak
|
|
61
|
+
tags: [quick, free]
|
|
62
|
+
auth: "env:GEMINI_API_KEY"
|
|
63
|
+
preference_order: 10
|
|
64
|
+
usage_url: "https://aistudio.google.com/usage"
|
|
65
|
+
transports:
|
|
66
|
+
generate_new:
|
|
67
|
+
url: "https://generativelanguage.googleapis.com/v1beta/openai/chat/completions"
|
|
68
|
+
env: GEMINI_API_KEY
|
|
69
|
+
model: gemini-3.6-flash
|
|
70
|
+
edit_exists: "aider --model gemini/gemini-3.6-flash"
|
|
71
|
+
|
|
72
|
+
- id: gemini-3.5-flash
|
|
73
|
+
provider: google
|
|
74
|
+
model: gemini-3.5-flash
|
|
75
|
+
quota_scope: per_model
|
|
76
|
+
tier: weak
|
|
77
|
+
tags: [quick, free]
|
|
78
|
+
auth: "env:GEMINI_API_KEY"
|
|
79
|
+
preference_order: 10
|
|
80
|
+
usage_url: "https://aistudio.google.com/usage"
|
|
81
|
+
transports:
|
|
82
|
+
generate_new:
|
|
83
|
+
url: "https://generativelanguage.googleapis.com/v1beta/openai/chat/completions"
|
|
84
|
+
env: GEMINI_API_KEY
|
|
85
|
+
model: gemini-3.5-flash
|
|
86
|
+
edit_exists: "aider --model gemini/gemini-3.5-flash"
|
|
87
|
+
|
|
88
|
+
- id: gemini-3-flash-preview
|
|
89
|
+
provider: google
|
|
90
|
+
model: gemini-3-flash-preview
|
|
91
|
+
quota_scope: per_model
|
|
92
|
+
tier: weak
|
|
93
|
+
tags: [quick, free]
|
|
94
|
+
auth: "env:GEMINI_API_KEY"
|
|
95
|
+
preference_order: 10
|
|
96
|
+
usage_url: "https://aistudio.google.com/usage"
|
|
97
|
+
transports:
|
|
98
|
+
generate_new:
|
|
99
|
+
url: "https://generativelanguage.googleapis.com/v1beta/openai/chat/completions"
|
|
100
|
+
env: GEMINI_API_KEY
|
|
101
|
+
model: gemini-3-flash-preview
|
|
102
|
+
edit_exists: "aider --model gemini/gemini-3-flash-preview"
|
|
103
|
+
|
|
104
|
+
- id: gemini-3-pro-preview
|
|
105
|
+
provider: google
|
|
106
|
+
model: gemini-3-pro-preview
|
|
107
|
+
quota_scope: per_model
|
|
108
|
+
tier: strong
|
|
109
|
+
tags: [quick, free]
|
|
110
|
+
auth: "env:GEMINI_API_KEY"
|
|
111
|
+
usage_url: "https://aistudio.google.com/usage"
|
|
112
|
+
transports:
|
|
113
|
+
generate_new:
|
|
114
|
+
url: "https://generativelanguage.googleapis.com/v1beta/openai/chat/completions"
|
|
115
|
+
env: GEMINI_API_KEY
|
|
116
|
+
model: gemini-3-pro-preview
|
|
117
|
+
edit_exists: "aider --model gemini/gemini-3-pro-preview"
|
|
118
|
+
|
|
119
|
+
- id: gemini-3.1-pro-preview
|
|
120
|
+
provider: google
|
|
121
|
+
model: gemini-3.1-pro-preview
|
|
122
|
+
quota_scope: per_model
|
|
123
|
+
tier: strong
|
|
124
|
+
tags: [quick, free]
|
|
125
|
+
auth: "env:GEMINI_API_KEY"
|
|
126
|
+
usage_url: "https://aistudio.google.com/usage"
|
|
127
|
+
transports:
|
|
128
|
+
generate_new:
|
|
129
|
+
url: "https://generativelanguage.googleapis.com/v1beta/openai/chat/completions"
|
|
130
|
+
env: GEMINI_API_KEY
|
|
131
|
+
model: gemini-3.1-pro-preview
|
|
132
|
+
edit_exists: "aider --model gemini/gemini-3.1-pro-preview"
|
|
133
|
+
|
|
134
|
+
# ============ DeepSeek ============
|
|
135
|
+
- id: deepseek-chat
|
|
136
|
+
provider: deepseek
|
|
137
|
+
model: deepseek-chat
|
|
138
|
+
quota_scope: shared
|
|
139
|
+
tier: weak
|
|
140
|
+
tags: [quick]
|
|
141
|
+
auth: "env:DEEPSEEK_API_KEY"
|
|
142
|
+
preference_order: 10
|
|
143
|
+
usage_url: "https://platform.deepseek.com/usage"
|
|
144
|
+
transports:
|
|
145
|
+
generate_new:
|
|
146
|
+
url: "https://api.deepseek.com/v1/chat/completions"
|
|
147
|
+
env: DEEPSEEK_API_KEY
|
|
148
|
+
model: deepseek-chat
|
|
149
|
+
edit_exists: "aider --model deepseek/deepseek-chat"
|
|
150
|
+
|
|
151
|
+
- id: deepseek-reasoner
|
|
152
|
+
provider: deepseek
|
|
153
|
+
model: deepseek-reasoner
|
|
154
|
+
quota_scope: shared
|
|
155
|
+
tier: strong
|
|
156
|
+
tags: [quick, reasoning]
|
|
157
|
+
auth: "env:DEEPSEEK_API_KEY"
|
|
158
|
+
usage_url: "https://platform.deepseek.com/usage"
|
|
159
|
+
transports:
|
|
160
|
+
generate_new:
|
|
161
|
+
url: "https://api.deepseek.com/v1/chat/completions"
|
|
162
|
+
env: DEEPSEEK_API_KEY
|
|
163
|
+
model: deepseek-reasoner
|
|
164
|
+
edit_exists: "aider --model deepseek/deepseek-reasoner"
|
|
165
|
+
|
|
166
|
+
# ============ Z.ai (GLM) — OpenAI-compat with per-entry env override ============
|
|
167
|
+
- id: glm-4.7-flash
|
|
168
|
+
provider: zai
|
|
169
|
+
model: glm-4.7-flash
|
|
170
|
+
quota_scope: shared
|
|
171
|
+
tier: weak
|
|
172
|
+
tags: [quick, free]
|
|
173
|
+
auth: "env:ZAI_API_KEY (or ~/.claude/state/zai.key)"
|
|
174
|
+
preference_order: 15
|
|
175
|
+
usage_url: "https://z.ai/manage-apikey/apikey-list"
|
|
176
|
+
transports:
|
|
177
|
+
generate_new:
|
|
178
|
+
url: "https://api.z.ai/api/paas/v4/chat/completions"
|
|
179
|
+
env: OPENAI_API_KEY # per-entry override below routes the AIza… key here
|
|
180
|
+
model: glm-4.7-flash
|
|
181
|
+
edit_exists: "aider --model openai/glm-4.7-flash --openai-api-base https://api.z.ai/api/paas/v4"
|
|
182
|
+
env:
|
|
183
|
+
OPENAI_API_KEY: "@file:~/.claude/state/zai.key"
|
|
184
|
+
|
|
185
|
+
# ============ Groq — free tier, ~500-800 tok/s ============
|
|
186
|
+
- id: groq-llama-3.3-70b
|
|
187
|
+
provider: groq
|
|
188
|
+
model: llama-3.3-70b-versatile
|
|
189
|
+
quota_scope: shared
|
|
190
|
+
tier: weak
|
|
191
|
+
tags: [quick, fast, free]
|
|
192
|
+
auth: "env:GROQ_API_KEY"
|
|
193
|
+
preference_order: 8
|
|
194
|
+
usage_url: "https://console.groq.com/settings/usage"
|
|
195
|
+
transports:
|
|
196
|
+
generate_new:
|
|
197
|
+
url: "https://api.groq.com/openai/v1/chat/completions"
|
|
198
|
+
env: GROQ_API_KEY
|
|
199
|
+
model: llama-3.3-70b-versatile
|
|
200
|
+
edit_exists: "aider --model groq/llama-3.3-70b-versatile"
|
|
201
|
+
|
|
202
|
+
- id: groq-deepseek-r1-distill
|
|
203
|
+
provider: groq
|
|
204
|
+
model: deepseek-r1-distill-llama-70b
|
|
205
|
+
quota_scope: shared
|
|
206
|
+
tier: strong
|
|
207
|
+
tags: [quick, reasoning, free]
|
|
208
|
+
auth: "env:GROQ_API_KEY"
|
|
209
|
+
usage_url: "https://console.groq.com/settings/usage"
|
|
210
|
+
transports:
|
|
211
|
+
generate_new:
|
|
212
|
+
url: "https://api.groq.com/openai/v1/chat/completions"
|
|
213
|
+
env: GROQ_API_KEY
|
|
214
|
+
model: deepseek-r1-distill-llama-70b
|
|
215
|
+
edit_exists: "aider --model groq/deepseek-r1-distill-llama-70b"
|
|
216
|
+
|
|
217
|
+
# ============ OpenRouter — 50+ free models with :free tag ============
|
|
218
|
+
- id: openrouter-deepseek-r1-free
|
|
219
|
+
provider: openrouter
|
|
220
|
+
model: deepseek/deepseek-r1-distill-llama-70b:free
|
|
221
|
+
quota_scope: shared
|
|
222
|
+
tier: strong
|
|
223
|
+
tags: [quick, reasoning, free]
|
|
224
|
+
auth: "env:OPENROUTER_API_KEY"
|
|
225
|
+
usage_url: "https://openrouter.ai/settings/credits"
|
|
226
|
+
transports:
|
|
227
|
+
generate_new:
|
|
228
|
+
url: "https://openrouter.ai/api/v1/chat/completions"
|
|
229
|
+
env: OPENROUTER_API_KEY
|
|
230
|
+
model: deepseek/deepseek-r1-distill-llama-70b:free
|
|
231
|
+
edit_exists: "aider --model openrouter/deepseek/deepseek-r1-distill-llama-70b:free"
|
|
232
|
+
|
|
233
|
+
- id: openrouter-qwen-coder-32b-free
|
|
234
|
+
provider: openrouter
|
|
235
|
+
model: qwen/qwen-2.5-coder-32b-instruct:free
|
|
236
|
+
quota_scope: shared
|
|
237
|
+
tier: weak
|
|
238
|
+
tags: [quick, coding, free]
|
|
239
|
+
auth: "env:OPENROUTER_API_KEY"
|
|
240
|
+
preference_order: 15
|
|
241
|
+
usage_url: "https://openrouter.ai/settings/credits"
|
|
242
|
+
transports:
|
|
243
|
+
generate_new:
|
|
244
|
+
url: "https://openrouter.ai/api/v1/chat/completions"
|
|
245
|
+
env: OPENROUTER_API_KEY
|
|
246
|
+
model: qwen/qwen-2.5-coder-32b-instruct:free
|
|
247
|
+
edit_exists: "aider --model openrouter/qwen/qwen-2.5-coder-32b-instruct:free"
|
|
248
|
+
|
|
249
|
+
- id: openrouter-llama-3.3-70b-free
|
|
250
|
+
provider: openrouter
|
|
251
|
+
model: meta-llama/llama-3.3-70b-instruct:free
|
|
252
|
+
quota_scope: shared
|
|
253
|
+
tier: weak
|
|
254
|
+
tags: [quick, free]
|
|
255
|
+
auth: "env:OPENROUTER_API_KEY"
|
|
256
|
+
preference_order: 15
|
|
257
|
+
usage_url: "https://openrouter.ai/settings/credits"
|
|
258
|
+
transports:
|
|
259
|
+
generate_new:
|
|
260
|
+
url: "https://openrouter.ai/api/v1/chat/completions"
|
|
261
|
+
env: OPENROUTER_API_KEY
|
|
262
|
+
model: meta-llama/llama-3.3-70b-instruct:free
|
|
263
|
+
edit_exists: "aider --model openrouter/meta-llama/llama-3.3-70b-instruct:free"
|
|
264
|
+
|
|
265
|
+
# ============ Cerebras — ~2000 tok/s, 30 rpm free ============
|
|
266
|
+
- id: cerebras-llama-3.3-70b
|
|
267
|
+
provider: cerebras
|
|
268
|
+
model: llama3.3-70b
|
|
269
|
+
quota_scope: shared
|
|
270
|
+
tier: weak
|
|
271
|
+
tags: [quick, fast, free]
|
|
272
|
+
auth: "env:CEREBRAS_API_KEY"
|
|
273
|
+
preference_order: 7
|
|
274
|
+
usage_url: "https://cloud.cerebras.ai/platform/keys"
|
|
275
|
+
transports:
|
|
276
|
+
generate_new:
|
|
277
|
+
url: "https://api.cerebras.ai/v1/chat/completions"
|
|
278
|
+
env: CEREBRAS_API_KEY
|
|
279
|
+
model: llama3.3-70b
|
|
280
|
+
edit_exists: "aider --model cerebras/llama3.3-70b"
|
|
281
|
+
|
|
282
|
+
- id: cerebras-qwen-3-coder-480b
|
|
283
|
+
provider: cerebras
|
|
284
|
+
model: qwen-3-coder-480b
|
|
285
|
+
quota_scope: shared
|
|
286
|
+
tier: strong
|
|
287
|
+
tags: [coding, free]
|
|
288
|
+
auth: "env:CEREBRAS_API_KEY"
|
|
289
|
+
usage_url: "https://cloud.cerebras.ai/platform/keys"
|
|
290
|
+
transports:
|
|
291
|
+
generate_new:
|
|
292
|
+
url: "https://api.cerebras.ai/v1/chat/completions"
|
|
293
|
+
env: CEREBRAS_API_KEY
|
|
294
|
+
model: qwen-3-coder-480b
|
|
295
|
+
edit_exists: "aider --model cerebras/qwen-3-coder-480b"
|
|
296
|
+
|
|
297
|
+
# ============ Ollama Cloud (via localhost daemon → cloud proxy) ============
|
|
298
|
+
- id: ollama-gpt-oss-20b
|
|
299
|
+
provider: ollama-cloud
|
|
300
|
+
model: gpt-oss:20b-cloud
|
|
301
|
+
quota_scope: shared
|
|
302
|
+
tier: weak
|
|
303
|
+
tags: [quick, free]
|
|
304
|
+
auth: "cli:ollama"
|
|
305
|
+
preference_order: 20
|
|
306
|
+
usage_url: "https://ollama.com/settings/keys"
|
|
307
|
+
transports:
|
|
308
|
+
generate_new:
|
|
309
|
+
url: "http://localhost:11434/v1/chat/completions"
|
|
310
|
+
env: OLLAMA_UNUSED_KEY # Ollama daemon needs no key; env var is dummy
|
|
311
|
+
model: gpt-oss:20b-cloud
|
|
312
|
+
edit_exists: "aider --model ollama/gpt-oss:20b-cloud"
|
|
313
|
+
|
|
314
|
+
- id: ollama-gpt-oss-120b
|
|
315
|
+
provider: ollama-cloud
|
|
316
|
+
model: gpt-oss:120b-cloud
|
|
317
|
+
quota_scope: shared
|
|
318
|
+
tier: strong
|
|
319
|
+
tags: [quick, free]
|
|
320
|
+
auth: "cli:ollama"
|
|
321
|
+
usage_url: "https://ollama.com/settings/keys"
|
|
322
|
+
transports:
|
|
323
|
+
generate_new:
|
|
324
|
+
url: "http://localhost:11434/v1/chat/completions"
|
|
325
|
+
env: OLLAMA_UNUSED_KEY
|
|
326
|
+
model: gpt-oss:120b-cloud
|
|
327
|
+
edit_exists: "aider --model ollama/gpt-oss:120b-cloud"
|
|
328
|
+
|
|
329
|
+
# ============ Direct-CLI agentic reviewers (no OpenAI-compat, cli-only) ============
|
|
330
|
+
- id: cursor-agent
|
|
331
|
+
provider: cursor
|
|
332
|
+
model: default
|
|
333
|
+
tier: strong
|
|
334
|
+
tags: [agentic]
|
|
335
|
+
auth: "cli:cursor-agent"
|
|
336
|
+
transports:
|
|
337
|
+
edit_exists: "cursor-agent -p --output-format text"
|
|
338
|
+
|
|
339
|
+
- id: opencode
|
|
340
|
+
provider: sst
|
|
341
|
+
model: default
|
|
342
|
+
tier: weak
|
|
343
|
+
tags: [agentic]
|
|
344
|
+
auth: "cli:opencode"
|
|
345
|
+
transports:
|
|
346
|
+
edit_exists: "opencode -p"
|
|
347
|
+
|
|
348
|
+
# ============ Primary orchestrator (subscription CLI) ============
|
|
349
|
+
- id: codex
|
|
350
|
+
provider: openai
|
|
351
|
+
model: gpt-5.2-codex
|
|
352
|
+
tier: strong
|
|
353
|
+
tags: []
|
|
354
|
+
auth: "cli:codex"
|
|
355
|
+
usage_url: "https://platform.openai.com/usage"
|
|
356
|
+
transports:
|
|
357
|
+
edit_exists: "codex exec"
|