Skip to content

Latest commit

 

History

366 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

TokenOps

CI Release License Go Report

Predict rate-limit cutoffs inside your AI agent. Local MCP server + CLI that watches your flat-rate AI subscription window — Claude Max, ChatGPT Plus / Pro / Team, GitHub Copilot, Cursor, Mistral Le Chat Pro, Codex Plus — and tells the agent, before you hit the cap, to continue, slow_down, switch_model, or wait_for_reset.

Docs: https://klarlabs-studio.github.io/tokenops/ · Releases: https://github.com/klarlabs-studio/tokenops/releases

Install

brew trust klarlabs-studio/tap        # first time only
brew install --cask klarlabs-studio/tap/tokenops

Homebrew refuses to load a cask from a third-party tap it has not been told to trust, so the first install of anything from this tap needs brew trust klarlabs-studio/tap once — per machine, not per tool.

Or via Go:

go install go.klarlabs.de/tokenops/cmd/tokenops@latest

Or grab a prebuilt binary from the releases page (darwin amd64/arm64, linux amd64/arm64).

90-second quickstart

tokenops init                                  # writes config, registers MCP, installs hooks
tokenops plan set anthropic claude-max-20x     # bind your tier (init tells you if it can't)
tokenops daemon install                        # supervise `tokenops start` so ingestion survives reboot

init does the wiring. It finds the MCP hosts you actually have (Claude Code, Claude Desktop), registers tokenops serve with each — pinned to the absolute binary path, so a host can never silently run a stale build — installs the Claude Code hooks, and prints what still needs you:

Wiring tokenops into this machine:
  ✓ MCP: Claude Code       registered — restart Claude Code to load the tools
  ✓ Claude Code hooks      installed coach-hook + read-guard
  · plan binding           detected anthropic but not which tier you pay for

Re-run it any time to repair drift. It is idempotent, backs up every file it touches, and refuses to overwrite a host config it cannot parse. Two things stay yours: picking your plan tier (the tiers differ 4x in headroom, so guessing would make every figure confidently wrong) and pointing a client at the proxy (that reroutes your real traffic). --no-wire writes the config only.

Then restart your MCP host and ask the agent for any of: tokenops_session_budget, tokenops_burn_rate, tokenops_dashboard, tokenops_plan_headroom. Or open the browser dashboard the agent links you to (http://tokenops.local:7878/dashboard?token=…).

Features

🧮 13 plan catalog Claude Max 5x/20x, Claude Pro, Claude Code (Max + Pro), ChatGPT Plus / Pro / Team, GitHub Copilot Individual / Business, Cursor Pro / Business, Mistral Le Chat Pro, Codex Plus — each with a dated vendor source URL pinned in code
🔌 Provider-agnostic 17 proxy-metered providers — OpenAI, Anthropic, Gemini, Mistral, Cohere, the OpenAI-compatible fleet (Groq, DeepSeek, xAI, Perplexity, Fireworks, Cerebras, Together, OpenRouter), plus local/self-hosted (Ollama, LM Studio, LiteLLM, Vercel AI Gateway). Bind any with tokenops provider set <name>
📊 Interactive dashboard Vue 3 + D3 dashboard at /dashboard — cost line, per-model stacked area, tokens-per-bucket, KPI tiles, 15s auto-refresh, provider + model filters that persist across refresh
📍 mDNS-discoverable Daemon advertises tokenops.local over zeroconf so the dashboard URL is memorable on every host
🔐 Dashboard auth Shared-secret token, auto-minted on first start, accepted via header / query / cookie. tokenops dashboard rotate-token revokes
📡 Vendor /usage ingestion Live per-turn JSONL readers for Claude Code (~/.claude/projects/) and Codex CLI (~/.codex/sessions/), plus GitHub Copilot OAuth quota, Cursor cookie scrape, Anthropic cookie scraper (only source of the official Claude Max weekly %). Each source has a tokenops vendor-usage enable <source> wizard with env-var fallback for secrets
💰 Cache-aware pricing Claude + Codex cache reads bill at ~10% of the new-input rate. For agent-heavy workloads cache reads are >95% of input — the dashboard Cache hit: XX.X% tile + cost-aware aggregator make the difference between a naive $94k estimate and the real $10k. Per-provider rate cards ship in code
🧪 Per-project / per-session attribution JSONL pollers stamp agent_id = "claude-code:<project>" and workflow_id = "claude-code:<project>:<session>" (analogous for Codex). group=agent answers "which project burns the most"; coach finds per-session waste
🧠 Prompt coach tokenops coach prompts heuristic feedback on your real prompting patterns — length distribution, vague/ack/repeat detection, concrete recommendations. Auto-discovers Claude Code + Codex JSONLs. Prompt text never persisted. Ranked recommendations (v0.18) project tangible savings: turns × tokens × dollars × hours per win
📋 Reply coach tokenops coach replies detects output-compression patterns (caveman skill, article density, filler density) per session
⏱️ Task boundaries tokenops task start "fix X" / done / list --metrics — operator-marked task units persisted to ~/.tokenops/tasks.jsonl. List view rolls up turns / cost / TTFUO / cost-per-turn from the events store within each task window
📐 8-KPI agent scorecard FVT / TEU / SAC (wedge) plus CHR / CGR / RGR / TCS / DAR (agent-workflow), all graded A–F against tuneable thresholds. v0.21.1 honest grading: TEU N/A when optimiser isn't wired; autonomous-loop sentinels filtered from CGR; column→payload attribution sync so SAC reflects reality
🩺 Agent DX metrics tokenops dx + tokenops_agent_dx — turns, wall-clock, tokens and tool calls per instruction, plus rework / interrupt / escalation / first-try rates, context growth and compactions. Each graded, with the single highest-leverage change named. Derived from transcripts; no proxy needed
🪝 Coaching on every client coach-hook nudges on Claude Code, Codex and Cursor (Stop) and opencode (session.idle, delivered as a TUI toast from a generated plugin). read-guard refuses a redundant re-read on Claude Code and opencode — the two whose hooks can decline one. Codex has no file-read tool and Cursor's beforeReadFile is observe-only; hooks install refuses both with the reason instead of writing a hook that never fires
📖 Work storytelling tokenops story + tokenops_story — reconstructs your work as an account of it, one task at a time: the instruction you typed, what the agent did before the next one, what it cost, where it went sideways. One structure, four renderings: candid for you, JSON for an agent, --for report as evidence for someone you bill, --for handoff as state-of-the-world for a teammate. Titles are your own instructions, quoted — never summarised
🧠 Smart routing optimizer.smart_routing decides per turn with no rules table: task class × plan-window pressure × the live pricing table. Downwards only, mechanical work only, only while the window is tight, never past your preferred-model ceiling. Enforcement needs the proxy; tokenops_routing_advise is the same policy as advice, reachable on any MCP client — it recommends and never applies
🧭 Context-aware routing Rules scope to what a turn is (when_class: mechanical) and to how tight your plan window is (when_window_pct_above: 70) — keep your best model while there's headroom, conserve it only when there isn't. Both abstain rather than guess: an unclassifiable turn or an unmeasured window leaves the model alone
🛡️ Preferred model ceiling preferred_models per provider. Cheaper routes apply automatically; a pricier one is refused and surfaced for your answer via MCP, with your preferred model offered as the alternative
🔄 Self-refreshing rate card The daemon fetches the public rate card daily and applies it to the running engine, so a model released after your binary does not silently price at zero. It downloads and sends nothing; verified rows and your negotiated overrides outrank anything fetched. One line to switch off
🎯 Honest signal quality Every prediction carries signal_quality.level (low / medium / high) plus a one-line caveat. Heuristic mode is labelled; proxied mode is labelled
✂️ Command-output compression tokenops fmt -- <cmd> shrinks a command's stdout before it hits the agent context — 46 built-in formatters (git, go/pytest/jest/…, npm/pip/uv/…, mvn/gradle/bazel/dotnet/…, docker/kubectl/helm, terraform/pulumi/ansible, aws/gcloud/az, and more) plus user-defined formatters in config (no recompile). Deterministic + critical-line-safe: errors/failures/changed-state never dropped, full output kept in ~/.tokenops/recovery/. Balanced ~57% / aggressive ~68% stdout reduction. Self-tunes per user via fmt learn --apply
🤖 MCP-first 29 MCP tools agents call directly. Inline SVG sparkline + headroom gauge rendered in markdown so every MCP client shows them today
🧠 Dynamic-cheapest coaching Coaching pipeline picks the lowest blended-rate model per provider at runtime from the pricing table — no hardcoded model names
💾 Local-first, open source SQLite database, no cloud account, no telemetry. Apache 2.0. Demo-data isolation by default so synthetic seeds never contaminate the real signal

See docs/architecture-ddd.md for the bounded contexts and layer rules; docs/plan-cost-model.md for the plan catalog model.

CLI surface

init                              Scaffold config (sqlite + rules on); --detect sniffs installed clients
start                             Run the daemon in the foreground (proxy + analytics + bus + dashboard)
daemon {install|uninstall|status} Supervise `tokenops start` via launchd (macOS) or systemd --user (Linux)
serve                             MCP server over stdio
demo                              Seed 7d of synthetic events
status                            Daemon health + blockers[] / next_actions[]
spend [--forecast]                Spend / burn / 7d forecast
plan {list|set|headroom|catalog}  Subscription plan headroom
provider {list|set|unset}         Upstream LLM provider URLs
vendor-usage {status|backfill}    Inspect / backfill vendor-side pollers
dashboard rotate-token            Mint + persist a fresh dashboard auth token
config show                       Active configuration (redacted)
audit                             Query audit log
events                            Per-kind domain-event counts
rules {analyze|conflicts|...}     Rule intelligence
scorecard                         Wedge KPI scorecard
coverage-debt                     Risk-weighted coverage debt
eval                              Optimizer eval harness + gate
replay <id>                       Replay a session through the optimizer
fmt -- <cmd>                      Run <cmd>, compress its output deterministically before it reaches the agent (full output kept in ~/.tokenops/recovery/)
fmt bench --corpus <dir>          Measure formatter savings over captured command outputs
fmt hook [--shell zsh|bash]       Emit env-gated shell wrappers (activate with TOKENOPS_FMT=1)
fmt recover <id>                   Print the full stored output for a run (records the re-access)
fmt learn                         Mine fmt telemetry for next-formatter priorities + over-compression

Most CLI verbs have a matching MCP tool (tokenops_<name>). fmt is CLI-first (it wraps a shell command); its learning report is exposed to agents via tokenops_fmt_learn.

Upgrading signal quality

Default install reports low confidence (MCP pings only). Two zero-network upgrades:

# ~/.config/tokenops/config.yaml
vendor_usage:
  claude_code:
    enabled: true              # reads ~/.claude/stats-cache.json
    interval: 60s
  anthropic:
    enabled: true              # calls Anthropic Admin API
    admin_key: sk-ant-admin-…  # mint in claude.com console
    interval: 5m

tokenops vendor-usage status shows whether the pollers are emitting; use tokenops vendor-usage backfill --hours 168 to pull a week of history from Anthropic Admin in one shot after configuring the key.

The Anthropic Admin API only covers metered API usage. Claude Max plan window state has no documented endpoint and stays heuristic — the cache reader is the only locally-available Max signal and reports daily granularity with an explicit caveat.

Architecture

Clients / SDKs / CLIs / MCP hosts
            |
            v
   Local TokenOps daemon (Go)
      /     |       \
 Proxy    MCP      Dashboard
   |     server     /api/*
   v        |        |
 Provider routes     Vue+D3
 (OpenAI/Anth/Gem/Mistral)
            |
            v
    SQLite event store
            |
            v
 Spend / forecast / coaching

DDD-organised: contexts under internal/contexts/<ctx>/<pkg>, adapters (cli, mcp, proxy) stay flat. Layering enforced by internal/archlint (go test ./internal/archlint/...).

cmd/{tokenops,tokenopsd}/         # binaries
internal/
  contexts/                       # bounded contexts (rules, spend, security, ...)
  cli/                            # cobra subcommands
  mcp/                            # MCP tool surface
  proxy/                          # HTTP server + dashboard
  daemon/                         # boot sequence
  storage/sqlite/                 # event store
pkg/eventschema/                  # public envelope + payload types
web/docs/                         # VitePress docs site
.roady/                           # spec-driven planning

Integrations

TokenOps instruments AI usage on three planes; which ones a client supports is the whole integration story. Full matrix + provider list: docs/integrations/coverage.

Client Passive read MCP Proxy
Claude Code ~/.claude/projects ANTHROPIC_BASE_URL
Codex CLI ~/.codex/sessions OPENAI_BASE_URL
opencode ✅ SQLite store ✅ per-provider baseURL
Gemini CLI (no token log) ✅ base-URL override
Desktop apps (if MCP host)
  • Passive read — reads logs the client already writes; per-turn attribution (turn → session → project), zero wiring.
  • MCP (tokenops serve) — the agent calls TokenOps; tokenops_status reports what's live and the exact command to upgrade signal quality.
  • Proxy — point the client's base URL at TokenOps for ground-truth token/cost accounting. OpenRouter (tokenops provider set openrouter) is the universal fallback for any client with no local reader.

Honest boundaries: Gemini CLI has no local token log (proxy only); AWS Bedrock needs SigV4 the passthrough proxy can't do; fully-hosted agents (Jules) are out of reach — TokenOps is local-first with no telemetry.

Parity across clients does not exist, and the matrix says so. Desktop and GitHub clients have no local token log and no base-URL override, so coaching there is pull-only: no transcripts means no storytelling, no proactive nudges, no routing. What is left is the MCP surface, which on those clients is the whole product. The capability matrix lists what reaches which client, feature by feature, gaps included.

Disabled-subsystem contract

When a subsystem is off, the matching routes return 503 with a structured {error, hint} body instead of 404. tokenops status (and the MCP tokenops_status tool, and GET /readyz) surface stable identifiers in blockers[] plus the exact command in next_actions[]:

Blocker Fix
storage_disabled tokenops init then restart
rules_disabled tokenops init then restart
providers_unconfigured tokenops provider set …

Demo data isolation

Two event sources are excluded from every default rollup, because neither is real LLM traffic you paid for or waited on:

Source What it is
demo Synthetic PromptEvents seeded by tokenops demo
mcp-session Activity-proxy pings the MCP server records about itself

Re-admit them one at a time — --include-source (CLI, repeatable and comma-separated) or include_sources (MCP tool input):

tokenops spend --include-source=demo                # synthetic seeds too
tokenops spend --include-source=demo,mcp-session    # and the MCP pings

--include-demo / include_demo: true still work as aliases for demo alone.

Contributing

See CONTRIBUTING.md, CODE_OF_CONDUCT.md, and SECURITY.md. Plans and tasks live in .roady/ (see roady).

Changelog

See CHANGELOG.md — latest is v0.55.0.

License

Apache License 2.0. See LICENSE.

About

Predict rate-limit cutoffs inside your AI agent. Local MCP server + CLI that tracks Claude Max, ChatGPT Plus/Pro/Team, GitHub Copilot, Cursor plan windows and warns before you hit the cap.

Topics

Resources

Code of conduct

Contributing

Security policy

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages