@bacnh85/pi-permission

Granular permission system for Pi — allow/ask/deny rules per tool with wildcard patterns, external-directory boundary, and a doom-loop guard. Config-driven, opt-in companion to Pi's container-first philosophy. Inspired by OpenCode's permission config.

Packages

Package details

extension

Install @bacnh85/pi-permission from npm and Pi will load the resources declared by the package manifest.

$ pi install npm:@bacnh85/pi-permission
Package
@bacnh85/pi-permission
Version
0.2.0
Published
Aug 17, 2026
Downloads
372/mo · 325/wk
Author
bacnh85
License
MIT
Types
extension
Size
24.5 KB
Dependencies
0 dependencies · 0 peers
Pi manifest JSON
{
  "extensions": [
    "./extensions/index.js"
  ]
}

Security note

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

README

pi-permission

Granular permission system for Pi — an opt-in companion to Pi's container-first philosophy for users who can't always containerize.

Config-driven allow / ask / deny rules per tool, with wildcard pattern matching, an external-directory boundary, and a doom-loop guard. Inspired by OpenCode's permission config.

Pi's default stance is "No permission popups. Run in a container, or build your own." This package is the middle ground: a config-driven policy for users who run Pi without a container but still want guardrails.

Install

pi install npm:@bacnh85/pi-permission

Configuration

Add a permission object to .pi/settings.json (project) or ~/.pi/agent/settings.json (global):

{
  "permission": {
    "*": "ask",
    "bash": { "*": "ask", "git *": "allow", "npm *": "allow", "rm *": "deny" },
    "edit": { "*": "deny", "src/*.ts": "allow" },
    "write": { "*": "deny", "src/*": "allow" },
    "read": { "*": "allow", "*.env": "deny", "*.env.*": "deny" },
    "external_directory": { "~/projects/personal/*": "allow" }
  }
}

Actions

Action Behavior
allow Runs silently, no prompt
ask Prompts via the Pi UI (Allow once / Allow for this session / Add to permanent allowlist / Deny). "Allow for this session" skips prompts for the exact same call subject until the session ends; "Add to permanent allowlist" writes the allow rule into settings.json. Tools without a command/path subject get only Allow once/Deny. Dismissing the dialog blocks. Session promotions never override an explicit deny.
deny Blocks immediately

Patterns

  • * matches zero or more of any character (including /)
  • ? matches exactly one character
  • Everything else is literal
  • Last matching rule wins (OpenCode semantics)
  • ~ and $HOME expand at the start of path patterns

Rule keys

Key Matches
bash the shell command
read / write / edit the file path
grep / find / ls the path/glob/pattern
external_directory deny-gate for paths outside the project cwd
* global default

Flags

Flag Description
--yolo Auto-approve all ask prompts (explicit deny rules still enforced)
--auto Alias for --yolo

Doom-loop guard

Blocks the 3rd identical tool call in a row. Cheap insurance against model loops. Always on when pi-permission is configured.

Default security

By design, when no rule matches, pi-permission has no opinion (allows). This honors Pi's philosophy — the extension only acts when you've opted into rules. To lock down, set a "*": "ask" or "*": "deny" default.

The .env deny pattern (OpenCode's default) is a good baseline:

{ "read": { "*": "allow", "*.env": "deny", "*.env.*": "deny", "*.env.example": "allow" } }

Why

Pi's "no permission popups" philosophy is clean but binary: containerize, or trust everything. Many users run Pi locally without a container and still want to prevent rm -rf, protect .env, or restrict writes to src/. This package provides that middle ground, opt-in.

License

MIT