pi-use-last-selected-thinking-level

Remember the thinking level you last used per model and re-apply it when you switch back — without overriding settings pins.

Packages

Package details

extension

Install pi-use-last-selected-thinking-level from npm and Pi will load the resources declared by the package manifest.

$ pi install npm:pi-use-last-selected-thinking-level
Package
pi-use-last-selected-thinking-level
Version
0.1.1
Published
Aug 10, 2026
Downloads
144/mo · 36/wk
Author
dracond
License
MIT
Types
extension
Size
18.8 KB
Dependencies
0 dependencies · 1 peer
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

pi-use-last-selected-thinking-level

Per-model thinking-level memory for pi: remembers the thinking level each model was last used at, and re-applies it when you switch back to that model. No pins, no settings edits, nothing to configure.

The problem

pi has two ways of deciding a thinking level:

  • Pinned levelsenabledModels patterns in settings.json, e.g. "opencode-go/deepseek-v4-flash:max" or "*luna*:max". These are meant to always apply when that model is selected — but pi only actually applies them at startup and when tab-cycling models. Selecting a pinned model via the picker or /model inherits the current session level instead (a pi quirk this extension compensates for by enforcing pins on every selection).
  • A single session-global level — when you switch to a model without a pin, pi just carries the current session level over and clamps it to the new model's capabilities.

There is no "what did I last use with this model" memory. Switch from a model you ran at max to one you ran at low, and back — the second model's low follows you, and your first model silently loses its max. With a global default of high, a model you always run at max needs the pin — or you must remember to bump it every single time. This extension removes that whole class of friction.

How selection and the thinking-level picker work (nothing changes for you)

Model selection and thinking levels work exactly like stock pi. The extension only listens to events pi already fires:

  • Selecting a model — use any way you normally do: the model picker, /model, or cycling. The selection process is completely unchanged; nothing about it is intercepted or modified.
  • Setting a thinking level — in the same place you always set it: the thinking-level picker in the model selector (the off / minimal / low / medium / high / xhigh / max list shown for the selected model). Pick a level while a model is active and that is the level pi runs the model at.
  • What gets remembered — the effective level of the model that was active when the level changed. Set model X to high in the picker → the extension records X → high and re-applies it automatically whenever you come back to X (model switch or new session).
  • What is NOT remembered — levels pi applies by itself during a switch (inheritance and capability clamping) and settings pins. These are attributed to the model being left, so they can never pollute the memory.

Because of that, models you never level manually behave exactly as before: they inherit the current session level (seeded from defaultThinkingLevel at a new session) — stock behavior, untouched.

Note: setting levels only by editing defaultThinkingLevel in settings.json seeds the session-start default but does not feed the memory (it doesn't fire pi's level-change event). Set per-model levels in the picker — that is where the memory is captured.

What this extension does

  • Remembers the effective thinking level of every model you use, persisted in ~/.pi/agent/thinking-memory.json.
  • Re-applies it when you switch to that model again (model picker or /model cycling) — so each model snaps back to the level you actually used with it.
  • Enforces settings pins on every selection. pi itself only applies pinned levels at startup and when tab-cycling models — selecting a pinned model via the picker or /model goes through setModel(), which inherits the current session level and never consults the pin. This extension checks the level after every switch and lifts the model back to its pin when pi didn't (e.g. *luna*:max arrives at low → lifted to max).
  • Applies at session start (startup and /new) for the session's active model, so your default model also starts at its remembered level.
  • Leaves /resume and /fork alone — those keep the session's own stored level.
  • Settings pins always win — a model pinned in enabledModels (e.g. *luna*:max) runs at its pinned level; its memory stays dormant until the pin is removed. Remove the pin later and the memory takes over automatically.
  • Notifies briefly when a pinned or remembered level is applied on a model switch (and only when it actually changes the level).

How it works

The extension subscribes to three events, all handled synchronously so ordering is deterministic:

  • thinking_level_select — records the level for the active model. When the change comes from a model switch (pi updates ctx.model before firing this event, while previousLevel is still the outgoing model's level), it records the outgoing model's level instead, so switch clamps/pins never pollute the memory.
  • model_select — looks up the incoming model's pinned level first; if pinned and the model arrived at a different level, lifts it to the pin (pi misses pins on picker//model selections — only startup and tab-cycling apply them). Otherwise looks up the remembered level and applies it via pi.setThinkingLevel() (which clamps to model capabilities automatically).
  • session_start (reason startup/new) — applies the remembered level of the active model, silently.

The state file is written atomically (temp file + rename) and tolerates missing/corrupt files.

Installation

# everyone (published package):
pi install npm:pi-use-last-selected-thinking-level

# or straight from GitHub:
pi install git:github.com/DraconDev/pi-use-last-selected-thinking-level

# or a local checkout, for development:
pi install /path/to/pi-use-last-selected-thinking-level

Then /reload (or restart pi). To uninstall: pi remove pi-use-last-selected-thinking-level.

Usage

There is nothing to configure — switching models and changing thinking levels in the picker records and applies memory automatically.

  • /thinking-memory — list remembered levels (provider/model: level), with (current) and [pinned by settings — dormant] markers, plus the state file path.
  • /thinking-memory clear — forget everything.
  • /thinking-memory clear <fragment> — forget only models whose provider/model contains the fragment (e.g. /thinking-memory clear luna).

Forget a single model's level to make it fall back to pi's default behavior again.

Examples

With enabledModels: ["opencode-go/deepseek-v4-flash:max", "*luna*:max", "**"]:

  1. Start pi — deepseek-v4-flash is active. It's pinned at max, so nothing changes.
  2. Switch to an unpinned model, set it to low in the picker, use it for a while.
  3. Switch back to deepseek-v4-flash — the pin applies max (memory dormant). Switch to the unpinned model again — low is applied automatically, no manual re-selection.
  4. Remove *luna*:max from enabledModels later — every luna model you used before now gets its remembered level instead of the pin.

Troubleshooting

  • Nothing is remembered — check that the extension is loaded (pi list / /reload), then change a thinking level once in the picker; the memory file appears at ~/.pi/agent/thinking-memory.json.
  • A model always gets a level you don't want — run /thinking-memory clear <fragment> for it. If it's pinned in enabledModels, remember pins win by design — a pinned model is lifted to its pin on every selection; remove the pin to let the memory apply.
  • State file corrupt — delete ~/.pi/agent/thinking-memory.json; the extension starts fresh and logs a warning.