Opinionated toolchain enforcement. Transparently rewrites commands to use preferred tools.

Opinionated toolchain enforcement for pi. Transparently rewrites commands to use preferred tools instead of blocking and forcing retries.
pi install npm:@aliou/pi-toolchain
Or from git:
pi install git:github.com/aliou/pi-toolchain
These features rewrite commands before shell execution. By default the agent does not see that the command was changed, but you can enable optional rewrite notifications in the config.
npm/yarn/bun commands to the selected package manager. Also handles npx -> pnpm dlx/bunx.python/python3 to uv run python and pip/pip3 to uv pip.GIT_EDITOR=true and GIT_SEQUENCE_EDITOR=: env vars for git rebase commands so they run non-interactively.These features block commands that have no clear rewrite target.
brew commands. Homebrew has no reliable 1:1 mapping to Nix.docker inspect and common docker exec env-exfiltration commands (env, printenv, /proc/*/environ).pyproject.toml), shows a confirmation dialog. Also blocks poetry/pyenv/virtualenv unconditionally.Run /toolchain:settings to open an interactive settings UI with two tabs:
.pi/extensions/toolchain.json)~/.pi/agent/extensions/toolchain.json)Use Tab / Shift+Tab to switch tabs. Feature modes, the package manager, and bash source mode can be changed directly. Configure rewrite notification visibility in JSON for now.
Configuration is loaded from two optional JSON files, merged in order (project overrides global):
~/.pi/agent/extensions/toolchain.json.pi/extensions/toolchain.json{
"enabled": true,
"features": {
"enforcePackageManager": "disabled",
"rewritePython": "disabled",
"gitRebaseEditor": "rewrite"
},
"packageManager": {
"selected": "pnpm"
},
"bash": {
"sourceMode": "override-bash"
},
"ui": {
"showRewriteNotifications": false
}
}
All fields are optional. Missing fields use the defaults shown above.
| Feature | Default | Description |
|---|---|---|
enforcePackageManager | "disabled" | Opt-in. Rewrites or blocks package-manager commands. |
rewritePython | "disabled" | Opt-in. Rewrites or blocks python/pip commands to uv equivalents. |
gitRebaseEditor | "rewrite" | On by default. Injects non-interactive env vars for git rebase. |
bash.sourceMode | "override-bash" | Select how rewrite hooks reach bash at runtime. Only matters when at least one feature is set to "rewrite". |
ui.showRewriteNotifications | false | Show a visible Pi notification each time a rewrite happens. |
Enforce pnpm, rewrite python commands, use explicit override mode, and show rewrite notifications:
{
"features": {
"enforcePackageManager": "rewrite",
"rewritePython": "rewrite"
},
"packageManager": {
"selected": "pnpm"
},
"bash": {
"sourceMode": "override-bash"
},
"ui": {
"showRewriteNotifications": true
}
}
Use composed bash integration with an external bash composer:
{
"features": {
"enforcePackageManager": "rewrite"
},
"packageManager": {
"selected": "pnpm"
},
"bash": {
"sourceMode": "composed-bash"
}
}
Block package-manager mismatches instead of rewriting them:
{
"features": {
"enforcePackageManager": "block"
},
"packageManager": {
"selected": "pnpm"
}
}
The extension uses two pi mechanisms:
createBashTool with spawnHook): Rewrites commands before shell execution. The agent sees the original command in the tool call UI but gets the output of the rewritten command.ui.showRewriteNotifications is enabled, a warning-level Pi notification is shown before the rewritten command runs. The message is prefixed with [override-bash] or [composed-bash] for debug clarity.tool_call hooks run first (permission gate, env protection)tool_call hooks run (blockers, optional rewrite notifications)rewrite mode, runtime routing depends on bash.sourceMode:
override-bash: toolchain registers its own bash tool with spawn hookcomposed-bash: toolchain waits for an external composer to request and compose its spawn hookAll rewriters use structural shell parsing via @aliou/sh to identify command names in the AST. This avoids false positives where tool names appear in URLs, file paths, or strings. If the parser fails, the command passes through unchanged — a missed rewrite is safe, a false positive rewrite corrupts the command.
bash.sourceMode controls how rewrite hooks attach to bash at runtime.
override-bash (default): toolchain registers bash when rewrite is active.composed-bash: toolchain contributes its rewrite hook to an external bash composer.Important:
"rewrite"."block" are unaffected.override-bash mode, Pi core still uses first-wins tool registration. If another extension earlier in load order already registered bash, toolchain cannot replace it.composed-bash mode, rewrites run only if an external composer emits ad:bash:spawn-hook:request and collects contributors.composed-bash mode by design.If you were using preventBrew, preventPython, or enforcePackageManager in your guardrails config:
@aliou/pi-toolchain.pi/extensions/toolchain.json with the equivalent configThe guardrails extension will continue to honor these features with a deprecation warning until they are removed in a future version.