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

claude-stat

v0.2.0

Published

A compact, information-dense status line for Claude Code. Shows context window usage, rate limits, prompt cache hit percentage, model, effort level, git branch, and session token totals. Zero dependencies.

Readme

claude-stat - A Status Line for Claude Code

A compact, information-dense status line for Claude Code showing context window usage, rate limits, cache-hit percentage, model, effort level, git branch, and session totals. Zero dependencies - just Node.js.

Claude Code status line example showing project name, git branch, model, effort badge, context window bar, rate limits, and session token totals with cache hit percentage

Claude Code status line example showing project name, git branch, model, effort badge, context window bar, rate limits, and session token totals with cache hit percentage, shows claude chat too

claude-stat replaces Claude Code's default status bar with a dense, color-coded read-out of everything that matters during a coding session: how much of your context window is used, how close you are to your 5-hour and 7-day rate limits, what percentage of input tokens came from the prompt cache (i.e., nearly free), plus the model, effort level, git state, and output style. It's a single ~270-line Node.js script - no npm dependencies, no background processes, no network calls.

Features

  • Model-aware context window bar - auto-detects the active model's ceiling (200k, 1M, etc.) from the Claude Code payload. Color shifts green → lime → yellow → orange → red as you fill.
  • Live rate-limit display - shows % used and time-until-reset for both the Claude.ai 5-hour and 7-day quotas. Hidden for API-key users.
  • Cache-hit percentage - parses the session transcript to compute the fraction of input tokens served from the prompt cache. Size-keyed cache keeps repaints cheap (typical render: 5–20 ms).
  • Live effort badge - LO·MD·HI·XH·MX color-coded from cheap → cost-danger, read from the payload's live session value, so mid-session /effort changes show up immediately. Dims when extended thinking is off, and shows · on models with no effort control.
  • Git-aware - directory name + branch, orange for uncommitted changes, worktree badge when applicable.
  • Conditional badges - vim mode (INS/NRM), subagent name, git worktree, non-default output style.
  • Zero dependencies - pure Node.js standard library. No npm install, no background daemons.
  • Non-destructive install - backs up ~/.claude/settings.json with a timestamped filename before touching it. Leaves hooks, plugins, env, and permissions untouched.

Install

Option 1 - One-liner via npx (recommended)

npx claude-stat

This runs the installer from the npm package. No clone required. To update later, see Update - use @latest.

Option 2 - From source

git clone https://github.com/waelmas/claude-stat.git
cd claude-stat
node install.js

After either install path, start a new Claude Code session (or reload) - the new status line appears on the next prompt.

What the installer does

  • Copies statusline.js~/.claude/statusline-command.js (mode 0755).
  • Backs up your existing ~/.claude/settings.json to settings.json.backup-<timestamp>.
  • Sets settings.json.statusLine to { "type": "command", "command": "node ~/.claude/statusline-command.js" }.
  • Touches nothing else.

Manual install

If you'd rather not run the installer:

  1. Copy statusline.js somewhere stable (e.g. ~/.claude/statusline-command.js).
  2. In ~/.claude/settings.json, add or update:
    {
      "statusLine": {
        "type": "command",
        "command": "node /absolute/path/to/statusline-command.js"
      }
    }
  3. Reload Claude Code.

Update

Updating is just re-installing - the installer is idempotent and overwrites the copied script in place.

npx claude-stat@latest

The @latest matters. A bare npx claude-stat may resolve from the npx cache and quietly reinstall the version you already have.

npx installs from npm, not from GitHub. npx claude-stat@latest gives you the latest published version. A change that is committed and pushed to GitHub but not yet npm published will not arrive this way - you'll silently reinstall the last published release. If you're testing an unreleased change, install from the clone instead.

From a clone:

git pull
node install.js        # or: node install.js update

git pull alone is not enough - the installer copies statusline.js to ~/.claude/statusline-command.js, so the running status line is a copy, not a link. It only changes when you re-run the installer.

Start a new Claude Code session (or reload) to pick up the new version.

Every install and uninstall writes another ~/.claude/settings.json.backup-<timestamp>. They accumulate across updates and are safe to delete once you're happy with the result.

Developing on claude-stat? Symlink instead, so edits are live without reinstalling: ln -sf "$PWD/statusline.js" ~/.claude/statusline-command.js A later node install.js replaces the symlink with a normal copy.

Releasing (maintainers)

Pushing to GitHub does not update the npm package. Until npm publish runs, npx claude-stat@latest keeps serving the previous release:

npm version patch|minor|major   # or edit package.json by hand
npm publish
npm view claude-stat version    # confirm the registry actually moved

Verify what you shipped rather than assuming - npm pack claude-stat@latest downloads the published tarball so you can inspect the exact files users will receive.

What it shows

Left to right, separated by :

| Segment | Example | Meaning | |---|---|---| | Project + branch | claude-stat on main● | Directory name + git branch. Orange = uncommitted changes. Branch truncates at 22 chars. | | Model + effort | Opus 4.7 XH | Model name (strips parentheticals like (1M context)). Badge = live effort level: LO·MD·HI·XH·MX, colored from meh (gray) → cost-danger (red). See Effort badge. | | Context bar | [██░░░░░░] 28.4% 284k/1.0M | Fill bar for context-window usage. Color shifts green → lime → yellow → orange → red as you fill. Ceiling adapts to the active model. | | Rate limits | 5h:50%·3h 7d:54%·2d4h | Claude.ai subscription quotas. % used + time until reset. Hidden for API-key users. | | Session totals | in↑12.2k(+98% cached) out↓353k | Cumulative billed input + output tokens. (+98% cached) = fraction of input served from the prompt cache. | | Badges (conditional) | INS ⬡ agent ⎇ worktree ✳ style | Only shown when present: vim mode, subagent name, git worktree, non-default output style. |

How the numbers are computed

  • Context %, used, ceiling - read directly from Claude Code's statusline JSON payload (context_window.used_percentage, context_window_size, etc.). Model-aware; no hardcoded 200k.
  • Billed input / output - context_window.total_input_tokens / total_output_tokens. These track uncached input - what you actually pay for.
  • Cache-hit % - computed by parsing the session transcript JSONL and summing cache_read_input_tokens across all assistant turns. Formula: cache_read / (cache_read + cache_creation + fresh_input). Cache-creation is in the denominator because those tokens are billed (at the write rate). Cached by transcript file size to keep repaints cheap.
  • Rate-limit % and reset time - read from rate_limits.{five_hour,seven_day}.{used_percentage,resets_at}.
  • Effort badge - read from the payload's effort.level, which is the live session value. /effort changes, --effort, and CLAUDE_CODE_EFFORT_LEVEL are all reflected immediately. See below.

Effort badge

Claude Code exposes five reasoning-effort levels. There is no ultra level - ultracode is a separate keyword that Claude Code runs at xhigh.

| Level | Badge | Color | |---|---|---| | low | LO | gray | | medium | MD | cyan | | high | HI | green | | xhigh | XH | yellow | | max | MX | red |

Two states render dim, on the rule that dim means inactive:

  • HI in dim gray (any level, dimmed) - extended thinking is off, so the configured effort isn't doing anything. The level still shows, because that's what resumes when you turn thinking back on.
  • · in dim gray - the current model has no reasoning-effort control at all.

Support is per-model, and claude-stat doesn't guess at it. Claude Code only includes effort in the payload when the active model supports it, and the value it sends is already resolved - downgraded if the model doesn't support that rung, and capped if your organization limits it. So the badge shows what you're actually getting, not what you asked for. At the time of writing, xhigh needs Fable 5 / Opus 4.7+ / Sonnet 5, and max needs Fable 5 / Opus 4.6+ / Sonnet 4.6+ - but that list lives here as prose only, because hardcoding it into the script would go stale at the next model launch.

On Claude Code versions predating the effort payload field, the badge falls back to ~/.claude/settings.json.effortLevel. That's the persisted preference, so it can't see mid-session changes and never shows MX (Claude Code won't persist max). Upgrade Claude Code to get the live value.

What resets when

| Action | Context % | in↑/out↓ | Cache-hit % | |---|---|---|---| | New session (/clear) | resets | resets | resets | | Compact (/compact) | drops | keeps growing | keeps growing | | Resume session | continues | continues | continues |

So: drop in context bar + stable session totals = compaction. Everything at zero = new session.

Customize

All styling lives at the top of statusline.js:

  • Colors - edit the ANSI color constants (GREEN, YELLOW, ORANGE, etc.). They use 256-color codes (c(n)), so you can swap any to your preferred hue.
  • Thresholds - ctxBar() defines when the bar turns lime / yellow / orange / red. fmtRL() defines the same for rate-limit colors. cacheHitPct thresholds are inline where the cached-% is rendered.
  • Effort badge labels / colors - EFFORT_MAP object. Change LO·MD·HI·XH·MX labels or their colors. Note the map has no dim field on purpose: dim is reserved to mean "inactive" (thinking off, or no effort support), so giving a level its own dim styling would make the two indistinguishable. The dim/unsupported rendering lives in buildEffortBadge().
  • Segment order / separator - scroll to the bottom where parts is assembled. Reorder the parts.push(...) calls to taste. SEP defines the group separator.
  • Branch / model truncation - branch.length > 22 and modelShort.length > 20. Adjust for your terminal width.

How Claude Code statusline scripts work

On every prompt repaint, Claude Code spawns your configured statusLine.command as a subprocess and pipes a JSON payload to its stdin. Your script writes ANSI-styled text to stdout, and that becomes the status line.

The payload includes (among other fields):

{
  "session_id": "...",
  "transcript_path": "...",
  "cwd": "...",
  "model":  { "id": "...", "display_name": "..." },
  "workspace": { "current_dir": "..." },
  "context_window": {
    "total_input_tokens": 426,
    "total_output_tokens": 21654,
    "context_window_size": 1000000,
    "current_usage": { "input_tokens": 1, "cache_read_input_tokens": 53138, "...": "..." },
    "used_percentage": 6
  },
  "rate_limits": {
    "five_hour":  { "used_percentage": 50, "resets_at": 1776733200 },
    "seven_day":  { "used_percentage": 54, "resets_at": 1776970800 }
  }
}

Rendering a status line is pure formatting - almost every number you'd want is pre-computed by Claude Code. The only exception is the cache-hit %, which requires summing per-turn values across the transcript JSONL.

Performance

Every prompt repaint invokes the script, so it's engineered to be cheap:

  • Git calls use GIT_OPTIONAL_LOCKS=0 so they never wait on a lock held by another process.
  • Transcript parsing (for cache-hit %) is cached by transcript file size in os.tmpdir(). The JSONL file is append-only, so a matching size means nothing has changed and we reuse the cached totals. Fresh turns invalidate the cache and trigger one re-parse.
  • No network calls, no dynamic dependencies, no background processes.

Typical render time: 5–20 ms.

Uninstall

npx claude-stat uninstall

Or manually:

  1. Remove the statusLine key from ~/.claude/settings.json.
  2. Delete ~/.claude/statusline-command.js.
  3. Optionally delete cached transcript totals: rm /tmp/statusline-cache-*.json (macOS/Linux) or the equivalent in %TEMP% on Windows.

FAQ

Q: How do I update to a newer version? A: npx claude-stat@latest, or git pull && node install.js from a clone. Installing and updating are the same operation. See Update - and note the @latest, since a bare npx claude-stat can serve a cached copy.

Q: My effort badge is dimmed, or shows ·. What does that mean? A: A dimmed level (e.g. a gray XH instead of yellow) means extended thinking is off, so the configured effort is inert. A dim · means the current model has no reasoning-effort control at all - Claude Code omits the effort field entirely for those models. See Effort badge.

Q: Why doesn't my effort badge ever show MX? A: Most likely your Claude Code predates the effort payload field, so claude-stat is falling back to ~/.claude/settings.json.effortLevel - and Claude Code never persists max to that key (its schema stops at xhigh). Update Claude Code and the badge will track the live session value, MX included. Failing that, your model may not support max, in which case Claude Code silently runs at high.

Q: Does claude-stat work with both Claude.ai subscriptions and API keys? A: Yes. Rate-limit segments are automatically hidden when the rate_limits field is absent from the payload (the API-key case). Everything else - context window, model, cache stats - works identically.

Q: Does it work with Claude Code plugins, hooks, or output styles? A: Yes. The installer only touches the statusLine key in settings.json. Hooks, plugins, permissions, env vars, and output styles are preserved. Non-default output styles show up as a ✳ style-name badge.

Q: Why is my cache-hit percentage lower than expected? A: Claude Code's prompt cache writes new entries at a higher token cost than reads (cache-write vs. cache-read pricing). claude-stat counts cache-creation tokens in the denominator of the cache-hit % because they're billed (just at the write rate), so they're honestly "not a hit." Pure cache-read percentage would look higher but would overstate the cost savings.

Q: Can I use this with git worktrees? A: Yes. When a Claude Code session is in a git worktree, the ⎇ worktree-name badge appears. Branch, dirty state, and project name all resolve correctly inside worktrees.

Q: Does it support vim mode? A: Yes. When input.vim.mode is present, an INS (green) or NRM (yellow) badge appears.

Q: Is claude-stat affiliated with Anthropic? A: No. It's an independent open-source project. Claude Code is Anthropic's official CLI; claude-stat is a community-built renderer for the statusLine extension point that Claude Code exposes.

Q: Does it run on Windows? A: Yes, on Windows with Node.js installed. The installer uses cross-platform path joins. On Windows, the temp cache lives in %TEMP% instead of /tmp. Git commands work via the system git on PATH.

Q: How do I change colors or the segment order? A: Edit ~/.claude/statusline-command.js directly after install - color constants and the parts.push(...) assembly are at the top and bottom of the file respectively. See the Customize section above.

Q: Will heavy transcript parsing slow down my prompt? A: No. The cache-hit % calculation is memoized by transcript file size and stored in os.tmpdir(). A repaint with no new assistant turns is effectively free. Full typical render time is 5–20 ms.

Contributing

Issues and PRs welcome at github.com/waelmas/claude-stat. Scope is intentionally narrow: a fast, zero-dependency status line. New segments should keep the "5–20 ms render" budget.

License

MIT - see LICENSE.