tokenoscopy
v0.5.0
Published
Flight recorder & spend control for AI agents and the apps that call Claude. Records Claude Code sessions, enforces budgets, and puts stop-limits on production Anthropic API spend.
Maintainers
Readme
tokenoscopy
Flight recorder & spend control for coding-agent fleets — and stop-limits for the production apps that call Claude. Records every Claude Code session — every prompt, tool call, file edit, and dollar — into a replayable timeline with budgets that can actually stop a runaway run.
npm install -g tokenoscopy
tokenoscopy initNo key to paste: init opens your browser to pair the machine with your
workspace, you confirm the code it shows, and it finishes in the terminal.
The Setup screen at tokenoscopy.com then waits
for your first session and shows it to you as it lands. Headless or CI? Pass
a key from Settings → Ingest keys with --key tok_… (or TOKENOSCOPY_KEY).
Install globally rather than relying on npx: the budget guard runs before
every Bash and MCP tool call, and npx re-resolves the package each time.
Production apps: tokenoscopy/anthropic
For apps and jobs that call the Anthropic API directly — no Claude Code session, no admin key:
import Anthropic from "@anthropic-ai/sdk";
import { monitor, flush } from "tokenoscopy/anthropic";
const anthropic = monitor(new Anthropic(), { service: "checkout-api" });
const msg = await anthropic.messages.create({ /* unchanged */ });
// Serverless: upload before the function returns.
await flush();- Reports counts, never content. Token counts, request and error counts,
the model, and the
service/featurelabels you give it — uploaded every 10 seconds withTOKENOSCOPY_KEY. Tokenoscopy prices them. - Stop-limits, enforced in your app. Set a
blocklimit for a service on the Production page. The wrapper refreshes the decision every 15 seconds in the background (no added latency) and throwsTokenoscopyLimitErrorbefore the next call is sent.onLimit: "warn"logs instead. - Fails open, always. No key, no network, a timeout, a bad response, or a Tokenoscopy outage — the call goes through. Only an explicit block stops one.
- Any runtime. One self-contained file with no imports: Node, Bun, Deno,
Vercel Functions, edge. Works with the Bedrock / Vertex / Foundry clients too
(same
messagessurface).
Observed: messages.create (streaming and not), messages.parse,
messages.stream, and their beta.messages twins. Not observed:
withResponse() on a streaming create, a raw stream consumed via
toReadableStream(), and the Batches API.
Commands
| Command | What it does |
|---|---|
| init | Wires Claude Code hooks (live events + transcript flush + budget guard) into ~/.claude/settings.json. Idempotent; keeps a backup; never touches your other hooks. --project targets ./.claude/settings.json for CI. --print shows the config without writing. |
| flush | Parses the current session transcript, computes list-price spend, redacts secrets client-side, uploads. Called by hooks; safe to run manually with --transcript <path>. |
| guard | PreToolUse budget check. Hard 1500ms timeout; every failure path fails open — your session never stalls on us. |
| tail | Watches ~/.claude/projects and flushes transcripts as they change. --backfill uploads the last 7 days first; --since <days> widens that and relabels each session's billing lane. |
| doctor | Verifies config, hook wiring, API reachability, key validity, and the billing lane (with the evidence that decided it). |
Privacy
Redaction runs on your machine before anything uploads: credential shapes (Anthropic/OpenAI/GitHub/Slack/AWS/Google/Stripe), JWTs, private-key blocks, Authorization headers, connection-string passwords, secret assignments, and emails in content. Replays include the paths of files the agent read or edited (and each one relative to the repo root); branch drift is counted from local git refs, with no network call.
Environment
TOKENOSCOPY_KEY— ingest key (overrides config file; use in CI)TOKENOSCOPY_API_URL— API base (defaulthttps://tokenoscopy.com)TOKENOSCOPY_CONFIG_DIR— config location (default~/.config/tokenoscopy)
MIT © Tokenoscopy
