claude-finops 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 ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Mohit Raj Purohit
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,361 @@
1
+ # Claude FinOps Command Center
2
+
3
+ A local, executive-and-developer FinOps dashboard for your own Claude usage, built
4
+ from the Claude Code transcripts already on this machine.
5
+
6
+ It answers, in a few clicks:
7
+
8
+ > **What I used → what it cost → why it cost that much → whether it was efficient →
9
+ > what is likely to happen next → and what I should change.**
10
+
11
+ Everything runs on `127.0.0.1` with the Python standard library. No dependencies, no
12
+ network calls, no data leaves the machine.
13
+
14
+ ```bash
15
+ npx claude-finops
16
+ ```
17
+
18
+ That is the whole setup. It finds your transcripts, builds a local warehouse, and
19
+ opens the dashboard at <http://127.0.0.1:8787>. No account, no API key, no config
20
+ file to write first.
21
+
22
+ ![Executive overview](https://raw.githubusercontent.com/mohit-raj-purohit/claude-finops/main/docs/img/overview.png)
23
+
24
+ <sub>Screenshots are real output from a real warehouse; project names, session titles
25
+ and prompt text have been replaced with placeholders.</sub>
26
+
27
+ ---
28
+
29
+ ## Try it in 60 seconds
30
+
31
+ **1. Run it.** Nothing to install first — `npx` fetches and runs it.
32
+
33
+ ```bash
34
+ npx claude-finops
35
+ ```
36
+
37
+ First run reads `~/.claude/projects` and builds the warehouse (roughly a minute for a
38
+ few hundred transcripts). Every run after that starts in about a second.
39
+
40
+ **2. Open <http://127.0.0.1:8787>.** You land on the executive overview above: spend,
41
+ tokens, burn rate, forecast, and a ranked list of what to fix first.
42
+
43
+ **3. Ask it what to do.** "Why so many tokens?" explains where your tokens actually
44
+ went and gives you a prompt you can paste straight into Claude Code to fix it.
45
+
46
+ ![Why so many tokens?](https://raw.githubusercontent.com/mohit-raj-purohit/claude-finops/main/docs/img/diagnose.png)
47
+
48
+ **4. Stop when you are done.**
49
+
50
+ ```bash
51
+ claude-finops --stop
52
+ ```
53
+
54
+ Want it permanently available?
55
+
56
+ ```bash
57
+ npm install -g claude-finops # then `claude-finops` from anywhere
58
+ ```
59
+
60
+ ---
61
+
62
+ ## What you actually get
63
+
64
+ **Where the money goes, per project.** Every project ranked by cost, drilling down
65
+ Project → Session → Prompt.
66
+
67
+ ![Projects](https://raw.githubusercontent.com/mohit-raj-purohit/claude-finops/main/docs/img/projects.png)
68
+
69
+ **A grade, not just numbers.** A 0–100 FinOps scorecard across five dimensions, each
70
+ with the reasoning behind the score, so you know whether your usage is healthy.
71
+
72
+ ![FinOps scorecard](https://raw.githubusercontent.com/mohit-raj-purohit/claude-finops/main/docs/img/scorecard.png)
73
+
74
+ **Waste you can act on.** Repeated prompts, abandoned sessions, context carried for
75
+ no reason — each with the estimated money attached.
76
+
77
+ ![Waste detection](https://raw.githubusercontent.com/mohit-raj-purohit/claude-finops/main/docs/img/waste.png)
78
+
79
+ **Whether the model you are on is the right one.** Per-model cost and efficiency,
80
+ plus a switch analysis that prices the same workload on a cheaper model.
81
+
82
+ ![Model analysis](https://raw.githubusercontent.com/mohit-raj-purohit/claude-finops/main/docs/img/models.png)
83
+
84
+ **What next month looks like.** Forecast from your own history, against budgets you
85
+ set.
86
+
87
+ ![Forecast](https://raw.githubusercontent.com/mohit-raj-purohit/claude-finops/main/docs/img/forecast.png)
88
+
89
+ ---
90
+
91
+ ## Why it is easy to use
92
+
93
+ - **One command, zero configuration.** `npx claude-finops`. No API key, no sign-up, no
94
+ config file — it reads transcripts Claude Code already wrote.
95
+ - **No dependencies.** Pure Python standard library. Nothing to `pip install`, nothing
96
+ to build, no lockfile to resolve.
97
+ - **Nothing to learn.** Every screen states its own conclusion in plain English before
98
+ it shows you a chart, and every number carries a badge saying whether it is measured
99
+ or estimated.
100
+ - **Your data stays put.** It binds to `127.0.0.1` and makes no outbound calls. The
101
+ warehouse lives in `~/.claude-finops`, so upgrading or deleting the package never
102
+ touches it.
103
+ - **It tells you what to change**, not just what happened — usually with a prompt you
104
+ can paste into Claude Code.
105
+
106
+ ---
107
+
108
+ ## The accuracy contract
109
+
110
+ This is the part that matters most, so it is stated first. Every figure in the UI
111
+ carries one of four badges, and nothing is invented.
112
+
113
+ | Badge | Meaning |
114
+ |---|---|
115
+ | **Actual** | Read straight out of your transcripts: token counts, timestamps, models, effort, tool calls, file paths, session and project identity. |
116
+ | **Estimated** | Derived. **Every dollar figure is estimated**, because Claude Code transcripts contain token counts but no billed amount. Cost = tokens × the price table in `config/pricing.json`. |
117
+ | **Forecast** | Projected from your history. Assumes the recent pattern continues. |
118
+ | **Recommendation** | A modelled opportunity. Savings estimates hold token usage constant on the alternative and do **not** model output quality. |
119
+
120
+ ### Deliberately not fabricated
121
+
122
+ These are simply not present in Claude Code transcripts, so the dashboard says so
123
+ rather than guessing:
124
+
125
+ - Plan tier, allowance, and remaining credits
126
+ - Message / request allowances
127
+ - Billed invoice amounts
128
+ - Assistant response text (only usage metadata is extracted)
129
+ - Lines changed, commits, pull requests, bugs fixed
130
+
131
+ Wherever one of these would appear, you get **"Unavailable from connected Claude
132
+ data"**. Several of them can be *declared by you* in `config/settings.json` — do that
133
+ and the usage-vs-limit, days-until-limit, and limit-date projections light up, clearly
134
+ labelled as your own configured figures.
135
+
136
+ ---
137
+
138
+ ## What is in it
139
+
140
+ **Command center** — Executive overview (spend, tokens, usage %, remaining, forecast),
141
+ an AI FinOps Advisor that answers "what should I do today?" from live data, and a
142
+ 0–100 FinOps scorecard with per-dimension reasoning.
143
+
144
+ **Usage** — Interactive timeline across 10 metrics and 6 time ranges with day
145
+ drill-down; burn rate and limits with a gauge, days-until-limit and projected overage;
146
+ per-model FinOps table with superlatives (most expensive, most used, most
147
+ token-efficient, best cost-per-output); context-size distribution and cache
148
+ with-vs-without analysis.
149
+
150
+ **Drill-down** — Project → Session → Prompt, everywhere. A prompt explorer over every
151
+ prompt with full text, category, tokens, cache split, tool calls, files touched,
152
+ latency and efficiency; five leaderboards; prompt intelligence (spend by activity);
153
+ and a Claude Code view (tools, files, branches, cost per repository).
154
+
155
+ **Optimize** — A waste detector with seven rules, each showing the exact prompts or
156
+ sessions it flagged; a recommendation engine that stays quiet without evidence; and
157
+ anomaly detection you can click through to the underlying sessions.
158
+
159
+ **Plan** — Forecast with conservative/expected/high scenario bands, and budgets with
160
+ Budget → Actual → Forecast → Variance and configurable alert thresholds.
161
+
162
+ Global search spans prompt text, sessions, projects, models, tools and dates. Global
163
+ filters (date, model, project, category, cost/token thresholds, sandbox toggle) update
164
+ every chart and KPI. Everything exports to CSV/JSON, plus a printable PDF report.
165
+
166
+ ---
167
+
168
+ ## Configuration
169
+
170
+ Two files, both editable without touching code. The server picks up changes to
171
+ `settings.json` immediately; `pricing.json` needs a restart.
172
+
173
+ ### `config/pricing.json`
174
+
175
+ Model prices per million tokens, kept strictly separate from usage data so the table
176
+ can be updated as prices change. A model with no entry falls back to
177
+ `default_model_pricing` and is flagged as such in the Model analysis view.
178
+
179
+ ### `config/settings.json`
180
+
181
+ ```jsonc
182
+ {
183
+ "billing_period": { "mode": "calendar_month", "anchor_day": 1 },
184
+ "limits": { // null => reported as unavailable, never guessed
185
+ "monthly_cost_allowance_usd": null,
186
+ "monthly_token_allowance": null,
187
+ "monthly_request_allowance": null,
188
+ "remaining_credits_usd": null
189
+ },
190
+ "budgets": { "monthly_usd": null, "daily_usd": null, "per_project_usd": {} },
191
+ "alert_thresholds_pct": [50, 75, 90, 100],
192
+ "waste_rules": { /* thresholds for each detector */ },
193
+ "anomaly": { /* z-score and ratio triggers */ },
194
+ "scorecard": { /* the reference points each dimension is graded against */ }
195
+ }
196
+ ```
197
+
198
+ The **Budgets** view edits limits, budgets and thresholds from the browser and writes
199
+ them back to this file.
200
+
201
+ Note on `waste_rules.low_output_ratio_vs_median`: sessions are flagged relative to
202
+ *your own* median output ratio rather than an absolute number, because a healthy ratio
203
+ depends entirely on how agentic your workload is.
204
+
205
+ ---
206
+
207
+ ## How it works
208
+
209
+ ```
210
+ ~/.claude/projects/**/*.jsonl
211
+ │
212
+ ▼ finops/etl.py stream-parse, normalize, roll up
213
+ ~/.claude-finops/data/finops.db SQLite warehouse
214
+ │
215
+ ▼ finops/analytics.py KPIs · burn · forecast · waste · anomalies · scorecard
216
+ finops/api.py stdlib HTTP: JSON API + static files (127.0.0.1 only)
217
+ │
218
+ ▼ web/ vanilla JS, inline-SVG charts, no build step
219
+ ```
220
+
221
+ ### Data model
222
+
223
+ `projects` → `sessions` → `prompts` → `requests` (the usage event) → `tool_calls`,
224
+ plus `files_touched`. A request carries the full token split (input, output, thinking,
225
+ cache read, cache write 5m/1h), derived `billable_tokens` and `context_tokens`,
226
+ estimated cost, a no-cache counterfactual cost, and measured latency.
227
+
228
+ ### Definitions worth knowing
229
+
230
+ - **billable_tokens** = input + output + cache read + cache write. Agentic coding is
231
+ dominated by cache reads, so this number is large by nature.
232
+ - **context_tokens** = input + cache read + cache write — the prompt side of one
233
+ request, used as the context-size proxy.
234
+ - **latency** = gap to the preceding message, discarded above 15 minutes since that is
235
+ idle time rather than model latency.
236
+ - **Cache savings** price every cached token at the plain input rate as a
237
+ counterfactual. It is a model, not a bill you avoided.
238
+ - **Prompt categories** are transparent keyword rules (`finops/classify.py`); every
239
+ prompt records the matched terms and a confidence, both visible in its detail view.
240
+
241
+ ### Rebuilding
242
+
243
+ ```bash
244
+ python3 -m finops.etl # default ~/.claude/projects
245
+ python3 -m finops.etl /path/to/transcripts # or a specific directory
246
+ ```
247
+
248
+ The build is destructive and idempotent — it drops and recreates `~/.claude-finops/data/finops.db`.
249
+
250
+ ---
251
+
252
+ ## Commands
253
+
254
+ ```
255
+ claude-finops start the dashboard
256
+ claude-finops --rebuild re-read transcripts, then start
257
+ claude-finops --stop stop it
258
+ claude-finops --where where your data, settings and keys live
259
+ claude-finops --set-key store a provider API key (hidden prompt, 0600)
260
+ claude-finops --keys which provider keys are configured
261
+ claude-finops --help everything
262
+ ```
263
+
264
+ Installed globally (`npm i -g claude-finops`) or run ad hoc (`npx claude-finops`),
265
+ these work from any directory. From a source checkout, `./run.sh` takes the same flags.
266
+
267
+ ---
268
+
269
+ ## Where your data lives
270
+
271
+ Everything the app writes lives outside the install folder, in one state directory:
272
+
273
+ ```
274
+ ~/.claude-finops/
275
+ data/finops.db SQLite warehouse (your prompt text)
276
+ data/cloud_cache.json cached billing figures
277
+ data/server.pid|.log running server
278
+ settings.local.json budgets and limits set in the UI
279
+ secrets.local.json provider API keys (0600)
280
+ ```
281
+
282
+ Set `CLAUDE_FINOPS_HOME=/some/path` to put it elsewhere. The install folder holds
283
+ only code and the shared defaults in `config/`, so it can be replaced on upgrade —
284
+ or shipped as a package — without touching your data. An older in-tree `data/`
285
+ layout is copied across automatically on first run; the originals are left in
286
+ place for you to delete once you are happy.
287
+
288
+ ---
289
+
290
+ ## Privacy
291
+
292
+ `~/.claude-finops/data/finops.db` and the prompt/CSV exports contain **your full prompt text**. The
293
+ server binds to `127.0.0.1` only and makes no outbound requests, but treat the
294
+ database and any export you generate as sensitive.
295
+
296
+ ---
297
+
298
+ ## Sharing it
299
+
300
+ The app has nothing tied to one person. Whoever runs it sees **their own** Claude usage:
301
+
302
+ - It reads `~/.claude/projects` on the machine it runs on (override with `CLAUDE_PROJECTS=/path`).
303
+ - The account label comes from that machine's `~/.claude.json`.
304
+ - Budgets and limits you set in the UI are saved to `~/.claude-finops/settings.local.json`. The committed `config/settings.json` holds only shared defaults.
305
+
306
+ **Requirements:** macOS, Windows or Linux; Python 3.9+; Claude Code used at least once.
307
+ Nothing else to install.
308
+
309
+ | OS | Start | Stop | Package to share |
310
+ |---|---|---|---|
311
+ | macOS / Linux | `./run.sh` | `./run.sh --stop` | `./share.sh` |
312
+ | Windows | `run.cmd` (or `py run.py`) | Ctrl-C | `py run.py --share` |
313
+
314
+ **To share:** run `./share.sh`, which writes `../claude-finops.zip` containing code and defaults
315
+ only. Your data never lives in the folder, so there is nothing to strip. **Never send
316
+ `~/.claude-finops/`**, because `finops.db` holds your prompt text.
317
+
318
+ **Recipient:** unzip, then `./run.sh` (macOS/Linux) or double-click `run.cmd` (Windows), and open
319
+ <http://127.0.0.1:8787>.
320
+
321
+ Free-model setup per OS: macOS installs Ollama with Homebrew, Windows with winget. Linux needs
322
+ sudo, so the app shows the one command to run yourself. Launchers go to `~/.local/bin`, as `.cmd`
323
+ files on Windows.
324
+
325
+ ---
326
+
327
+ ## Actions (these change your machine, and only when you click)
328
+
329
+ - **⟳ Sync** (top bar) re-reads `~/.claude` and swaps in fresh data without restarting.
330
+ - **Free models** adds a launcher such as `claude-qwen` in `~/.local/bin` that runs Claude Code
331
+ on a free model (Ollama locally, or OpenRouter). It lists every step first, and asks before it
332
+ installs Ollama or downloads a model. Your normal `claude` is unchanged. Edit the list in
333
+ `config/free_models.json`.
334
+ - **Skills & MCP** suggests MCP servers and skills from work you repeat, with the evidence.
335
+ "Add" runs `claude mcp add -s user …`; "Create skill" writes `~/.claude/skills/<name>/SKILL.md`.
336
+
337
+ ---
338
+
339
+ ## Multi-agent
340
+
341
+ Besides Claude Code, the warehouse loads every other coding agent it finds on the machine:
342
+
343
+ | Agent | Read from | What it gives |
344
+ |---|---|---|
345
+ | Codex | `~/.codex/sessions` | Tokens + model per turn; cost at OpenAI list price |
346
+ | Gemini CLI | `~/.gemini/tmp/*/chats` | Tokens + model per reply; cost at Gemini list price |
347
+ | Cursor | `~/.cursor/projects/*/agent-transcripts`, Cursor IDE `state.vscdb` (read-only) | Prompts + tool calls; tokens only where Cursor stored them; no model, not priced |
348
+
349
+ Pick agents with the chips at the top: click for one, Cmd/Ctrl-click to combine, **All** for
350
+ everything. Every page follows the selection, and **Agents** shows them side by side.
351
+ Prices for the other providers live in `config/pricing.json` with their source URLs.
352
+
353
+
354
+ ---
355
+
356
+ ## License and trademarks
357
+
358
+ MIT — see [LICENSE](LICENSE).
359
+
360
+ Not affiliated with, endorsed by, or sponsored by Anthropic. "Claude" and "Claude Code"
361
+ are trademarks of Anthropic, PBC, used here only to describe what this tool reads.
@@ -0,0 +1,74 @@
1
+ #!/usr/bin/env node
2
+ "use strict";
3
+ /*
4
+ * npm entry point. Node does no work here beyond finding a Python 3.9+ and
5
+ * handing control to run.py, which stays the single source of truth.
6
+ *
7
+ * Interpreter search order: $CLAUDE_FINOPS_PYTHON, then the platform default.
8
+ * The app writes only to ~/.claude-finops, so it runs fine from a read-only
9
+ * npx cache.
10
+ */
11
+ const { spawn, spawnSync } = require("child_process");
12
+ const path = require("path");
13
+
14
+ const RUN_PY = path.join(__dirname, "..", "run.py");
15
+ const MIN = [3, 9];
16
+
17
+ function candidates() {
18
+ const explicit = process.env.CLAUDE_FINOPS_PYTHON;
19
+ if (explicit) return [{ cmd: explicit, pre: [] }];
20
+ return process.platform === "win32"
21
+ ? [{ cmd: "py", pre: ["-3"] }, { cmd: "python", pre: [] }, { cmd: "python3", pre: [] }]
22
+ : [{ cmd: "python3", pre: [] }, { cmd: "python", pre: [] }];
23
+ }
24
+
25
+ // Ask the interpreter its own version rather than parsing `--version` output,
26
+ // which differs across builds.
27
+ function versionOf(c) {
28
+ const probe = spawnSync(c.cmd, [...c.pre, "-c", "import sys;print('%d.%d' % sys.version_info[:2])"],
29
+ { encoding: "utf8" });
30
+ if (probe.error || probe.status !== 0) return null;
31
+ const parts = String(probe.stdout).trim().split(".").map(Number);
32
+ return parts.length === 2 && parts.every(Number.isFinite) ? parts : null;
33
+ }
34
+
35
+ function resolve() {
36
+ let best = null;
37
+ for (const c of candidates()) {
38
+ const v = versionOf(c);
39
+ if (!v) continue;
40
+ if (v[0] > MIN[0] || (v[0] === MIN[0] && v[1] >= MIN[1])) return { ...c, v };
41
+ best = best || { ...c, v };
42
+ }
43
+ return { tooOld: best };
44
+ }
45
+
46
+ const py = resolve();
47
+
48
+ if (py.tooOld) {
49
+ console.error(`Claude FinOps needs Python ${MIN.join(".")}+, but found ${py.tooOld.v.join(".")}.`);
50
+ console.error("Install a newer Python: https://www.python.org/downloads/");
51
+ process.exit(1);
52
+ }
53
+ if (!py.cmd) {
54
+ console.error("Claude FinOps needs Python 3.9+, which was not found on your PATH.");
55
+ console.error(process.platform === "darwin"
56
+ ? "Install it with: brew install python3 (or https://www.python.org/downloads/)"
57
+ : "Install it from: https://www.python.org/downloads/");
58
+ console.error("Already have one elsewhere? Set CLAUDE_FINOPS_PYTHON=/path/to/python3");
59
+ process.exit(1);
60
+ }
61
+
62
+ const child = spawn(py.cmd, [...py.pre, "-X", "utf8", RUN_PY, ...process.argv.slice(2)],
63
+ { stdio: "inherit" });
64
+
65
+ // Forward the signals a user actually sends, so Ctrl-C stops the dashboard
66
+ // rather than orphaning it.
67
+ for (const sig of ["SIGINT", "SIGTERM", "SIGHUP"]) {
68
+ process.on(sig, () => { try { child.kill(sig); } catch { /* already gone */ } });
69
+ }
70
+ child.on("error", (err) => {
71
+ console.error(`Could not start ${py.cmd}: ${err.message}`);
72
+ process.exit(1);
73
+ });
74
+ child.on("exit", (code, signal) => process.exit(signal ? 1 : code === null ? 1 : code));
@@ -0,0 +1,49 @@
1
+ {
2
+ "_comment": "Free models Claude Code can talk to. 'Adding' one creates a launcher command (e.g. claude-qwen) that starts Claude Code pointed at that model. Your normal `claude` is never changed. Edit this list to add more.",
3
+ "models": [
4
+ {
5
+ "id": "qwen-local",
6
+ "name": "Qwen 3.5 9B (local, Ollama)",
7
+ "provider": "ollama",
8
+ "model": "qwen3.5:9b",
9
+ "command": "claude-qwen",
10
+ "download_gb": 6.6,
11
+ "min_ram_gb": 16,
12
+ "good_for": "Best local pick for 16 GB Macs. Tools + thinking, 256K context. Routine edits, tests, docs.",
13
+ "limits": "Slower than Claude and weaker on large multi-file changes. Runs on your CPU/GPU."
14
+ },
15
+ {
16
+ "id": "qwen38-local",
17
+ "name": "Qwen 3.8 27B (local, Ollama)",
18
+ "provider": "ollama",
19
+ "model": "qwen3.8:27b",
20
+ "command": "claude-qwen38",
21
+ "download_gb": 18,
22
+ "min_ram_gb": 32,
23
+ "good_for": "Newest Qwen. Strongest local option for multi-file work, 256K context.",
24
+ "limits": "Needs a 32 GB+ Mac (18 GB model). On 16 GB it will be unusably slow or fail to load."
25
+ },
26
+ {
27
+ "id": "qwen-coder-small",
28
+ "name": "Qwen 2.5 Coder 7B (local, Ollama)",
29
+ "provider": "ollama",
30
+ "model": "qwen2.5-coder:7b",
31
+ "command": "claude-qwen-coder",
32
+ "download_gb": 4.7,
33
+ "min_ram_gb": 8,
34
+ "good_for": "Lightweight laptops. Small code questions and single-file edits.",
35
+ "limits": "Older (2024) and weakest at tool use. Prefer Qwen 3.5 9B if you have 16 GB RAM."
36
+ },
37
+ {
38
+ "id": "qwen-openrouter",
39
+ "name": "Qwen3 Coder (free, OpenRouter cloud)",
40
+ "provider": "openrouter",
41
+ "model": "qwen/qwen3-coder:free",
42
+ "command": "claude-qwen-cloud",
43
+ "download_gb": 0,
44
+ "min_ram_gb": 0,
45
+ "good_for": "Big free coding model with nothing to download.",
46
+ "limits": "Needs a free OpenRouter API key. Free tier is rate-limited, and prompts are sent to OpenRouter."
47
+ }
48
+ ]
49
+ }
@@ -0,0 +1,13 @@
1
+ {
2
+ "_comment": "Qualitative 1-5 ratings for the Compare view. Judgement from model size, age and known behaviour in agentic coding. Not benchmark scores; edit freely. Keys match model ids in pricing.json or ids in free_models.json.",
3
+ "ratings": {
4
+ "claude-opus-5": {"tools": 5, "reasoning": 5, "multifile": 5, "speed": "Fast", "best_for": "Hard bugs, architecture, reviews"},
5
+ "claude-sonnet-5": {"tools": 5, "reasoning": 4, "multifile": 5, "speed": "Fast", "best_for": "Everyday coding: best value"},
6
+ "claude-fable-5-1": {"tools": 5, "reasoning": 4, "multifile": 4, "speed": "Fast", "best_for": "Same price tier as Sonnet"},
7
+ "claude-haiku-4-5-20251001": {"tools": 4, "reasoning": 3, "multifile": 3, "speed": "Fastest", "best_for": "Lookups, Explore subagents, small edits"},
8
+ "qwen-openrouter": {"tools": 3, "reasoning": 3, "multifile": 3, "speed": "Medium, throttled on free tier", "best_for": "Free general coding, if sending code to OpenRouter is OK"},
9
+ "qwen38-local": {"tools": 3, "reasoning": 3, "multifile": 3, "speed": "Needs 32 GB+ RAM", "best_for": "Strongest local option on a big machine"},
10
+ "qwen-local": {"tools": 2, "reasoning": 2, "multifile": 2, "speed": "Slow; slower as context grows", "best_for": "Offline or private small tasks"},
11
+ "qwen-coder-small": {"tools": 1.5, "reasoning": 1, "multifile": 1, "speed": "Slow", "best_for": "Snippets and explanations only"}
12
+ }
13
+ }