npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

tokensniff

v0.1.1

Published

Claude Code telemetry proxy and live terminal status line HUD. Real-time token tracking, API costs, TTFT, and calendar heatmap dashboard. Zero dependencies.

Readme

tokensniff

Local telemetry sidecar for AI coding CLIs.

Track every token, every turn, every dollar — live in your terminal and on a calendar heatmap dashboard. Zero runtime dependencies.

npm version License: MIT Node.js


What Is tokensniff?

tokensniff is a transparent HTTP reverse proxy and local telemetry sidecar designed specifically for the Claude Code CLI harness running alongside the local antigravity-claude-proxy.

By default, tokensniff orchestrates and connects to antigravity-claude-proxy to route Claude Code API requests through Google Antigravity / Cloud Code, allowing you to utilize your Antigravity Gemini quota directly inside Claude Code.


⚠️ Important Notice: Use At Your Own Risk & Account Warning

[!CAUTION] Use at your own risk. By default, tokensniff routes traffic through antigravity-claude-proxy, which accesses Google Antigravity / Cloud Code endpoints using unofficial proxying techniques.

  • Risk of Account Suspension / Bans: Google actively monitors and enforces Terms of Service (ToS) restrictions. Accounts connected to unofficial Cloud Code and Antigravity reverse proxies risk being shadow-banned, quota-restricted, or permanently banned.
  • No Guarantees & Zero Liability: The creators and maintainers of tokensniff provide no guarantees or warranties of any kind, express or implied. We are not responsible or liable for any account bans, suspensions, quota penalties, data loss, or any other consequences resulting from the use of this software.
  • Safety Recommendation: Do not use your primary, personal, or corporate Google account. If you choose to use this integration, use a dedicated burner/disposable Google account.
  • Learn More: Read the upstream antigravity-claude-proxy GitHub Repository and its Safety, Usage, and Risk Notices to understand how the underlying authentication and proxying operate.

It captures every API turn flowing through it and gives you:

  • Per-turn token counts — input, output, cache-read, cache-write, thinking tokens
  • Real-time cost tracking — per turn, per session, per day (in USD)
  • Performance metrics — Time to First Token (TTFT), tokens per second (TPS), turn duration
  • Live terminal status line — a single-line HUD rendered directly inside Claude Code's status bar
  • Calendar heatmap dashboard — a beautiful, self-contained HTML page showing your daily token spend over the entire year
  • Multi-terminal session management — run multiple terminals against the same proxy without conflicts
  • Tool call tracking — which tools the model called, how many times, argument token sizes
  • Context window monitoring — how full your context is, with color-coded warnings (green → yellow → red)

All of this happens transparently. Your AI tool doesn't know tokensniff exists. It just thinks it's talking to the normal API. tokensniff forwards every byte with zero latency overhead, while quietly recording the telemetry.


How It Works

flowchart TD
    CLI["Claude Code CLI<br/><code>ANTHROPIC_BASE_URL:4000</code>"]
    TS["tokensniff<br/><code>Reverse Proxy :4000</code>"]
    Proxy["antigravity-claude-proxy<br/><code>Local Upstream :8085</code>"]
    Google["Google Cloud Code API<br/><code>Gemini Backend / Quota</code>"]

    subgraph Telemetry["Telemetry Engine"]
        T1["latest.json"]
        T2["totals.json"]
        T3["history.ndjson"]
        T4["/dashboard (HTML)"]
    end

    Statusline["Claude Code Statusline HUD"]
    Dashboard["Live Calendar Heatmap<br/><code>http://localhost:4000/dashboard</code>"]

    CLI <-->|"1. Anthropic API Requests / Streams"| TS
    TS <-->|"2. Forward"| Proxy
    TS -->|"3. Telemetry (Async)"| Telemetry
    Proxy <-->|"4. Protocol Translation"| Google

    T1 --> Statusline
    T4 --> Dashboard
  1. Harness Redirection: You point Claude Code to http://localhost:4000 by setting ANTHROPIC_BASE_URL in ~/.claude/settings.json. Claude Code continues sending standard Anthropic Messages API requests normally.
  2. Upstream Proxy Startup: When launched, tokensniff checks port 8085 and automatically starts the local upstream proxy command (npx antigravity-claude-proxy@latest start) if it is not already running.
  3. Protocol & Quota Translation: The local antigravity-claude-proxy receives the Anthropic-formatted request, authenticates with your Google Antigravity / Cloud Code OAuth credentials, translates the schema to Google Generative AI format, and submits it to Google Cloud Code's backend to consume your Antigravity Gemini quota.
  4. Streaming Response Pass-Through: As Google's response streams back, antigravity-claude-proxy transforms it into Anthropic-compatible SSE events or buffered JSON. tokensniff instantly relays every raw byte back to Claude Code (res.write(chunk)) with zero latency overhead.
  5. Telemetry Extraction: Concurrently and non-blockingly, tokensniff's parser inspects the response payload. It extracts Google's usageMetadata (input, output, cache-read, cache-write, and thinking/reasoning tokens), measures Time to First Token (TTFT) and token generation speed (TPS), and tracks turn duration.
  6. Live Pricing Calculation: tokensniff queries live pricing from OpenRouter's model catalog, computing turn cost, session cumulative spend, and daily totals.
  7. Statusline HUD & Calendar Heatmap: Telemetry snapshots are written atomically to disk (latest.json, totals.json, history.ndjson). Claude Code's status bar runs tokensniff-status to display the live single-line HUD, and tokensniff serves an interactive calendar heatmap dashboard at http://localhost:4000/dashboard.

Quick Start

1. Install

npm install -g tokensniff

Or with pnpm:

pnpm add -g tokensniff

2. Initialize Configuration

tokensniff init

This creates a configuration file at ~/.tokensniff/config.json with sensible defaults:

{
  "upstreamCommand": "npx antigravity-claude-proxy@latest start",
  "upstreamHost": "localhost",
  "upstreamPort": 8085,
  "listenPort": 4000,
  "harnessCommand": "claude"
}

Default Upstream: Out of the box, tokensniff is pre-configured to launch antigravity-claude-proxy on port 8085, allowing you to route Claude Code prompts through your Antigravity Gemini quota. Please review the Risk & Terms of Service Warning before running with this configuration.

3. Configure Claude Code

Add the following to your ~/.claude/settings.json file:

{
  "env": {
    "ANTHROPIC_BASE_URL": "http://localhost:4000"
  },
  "statusLine": {
    "type": "command",
    "command": "tokensniff-status",
    "padding": 0
  }
}

This does two things:

  • ANTHROPIC_BASE_URL — Tells Claude Code to send all API requests through tokensniff's proxy on port 4000 instead of directly to Anthropic
  • statusLine — Tells Claude Code to run tokensniff-status and display its output as a live status bar at the bottom of the terminal

4. Run

tokensniff

That's it. tokensniff will:

  1. Start the upstream proxy (if configured)
  2. Start the telemetry proxy on port 4000
  3. Launch Claude Code (or whatever harness command you configured)
  4. Show you a live status line and dashboard URL

Open the dashboard in your browser:

http://localhost:4000/dashboard

CLI Commands

tokensniff

Runs the full telemetry pipeline: starts the upstream proxy, starts the tokensniff proxy, and launches your AI coding tool.

tokensniff

tokensniff init

Generates the global configuration file at ~/.tokensniff/config.json and prints the Claude Code settings.json instructions.

tokensniff init

tokensniff dashboard

Prints the URL of the live calendar heatmap dashboard.

tokensniff dashboard
# Output: [tokensniff] live heatmap dashboard: http://127.0.0.1:4000/dashboard

tokensniff-status

This is the statusline renderer. You don't run this directly — Claude Code runs it automatically via the statusLine setting. It reads the latest telemetry snapshot from disk and outputs a formatted single-line status bar.

If you want to test it manually:

echo '{}' | tokensniff-status

To get raw JSON output instead of the formatted status line:

TOKENSNIFF_JSON=1 echo '{}' | tokensniff-status

The Status Line

When running inside Claude Code, you'll see a live status line at the bottom of your terminal that looks like this:

Wide terminals (≥ 180 columns) — single line:

turn 3 [3.8-flash] | ctx: 38.5k/1M (3.9%) [cache: 25k (64.9%)] | input: +4.5k tok, output: 42 tok, think: 180 tok | ttft: 1.2s, 110 tok/s | cost: turn $0.0042, sess $0.058, today $0.245

Standard terminals (< 180 columns) — clean 2-line stack:

turn 3 [3.8-flash] | ctx: 38.5k/1M (3.9%) [cache: 25k (64.9%)]
input: +4.5k tok, output: 42 tok, think: 180 tok | ttft: 1.2s, 110 tok/s | cost: turn $0.0042, sess $0.058, today $0.245

What Each Segment Means

| Segment | Example | Meaning | |---------|---------|---------| | Turn | turn 3 | Which turn number this is in the current session | | Model | [3.8-flash] | The AI model being used (vendor prefix stripped for readability) | | [bg] | [bg] | Shown when this is a background agent turn (via x-app: cli-bg header) | | Context | ctx: 38.5k/1M (3.9%) | Current context usage / max window size (percentage full) | | Cache | [cache: 25k (64.9%)] | How many tokens were served from cache and the cache hit ratio | | Input | input: +4.5k tok | New tokens added to context this turn (delta). Shows freed when context shrinks | | Output | output: 42 tok | Tokens generated by the model this turn | | Thinking | think: 180 tok | Reasoning/thinking tokens used (for models with extended thinking) | | Tool | tool: Read (45 tok) | Which tool was called and how many argument tokens it used | | TTFT | ttft: 1.2s | Time to First Token — how long before the model started generating | | Speed | 110 tok/s | Generation velocity in tokens per second | | Turn Cost | turn $0.0042 | How much this specific turn cost in USD | | Session Cost | sess $0.058 | Total spend for this entire session | | Today Cost | today $0.245 | Total spend across all sessions today (resets at local midnight) | | [idle] | [idle] | Shown when the last turn was more than 120 seconds ago |

Color Coding

The context percentage is color-coded based on how full your context window is:

  • 🟢 Green — Under 60% (plenty of room)
  • 🟡 Yellow — 60-80% (getting full, consider starting a new session)
  • 🔴 Red — Over 80% (context is nearly full, model may start forgetting earlier context)

These thresholds are configurable via warnPct and critPct.


The Dashboard

tokensniff serves a live calendar heatmap dashboard directly on the proxy port. Open it in any browser:

http://localhost:4000/dashboard

The dashboard shows:

  • Total Spend — cumulative USD spent across all sessions
  • Total Tokens — cumulative token volume processed
  • Cache Ratio — what percentage of tokens were served from cache
  • Total Turns — how many API turns have been recorded
  • Calendar Heatmap — a GitHub-contributions-style grid showing daily token volume across the year

Heatmap Tiers

The calendar tiles are colored using a 5-tier emerald luminosity scale:

| Tier | Daily Volume | Color | |------|-------------|-------| | 0 | No activity | Dark (nearly invisible) | | 1 | < 5M tokens | Dark emerald | | 2 | 5M – 25M tokens | Medium emerald | | 3 | 25M – 100M tokens | Bright emerald | | 4 | > 100M tokens | Vivid emerald (glowing) |

Hover over any tile to see a detailed tooltip with exact token counts, cost, cache leverage, and turns logged for that day.

Dashboard API

There's also a JSON API endpoint for programmatic access:

curl http://localhost:4000/api/daily

Returns the raw daily rollup data as JSON.


Configuration

tokensniff uses a strict hierarchical configuration system:

Environment Variables  >  Config File  >  Embedded Defaults
          (highest)                          (medium)                   (lowest)

Config File Location

~/.tokensniff/config.json

You can override this path with the TOKENSNIFF_CONFIG environment variable:

TOKENSNIFF_CONFIG=/path/to/custom/config.json tokensniff

All Configuration Options

| Config Key | Env Variable | Default | Description | |-----------|-------------|---------|-------------| | listenPort | TOKENSNIFF_PORT | 4000 | Port the tokensniff proxy listens on | | listenHost | TOKENSNIFF_HOST | 127.0.0.1 | Host/IP the proxy binds to | | upstreamHost | TOKENSNIFF_UPSTREAM_HOST | localhost | Hostname of the upstream API server | | upstreamPort | TOKENSNIFF_UPSTREAM_PORT | 8085 | Port of the upstream API server | | upstreamTimeoutMs | TOKENSNIFF_UPSTREAM_TIMEOUT_MS | 300000 (5 min) | Timeout for upstream requests in milliseconds (range: 1,000 – 3,600,000) | | maxBodyBytes | TOKENSNIFF_MAX_BODY_BYTES | 10485760 (10 MB) | Maximum request/response body size. Requests exceeding this get a 413 error (range: 1,024 – 104,857,600) | | statusDirs | TOKENSNIFF_STATUS_DIRS | ~/.tokensniff/status | Comma-separated list of directories where telemetry snapshots are written | | maxSessions | TOKENSNIFF_MAX_SESSIONS | 50 | Maximum number of tracked sessions before oldest are evicted (range: 1 – 1,000) | | deadSessionMs | TOKENSNIFF_DEAD_SESSION_MS | 259200000 (72 hrs) | How long to keep stale session files before pruning (range: 1 hour minimum) | | staleAfterS | TOKENSNIFF_STALE_AFTER_S | 120 | Seconds of inactivity before a session shows [idle] in the status line (range: 5 – 86,400) | | labelMaxIn | TOKENSNIFF_LABEL_MAX_IN | 2000 | Maximum input tokens for a turn to be classified as a micro-label | | labelMaxOut | TOKENSNIFF_LABEL_MAX_OUT | 60 | Maximum output tokens for a turn to be classified as a micro-label | | warnPct | TOKENSNIFF_WARN_PCT | 60 | Context utilization % threshold for yellow warning color (range: 1 – 99) | | critPct | TOKENSNIFF_CRIT_PCT | 80 | Context utilization % threshold for red critical color (range: 2 – 100) | | color | TOKENSNIFF_COLOR | true | Enable/disable ANSI color output. Automatically disabled when NO_COLOR env var is set (per no-color.org) | | upstreamCommand | TOKENSNIFF_UPSTREAM_CMD | npx antigravity-claude-proxy@latest start | Shell command to start the upstream proxy server | | upstreamStopCommand | TOKENSNIFF_UPSTREAM_STOP_CMD | (empty) | Shell command to stop the upstream proxy on shutdown | | harnessCommand | TOKENSNIFF_HARNESS_CMD | claude | The AI coding tool to launch (e.g., claude, codex, or any executable) |

Example Config File

{
  "listenPort": 4000,
  "listenHost": "127.0.0.1",
  "upstreamHost": "localhost",
  "upstreamPort": 8085,
  "upstreamCommand": "npx antigravity-claude-proxy@latest start",
  "upstreamStopCommand": "",
  "harnessCommand": "claude",
  "maxSessions": 50,
  "staleAfterS": 120,
  "warnPct": 60,
  "critPct": 80,
  "color": true
}

Environment Variable Examples

# Change the proxy port
TOKENSNIFF_PORT=5000 tokensniff

# Point to a different upstream
TOKENSNIFF_UPSTREAM_HOST=api.anthropic.com TOKENSNIFF_UPSTREAM_PORT=443 tokensniff

# Disable colors
NO_COLOR=1 tokensniff

# Use a custom config file
TOKENSNIFF_CONFIG=./my-config.json tokensniff

# Write status to multiple directories
TOKENSNIFF_STATUS_DIRS="/path/a,/path/b" tokensniff

Multi-Terminal Support

tokensniff supports multiple terminal sessions running simultaneously against the same proxy. This is how it works:

  1. When you run tokensniff, it first checks if a proxy is already running on port 4000
  2. If yes, it attaches to the existing proxy (no duplicate servers) and just launches your harness
  3. Each terminal session registers itself in ~/.tokensniff/sessions/ with a PID lock file
  4. When you close a terminal (Ctrl+C or exit):
    • If other terminals are still active → only the local harness is terminated; the proxy stays alive
    • If this was the last terminal → the proxy and upstream are cleanly shut down
  5. Dead PID lock files (from crashed terminals) are automatically pruned

This means you can have 5 Claude Code windows all routing through the same tokensniff proxy, and the telemetry stays unified. Session costs are tracked independently, but today cost accumulates across all sessions.


Supported Providers

tokensniff's parser understands multiple API response formats:

| Provider | Format | Detection | |----------|--------|-----------| | Anthropic (Claude) | SSE streams (text/event-stream) | event: message_start framing | | Anthropic (Claude) | Buffered JSON (application/json) | usage.input_tokens / usage.output_tokens | | Google Gemini (Antigravity) | Buffered JSON | candidates[].content.parts[] + usageMetadata |

The parser automatically detects the format from the response content-type and payload structure. You don't need to configure anything.

Pricing

tokensniff fetches live per-token pricing from OpenRouter's public model catalog. This means:

  • Pricing is always up to date — no hardcoded rate tables to maintain
  • Any model listed on OpenRouter is automatically priced correctly
  • Pricing includes prompt, completion, cache-read, and cache-write tiers
  • Context window sizes are also pulled dynamically from the catalog

If a model isn't found on OpenRouter, costs default to $0.00 (zero-rate boundary) rather than guessing wrong. The context window defaults to 128K tokens for unknown models.

The pricing cache is populated on-demand (first turn using a new model triggers a background fetch) and persists in memory for the lifetime of the proxy process.


Telemetry Data Files

tokensniff stores all telemetry in ~/.tokensniff/status/:

| File | Format | Purpose | |------|--------|---------| | latest.json | JSON | Most recent telemetry snapshot (any session) | | latest-<session_id>.json | JSON | Most recent snapshot for a specific session | | totals.json | JSON | Cumulative spend per session | | history.ndjson | Newline-delimited JSON | Append-only turn-by-turn ledger (feeds the heatmap) |

latest.json Schema (v1)

{
  "v": 1,
  "session_id": "abc-123",
  "turn_index": 5,
  "ts": 1726056000000,
  "model": "gemini-3.8-flash-tiered",
  "is_bg": false,
  "ctx": 38500,
  "window": 1000000,
  "pct": 3.9,
  "cache_read": 25000,
  "cache_create": 0,
  "delta_in": 4500,
  "in_tokens": 13500,
  "out_tokens": 42,
  "thinking": true,
  "thinking_tokens": 180,
  "tool": "Read",
  "tool_tk": 45,
  "tools_summary": [{ "name": "Read", "count": 1, "arg_tk": 45 }],
  "stop_reason": "end_turn",
  "is_label": false,
  "label": "",
  "ttft_ms": 1200,
  "tps": 110,
  "dur_s": 1.6,
  "cost_turn": 0.0042,
  "cost_session": 0.058,
  "cost_today": 0.245,
  "error": null,
  "status": 200,
  "quota_pct": null,
  "quota_reset": null,
  "tier": null
}

history.ndjson Record Format

Each line is a compact JSON object:

{"d":"2026-09-11","ts":1726056000000,"s":"abc-123","t":5,"m":"gemini-3.8-flash","tk":38542,"c":0.0042,"cr":25000,"th":180}

| Field | Meaning | |-------|---------| | d | Local calendar date (YYYY-MM-DD) | | ts | Unix timestamp in milliseconds | | s | Session ID | | t | Turn number | | m | Model name | | tk | Total tokens (context + output) | | c | Cost in USD | | cr | Cache-read tokens | | th | Thinking tokens |


Programmatic API

tokensniff exports its entire engine as a library. You can use it in your own Node.js projects:

npm install tokensniff

Start the Proxy Programmatically

import { startProxy } from 'tokensniff';

const server = startProxy({
  listenPort: 4000,
  listenHost: '127.0.0.1',
  upstreamHost: 'localhost',
  upstreamPort: 8085,
});

// server is a standard Node.js http.Server
server.on('listening', () => {
  console.log('tokensniff proxy is running');
});

Calculate Costs

import { costFor, ratesFor, resolveModelRates } from 'tokensniff/pricing';

// Synchronous (from cache, or zero if not yet fetched)
const rates = ratesFor('claude-3-7-sonnet');

// Async (fetches from OpenRouter if needed)
const rates2 = await resolveModelRates('gemini-2.5-pro');

// Calculate cost
const cost = costFor(rates, {
  input: 10000,
  output: 500,
  cacheRead: 8000,
  cacheCreate: 0,
});

console.log(`Turn cost: $${cost.toFixed(4)}`);

Use the Schema

import { buildLatest, isTokenSniffLatest, SCHEMA_VERSION } from 'tokensniff/schema';

// Build a telemetry snapshot with safe defaults
const snapshot = buildLatest({
  session_id: 'my-session',
  model: 'gemini-3.8-flash',
  ctx: 25000,
  window: 1000000,
  pct: 2.5,
});

// Validate unknown data
if (isTokenSniffLatest(someData)) {
  console.log('Valid telemetry snapshot');
}

Full API Exports

import {
  // CLI Orchestrator
  runCli,
  countActiveSessions,
  getSessionsDir,
  isPortActive,
  isProcessAlive,
  registerSession,
  waitForTcp,
  writeInitFile,
  printClaudeInstructions,

  // Configuration
  loadConfig,
  getGlobalDir,
  getGlobalConfigPath,

  // Proxy Server
  startProxy,

  // Dashboard & Analytics
  importCapturesDirectory,
  loadDailyRollup,
  renderHeatmapHtml,

  // Statusline Renderer
  formatStatus,
  formatTokenCount,
  formatToolSegment,
  runStatusRenderer,
  readStdin,
  pickLatest,
  extractModel,

  // Pricing Engine
  costFor,
  ratesFor,
  resolveModelRates,
  normalizeModelName,
  syncOpenRouterCatalog,

  // Schema & Types
  buildLatest,
  isTokenSniffLatest,
  extractCleanLabel,
  SCHEMA_VERSION,
} from 'tokensniff';

Sub-path Exports

// Just the schema types and guards
import { buildLatest, isTokenSniffLatest } from 'tokensniff/schema';

// Just the pricing engine
import { costFor, resolveModelRates } from 'tokensniff/pricing';

Architecture

tokensniff/
├── bin/
│   ├── tokensniff.js          # CLI entrypoint → dist/cli.js
│   └── tokensniff-status.js   # Statusline entrypoint → dist/status.js
├── src/
│   ├── index.ts               # Public API facade (re-exports everything)
│   ├── cli/
│   │   └── run.ts             # Master CLI orchestrator & multi-terminal lifecycle
│   ├── collector/
│   │   ├── config.ts          # Hierarchical config loader (env > file > defaults)
│   │   ├── index.ts           # HTTP reverse proxy server & telemetry capture
│   │   ├── parse.ts           # SSE stream & JSON payload parser (multi-provider)
│   │   └── store.ts           # Atomic file persistence engine (Windows-safe)
│   ├── dashboard/
│   │   └── heatmap.ts         # Calendar heatmap HTML renderer & capture importer
│   ├── renderer/
│   │   ├── format.ts          # Responsive statusline formatter
│   │   └── index.ts           # Statusline CLI renderer (stdin consumer)
│   └── shared/
│       ├── pricing.ts         # Dynamic pricing engine (OpenRouter catalog sync)
│       └── schema.ts          # Domain schemas, type guards, label extraction
└── test/
    ├── fixtures.ts            # Synthetic SSE/JSON payload generators
    ├── collector.test.ts      # Integration: proxy, streaming, 502, 413, dashboard
    ├── format.test.ts         # Statusline formatting & responsive layouts
    ├── heatmap.test.ts        # Daily rollups, capture import, HTML rendering
    ├── parse.test.ts          # SSE/JSON parsing, multi-provider, tool grouping
    ├── pricing.test.ts        # Cost math, OpenRouter sync, model normalization
    ├── run.test.ts            # CLI routing, TCP probing, session lifecycle
    ├── schema.test.ts         # Type guards, buildLatest, label extraction
    └── store.test.ts          # Atomic writes, totals, history, pruning, config

Key Design Decisions

  • Zero runtime dependencies — The entire package uses only Node.js built-in modules (http, fs, net, path, os, child_process). No Express, no Axios, no anything. This keeps the install tiny and avoids supply chain risk.

  • Atomic file writes — All file persistence uses a temp-file + OS rename pattern. This means readers (the statusline renderer) never see a half-written JSON file. On Windows, retries with exponential backoff handle EPERM/EBUSY file lock contention.

  • Streaming-first proxy — Response bytes are forwarded to the client as they arrive (res.write(chunk)). tokensniff never buffers the full response before forwarding. This means zero latency overhead. The telemetry parsing happens on the buffered copy.

  • LRU-bounded memory — Internal maps (context history, turn indices) are capped at 500 entries using LRU eviction. The proxy can run for weeks without leaking memory.

  • Defensive parsing — The parser never throws. Corrupt payloads, truncated SSE streams, binary noise — everything returns a safe fallback result. This is critical because the proxy sits in the hot path of your AI tool.


Development

Prerequisites

  • Node.js ≥ 22.0.0
  • pnpm 11.x

Setup

git clone https://github.com/neerajsahu0306/tokensniff.git
cd tokensniff
pnpm install

Build

pnpm build

Run Tests

pnpm test

Type Check

pnpm typecheck

Lint

pnpm lint

Auto-fix Lint Issues

pnpm lint:fix

Watch Mode (Development)

pnpm dev

Validate Package Structure

pnpm check:package

Troubleshooting

"waiting for first turn..."

The status line shows this message when tokensniff hasn't received any API requests yet. Make sure:

  1. Your ANTHROPIC_BASE_URL is set to http://localhost:4000 in ~/.claude/settings.json
  2. The tokensniff proxy is actually running (check terminal output)
  3. You've made at least one prompt in Claude Code

Port 4000 is already in use

Another tokensniff instance (or another program) is using port 4000. Either:

  • Let tokensniff attach to it (it will do this automatically if the existing proxy is tokensniff)
  • Change the port: TOKENSNIFF_PORT=5000 tokensniff
  • Kill the existing process: find and terminate whatever is using port 4000

Upstream proxy failed health check

tokensniff couldn't connect to the upstream API server. Check that:

  1. Your upstreamCommand is valid and the upstream server starts correctly
  2. The upstreamHost and upstreamPort match where the upstream is listening
  3. The upstream server is not firewalled or blocked

tokensniff will continue running even if the upstream health check fails — downstream requests will get 502 errors until the upstream becomes available.

Costs showing $0.0000

This means tokensniff couldn't find pricing for the model you're using on OpenRouter. This can happen if:

  • The model is brand new and not yet listed on OpenRouter
  • The OpenRouter API was unreachable when tokensniff tried to fetch pricing
  • You're using a custom/private model that isn't publicly listed

The proxy and telemetry still work perfectly — only the cost calculation defaults to zero.

Status line not appearing in Claude Code

Make sure your ~/.claude/settings.json has the exact statusLine block:

{
  "statusLine": {
    "type": "command",
    "command": "tokensniff-status",
    "padding": 0
  }
}

Also verify that tokensniff-status is accessible in your PATH (it should be if you installed tokensniff globally).


Requirements

  • Node.js ≥ 22.0.0
  • OS: Windows, macOS, or Linux
  • Terminal: Any terminal that supports ANSI colors (for the status line color coding)

License

MIT © 2026 tokensniff contributors