Pi custom / variant model
When to Use
Pi's saved default only loads if the exact provider/id exists in its model registry. Pi ships a static bundled list per provider — so OpenRouter routing-shortcut variants (:nitro = sort by throughput, :floor = cheapest, :exacto = quality tool-use) and any brand-new slug are NOT in it. When the default doesn't resolve, Pi silently falls through to its built-in per-provider default (for openrouter that's moonshotai/kimi-k2.6) — looking like Pi "reset" your model. Fix = register the slug as a custom model so find(provider, id) matches.
Files (global)
~/.pi/agent/settings.json — defaultProvider, defaultModel, defaultThinkingLevel
~/.pi/agent/models.json — custom models, keyed by provider
~/.pi/agent/auth.json — provider credentials (check the provider key exists)
Steps
- Confirm the slug is real before adding it (e.g. check the OpenRouter model/variant exists). A typo'd id also silently falls back.
- Confirm auth. The provider must have a key in
auth.json (or an env var like OPENROUTER_API_KEY). No auth → the model is registered but unavailable → still falls back.
- Add the model to
models.json under providers.<provider>.models. For a built-in provider (openrouter, anthropic, etc.) you only supply metadata — api, baseUrl, and auth are inherited from the bundled defaults. Example:{
"providers": {
"openrouter": {
"models": [
{
"id": "z-ai/glm-5.2:nitro",
"name": "Z.ai: GLM 5.2 (nitro)",
"reasoning": true,
"thinkingLevelMap": { "xhigh": "xhigh" },
"input": ["text"],
"cost": { "input": 0.95, "output": 3, "cacheRead": 0.18, "cacheWrite": 0 },
"contextWindow": 1048576,
"maxTokens": 32768,
"compat": { "supportsDeveloperRole": false, "thinkingFormat": "openrouter" }
}
]
}
}
}
Copy cost/contextWindow/compat from the base model (the variant shares them) — find the bundled entry in <pi-pkg>/node_modules/@earendil-works/pi-ai/dist/providers/<provider>.models.js. Don't hardcode generic 128k/16k if the real model is bigger.
- Set the default in
settings.json: defaultProvider + defaultModel = the exact id. Leave defaultThinkingLevel as the user has it.
- Verify:
pi --list-models | grep <id> shows it, and JSON parses. Optionally smoke-test: pi --provider <p> --model "<id>" "which model are you?".
Quirks
- Exact match only.
find() is exact provider+id — no fuzzy/colon-stripping for the saved default path. The slug in settings.json and models.json must be byte-identical.
- Silent fallback. Pi prints no error when the default doesn't resolve; it just shows a different model in the footer. That's the tell.
- Don't edit
settings.json alone. Setting defaultModel to an unregistered slug does nothing — models.json is the actual fix.
enabledModels (optional) pins the model picker so Ctrl+P cycling can't drift back: "enabledModels": ["<provider>/<id>:<thinking>"].
- Project override. A repo's
.pi/settings.json overrides global. If a default reverts only inside one project, check that file first.
- Restart Pi fully — the registry loads at startup.
Limitations
- Adapted from
davidondrej/skills; verify local paths, tools, credentials, and agent features before acting.
- For commands, remote access, scheduling, browser automation, or file-changing workflows, get explicit user approval and confirm the target environment first.
Source: sickn33/agentic-awesome-skills → skills/pi-custom-model/SKILL.md
Also appears in: sickn33/agentic-awesome-skills/plugins/agentic-awesome-skills/skills/pi-custom-model/SKILL.md, sickn33/agentic-awesome-skills/plugins/agentic-awesome-skills-claude/skills/pi-custom-model/SKILL.md
1---2name: pi-custom-model3description: Register custom Pi Agent model slugs so saved OpenRouter variants resolve correctly.4---567# Pi custom / variant model89## When to Use10Pi's saved default only loads if the exact `provider/id` exists in its model registry. Pi ships a static bundled list per provider — so OpenRouter **routing-shortcut variants** (`:nitro` = sort by throughput, `:floor` = cheapest, `:exacto` = quality tool-use) and any brand-new slug are NOT in it. When the default doesn't resolve, Pi silently falls through to its built-in per-provider default (for openrouter that's `moonshotai/kimi-k2.6`) — looking like Pi "reset" your model. Fix = register the slug as a custom model so `find(provider, id)` matches.1112## Files (global)13- `~/.pi/agent/settings.json` — `defaultProvider`, `defaultModel`, `defaultThinkingLevel`14- `~/.pi/agent/models.json` — custom models, keyed by provider15- `~/.pi/agent/auth.json` — provider credentials (check the provider key exists)1617## Steps181. **Confirm the slug is real** before adding it (e.g. check the OpenRouter model/variant exists). A typo'd id also silently falls back.192. **Confirm auth.** The provider must have a key in `auth.json` (or an env var like `OPENROUTER_API_KEY`). No auth → the model is registered but unavailable → still falls back.203. **Add the model to `models.json`** under `providers.<provider>.models`. For a **built-in provider** (openrouter, anthropic, etc.) you only supply metadata — `api`, `baseUrl`, and auth are inherited from the bundled defaults. Example:21 ```json22 {23 "providers": {24 "openrouter": {25 "models": [26 {27 "id": "z-ai/glm-5.2:nitro",28 "name": "Z.ai: GLM 5.2 (nitro)",29 "reasoning": true,30 "thinkingLevelMap": { "xhigh": "xhigh" },31 "input": ["text"],32 "cost": { "input": 0.95, "output": 3, "cacheRead": 0.18, "cacheWrite": 0 },33 "contextWindow": 1048576,34 "maxTokens": 32768,35 "compat": { "supportsDeveloperRole": false, "thinkingFormat": "openrouter" }36 }37 ]38 }39 }40 }41 ```42 Copy `cost`/`contextWindow`/`compat` from the base model (the variant shares them) — find the bundled entry in `<pi-pkg>/node_modules/@earendil-works/pi-ai/dist/providers/<provider>.models.js`. Don't hardcode generic 128k/16k if the real model is bigger.434. **Set the default** in `settings.json`: `defaultProvider` + `defaultModel` = the exact id. Leave `defaultThinkingLevel` as the user has it.445. **Verify:** `pi --list-models | grep <id>` shows it, and JSON parses. Optionally smoke-test: `pi --provider <p> --model "<id>" "which model are you?"`.4546## Quirks47- **Exact match only.** `find()` is exact `provider`+`id` — no fuzzy/colon-stripping for the *saved default* path. The slug in `settings.json` and `models.json` must be byte-identical.48- **Silent fallback.** Pi prints no error when the default doesn't resolve; it just shows a different model in the footer. That's the tell.49- **Don't edit `settings.json` alone.** Setting `defaultModel` to an unregistered slug does nothing — `models.json` is the actual fix.50- **`enabledModels`** (optional) pins the model picker so Ctrl+P cycling can't drift back: `"enabledModels": ["<provider>/<id>:<thinking>"]`.51- **Project override.** A repo's `.pi/settings.json` overrides global. If a default reverts only inside one project, check that file first.52- Restart Pi fully — the registry loads at startup.5354## Limitations5556- Adapted from `davidondrej/skills`; verify local paths, tools, credentials, and agent features before acting.57- For commands, remote access, scheduling, browser automation, or file-changing workflows, get explicit user approval and confirm the target environment first.5859---6061**Source:** [`sickn33/agentic-awesome-skills`](https://github.com/sickn33/agentic-awesome-skills) → `skills/pi-custom-model/SKILL.md`6263**Also appears in:** `sickn33/agentic-awesome-skills/plugins/agentic-awesome-skills/skills/pi-custom-model/SKILL.md`, `sickn33/agentic-awesome-skills/plugins/agentic-awesome-skills-claude/skills/pi-custom-model/SKILL.md`