配置统一:权限策略、硬防御、Tool Search、提示词封面以及新迁入的 RTK、pi-compaction、pi-worktree、pi-hermes-memory 配置全部由扩展 直接读取已安装组合包内的 config/,pi install / pi update 即完成部署; 删除 rebuild-bundle-config.mjs 与 bundle-manifest.json,my-pi/ 只保留 日志与缓存。update.sh 成功升级后将默认 git 来源的已安装副本 reset 回发布版本。AGENTS.md 新增「组合包配置原则」。 脚本整合:search_config.sh / ssh_config.sh 合并为 configure.sh search|ssh;install.sh / update.sh 共享函数抽到 scripts/lib.sh,远程 安装器改为先下载到临时文件再执行,下载失败可被检测。 权限:hard-guards 新增 protectedWrites,写入 Pi 凭据/设置、已安装 组合包与扩展目录、pi-ssh 凭据库时一律人工确认(跳过 AutoReview、 yolo 与 Session grant,无 UI 时拒绝);放行 ls、LSP 查询、ctx 只读、 web_search、Chrome 只读与 git 只读命令,skill_manage 改为 ask。 Generated with [Devin](https://devin.ai) Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
12 KiB
@gotgenes/pi-permission-system
Permission enforcement extension for the Pi coding agent that provides centralized, deterministic permission gates over tool, bash, MCP, skill, and special operations.
Fork notice: This package is a full fork of MasuRii/pi-permission-system, published to npm as
@gotgenes/pi-permission-system. It has diverged substantially from upstream in config format, internal architecture, and permission model.my-pi maintenance note: This directory was imported from upstream tag
pi-permission-system-v26.2.1at commitec4fdb11343dc94f7185b113e559a4cf9f8dc035. It is loaded from source and maintained directly by my-pi; npmdistoutput is not used. my-pi uses one global ordinary policy and a separate non-overridable hard-guard file; explicitly configured authorizers may approve any ordinary-policyask, includingpath.
What It Does
- Enforces
allow/ask/denyat tool-call time with UI confirmation dialogs - Uses one global ordinary policy file; project
policy.jsoncfiles are not loaded - Chooses the most specific matching pattern, so a specific deny wins over a broad
"*": "allow"regardless of declaration order - Applies a separate hard-guard policy first so session grants, per-agent rules, and model review cannot override high-risk denies
- Keeps protected writes human-only: files listed in
protectedWrites(Pi credentials, settings, the installed bundle itself, …) always reach the local human prompt — never AutoReview, never yolo, never a session grant — and are denied when no confirmation UI exists. Reads are unaffected. - Controls Bash, paths, MCP, skills, and tool surfaces while leaving active-tool ownership entirely to Tool Search
- Reviews ordinary
askrequests automatically with integrated AutoReview; itsallowverdict is final for ordinary tools andpath, whiledeferreaches the next authorizer or human terminal - Follows the session's current model: AutoReview asks the model you are already chatting with to judge each ask, so the review always reflects the model the operator actually selected; set
autoReview.providerandautoReview.modeltogether to pin a different reviewer - Decides through tool calls only: the reviewer reaches its verdict by calling exactly one of two tools,
approveorreject, each carrying a reason — prose answers, even well-formed JSON, are ignored - Never hard-denies on a refusal or failure: a
rejectverdict or any review failure defers the ask to the human prompt, with the model's reason shown and labelled model-generated - Forwards subagent
askdecisions to the parent authority and keeps structured audit logs
Install
pi install npm:@gotgenes/pi-permission-system
Quick Start
-
Ordinary policy lives in the installed bundle at
config/pi-permission-policy.jsonc(the bundle repository'sconfig/directory — edit it there for durable changes):{ "authorizerChain": ["auto-review"], "autoReview": { "enabled": true }, "permission": { "*": "ask", "read": "allow", "bash": { "*": "ask", "git status*": "allow" } } } -
Independent hard guards live beside it at
config/pi-permission-hard-guards.jsonc:{ "version": 1, "permission": { "*": "allow", "*.env": "deny", "*.env.*": "deny", "*.env.example": "allow", "~/.ssh/**": "deny" }, "protectedWrites": [ { "pattern": "{agentDir}/auth.json", "label": "Pi credentials" } ] } -
Restart Pi or run
/reload. Ordinaryaskrequests now reach AutoReview first; onlydeferopens the human dialog.
The path surface is a cross-cutting gate that applies to all file access — Pi tools, bash commands, MCP calls, and extension tools alike.
Extension and MCP tools that operate on paths (via input.path, a unified mcp proxy tool's input.arguments.path, or a registered access extractor) are gated by default, so a path deny cannot be overridden by a per-tool allow — making it the right place to protect sensitive files like .env or ~/.ssh/* from every tool at once.
A path pattern matches both the path as the agent references it and its canonical (symlink-resolved) form, so a deny still fires when a symlink aliases a sensitive target.
For per-tool path patterns (read, write, edit, find, grep, ls), patterns are matched against the file path from input.path.
This lets you express rules like "allow reads but deny .env files" at the individual tool level.
Like the cross-cutting path surface, per-tool patterns match both the referenced path and its canonical (symlink-resolved) form, so a per-tool deny resists symlink-alias evasion.
When Pi's current working directory is known, relative path inputs also match their cwd-normalized absolute form, so src/App.jsx can match both src/* and /workspace/project/*.
Paths outside the working tree have no separate boundary gate. Configure them with the same path, per-tool, and Bash patterns used for in-project paths. These layers still compose with most-restrictive-wins.
See docs/configuration.md for the full recipe.
Configuration
The integrated extension uses two independent global JSONC files:
| Purpose | Scope | Path |
|---|---|---|
| Ordinary policy, runtime knobs, AutoReview | Global only | config/pi-permission-policy.jsonc inside the installed bundle |
| Non-overridable hard guards | Global only | config/pi-permission-hard-guards.jsonc inside the installed bundle |
Project-level policy.jsonc files are ignored. Project agent Markdown remains a separate per-agent restriction mechanism.
Both files are read directly from the bundle's config/ directory — the single source of truth. Nothing is deployed to, seeded into, or migrated from the agent directory; pi update refreshes them with the bundle. Files left at the former ~/.pi/agent/my-pi/permission-system/ location are ignored.
Within a pattern map, the most specific match wins: exact patterns, then more literal characters, fewer wildcards, and longer patterns. Declaration order is only a tie-breaker.
There is no external_directory gate. Outside-CWD paths use the same configured tool, path, and Bash rules as other paths.
Tool Search alone owns Pi's active tool list. Permission System only decides whether an invoked tool call is allowed, denied, or requires confirmation.
See docs/configuration.md for the complete reference, including the protected writes format in the hard-guard file.
Documentation
| Document | Contents |
|---|---|
| docs/configuration.md | Full policy reference, runtime knobs, per-agent overrides, recipes |
| docs/session-approvals.md | Session-scoped rules, pattern suggestions, bash arity table |
| docs/cross-extension-api.md | Cross-extension service accessor, event bus integration, prompt and decision broadcasts |
| docs/subagent-integration.md | Permission forwarding, coexistence with subagent extensions |
| docs/guides/permission-frontmatter-for-subagent-extensions.md | Convention guide for subagent extension authors |
| docs/opencode-compatibility.md | OpenCode compatibility — shared concepts, divergences, porting guide |
| docs/troubleshooting.md | Common issues, diagnostic logging, threat model |
| docs/migration/legacy-to-flat.md | Migration from pre-v2 config layout |
| docs/migration/strict-config-validation.md | Strict config validation (breaking) — rejected configs, and the cross-scope fail-closed clamp |
| docs/migration/0644-project-trust-gating.md | Project-trust gating (breaking) — project config loads only after project trust |
| docs/migration/0745-prompt-payload-contracts.md | Prompt payload contracts (breaking) — the forwarded wire, the ui_prompt broadcast, and the deprecated preview caps |
| docs/migration/0746-review-log-fields.md | Review-log fields (breaking) — message replaced by request facts, and the reviewLogFieldMaxWidth bound |
Development
pnpm run check # Type-check TypeScript (no emit)
pnpm run lint # Biome + ESLint + lint:md
pnpm run lint:md # rumdl on README and docs
pnpm run test # Run tests from ./test
pnpm run test:watch # Run tests in watch mode
Pre-commit hooks
This project uses prek to run Biome, ESLint, and rumdl on staged files before each commit.
Run pnpm install to set up hooks automatically.
Acknowledgments
This project began as a fork of MasuRii/pi-permission-system. Thank you to MasuRii for the original work that made this possible.
Thank you to the OpenCode team for the permission model design that inspired the flat config format and evaluation semantics used in this extension.
