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

@timmyjl12/pi-model-picker

v0.1.0

Published

A stunning full-screen model picker overlay for the pi coding agent — fuzzy search, provider scopes, favorites, recents, and aligned per-model metrics.

Readme

@timmyjl12/pi-model-picker

A full-screen model picker overlay for the pi coding agent — section tabs, provider drill-down, a whole-catalogue Search tab, aligned metric columns, favorites and recents, and an Agents tab that can retarget the model an agent definition uses.

Built to emulate and improve on oh-my-pi's alt+p picker.

╭─ Model Picker — All ───────────────────────────────────────────────────────── 10 models · 5 providers · 2 scoped ╮
│                                                                                                                  │
│  Session-only switch — the model changes for this session only · ctrl+D also saves it as the default             │
│ ⌕ Search models by name, id, or provider…                                                          10/10 · smart │
│                                                                                                                  │
│  All 10    Search 10    Recent 2    Favorites 2    Scoped 2    Agents 4                                           │
├─ Providers ─────────────┬────────────────────────────────────────────────────────────────────────────────────────┤
│ ● All models         10 │     MODEL                                                         ◫     ↧          $   │
│ ○ Anthropic           3 │ ▾ Anthropic  3                                                                         │
│ ○ Google              2 │     claude-haiku-4-5                                           200k   64k       $1/5   │
│ ○ Local Llama         1 │     claude-opus-4-5                                            200k   64k     $15/75   │
│ ○ Openai              3 │   ● claude-sonnet-4-5                                          200k   64k      $3/15   │
│ ○ OpenRouter          1 │ ▾ Google  2                                                                            │
│                         │     gemini-2.5-pro                                               1M   64k   $1.25/10   │
│                         │ ▾ Openai  3                                                                            │
│                         │     gpt-5.2                                                    400k   64k   $1.25/10   │
├─────────────────────────┴────────────────────────────────────────────────────────────────────────────────────────┤
│   Claude Sonnet 4.5 · Anthropic · 200k ctx · 64k out · $3/15 per M · reasoning · vision · anthropic-messages     │
│   ● current · ○ scoped · ◉ thinking high · ctrl+T to change                                                      │
├──────────────────────────────────────────────────────────────────────────────────────────────────────────────────┤
│  ↑↓ move · → models · Tab section · ctrl+F ★ favorite · ctrl+T thinking · ctrl+S sort · esc close                 │
╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯

That frame is real output — run npm run preview to render every screen, including the Agents tab.

Install

pi install npm:@timmyjl12/pi-model-picker

Try it without installing:

pi -e npm:@timmyjl12/pi-model-picker

From a local checkout:

pi install /absolute/path/to/pi-model-picker

Restart pi (or run /reload) after installing.

Use

| Trigger | | |---|---| | /model-picker | open the picker | | /models | alias, for muscle memory | | ctrl+/ | keyboard shortcut, also Ctrl+Numpad-/ (needs a terminal with extended key reporting, e.g. Windows Terminal, Kitty, WezTerm, Ghostty); press again inside the picker to close it | | ctrl+shift+m | keyboard shortcut that works in every terminal; also toggles |

/model itself is a reserved built-in pi command and cannot be overridden, which is why the primary command is /model-picker.

Navigation

Three levels: tabs → providers → models.

  All │ Search │ Recent │ ★ Favorites │ Scoped │ Agents   ← Tab / shift+Tab
        ↓
  ● All models  10        ↑↓ walks the providers
    ○ Anthropic  3
    ○ Openai     9        → drills into that provider's models
        ↓
  ❯ ● claude-sonnet-4-5   ↑↓ walks models, Enter chooses, ← backs out

| Key | Action | |---|---| | Tab / shift+Tab | next / previous section | | ↑ ↓ | move within the focused pane | | → | drill into the model list (or Enter on a provider) | | ← | back out to the provider list | | PageUp PageDown | move by a page | | Home End | jump to the first / last row | | Enter | use this model for the session | | t / T | cycle the highlighted model's thinking level forward / back (model list, search box closed) | | / | open the search box, where every letter types — use it for a query starting with t; Esc leaves it | | ctrl+D | use it and save it as the startup default | | ctrl+F | add / remove the highlighted model from favorites | | ctrl+T | cycle the thinking level for the highlighted model (same as t) | | ctrl+S | cycle sort: smart → name → cheapest → largest context | | ctrl+G | toggle provider group headers | | F5 | re-read the model catalogue and agent definitions | | type | fuzzy search across name, id, provider, and provider/id, within the active section (the Search tab searches the whole catalogue) | | ctrl+U | clear the search | | esc | unwind one level: back out of the model list → clear the search → close | | ctrl+C | close |

Mouse works too: wheel scrolls the model list, hover highlights, clicking a provider focuses it, and clicking a model selects it — click again to use it.

F5 re-pulls the catalogue and the agent definitions. A background refresh that lands while the overlay is already open would otherwise only show up on the next open, so F5 gives you an explicit way to pull; the status row reports while it is in flight, and a failed pull leaves the list exactly as it was rather than emptying it.

The Agents tab

Reads agent definitions from <agent dir>/agents (i.e. ~/.pi/agent/agents) and the nearest <cwd>/<config>/agents, with project agents shadowing user agents of the same name — the same precedence pi itself uses. A .md file only counts as an agent when its frontmatter has string name and description, which is what keeps shared rule files such as AGENTS.md out of the list.

The left pane lists agents (filled dot = the agent pins its own model, hollow = it inherits the session's), and the right pane inspects the highlighted one: model, thinking level, tools, source, file path, and prompt size.

Enter assigns a model. That opens the picker in assign mode — same tabs, same search — and on selection shows you the exact frontmatter change and asks for confirmation before writing:

Update explore?
model: neuralwatt/deepseek-v4.1-flash-flex → openai/gpt-5.2

File: /home/u/.pi/agent/agents/explore.md
A timestamped backup is written alongside it.

The write is deliberately surgical:

  • Only the top-level model: line (and thinking:, and only if you actually cycled the level in the picker) is rewritten. Assigning a model never silently resets an agent's own thinking level.
  • The frontmatter region is located with the same rule as pi's parseFrontmatter, so the text edited is exactly the text pi reads. Bodies containing --- rules are safe.
  • Commented-out alternates (#model: ...), inline trailing comments, indentation, the entire body, every other key, CRLF endings, and a leading BOM are all preserved byte-for-byte.
  • Indented keys inside nested YAML (an output: schema, for instance) are never matched.
  • A timestamped .bak-model-picker-<stamp> copy is written first, then the edit goes in atomically.
  • The file is re-parsed before writing, and the edit is refused outright if the parsed name does not match the agent you selected.

What it does

Search that ranks like you'd expect. Four relevance tiers — exact id/name/selector, contiguous substring, all-tokens-present, then fuzzy subsequence. Tiers always win over ordering heuristics, so a perfect text match is never buried under your recent history. Inside a tier, favorites and recents break ties.

A Search tab for the whole catalogue. The search field filters within the active section — typing on Recent only ranks your recents, on Favorites your stars. The Search tab always searches the entire catalogue by model id or name, relevance-ranked, so a query finds a model wherever it lives. While a query is active its tab count shows live matches, and the provider facet pane still works on the results.

Sections as colored tabs. All · Search · Recent · Favorites · Scoped (--models / enabledModels) · Agents — each with a live count, each with its own hue drawn from the active theme's palette. Recent and Favorites are always visible, even at zero, so they're discoverable before you've used them.

Providers as a facet list. Whatever the active section contains is grouped by provider, with an "All …" row first. Search turns the counts into per-provider match counts and dims providers with no hits, so you can see where matches live before drilling in.

Aligned metrics with header icons. ◫ context, ↧ output limit, $ price — measured per visible window and right-aligned so they line up exactly, including with their own header row. Columns collapse independently at narrow widths rather than truncating.

Saved preferences, in their own file. Recents, favorites, sort mode, and the last section persist to ~/.pi/agent/model-picker.json — write-through, atomic, and never mixed into pi's own settings.json. (ctrl+D is the only thing that touches settings.json, and it goes through pi's SettingsManager so every other key is preserved.)

Thinking level in the same flow. Pick the level you want before switching, instead of switching and then cycling: t steps forward, T steps back, ctrl+T still works. Levels a model marks unsupported via thinkingLevelMap are skipped, and the extended tiers (xhigh, max) are only offered when the model entry explicitly maps them — matching pi-ai's capability rules — so the picker never picks a level pi's runtime clamp would take away.

Responsive and theme-native. Everything paints through pi's Theme tokens (fg, bg, bold, the per-level thinking colors, and the scrollbar tokens), so it follows whichever theme you have active. At ≥ 64 columns you get the two-pane layout; below that the provider pane is dropped and the list runs full width, with the tab track still on top. The overlay fills the terminal (100% width and height, no inset margin) and hides entirely on terminals narrower than 48 columns or shorter than 20 rows.

Over-context awareness. When the session transcript exceeds a model's context window, that model's context cell turns to the warning color and the detail block says exactly what will happen: 400k of transcript exceeds this model's 32.8k window — switching may compact. The model stays selectable.

Improvements over oh-my-pi's picker

oh-my-pi's picker is a fine piece of work and the direct inspiration for this one. Where this goes further:

| | oh-my-pi | this picker | |---|---|---| | Navigation | flat list + @role virtual rows | tabs → providers → models, with ←/→ drill-in | | Overlay size | bottom-anchored, 40% of height | full-screen: 100% width and height | | Sections | single ─── separator | colored, counted tabs that stay visible at zero | | Columns | context, cost, intelligence, perf | context, output limit, cost — with header icons and measured alignment | | Scope counts while searching | — | per-provider match counts, zero-match providers dimmed | | Thinking level | separate control | t/T (or ctrl+T) in the picker, applied with the switch | | Agents | @role rows bound to omp's role system | an Agents tab that inspects and rewrites agent definitions | | Over-context | row grayed, context>Nk marker | warning-colored cell plus a detail line explaining the consequence | | Mouse | reserved for fullscreen overlays | wheel, hover, and click in the picker overlay | | Narrow terminals | fixed layout | provider pane dropped, tabs kept, bottom-pane scrolling | | Glyph safety | Nerd Font icons with spacing workarounds | plain symbols by default, PI_MODEL_PICKER_GLYPHS=ascii for strict terminals |

Two omp features are not reproducible on pi, and the code is honest about it rather than faking them: omp's ~118t/s and intelligence columns (pi's Model has no tps or int fields), and omp's Nerd-Font icon vocabulary — omp's picker reaches for nine theme token groups (boxRound, icon, nav.cursor, status.*, symbol, sep.powerline*, spinnerFrames, fg/bg, getFgAnsi) and pi's Theme exposes only three of them (fg/bg/bold, plus getFgAnsi). So glyphs are hardcoded here, with an ASCII fallback, and colors come from pi's semantic tokens instead.

Improvements over rilham97/pi-model-picker

That extension is a single-provider-tab list. Notable differences:

  • Search is ranked and tiered, not a single includes() filter.
  • Favorites, recents, and the configured scope are real counted sections, not just remembered search strings per tab.
  • Provider facets show counts and search-match counts, and only providers with hits stay bright.
  • Aligned metric columns with a header row, a detail block, and an agent inspector.
  • Mouse support, responsive narrow layout, memoized rendering, and a real test suite.
  • Imports the current @earendil-works/* packages. (rilham97 still imports the older @mariozechner/* scope, and its Focusable implementation does not set the embedded Input's focused flag, so IME cursor positioning doesn't work.)

Development

npm install
npm run preview     # render every screen to your terminal
npm test            # vitest suite
npm run typecheck   # tsc --noEmit (includes tests)
npm run check       # both

The layout is a pure function of (width, terminal rows, catalogue, agents, state). The test suite's highest-value assertions are the frame contracts: every state is rendered at nine widths and four terminal heights, and every line must measure exactly the requested width and the frame must be exactly the documented height, because the TUI rejects anything wider and the overlay host clips anything taller. The agent editor is tested against a temp directory, including commented-out model lines, ----heavy bodies, CRLF files, and nested YAML.

Layout

index.ts          command/shortcut registration, overlay wiring, choice application, agent writeback
src/picker.ts     the overlay component: tabs, drill-down, rendering, input, mouse
src/models.ts     model entries, ordering, tiered search, metric formatting
src/agents.ts     agent discovery + surgical frontmatter editing
src/chrome.ts     frame chrome, tab track, alignment helpers, glyph set
src/state.ts      MRU / favorites / sort persistence
test/             unit + integration tests, theme/TUI doubles, visual preview

Configuration

| Variable | Effect | |---|---| | PI_MODEL_PICKER_GLYPHS=ascii | use ASCII glyphs and word column headers instead of ❯ ● ○ ★ ▾ ⌕ ◫ ↧ ◉ | | PI_MODEL_PICKER_STATE=/path/to.json | override the state file location | | PI_CODING_AGENT_DIR | pi's own override; also relocates the agent definitions this read/writes |

License

MIT