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.

Packages

Package details

extension

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_result and before_agent_start events and rewrites tool results. It does not spawn processes, install anything, or reach the network. The package-manager detection reads a few fixed paths via ls (/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):

  1. 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 directory for an executable
    • is 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.
  2. 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 refused
  • fatal: 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