One command installs the daemon, pairs this machine, and wires the modelstat MCP into every AI tool you have (Claude Code, Claude Desktop, Cursor, Codex, …). Paste it into a terminal — or into Claude Code / Codex / Cursor and let it run.
curl -fsSL https://modelstat.ai/install.sh | sh
Windows (PowerShell):
MCP server for modelstat — ask any MCP-compatible AI tool about your token spend.
2026-11-13
ดาว
—
เครื่องมือ
—
อัปไทม์
—
irm https://modelstat.ai/install.ps1 | iex
The installer downloads a small static binary, verifies its SHA-256 checksum, pairs this machine, and installs a background service. No Node, no Python, no package manager — the binaries are self-contained. Re-run it any time to upgrade (auto-update is on by default).
That's it. Open your dashboard at modelstat.ai/dashboard. The daemon runs on macOS 13+, every glibc Linux distro, and Windows 10/11. Full options (modes, flags, headless installs): daemon/docs/INSTALL.md.
Why modelstat
Real work, not just raw tokens. After about a week of passive collection, modelstat learns your team's own vocabulary of projects and work-types — so the dashboard shows "$133 on DevOps, $114 on testing", not just "you spent $400 on Claude." No manual tagging.
Your actual sessions. It reads the logs Claude Code, Codex, Cursor, Cline, Continue, Aider, Windsurf, Zed, Copilot, and Claude Desktop already write — nothing to instrument, nothing to intercept.
Redaction always runs on your machine. Every session is scrubbed for secrets and PII on your box — a regex floor plus an on-device NER model — before a single byte is uploaded, in every mode. Raw keys, passwords, and personal data never leave. You choose where the summary is written: on this machine, your own server, or modelstat's cloud (the default) — see the three modes below. Audit it below.
What this repo is
This is the public source for everything that runs on your machine:
modelstat daemon — the native Rust daemon: two static binaries (the collector and the summariser engine) that watch your AI-tool log files, price them, redact client-side, and upload metadata. The collector's modelstat mcp subcommand is also the local Model Context Protocol server, so Claude Desktop / Claude Code / Cursor / Cline / Continue / Zed can answer "how much did we spend on X?" in chat.
@modelstat/sdk — the backend SDK: capture the LLM calls your own services make, redacted + compacted client-side before they leave the box.
Why it's open. The code that reads your files should be auditable. The hosted service that aggregates your team's metadata is closed-source; everything that runs on your laptop is right here — read it, fork it, build your own binaries, or pin a commit and install from source. See LICENSE.
What it does on your machine
your AI coding tools on YOUR machine modelstat cloud
┌──────────────────────────┐ ┌─────────────────────────┐ ┌──────────────────────┐
│ Claude Code · Codex │ │ modelstat daemon │ │ analytics dashboard │
│ Cursor · Cline · Aider │ session │ • parse + price turns │ redacted │ spend & ROI grouped │
│ Windsurf · Zed · Copilot │ ───────▶ │ • redact (PII / keys) │ ───────▶ │ by activity · repo · │
│ Claude Desktop · … │ logs │ • summarise (see modes) │ HTTPS │ model · person — │
│ (logs already on disk) │ │ → tokens + abstract │ │ the charts above │
└──────────────────────────┘ └─────────────────────────┘ └──────────────────────┘
↑ secrets & PII are stripped on your machine before anything leaves ↑
Detects installed tools — scans ~/.claude, ~/.codex, ~/.cursor, ~/.aider, ~/.config/continue, and other tool-specific locations.
Parses local log files — Claude Code's JSONL logs, Cursor's SQLite DB, Codex's conversation files, and so on. The per-tool parsers are the only code that opens these files.
Redacts on-device — in every mode — every excerpt goes through a regex pass for secrets/PII and an on-device NER model before the uploader ever sees it. This never moves off your machine, regardless of the mode below.
Summarises — you choose where (at install) — the redaction in step 3 always runs locally; only where the summary is written differs:
Local — a small ~2.7 GB LLM summarises each work-segment on this machine into a ≤240-char abstract. Raw turns stay on disk; only the abstract goes up. (The only mode that downloads the model.)
Self-hosted — your org's own OpenAI-compatible endpoint summarises the cleaned excerpts (URL + model set at install). Only the abstract goes up; no local model.
Cloud(default) — no local model at all; the cleaned, redacted turns are uploaded and modelstat's servers summarise them.
Change it any time with modelstat mode <local|self-hosted|cloud>.
Uploads what the mode implies — per-session totals (tokens, model, cost, duration) + provenance always. In Local/Self-hosted, the redacted ≤240-char abstract. In Cloud, the redacted turns (so the server can summarise them). Never raw prompts, code, or secrets — redaction runs on-device first in every mode.
Build from source (the trust path)
git clone https://github.com/modelstat/modelstat.git
cd modelstat/daemon && cargo build --release
Requirements: a stable Rust toolchain, and an account at modelstat.ai to pair with. (The SDKs build with their own toolchains — Node 20.18+/pnpm 10.7+ for sdks/node; Swift 5.9+ for the macOS tray.)
The installer wires the local MCP server (modelstat mcp) into every AI tool it detects — nothing to configure. No daemon on this machine? Connect the hosted server instead: add https://mcp.modelstat.ai to any MCP-compatible client and sign in via the browser on first use.
"How much did my team spend on Claude Code last week?""Which project is driving my Cursor cost?""Recommend a model for a code-review task — based on what worked for us before."
You can verify, from this repository alone, exactly what does and doesn't leave your machine.
The boundary. Exactly one crate talks to our ingest endpoints: modelstat-ingest (DeviceApi::upload_batch). It POSTs to /v1/ingest in Local and Self-hosted modes (pre-summarised abstracts) or /v1/ingest/raw in Cloud mode (the redacted turns the server summarises). There is no other outbound data channel. The wire-format types live in daemon/crates/modelstat-wire/src/schema.rs — if a field isn't there, the uploader literally cannot send it.
What we receive — always: model/provider/tool, per-class token counts, the cost we computed, scrubbed cwd/git metadata, filenames (paths scrubbed), redaction counts (never the matched text), and a provenance stamp. Plus, depending on your mode: a ≤240-char on-device abstract (Local / Self-hosted), or the redacted conversation turns themselves (Cloud — that is exactly what our servers summarise for you).
What we never receive: your raw prompts, your code, or any API key / token / password. Redaction runs on your machine in every mode before anything leaves it — Cloud mode's uploaded turns are redacted turns, not raw ones, and Self-hosted mode runs the same on-device scrub before excerpts reach your org's endpoint. Text fields are size-capped by Zod; the paranoid policy drops entire stdout/stderr/tool_output/raw_text blobs before upload.
Defence-in-depth, every byte crossing the boundary passes through: parser scoping → secrets regex (Anthropic/OpenAI/Google/AWS/GitHub/Slack/Stripe keys, JWTs, PEM blocks, bearer headers, DB passwords) → PII regex (emails, public IPs, URL creds, home paths) → a Shannon-entropy catcher for unknown key shapes → on-device NER → wire-schema byte caps → provenance stamp. The regex + entropy floor lives in daemon/crates/modelstat-redact/; the caps in daemon/crates/modelstat-wire/src/caps.rs. In Cloud mode the daemon is fail-closed on the NER pass: if that on-device model can't load, it will NOT ship raw turns with regex-only redaction — it falls back to local extractive abstracts instead (no raw egress).
Audit it yourself — three places tell the whole story:
modelstat is the cross-tool AI spend analytics layer for engineering teams — the questions your finance team actually asks: How much did we spend on project X? Which work-type eats our budget? Personal vs company accounts on the same machine? Opus vs GPT-5 vs Sonnet on the same kind of task?