@spikat/pi-commands-whitelist

Review shell commands and file edits before Pi executes them

Packages

Package details

extension

Install @spikat/pi-commands-whitelist from npm and Pi will load the resources declared by the package manifest.

$ pi install npm:@spikat/pi-commands-whitelist
Package
@spikat/pi-commands-whitelist
Version
1.1.2
Published
Aug 24, 2026
Downloads
173/mo · 23/wk
Author
spikat
License
MIT
Types
extension
Size
47.8 KB
Dependencies
0 dependencies · 2 peers
Pi manifest JSON
{
  "extensions": [
    "./index.ts"
  ]
}

Security note

Pi packages can execute code and influence agent behavior. Review the source before installing third-party packages.

README

commands whitelist

commands-whitelist is a Pi extension that intercepts every bash tool call before it runs. It decomposes shell lists, lets you approve individual commands, and persists prefix-based allow/deny rules.

Behaviour

Before a shell call is executed, the extension splits |, |&, ;, &&, ||, &, and newlines. Redirections and comments are ignored for rule matching but remain intact in the command Pi executes. It recursively examines command substitutions, process substitutions, shell control blocks, and <shell> -c "..." commands. Quoted or escaped separators are not split.

For example:

find /path -name "*.go" | grep -v test | sort | xargs grep -i func 2>/dev/null | uniq -c | wc -l

is reviewed as:

🔁 find /path -name *.go *
🔁 grep -v test *
🔁 sort *
🔁 xargs grep -i func *
🔁 uniq -c *
🔁 wc -l *

* is a final prefix wildcard: ls foo * permits ls foo, ls foo bar, and ls foo bar baz, but not ls baz. Literal shell globs such as *.go stay literal. Variables and otherwise dynamic arguments collapse the remainder of a rule to one *.

Review keyboard controls

  • / : select a command, Validate current selection, or the assistant prompt input.
  • / : remove/add literal arguments in the selected rule.
  • Space: cycle 🔁 (session only), (persist allow), and (persist deny).
  • Enter: move to the next command; on Validate current selection, apply the selection; in the prompt input, cancel the shell call and send the prompt to the assistant.
  • Ctrl+C: cancel the pending call.
  • h: open detailed help; Esc returns from help.

A stored blacklist always wins over an allow rule. If all parts are already allowed, execution proceeds without a dialog. If any part is already denied, execution is blocked and Pi receives the original command, blocked parts, and matching rules. Unresolved 🔁 choices are allowed only for the current request and are not saved.

When a shell construct cannot be safely parsed (for example a shell function), the original complete command is shown as a single review entry.

Python scripts

Launching a Python script (python script.py, python3 script.py, and versioned Python executables) is treated as one opaque command. Its content is never inspected or split. Its review entry only supports 🔁 (allow this one execution) and (deny and persist a blacklist rule); it cannot receive a persistent allow rule, and left/right argument editing is disabled.

/whitelist

/whitelist list
/whitelist allow ls foo *
/whitelist add ls foo *
/whitelist deny git push *
/whitelist block git push *
/whitelist remove ls foo *
/whitelist rm ls foo *
/whitelist del ls foo *
/whitelist delete ls foo *
/whitelist help
/whitelist --help
/whitelist -h

Rules without * receive it automatically. A wildcard is valid only once and only as the final token. list prints rules alphabetically as ✅ | rule or ❌ | rule. Removing a blacklist rule requires confirmation.

File edit/write protection

The extension also keeps a gate for Pi edit and write calls. It supports an allow rule for a directory and all descendants, an exact-file allow rule, denial, and sending a prompt to the assistant. Session approvals remain only in memory; persistent approvals are stored in the configuration.

Pi Web integration

When @spikat/pi-web is active for the same Pi session, shell-command and file-edit permission requests are displayed in both the terminal and the local web dashboard. A waiting browser dialog is inserted into the transcript after the triggering prompt and before later agent output, rather than below the message composer. The first valid response wins atomically and closes the other view. The browser shell-command review exposes the same per-command controls as the terminal: session-only/persistent allow and deny states, literal argument-prefix adjustment, Python-script restrictions, validation, an assistant prompt, cancellation, and contextual help. Browser file-edit reviews support one-time or persistent directory/file approval, denial, and the same mirrored assistant-prompt editor as the terminal.

Configuration

The configuration is located at:

<git root>/.pi/commands-whitelist.json

Outside a Git repository it is located under the current working directory. It is written atomically and created only on first persistent save:

{
  "version": 2,
  "whitelist": ["ls foo *"],
  "blacklist": ["git push *"],
  "editDirectories": ["/absolute/project/src"],
  "editFiles": ["/absolute/project/README.md"]
}

Configurations with a version lower than 2 are deleted at startup. Invalid JSON, malformed version-2 content, or future versions cause a startup error.

Development

npm install
npm test
npm run check

Use it temporarily with:

pi -e ./index.ts

For project auto-discovery, install this directory under .pi/extensions/commands-whitelist/ and use /reload.