A pi extension that provides configurable allow/deny permission rules for tool calls — control which bash commands, file reads, writes, and edits the agent can perform.
- Define allow rules to whitelist specific commands
- Define deny rules to block dangerous operations
- Deny always wins — block
git pusheven ifgit *is allowed - Supports glob patterns with
*wildcards - Project-local or global configuration
pi install npm:pi-permissionsAlternative install methods
From the public git repo:
pi install git:github.com/NicoAvanzDev/pi-permissionsFrom a local clone:
pi install .Load without installing:
pi --no-extensions -e npm:pi-permissionsCreate .pi/permissions.json in your project (or ~/.pi/agent/permissions.json for global rules):
{
"permissions": {
"allow": [
"Bash(npm run *)",
"Bash(npm test *)",
"Bash(git commit *)",
"Bash(git diff *)",
"Bash(git status)",
"Bash(git log *)"
],
"deny": [
"Bash(git push *)",
"Bash(rm -rf *)",
"Write(*.env)",
"Edit(*.env)"
]
}
}On session start, the extension loads your rules and reports how many were found. Any tool call that matches a deny rule is blocked before execution.
> pi
Permissions loaded: 6 allow, 4 deny rules
> (agent tries to run `git push origin main`)
⛔ Blocked: Bash command matches deny rule "Bash(git push *)"
After editing permissions.json, type /reload in pi to apply the changes.
Rules use the format Tool(pattern) where:
- Tool — the pi tool name:
Bash,Write,Edit,Read - pattern — a glob pattern where
*matches any characters
| Tool | What the pattern matches against |
|---|---|
Bash(pattern) |
The bash command string |
Write(pattern) |
The file path being written |
Edit(pattern) |
The file path being edited |
Read(pattern) |
The file path being read |
For every tool call the extension:
- checks deny rules first — if any deny rule matches, the call is blocked
- checks allow rules next — if allow rules exist for that tool, the call must match at least one
- passes through — if no allow rules exist for the tool, all calls are permitted (unless denied)
This means:
- Use deny to block specific dangerous commands
- Use allow to whitelist only approved commands (everything else is blocked)
- Deny always wins over allow
| Pattern | Matches | Doesn't match |
|---|---|---|
Bash(git push *) |
git push origin main |
git pull |
Bash(npm run *) |
npm run build, npm run test |
npm install |
Bash(* --version) |
node --version, npm --version |
node index.js |
Write(*.env) |
.env, app.env |
.env.example |
Write(secrets/*) |
secrets/key.pem |
src/secrets.ts |
| Location | Scope |
|---|---|
.pi/permissions.json |
Project-local (checked first) |
~/.pi/agent/permissions.json |
Global fallback |
The extension checks the project-local path first. If not found, it falls back to the global config.
- rules are loaded once on session start
- use
/reloadto pick up changes without restarting - deny rules are always evaluated before allow rules
- if no allow rules exist for a tool type, all calls for that tool are permitted
- glob
*matches any sequence of characters (including path separators in file patterns)
MIT