@nicknisi/pi-model-switch

Cycle or fuzzy-pick from a machine-local, sectioned list of preferred Pi models

Packages

Package details

extension

Install @nicknisi/pi-model-switch from npm and Pi will load the resources declared by the package manifest.

$ pi install npm:@nicknisi/pi-model-switch
Package
@nicknisi/pi-model-switch
Version
0.3.0
Published
Sep 9, 2026
Downloads
223/mo · 156/wk
Author
nicknisi
License
MIT
Types
extension
Size
84.6 KB
Dependencies
0 dependencies · 3 peers
Pi manifest JSON
{
  "extensions": [
    "./index.ts"
  ]
}

Security note

Pi packages can execute code and influence agent behavior. Review the source before installing third-party packages.

README

@nicknisi/pi-model-switch

Cycle or fuzzy-pick from a machine-local, sectioned list of preferred Pi models.

This package is useful when the same Pi configuration is shared across machines but each machine has different providers, credentials, or model preferences. The extension reads an untracked local config instead of using enabledModels, skips unavailable entries, and leaves Pi's normal /model and Ctrl+L picker unchanged.

Install

From npm after the package is published:

pi install npm:@nicknisi/pi-model-switch

From a local checkout:

pi install ~/Developer/pi-extensions/packages/model-switch

Configure shortcuts

The defaults are Ctrl+Shift+M forward, Ctrl+Shift+Alt+M backward, and Ctrl+Shift+L for the fuzzy picker. Override any of them in Pi's existing ~/.pi/agent/keybindings.json:

{
  "model-switch.cycleForward": "ctrl+shift+m",
  "model-switch.cycleBackward": "ctrl+shift+alt+m",
  "model-switch.select": "ctrl+shift+l"
}

These extension-owned action IDs are ignored by Pi's built-in keybinding manager and read by model-switch during extension load. Run /reload or restart Pi after changing them. Each value must be one non-empty Pi key string; a missing or invalid value falls back to its default.

Configure models

Add models from Pi

Run /model-switch add to search Pi's available model catalog, pick a model, then choose an existing section to save it in. Run /model-switch add-current to save the model you're already using without opening the catalog picker. Both subcommands have argument completion.

If the config file is missing, either command asks you to name the first section and creates the file. With an existing config, the section picker includes empty sections too. Add more sections by editing the config below.

Adding a model does not switch the active model. Duplicate references in the chosen section are skipped, but the same model can belong to multiple sections. Escape cancels without writing. Saves preserve the legacy flat format, other sections, and extra config fields. Invalid configs produce a warning and are not overwritten.

The catalog picker requires Pi's terminal UI. add-current also works with RPC clients that support Pi's selection and input dialogs. Neither command registers new providers or model definitions. The model must already be known to Pi.

Edit the config file

Copy the example config:

mkdir -p ~/.pi/agent/configs
cp model-switch.example.json ~/.pi/agent/configs/model-switch.json

Or create ~/.pi/agent/configs/model-switch.json directly with named sections:

{
  "sections": {
    "work": ["cloudflare-ai-gateway/gpt-5.6-sol", "cloudflare-ai-gateway/claude-opus-5"],
    "personal": ["fireworks/accounts/fireworks/models/kimi-k3"]
  }
}

Section names are arbitrary — define as many as you want. The legacy flat format also works:

{
  "models": ["cloudflare-ai-gateway/gpt-5.6-sol"]
}

The file is read on every interaction, so edits take effect without reloading Pi.

Config schema

Field Type Default Description
sections Record<string, string[]> Named sections of ordered provider/model-id references. Preferred over models.
models string[] Legacy flat list. Treated as a single unnamed section when sections is absent.

The first / separates the provider from the model ID. Additional slashes belong to the model ID, so references such as fireworks/accounts/fireworks/models/kimi-k3 work as expected.

Keep this config machine-local and untracked. A personal machine and work machine can each provide their own sections while sharing the installed extension and the rest of your Pi dotfiles.

Behavior

Cycling

  • Ctrl+Shift+M moves forward through usable models in the active section.
  • Ctrl+Shift+Alt+M moves backward.
  • The active section is the one containing the current model. If the current model is not in any section, the first section is used.
  • Cycling wraps at both ends within the active section.

Fuzzy picker

  • Ctrl+Shift+L or /model-switch opens a fuzzy-searchable TUI picker.
  • Tab cycles between sections within the picker.
  • Type to fuzzy-filter models within the active section.
  • The picker preserves config order, marks the current model with , switches the chosen entry, and treats cancellation as a no-op.
  • Sections with no usable models are hidden from the picker.

General

  • Missing models and models without working provider authentication are skipped while preserving config order.
  • If no configured model is usable, Pi keeps the current model and shows a warning.
  • Invalid JSON or invalid config values produce a warning containing the config path.
  • The extension never changes the model at startup.

enabledModels is not read or modified. Pi's /model command and Ctrl+L picker continue to expose the normal available catalog.

Troubleshooting

The custom shortcuts do not respond

Check the model-switch.cycleForward, model-switch.cycleBackward, and model-switch.select values in ~/.pi/agent/keybindings.json, then run /reload. Check Pi's startup diagnostics for another extension using the same physical keys, and verify that your terminal reports the configured combinations as distinct modified key events. No built-in Pi keybinding changes are required.

A configured model is skipped

Check that Pi knows the exact reference and that its provider is authenticated:

pi --list-models

Model entries must use the full provider/model-id shown by Pi. Authentication is machine-specific and can be managed with /login and /logout.

No configured models are available

The config may be missing, empty, malformed, or contain only missing/unauthenticated entries. Pi's warning includes the active config path. PI_CODING_AGENT_DIR changes that path along with the rest of the agent configuration.

Caveats

  • This extension owns only its custom cycle and fuzzy picker; it cannot and does not mutate Pi's read-only scoped model list.
  • The picker uses a custom search + list component with ctx.ui.custom(); native /model and Ctrl+L remain available for the full catalog.
  • Terminal support for multi-modifier keys varies; configure simpler non-conflicting keys or use a terminal with the Kitty keyboard protocol when modified keys are not distinguishable.
  • Availability is checked on each interaction, which may resolve provider credentials before switching.
  • Duplicate references within a section are preserved as written; avoid them unless repeated cycle positions are intentional. The add commands never insert another copy of an existing reference.

Development

From the repository root:

pnpm vitest run packages/model-switch
pnpm typecheck
pnpm lint
pnpm format:check
pnpm build

Smoke-test extension loading with a scratch agent directory:

tmp=$(mktemp -d)
trap 'rm -rf "$tmp"' EXIT
PI_CODING_AGENT_DIR="$tmp" pi --no-extensions -e packages/model-switch/index.ts --list-models