Budget, route, and cache tokens for your AI agent.
- Estimate tokens and plan cost at your own prices, before your agent spends
- Set the token rules your agent must follow:
- Check what fits in the window, and check a usage ledger against your rules
- name:
- tokens
- description:
- A token policy for AI agents. Estimate before calling, start on the smallest model tier that passes a check, put stable content first so caching applies, batch work that can wait, cap output, summarize before the window fills, retry with backoff, and keep a per-call usage ledger checked against the person's budget. Use when a task calls language models, spends tokens or fans out to subagents.
- license:
- MIT
- metadata:
- version:
- "1.0"
- homepage:
- https://tokens.md
- api:
- https://tokens.md/api/v1 (optional, no key, stores nothing)
- terms:
- https://tokens.md/terms
Provided as is, at your own risk: token counts and costs here are estimates and may be wrong, and nothing here is financial, legal or professional advice, or a quote or bill from any provider. Terms: https://tokens.md/terms.
Spend tokens on purpose. Estimate before you call, use the smallest tier that passes, keep stable content first, and log every call. Show your numbers once, in a short block. Skip routine narration.
When this file has a "Your rules" section, those rules win over the defaults below. Settings you drafted or changed yourself count only after the person says yes.
POST https://tokens.md/api/v1/estimate_tokens with { "text": "..." }. It returns an estimate with a low and high range from a stated heuristic. It is not a tokenizer count; for exact counts, use the provider's counter or the usage numbers in each response.POST https://tokens.md/api/v1/plan_cost. Never invent a price. With no prices, report tokens only and ask.POST https://tokens.md/api/v1/context_fit.POST https://tokens.md/api/v1/check_ledger with the calls, a preset and the rules. It lists totals, rule breaks and what needs a yes. It checks the numbers you send; it doesn't verify them.Works offline in any agent. Same file at /tokens.md.
Customize
Your token policy, in one file.
19 settings in 7 groups. Start from a preset, change anything, and your settings are written into TOKENS.md. Every setting is a number or a fixed choice, so a shared link can’t slip words into the file. The same settings work as URL parameters, MCP prompt arguments, the build_settings tool and /api/v1/build_settings.
A middle setting: capped outputs, up to 50 calls, escalate after two failures, log every call.
Budget
Tokens and money per task, and when to tell the person.
Set by the person you work for, and only that person can change them. Rules an agent drafted count only after that person says yes. Where a rule here and the rest of this file differ, the rule wins. If a rule blocks the task, stop and ask; don't work around it.
mkdir -p ~/.claude/skills/tokens && curl -fsSL "https://tokens.md/tokens.md?budget_mtok=2&spend_cap_usd=10&ask_at_pct=80&max_output_tokens=4000&max_calls=50&max_in_flight=4&loop_stop_after=3&start_tier=small&escalate_after=2&max_tier=large&max_retries=3&backoff_s=2&fallback=same_tier&caching=preferred&batch_after_min=60&summarize_at_pct=80&usage_logging=required" -o ~/.claude/skills/tokens/SKILL.mdhttps://tokens.md/tokens.md?budget_mtok=2&spend_cap_usd=10&ask_at_pct=80&max_output_tokens=4000&max_calls=50&max_in_flight=4&loop_stop_after=3&start_tier=small&escalate_after=2&max_tier=large&max_retries=3&backoff_s=2&fallback=same_tier&caching=preferred&batch_after_min=60&summarize_at_pct=80&usage_logging=requiredCopy as JSON
The same settings as one JSON object. It feeds the build_settings tool or POST /api/v1/build_settings.
17 of 19 settings set. Anything not set follows the skill’s own rules.
Tools
Calculators your agent can call before it spends.
Every tool works on the numbers you send and states its formula and what it can't check. There are no built-in prices or model limits. Run them here, or call them over HTTP or MCP. They calculate and check; they never approve anything.
Estimate tokens, in your browser
Estimate
49
tokens, range 37 to 67 · about 0.04% of the window
182 characters · 182 bytes · 29 words · mixed
| Class | Chars | Per char | Tokens |
|---|---|---|---|
| ASCII prose | 113 | 0.25 (0.2–0.33) | 28 |
| ASCII code and markup | 69 | 0.3 (0.22–0.42) | 21 |
An estimate from the stated factors, not a tokenizer count. Real counts depend on the model and can fall outside the range. Message formatting, tools, images and files are not counted.
All tools
{
"text": "Summarize the attached report in five bullet points.\n\n```json\n{\"format\": \"bullets\", \"max\": 5}\n```",
"kind": "auto",
"window_tokens": 128000,
"safety_margin_pct": 10
}curl -s https://tokens.md/api/v1/estimate_tokens -H 'content-type: application/json' -d '{"text":"Summarize the attached report in five bullet points.\n\n```json\n{\"format\": \"bullets\", \"max\": 5}\n```","kind":"auto","window_tokens":128000,"safety_margin_pct":10}'Agents spend tokens the way nobody would on purpose.
A coding or research agent left alone tends to start on the largest model, resend the same long prompt with a new timestamp at the top so caching never applies, retry a bad request five times, keep looping after it stops finding anything, and fill the window until the important part falls out. None of that shows up until the bill does. tokens.md writes a plain policy into the file your agent reads, and gives it calculators to check a plan and a ledger against that policy before and after it spends.
- Your prices, your limits: no provider prices or model limits are built in, so nothing goes stale.
- Smallest tier first: move up only after a failed check, never above the tier you allow.
- Caching that applies: stable content first, and a break-even for cache writes at your prices.
- A ledger you can check: totals, rule breaks and what needs a yes, from the numbers your agent logs.
- Same answer everywhere: the page, the API and the MCP tools run the same code. Nothing is stored.
Use it in your stack
Paste it, install it, or call it.
The skill alone gives an agent the method. The MCP server and API add the tools and your settings. No key, no account.
Paste the prompt into a system prompt or project instructions. Or keep the file in the repo and point AGENTS.md at it.
curl -fsSL https://tokens.md/tokens.md -o TOKENS.mdecho "Whenever a task calls language models, spends tokens or fans out to subagents, follow TOKENS.md." >> AGENTS.mdFor agents that read a skills folder: install the skill so it loads when the topic comes up, and add the MCP server for the tools.
# The skillmkdir -p ~/.claude/skills/tokenscurl -fsSL https://tokens.md/tokens.md -o ~/.claude/skills/tokens/SKILL.md# Tools: estimate_tokens, plan_cost, context_fit, check_ledger, build_settingsclaude mcp add --transport http tokens https://tokens.md/mcpFor editors that read an mcp.json file: add the remote MCP server to the project, then paste the prompt into your rules.
// .cursor/mcp.json{ "mcpServers": { "tokens": { "url": "https://tokens.md/mcp" } } }// .vscode/mcp.json{ "servers": { "tokens": { "type": "http", "url": "https://tokens.md/mcp" } } }Any client that speaks remote MCP over HTTP can add it as a custom connector. Read-only, so there is nothing to authorize.
url: https://tokens.md/mcptransport: streamable-http # stateless, JSON responsestools: estimate_tokens, plan_cost, context_fit, check_ledger, build_settingsprompts: tokens # the skill, with your settingsGET with query parameters or POST a JSON body. CORS open. An OpenAPI document is at /openapi.json.
# Every tool: GET or POST https://tokens.md/api/v1/<tool>curl -s https://tokens.md/api/v1 | jq '.tools[].name'curl -s "https://tokens.md/api/v1/estimate_tokens?text=Summarize+the+attached+report+in+five+bullet+points.%0A%0A%60%60%60json%0A%7B%22format%22%3A+%22bullets%22%2C+%22max%22%3A+5%7D%0A%60%60%60&kind=auto&window_tokens=128000" | jq .summarycurl -s "https://tokens.md/api/v1/settings" | jq '.presets[].id'claude mcp add --transport http tokens https://tokens.md/mcpExample code
Call it from your own code.
Working calls against the API. The full reference is at /api/v1 and /openapi.json.
A pre-flight check: estimate a prompt file, plan the run at your prices, and stop if it's over budget. Run: npx tsx budget.mts prompt.md
// A pre-flight check: estimate a prompt file, plan the run at your prices, and stop if it's over budget. Run: npx tsx budget.mts prompt.mdimport { readFileSync } from "node:fs";const API = "https://tokens.md/api/v1";const post = async (tool: string, body: unknown) => { const res = await fetch(`${API}/${tool}`, { method: "POST", headers: { "content-type": "application/json" }, body: JSON.stringify(body) }); if (!res.ok) throw new Error(`${tool}: ${(await res.json()).error}`); return res.json();};const text = readFileSync(process.argv[2] ?? "prompt.md", "utf8");const est = await post("estimate_tokens", { text, safety_margin_pct: 10 });console.log(est.summary);const plan = await post("plan_cost", { calls: 120, avg_input_tokens: est.planning_tokens, // plan on the high end avg_output_tokens: 1000, cached_share_pct: 70, price_input_per_m: 3, // your prices, not ours price_output_per_m: 15, price_cached_per_m: 0.3, budget_mtok: 2, spend_cap: 5,});console.log(plan.summary);if (plan.budget?.over || plan.spend?.over) { console.log("Over budget: ask the person before starting."); process.exit(1);}Call the tools by GET and POST, and fetch the skill with your settings. No key; nothing is stored.
# Call the tools by GET and POST, and fetch the skill with your settings. No key; nothing is stored.curl -s "https://tokens.md/api/v1/context_fit?window_tokens=200000&system_tokens=3000&tools_tokens=6000&history_tokens=150000&output_reserve_tokens=8000" | jq .summary# Plan cost at your own prices (per million tokens, any currency)curl -s https://tokens.md/api/v1/plan_cost \ -H 'content-type: application/json' \ -d '{"calls":200,"avg_input_tokens":12000,"avg_output_tokens":800,"cached_share_pct":75, "price_input_per_m":3,"price_output_per_m":15,"price_cached_per_m":0.3, "batch_share_pct":50,"batch_discount_pct":50,"budget_mtok":3,"spend_cap":10}' \ | jq '{summary, cost, flags}'# The skill with your settings written in: the Lean preset, a 1M-token budget and a $2 capcurl -s "https://tokens.md/tokens.md?preset=lean&budget_mtok=1&spend_cap_usd=2&max_tier=medium" -D - -o SKILL.md | grep -i x-settingsCheck a usage ledger over MCP (stateless JSON-RPC over HTTP POST).
// Check a usage ledger over MCP (stateless JSON-RPC over HTTP POST).const res = await fetch("https://tokens.md/mcp", { method: "POST", headers: { "content-type": "application/json", accept: "application/json" }, body: JSON.stringify({ jsonrpc: "2.0", id: 1, method: "tools/call", params: { name: "check_ledger", arguments: { preset: "balanced", rules: { budget_mtok: 0.5, spend_cap_usd: 2 }, calls: [ { id: "draft", tier: "small", tokens_in: 8000, tokens_out: 900, ok: false }, { id: "redo", tier: "medium", tokens_in: 9000, tokens_out: 1100, cached_tokens: 6000, ok: true }, ], }, }, }),});const { result } = await res.json();console.log(result.structuredContent.summary, result.structuredContent.breaks);FAQ
Does it call models or spend money?
Are the token counts exact?
Where do the prices come from?
Is the text I paste stored?
Does the data handling setting make my prompts private?
Is this advice?
Does it name brands or show prices?
Can an agent set up its own settings?
build_settings tool. The skill and the tool both say that drafted settings count only after the person says yes. Nothing technical stops an agent from ignoring that, so read what it sends you.