Pi coding-agent extension that asks before the agent modifies files.
-
Reads stay free —
read/grep/find/lsare never prompted -
Writes need approval — built-in
write/edit, plus common mutator tool names (e.g. MCPreplace) - Workspace-aware — separate policies for paths inside vs outside the project (git root or cwd)
- Session shortcuts — allow one file, or all workspace writes, for the rest of the session
Keywords for discovery: pi-package, pi, pi-extension, pi-coding-agent.
Pi has no built-in “confirm before edit” switch. This package adds that gate via the extension
tool_callhook.
Requires Pi (@earendil-works/pi-coding-agent).
You can install from npm or GitHub — both are supported.
Published as pi-edit-approval on the public npm registry.
pi install npm:pi-edit-approvalPin a version:
pi install npm:pi-edit-approval@0.1.0pi install git:github.com/ShawnMa123/pi-edit-approvalEquivalent forms:
pi install https://github.com/ShawnMa123/pi-edit-approval
pi install git:github.com/ShawnMa123/pi-edit-approval@mainPin a tag or commit when you want a fixed revision:
pi install git:github.com/ShawnMa123/pi-edit-approval@v0.1.0pi -e npm:pi-edit-approval
pi -e git:github.com/ShawnMa123/pi-edit-approvalpi install /path/to/pi-edit-approval
# or
pi -e ./extensions/edit-approval.tsWrites to .pi/settings.json (shared with the repo) instead of your user settings:
pi install -l npm:pi-edit-approval
# or
pi install -l git:github.com/ShawnMa123/pi-edit-approvalAfter install, start a new session or run /reload.
If you previously copied edit-approval.ts into ~/.pi/agent/extensions/, remove that copy to avoid loading the extension twice.
| Tool / path | Default |
|---|---|
read, grep, find, ls
|
Always allow |
write / edit inside workspace |
Ask |
write / edit outside workspace |
Ask (labeled OUTSIDE workspace) |
| Other tools matching mutator name patterns | Ask (same path rules) |
bash |
Not gated (see gateBash) |
Non-interactive (-p / no UI) when policy is ask
|
Block (no silent writes) |
Workspace root = git rev-parse --show-toplevel when available, otherwise the session cwd.
When a confirmation appears you can typically choose:
- Yes — allow this call only
- Yes, this file this session — skip further prompts for that absolute path
- Yes, all workspace writes this session — if enabled in config (in-workspace only)
- Yes, all outside writes this session — only if you enable it in config
- No — block the tool call
Optional file:
~/.pi/agent/edit-approval.json
Copy the example:
# Linux / macOS
cp "$(npm root -g)/../..." # or copy from the cloned repo:
cp edit-approval.example.json ~/.pi/agent/edit-approval.json
# Windows (PowerShell)
Copy-Item edit-approval.example.json $env:USERPROFILE\.pi\agent\edit-approval.json{
"workspaceWrites": "ask",
"outsideWrites": "ask",
"allowSessionBypassInWorkspace": true,
"allowSessionBypassOutside": false,
"gateBash": false,
"extraMutatingTools": []
}Allow free edits inside the repo; confirm (or deny) anything outside:
{
"workspaceWrites": "allow",
"outsideWrites": "ask",
"allowSessionBypassInWorkspace": true,
"allowSessionBypassOutside": false,
"gateBash": false,
"extraMutatingTools": []
}{
"workspaceWrites": "ask",
"outsideWrites": "deny"
}| Key | Type | Default | Meaning |
|---|---|---|---|
workspaceWrites |
"allow" | "ask" | "deny"
|
"ask" |
Policy for paths inside the workspace |
outsideWrites |
"allow" | "ask" | "deny"
|
"ask" |
Policy for paths outside the workspace |
allowSessionBypassInWorkspace |
boolean |
true |
Offer “all workspace writes this session” |
allowSessionBypassOutside |
boolean |
false |
Offer “all outside writes this session” |
gateBash |
boolean |
false |
If true, confirm every bash call |
extraMutatingTools |
string[] |
[] |
Extra tool names to treat as mutators |
Reload config without restarting Pi:
/edit-approval reload
| Command | Action |
|---|---|
/edit-approval |
Show workspace root, policies, session bypass state, config path |
/edit-approval reset |
Clear session allow-lists / bypasses |
/edit-approval reload |
Re-read ~/.pi/agent/edit-approval.json
|
Always treated as mutators:
- Built-in
write,edit
Also matched by name (case-insensitive), including MCP-style names:
-
replace,create_file,delete_file,apply_patch,str_replace - Patterns like
fastctx_replace,mcp_foo_write, …
Path fields inspected on tool input:
path, file_path, filePath, filepath, target, target_path, filename, paths[]
Add stubborn custom tool names via extraMutatingTools.
-
bashcan bypass file gates unlessgateBashistrue(noisy). Redirects likeecho hi > fileare not parsed specially. - This is not an OS sandbox. It only intercepts Pi tool calls the extension sees.
- Unknown mutators with odd argument shapes may only show a generic confirmation.
- In print / headless modes without UI,
askbecomes a hard block by design.
For stronger isolation, combine with containers or a sandbox package; see Pi security docs.
pi-edit-approval/
├── package.json # pi-package manifest + keywords
├── extensions/
│ └── edit-approval.ts # extension entry
├── edit-approval.example.json # sample config
├── LICENSE # GPL-3.0-only
└── README.md
package.json declares:
{
"keywords": ["pi-package", "pi", "pi-extension", "pi-coding-agent"],
"pi": {
"extensions": ["./extensions"]
}
}That pi-package keyword is what the Pi package gallery uses for discovery (this package is on npm, so it is eligible for the gallery index).
git clone https://github.com/ShawnMa123/pi-edit-approval.git
cd pi-edit-approval
# load from this checkout
pi -e ./extensions/edit-approval.ts
# or
pi install .No build step: Pi loads the TypeScript extension directly.
Remove whichever source you installed:
pi remove npm:pi-edit-approval
pi remove git:github.com/ShawnMa123/pi-edit-approvalAlso delete ~/.pi/agent/edit-approval.json if you no longer need it.
- Pi packages documentation
- Pi extensions documentation
- Upstream examples:
permission-gate.ts,protected-paths.tsin the Pi repo - Similar ecosystem packages:
pi-show-diffs, variouspi-permission-*tools (heavier / different focus)