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

meterly

v0.1.0

Published

See where your Claude Code spend actually goes — per project, model, MCP server, subagent and branch. Local-first, no API key.

Downloads

17

Readme

meterly

See where your Claude Code spend actually goes — per project, model, MCP server, subagent, skill and git branch.

Claude Code already writes every token count to disk. meterly reads those local transcripts and turns them into a cost report. No API key, no account, no network calls.

npx meterly

There's also a VS Code extension — live cost in the status bar for the folder you're in, plus a full report panel. Install the .vsix from the latest release:

code --install-extension meterly-vscode-0.1.0.vsix

Example output (illustrative figures):

═══ Claude Code spend ═══
  Billable messages  4,120
  Total tokens       980,455,000
  Total cost         $1184.00

  Cost breakdown
    input                  $2.10
    output               $141.60
    cache read           $712.40   1.0B tok
    cache write          $327.90   5m 40.0k / 1h 22.0M tok

By project
  ~/work/api-gateway                  $602.10   50.9%   498.0M tok
  ~/work/web-client                   $284.55   24.0%   221.0M tok
  ~/work/infra                        $167.30   14.1%   132.0M tok

By MCP server
  postgres             $188.40   15.9%   171.0M tok
  playwright           $141.20   11.9%   118.0M tok
  github                $96.75    8.2%    88.0M tok

Budgets that warn before you overrun

A dashboard tells you what you already spent — the cheap half of the problem. By the time a number looks bad, the money is gone.

Drop a .meterly.json beside your project (or in your home directory):

{
  "budgets": [
    { "name": "daily cap", "period": "day",   "limit": 25 },
    { "name": "team",      "period": "month", "limit": 2000, "warnAt": 0.7 },
    { "project": "backend", "period": "week", "limit": 100 }
  ]
}

Budgets trip on trajectory, not just arrival. Spend is extrapolated over the remaining period, so $30 by 6am against a $100/day cap is flagged as heading for $120 while there's still time to act:

Budgets
  [ over?] ███████|·················  daily cap: on track to overrun — $30.00 of $25.00
                                     with 75% of the day left, heading for $120.00
  (| marks how far through the period you are)

--check exits 3 when any budget is over or projected over, so it works as a guardrail rather than a report — wire it into CI, a cron job, or a shell hook:

meterly --check || notify-send "AI spend over budget"

Exit codes are distinct on purpose: 3 is a budget breach, 1 is no data, 2 is bad usage — so a caller can tell a breach apart from the tool failing to run.

Why another usage tracker

Most of them get the arithmetic wrong, and none of them tell you which part of your setup is expensive.

1. One API response is many log records

Claude Code writes one record per content block — a thinking block, a text block, each tool_use — and every one of them repeats the same message-level usage object verbatim.

Sum the records and you count the same tokens three or four times. Across the transcript set this was developed against, assistant records outnumbered actual billable messages by 2.64× — so a record-summing tracker reports a bill more than two and a half times the real one.

meterly dedupes on message.id, which is the actual billable unit. (Not requestId — a server-side fallback re-runs one request on a second model, and both messages are billed.)

2. Cache writes are not one price

A 1-hour-TTL cache write costs 2× base input. A 5-minute write costs 1.25×. The logs break this out under cache_creation.ephemeral_1h_input_tokens / ephemeral_5m_input_tokens, but the flat cache_creation_input_tokens field lumps them together.

On the same dataset over 99% of cache-write tokens were 1-hour. Pricing them all at 1.25× understates the cache-write line by 37% — and cache writes were the second-largest cost component, so that is not a rounding error.

3. Things that aren't tokens still cost money

  • Web search bills $10 per 1,000 searches, entirely separate from tokens. Invisible to anything that only sums token fields.
  • inference_geo: "us" applies a 1.1× multiplier to every token category. It's in the logs; nothing else applies it.
  • Fast mode on Opus 5 / 4.8 bills at $10/$50 rather than $5/$25.
  • Code execution bills by container-hour with 1,550 free hours/month — so it is counted but deliberately not priced, because a per-call figure would be invented.

4. Unknown models are never silently free

A model with no known rate contributes $0 and a loud warning, and the report says the total is a floor. A confident wrong number is worse than a stated gap.

What it attributes

| Axis | Question it answers | |---|---| | Project (cwd) | Which repo is burning the budget? | | Model | What's the mix, and what does each tier actually cost? | | MCP server | Which integration is expensive? | | MCP tool | Which individual call inside it is expensive? | | Skill / plugin | Which of these is pulling its weight? | | Session | Which single conversation ran away with the budget? | | Git branch | What did that refactor cost? | | Day | Trend over time | | Subagents (isSidechain) | How much goes to delegated work? | | Failed API calls | Spend that returned nothing | | Compaction | Cost of context summarisation |

Usage

npx meterly                      # everything
npx meterly --since 7d           # last week (also 24h, 30m, or 2026-07-01)
npx meterly --project api-gateway  # one project
npx meterly --top 25             # more rows
npx meterly --json               # full report as JSON
npx meterly --csv > spend.csv     # every dimension as CSV, for chargeback

--root <path> or CLAUDE_CONFIG_DIR if your config isn't at ~/.claude.

As a library

Zero dependencies, streaming, and safe on large transcripts — real sessions reach 150 MB+, so nothing is ever fully loaded into memory.

import { findTranscripts, parseTranscript, buildReport } from 'meterly';

const seen = new Set<string>();          // shared: resumed sessions repeat messages
const records = [];
for (const f of await findTranscripts()) {
  const { records: r } = await parseTranscript(f.path, seen);
  records.push(...r);
}

const report = buildReport(records);
console.log(report.totals.cost.total);
console.log(report.byMcpServer);
console.log(report.diagnostics.unpricedModels);   // always check this

Pricing is overridable if rates change before this package does:

buildReport(records, {
  models: { 'claude-opus-5': { input: 4, output: 20 } },
  serverTools: { web_search_requests: 0.008 },
});

Accuracy

Rates are transcribed from Anthropic's published pricing (verified 2026-07-27) and live in one table in src/pricing.ts. Cache multipliers (1.25× / 2× / 0.1×), the batch discount (50%), the US inference-geo premium (1.1×) and fast-mode rates are applied as documented multipliers rather than hardcoded per-model figures, so they stay correct as models are added.

These are estimates for attribution, not an invoice. Your bill is what Anthropic's console says. Discounts, enterprise rates and Bedrock/Vertex/Foundry pricing are not modelled.

Privacy

Everything runs locally. meterly reads token counts, model IDs, timestamps, working directories and branch names — it never reads message content, and it never opens a network connection. Grep the source: there is no HTTP client in it.

License

MIT