@sagmans/pi-prefix
Configurable prefix key that maps a second key to Pi app actions, slash commands, or extension events
Package details
Install @sagmans/pi-prefix from npm and Pi will load the resources declared by the package manifest.
$ pi install npm:@sagmans/pi-prefix- Package
@sagmans/pi-prefix- Version
0.1.2- Published
- Sep 9, 2026
- Downloads
- 380/mo · 380/wk
- Author
- assagman
- License
- MIT
- Types
- extension, skill
- Size
- 41.8 KB
- Dependencies
- 0 dependencies · 2 peers
Pi manifest JSON
{
"extensions": [
"./index.ts"
],
"skills": [
"./skills"
]
}Security note
Pi packages can execute code and influence agent behavior. Review the source before installing third-party packages.
README
@sagmans/pi-prefix
A prefix key for Pi: press one configurable prefix key, then a second key, to trigger a Pi app action, a slash command, or an extension event.
- Zero-keymap by default. No prefix and no bindings ship with the package. Without configuration the extension is completely inert.
- Your keybindings stay authoritative. A prefix that collides with an
active main-editor binding disables pi-prefix and reports the exact
keybinding ids. pi-prefix never edits
keybindings.json. - No arbitrary code. Targets are app actions, slash commands, and events. There is no executable target.
Security warning
Pi packages execute with your user privileges. Review this repository before installing. Report vulnerabilities privately (see SECURITY.md).
Install
pi install npm:@sagmans/pi-prefix
Unpinned on purpose: pinned specs are skipped by pi update, so pinning
hides future upgrades. Then restart Pi (or run /reload).
Ask your agent
Ask your coding agent to configure pi-prefix for you, for example:
Set up @sagmans/pi-prefix for me: prefix ctrl+x, with m for model picker, h for /hotkeys submitted, and a binding for the open event of the extension I use.
The package ships a skill that guides agents through the same steps.
Configuration
Two layers, merged in order defaults → global → project:
| Layer | Path | When loaded |
|---|---|---|
| Global | ~/.pi/agent/pi-prefix.json |
always |
| Project | <project>/.pi/pi-prefix.json |
only when the project is trusted |
Project scalar values (prefix, timeoutMs) replace global values. Project
bindings add or replace global bindings by normalized key; null removes an
inherited binding. Activation needs an effective prefix and at least one
effective binding. Any parse or validation error fails the whole effective
config with the source path and reason.
~/.pi/agent/pi-prefix.json example:
{
"$schema": "https://unpkg.com/@sagmans/pi-prefix/schema.json",
"prefix": "ctrl+x",
"timeoutMs": 2000,
"bindings": {
"m": { "action": "app.model.select" },
"h": { "command": "/hotkeys", "submit": true },
"a": { "command": "/third-party-command", "submit": false },
"o": { "event": "example-extension:open", "payload": { "source": "pi-prefix" } }
}
}
Trusted project overlay example (<project>/.pi/pi-prefix.json):
{
"bindings": {
"o": null,
"w": { "command": "/project-command", "submit": true }
}
}
Schema reference
All properties are optional at layer level.
prefix— one key id, e.g.ctrl+x,f9,alt+shift+p. See Pi's keybinding format (modifier+key, modifiersctrl,shift,alt,super; aliasesesc/returnare normalized toescape/enter).timeoutMs— positive integer; prefix mode clears after this idle time. Default2000.bindings— map of second key id to exactly one target, ornullto remove an inherited binding:{ "action": "app.model.select" }— a Pi app action. Unknown or context-only actions notify when pressed instead of throwing.{ "command": "/hotkeys", "submit": true }— a slash command.submit: trueruns the command immediately; extension commands run without touching the editor draft, anything else replaces the draft and submits.submit: falsetypes the command and stops.{ "event": "example-extension:open", "payload": {} }— emits the event name and exact JSON payload throughpi.events. The extension that owns the event defines valid names and payloads.
Escape is reserved for canceling prefix mode; a binding on escape loads
with a warning and can never dispatch. Enter, tab, and arrows are valid second
keys.
Command behavior
With submit: true, extension commands (those listed by /commands with
the extension source, e.g. a mode toggle installed from another package) are
dispatched directly through Pi's command pipeline and the current editor draft
is preserved untouched. Any other command — built-ins like /model or
third-party commands Pi reports without the extension source — replaces the
draft and submits it through the editor,
matching manual typing. With submit: false the command text sits in the
editor until you press Enter, which is the right form for commands that take an
argument.
Conflicts and /pi-prefix
On startup pi-prefix scans Pi's main-editor bindings. A colliding prefix
disables pi-prefix with an error naming the exact keybinding ids. Existing
bindings are never changed. Fix by choosing another prefix or rebinding the
conflicting action yourself in ~/.pi/agent/keybindings.json, then /reload.
Third-party extension shortcuts cannot be inventoried publicly: Pi reports those collisions under [Extension issues] and resolves them by load order. That limitation is Pi's, not pi-prefix's.
/pi-prefix prints active/inactive state, loaded config paths, trust state,
effective prefix, timeout, a binding summary, config errors and warnings, and
any Pi keybinding conflicts.
What pi-prefix does not do
- No shipped prefix, keymap, or bindings.
- No self-registration protocol for other extensions.
- No arbitrary-code targets and no private Pi APIs.
- No automatic conflict edits; reports only.
- No raw global terminal input interception; activation goes through Pi's native shortcut registration.
Development
npm install
npm run typecheck
npm test
npm pack --dry-run # package-content gate