omp packages

@timmyjl12/pi-model-picker0.1.0

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

timmyjl12 Published 11 days ago MIT ~195 downloads/mo

Untested on omp

This is a pi package. No one has reported whether it works on omp yet. If you try it, add your result below.

Did it work for you?

Result

One report per person. A new report replaces your old one.

Reports 0

No reports yet.

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