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

usagelens

v0.6.0

Published

Local dashboard for your AI coding usage across Claude Code, Codex CLI, Cursor and Antigravity. Reads your machine's local data and serves an interactive dashboard on localhost. Accurate per-model pricing, cost-per-shipped-code, and per-session drilldown.

Readme

usagelens

A local dashboard for your AI coding usage — unified across Claude Code, Codex CLI, and Cursor. It reads the usage data those tools already store on your machine, and serves an interactive dashboard on localhost. Read-only, offline, zero runtime dependencies.

npx usagelens

That's it — it scans your local data, starts a server on http://localhost:4319, and opens your browser.

What you get

  • Tokens, est. cost, sessions, cache hit-rate, streak — with deltas vs the prior period
  • Daily activity bar chart and a when-you-work hour × weekday heatmap (hover for details)
  • Tool breakdown (Claude / Codex / Cursor / Antigravity) and model mix with per-model estimated cost
  • Cost per shipped code — AI spend mapped to real git commits & lines ($/commit, $/1K lines, per project)
  • Cost efficiency & model routing — premium (Opus) share, output/input leverage, and estimated savings if routine turns were routed to a cheaper tier
  • Tool usage — how often Bash / Edit / Read / etc. are called
  • Top projects, session shape, cache effectiveness, and code authorship (Cursor)
  • Budgets — month-to-date spend vs a configured monthly budget, with straight-line projection
  • Most expensive sessions — the top sessions by estimated cost; click any row to open a detail drawer with the spend curve, token composition, models, tool calls, stop reasons, priciest turns, and session metadata (CLI version, git branch, sandbox, reasoning effort…)
  • Plans — your plan for Claude / Codex / Cursor, read from local files (offline, always on)
  • Live quota (opt-in) — your real 5-hour and 7-day Claude quota, with reset times
  • Accurate pricing — per-model list prices synced from models.dev, version-aware
  • Custom date ranges — 7d / 30d / 90d presets, or any from → to window
  • Live refresh — re-scan your data without restarting; multi-account aware

CLI

usagelens [--port <n>] [--no-open] [--no-cache]   # start the dashboard (default command)
usagelens report [--json] [--range <r>]           # print a usage report to stdout, then exit
usagelens sync-pricing [--write]                  # refresh model prices from models.dev
usagelens clear-cache                             # drop the incremental parse cache

usagelens — start the dashboard

Scans your local AI data, starts an HTTP server bound to 127.0.0.1, and opens the dashboard in your browser.

| Flag | Default | Description | | --- | --- | --- | | --port <n> | 4319 | Port to listen on (loopback only). | | --no-open | off | Start the server but don't auto-open the browser. | | --no-cache | off | Re-parse every transcript instead of using the incremental cache. |

usagelens                    # start on http://localhost:4319 and open the browser
usagelens --port 8080        # use a custom port
usagelens --no-open          # headless (e.g. remote box, or you'll open it yourself)

The first scan parses every transcript; afterwards results are cached per file and only changed files are re-read (typically ~8s → ~0.1s).

usagelens report — headless report

Prints a report for the given range to stdout and exits (no server). Useful for CI, cron, piping to jq, or posting to Slack. Includes git cost-per-shipped-code.

| Flag | Default | Description | | --- | --- | --- | | --json | off | Emit the full data payload as JSON instead of Markdown. | | --range <r> | 30d | Reporting window: 7d, 30d, 90d, or any <n>d. |

usagelens report                       # Markdown report for the last 30 days
usagelens report --range 7d            # last 7 days
usagelens report --json                # full JSON payload
usagelens report --json --range 90d    # 90-day JSON, e.g. pipe to jq
usagelens report --json | jq '.summary.costUsd'   # extract a single number

Tip: from the running dashboard, the ↓ Export report button (top-right) downloads the same Markdown report for the selected range, and .json downloads the full payload — both include git cost-per-shipped-code.

usagelens sync-pricing — refresh model prices

Prices are per-model and version-aware, sourced from models.dev. A copy ships with the package; this command refreshes it into ~/.usagelens/pricing.json, which takes precedence.

| Flag | Default | Description | | --- | --- | --- | | (none) | — | Dry run: print the diff without saving. | | --write | off | Save the fetched prices to ~/.usagelens/pricing.json. |

usagelens sync-pricing            # show what would change
usagelens sync-pricing --write    # update local prices

Models that aren't in the price list are flagged in the dashboard and the report rather than silently guessed at.

usagelens clear-cache

Deletes the incremental parse cache (~/.usagelens/cache.db). The next run does a full re-scan.

Config (optional) — ~/.usagelens.json

{
  "sources": [
    { "tool": "claude", "dir": "~/.claude",          "label": "[email protected]" },
    { "tool": "claude", "dir": "~/.claude-personal", "label": "[email protected]" }
  ],
  "pricing": { "opus": { "input": 12, "output": 60 } },
  "budget":  { "monthlyUsd": 500, "monthlyTokens": 2000000000 },
  "git": true,
  "cache": true,
  "allowSubscriptionAccess": false
}
  • sources — point at multiple config dirs to track multiple accounts (each labeled).
  • pricing — override the synced per-model $/Mtoken rates (keys are matched as regexes).
  • budget — enables the budget panel + projection.
  • git — set false to skip the git correlation (cost-per-shipped-code).
  • cache — set false to disable the incremental parse cache.
  • allowSubscriptionAccess — set true to fetch your real plan & quota. See below.

Plans & quota

These are two different things, and only one of them uses the network.

Plans — offline, always on. Which plan you're on is already sitting in plain local files, so usagelens just reads it. No network, no Keychain, no opt-in:

| Tool | Read from | | --- | --- | | Claude | ~/.claude.jsonoauthAccount.organizationType (e.g. max) | | Codex | ~/.codex/auth.jsonid_token claim chatgpt_plan_type (e.g. business) | | Cursor | Cursor globalStorage/state.vscdbcursorAuth/stripeMembershipType |

No token is read for this — only plan and tier names, which aren't secrets.

Live quota — opt-in, network. Your real 5-hour / 7-day utilisation and reset times only exist server-side, so showing them needs one request. Click ⚡ Enable live quota in the dashboard (or set "allowSubscriptionAccess": true yourself) and usagelens reads the OAuth token Claude Code already stores (macOS Keychain, or ~/.claude/.credentials.json) and calls https://api.anthropic.com/api/oauth/usage.

This is the only feature that touches the network, and it is off until you turn it on. The token goes only to its own issuer, is never logged, never written to disk, and never appears in any API response or exported report.

Changed your mind? The same panel has a Disable live quota button, which flips the flag back and stops all network calls. Plans keep working — they never needed the network.

Why not on by default? Because npx usagelens should never read a credential and phone home on a stranger's machine without them asking. One click is a small price for that.

Data sources

Read-only, from your machine:

  • ~/.claude/projects/**/*.jsonl — Claude Code (tokens, models, projects, cache)
  • ~/.codex/sessions/** — Codex CLI (per-turn token usage)
  • ~/.cursor/ai-tracking/ai-code-tracking.db — Cursor (AI vs human code authorship)
  • ~/.gemini/antigravity/** — Antigravity (session & file activity; no token data)

Tools present but exposing no usable local usage data (GitHub Copilot, Ollama) are shown as detected-without-metrics rather than fabricated numbers.

Notes

  • Cost is estimated — list price × tokens ("API-equivalent value"), not a bill. Prices come from models.dev and are version-aware: claude-opus-4-1 and claude-opus-4-5 are priced differently, as they should be. Unpriced models are flagged, not guessed.
  • Never writes to your tool directories. ~/.claude, ~/.codex, ~/.cursor and ~/.gemini are opened read-only. usagelens writes only to its own ~/.usagelens/ (parse cache + synced prices).
  • Offline by default. The server binds to loopback (127.0.0.1) only. The only outbound requests are sync-pricing (when you run it) and plan/quota (when you opt in).
  • Requires Node ≥ 22.5 (uses the built-in node:sqlite).

License

MIT