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

@nerisma/pi-input-revamp

v1.2.0

Published

Revamped input editor for pi: full rounded frame, colored π prompt, and live session metrics bar.

Readme

@nerisma/pi-input-revamp

Replaces pi's input editor with a full rounded frame, a colored π prompt character, and a session metrics bar built into the border.

╭─ agent · anthropic/claude-sonnet-4-5 · high ──── 0.015$ · 15.2K/200K · 12.3% ─╮
│ π hello world                                                                 │
╰──────────────────────────────────────── T5 (3) · 12s · 0.004$ · OUT 8.3K ─────╯

pi-input-revamp preview

The border and the π use the active theme's accent color. Each of the four corners of the border is a quadrant you fill with the info elements you want — agent, model, cost, context usage, per-turn metrics, and more. By default the top bar shows session-wide info and the bottom-right shows the last turn, but the whole layout is configurable (see Configuration).

Installation

pi install npm:@nerisma/pi-input-revamp

Or via settings.json:

{
  "packages": ["npm:@nerisma/pi-input-revamp"]
}

Configuration

The layout and animations are driven by ~/.pi/pi-input-revamp.json. The file is created with the defaults on first run, so you can just edit it. Missing fields fall back to the defaults, and changes are picked up on the next pi restart.

{
  "layout": {
    "topLeft": ["agent", "model", "thinking-level", "cwd", "duration", "tools", "tok"],
    "topRight": ["session-label", "ctx-percent", "ctx-tokens-full", "session-cost", "session-out", "session-hit", "session-miss"],
    "bottomLeft": [],
    "bottomRight": ["turn", "turn-duration", "turn-cost", "turn-out", "turn-hit", "turn-miss"]
  },
  "animations": {
    "typingPulse": true,
    "submitFlash": true,
    "metricPulse": true,
    "tokPulse": true
  }
}

Layout

Each quadrant — topLeft, topRight, bottomLeft, bottomRight — is an ordered list of element IDs joined with ·. Elements that have no data (e.g. a model that isn't set, or a turn that hasn't completed) are skipped silently, so empty quadrants simply collapse into the border.

| Element | Shows | | ------------------ | ----------------------------------------------------------------- | | agent | Active agent name (PI_ACTIVE_AGENT) | | model | provider/id of the current model | | thinking-level | Thinking level (hidden when off) | | cwd | Working directory ($HOME collapsed to ~) | | duration | Elapsed session time (5m 12s) | | tools | Number of tools actually sent on the last request (12 tools) | | tok | Live token estimate of the text you're typing (~42 tok) | | session-label | The literal SESSION tag | | ctx-percent | Context window usage as a percentage (12.3%) | | ctx-tokens | Context tokens in use (15.2K) | | ctx-tokens-max | Context window size (200K) | | ctx-tokens-full | Used / max (15.2K/200K) | | session-cost | Whole-session cost in $ | | session-out | Whole-session output tokens (OUT 8.3K) | | session-hit | Whole-session cache-read tokens (HIT 2.1K) | | session-miss | Whole-session input / cache-miss tokens (MISS 1.2K) | | turn-cost | Last completed turn cost in $ | | turn-out | Last completed turn output tokens (OUT 8.3K) | | turn-hit | Last completed turn cache-read tokens (HIT 2.1K) | | turn-miss | Last completed turn input / cache-miss tokens (MISS 1.2K) | | turn | Turn number with metric-update count (T5 (3)) | | turn-duration | Duration of the last completed turn (12s) |

Every element is self-contained: the session-* variants always report whole-session totals and the turn-* variants always report the last completed turn, regardless of which quadrant you place them in.

Showing another extension in the bar

Extensions can publish a status line through pi's ctx.ui.setStatus(key, text) API. Normally that text is rendered by pi's footer — which this extension hides — so those statuses would be invisible. To surface one, add a slot of the form ext:<statusKey> to any quadrant:

{
  "layout": {
    "bottomRight": ["turn", "ext:pi-quotas-usage", "turn-cost"]
  }
}
  • <statusKey> is the exact key the other extension passes to setStatus() — it must match character for character. Check that extension's docs to find it.
  • Placement and ordering work like any other element: the quadrant decides where it shows, and it's joined with the same · separator.
  • The published text is shown as-is (extensions usually colour their own status), with no prefix added.
  • When that extension currently has no status set, the slot shows the key name in the warning colour as a placeholder, so you can tell the slot is wired up and waiting for data rather than silently empty.

You can wire up as many as you like, in any corner — nothing needs to be declared beyond the ext:<statusKey> entry itself.

Animations

Each effect can be toggled independently under animations:

| Key | Effect | | ------------- | --------------------------------------------------------------------- | | typingPulse | Border and π lerp toward white the faster you type | | submitFlash | Brief white border pulse when you submit (text goes non-empty → empty) | | metricPulse | Metric text pulses toward white when its value changes | | tokPulse | The ~N tok counter pulses each time the estimate updates |

The thinking equalizer (the ▁▂▃…█ bar shown while the model works) is always on.

How it works

The extension registers a custom editor on session_start (and hides the default footer), subclassing pi's CustomEditor and overriding render(width).

From-scratch rendering. Instead of calling super.render() and post-processing, it builds every line itself. It reserves columns for the borders and the π prefix, then calls the inherited layoutText() to word-wrap the input (which keeps paste markers and grapheme segmentation intact). The cursor is drawn by inverting the grapheme under it (\x1b[7m…), and each line is padded to the inner width and wrapped in border characters. The top and bottom borders are produced by fitRoundedBorder, which fits a left and a right text into one line, truncating them when space runs short.

Session metrics. On each render it reads the session entries from ctx.sessionManager.getEntries() and aggregates token usage and cost (whole session, and the current/last turn separately). Context usage comes from ctx.getContextUsage().

Tool count. The extension subscribes to before_provider_request and keeps a reference to the tools array packed into the request payload. The count is read lazily at render time, after the whole hook chain has run, so it reflects any in-place filtering other extensions apply (for example MCP-bridged tools that inflate the active set but never reach the wire) and reports exactly what was sent on the last request. Before the first request it falls back to pi.getActiveTools().

Color animations. Several effects share a brightness engine that parses an ANSI foreground color to RGB and re-emits it in the same terminal mode (truecolor or 256-color), so the animation is never a no-op on 256-color terminals:

  • Typing whitening — characters added are sampled over a sliding window to estimate WPM; the border and π lerp toward pure white the faster you type, with a fast attack and an exponential release when you stop.
  • Submit flash — a non-empty → empty text transition triggers a brief white border pulse.
  • Metrics pulse — when the session metrics change, the metric text pulses toward white and decays back.
  • Thinking equalizer — while the model works, a VU-meter bar (▁▂▃…█) and a status word animate on their own line, driven by an independent sinusoid so the border stays at the fixed accent.

Animations run on short setInterval timers that request a re-render and stop themselves once the effect has fully decayed; all timers are cleared in dispose().

Compatibility

  • pi >= 0.78

License

MIT © Sébastien SERVOUZE