pi-tool-missing-guard
Pi extension that detects missing tools/commands, interrupts the agent instead of letting it improvise with substitutes, and tells the user what to install plus available alternatives.
Package details
Install pi-tool-missing-guard from npm and Pi will load the resources declared by the package manifest.
$ pi install npm:pi-tool-missing-guard- Package
pi-tool-missing-guard- Version
0.1.2- Published
- Aug 25, 2026
- Downloads
- 450/mo · 17/wk
- Author
- thomasyangd
- License
- MIT
- Types
- extension
- Size
- 38.4 KB
- Dependencies
- 0 dependencies · 2 peers
Pi manifest JSON
{
"extensions": [
"./extensions"
]
}Security note
Pi packages can execute code and influence agent behavior. Review the source before installing third-party packages.
README
pi-tool-missing-guard
A pi extension that detects when a tool or command is missing from the current environment, interrupts the agent instead of letting it improvise with substitutes, and tells the user what to install plus available alternatives (when a genuine substitute exists).
⚠️ Security note for reviewers: Pi packages run with full system access. This extension is read-only / no-op — it only subscribes to the
tool_resultandbefore_agent_startevents and rewrites tool results. It does not spawn processes, install anything, or reach the network. The package-manager detection reads a few fixed paths vials(/usr/bin/apt-get,/usr/bin/dnf,/usr/bin/yum,/usr/bin/pacman,/usr/local/bin/brew,/nix/store).
Problem
By default, when an LLM agent tries to run a command that isn't installed (e.g. kubectl), bash just returns command not found. Models frequently ignore that small error and quietly fall back to a substitute (or worse, invent a tool that doesn't exist). The resulting work can be wrong, silently deviates from the real requirement, or wastes turns.
This extension flips that behavior: it replaces the tool result with a hard interrupt — a strong instruction the model cannot skip — telling the user exactly what's missing, how to install it, and what the real alternatives are (to be used only when the original cannot be installed).
How it works
Two layers, both via the tool_result event (pure hooks — it never replaces or re-routes a tool's execution path):
bash layer (missing command) — detects missing-command errors in bash output:
command not found(bash/zsh/sh/dash)not found(dash/bin/sh: 1: <cmd>: not found)No such file or directoryfor an executableis not recognized(pwsh),Unknown command(fish)Unable to locate package,cannot find
It extracts the missing command name, then rewrites the result to:
- ⛔ an explicit "stop, do not improvise with a substitute" instruction,
- the detected package manager (
apt/dnf/yum/pacman/brew/nix) and an install command, - a list of alternatives from a built-in database of 60+ common tools.
pi tool layer (hallucinated tool) — when the model calls a tool that isn't registered (
Unknown tool 'x',Tool x not found), it tells the user that the tool needs to be installed/registered via an extension, or that an already-available tool should be used instead.
It also appends a soft guideline to the system prompt (before_agent_start) so the model knows up front: if a tool/command is missing, stop and ask — do not improvise.
Install
pi install npm:pi-tool-missing-guard
Then reload pi (/reload) or restart.
Verify it's active:
/tool-missing
Usage
Nothing to configure. When a missing command is detected, the agent will stop and report something like:
### ⛔ Missing command detected — stop improvising with substitutes
The command `kubectl` is **not installed in the current environment**. Do **not** fall back to an improvised substitute tool or fake success...
**Install:** sudo apt-get install -y kubectl
**If `kubectl` truly cannot be installed, available substitutes:**
1. use the K3s-bundled kubectl on the current node — if the environment is K3s (alias kubectl='k3s kubectl')
2. oc (OpenShift CLI) — OpenShift substitute, compatible with most kubectl commands
3. helm / k9s — only for querying/interactive management
What is NOT intercepted
To avoid false positives, ordinary command errors are left untouched:
grep: no lines selected(exit 1)curl: try 'curl --help'ssh: Connection refusedfatal: not a git repository- any command that exits 0
Only genuine "command/program missing" patterns are intercepted.
Extending the tool database
The built-in table lives in extensions/index.ts as TOOL_DB. Each entry maps a command name to:
{
name: "jq",
askInstall: "jq is missing.",
pkgs: { deb: "jq", rpm: "jq", arch: "jq" },
alternatives: [
{ how: "parse with python", desc: "python3 -c '...'", install?: "..." },
],
note?: "...",
}
pkgs keys are deb / rpm / arch / brew (and nix), mapped from the detected package manager. Unknown commands fall back to a generic "search your package manager" hint rather than guessing.
Commands
| Command | Description |
|---|---|
/tool-missing |
Show extension status, built-in DB size, detected package manager, and intercept scope. |
Development
Type checking
npm run typecheck
Tests
Integration tests drive the extension through its exported toolMissingGuard factory with a mock pi API, verifying interception, language adaptivity, and non-interception of ordinary errors.
npm test
Requires Node.js 22+ (uses node:test and imports .ts natively). No test framework needs to be installed.
License
MIT