配置统一:权限策略、硬防御、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
OpenCode Compatibility
This extension's flat permission format and evaluation semantics were directly inspired by OpenCode's permission model (v1.1.x permission rework). If you are familiar with OpenCode's permission system, most concepts transfer directly — the same mental model applies.
Point-in-time reference. This comparison reflects OpenCode as of May 2026. See the official OpenCode permissions docs for the latest upstream behavior.
What Transfers Directly
The following concepts are shared between OpenCode and this extension:
| Concept | Description |
|---|---|
| Three actions | allow / ask / deny — identical semantics |
Flat permission object |
Top-level key in config; surface names as keys |
"*" universal fallback |
Sets the default action when no surface-specific rule matches |
| Granular object syntax | Surface key → string (catch-all) or { pattern: action } map |
| Last-match-wins | When multiple patterns match, the last one in config order wins |
* wildcard |
Matches zero or more of any character (including path separators) |
? wildcard |
Matches exactly one character |
| Home directory expansion | ~/, $HOME/, and ${HOME}/ expand to the OS home directory in patterns |
external_directory surface |
Gates access to paths outside the working directory |
bash surface |
Command patterns matched against shell commands |
skill surface |
Skill name patterns matched against skill invocations |
task surface |
Gates subagent/delegation tool calls |
| Session-scoped approvals | once / always / reject from the ask dialog; always adds a session rule |
| Per-agent overrides | Override global permissions for specific agents |
| Tool hiding | Denied tools are removed before the agent starts (no wasted turns probing) |
| Bash path extraction | Tree-sitter AST parsing to detect external paths in shell commands (see details below) |
| Bash arity table | Generates smart approval pattern suggestions (e.g., git checkout * not git *) |
| Trailing wildcard optionality | "ls *" matches bare "ls" — the trailing * is optional |
If your OpenCode config uses these features, the equivalent works in this extension with minimal translation (see Porting Guide below).
Where They Diverge
Summary Table
| Area | OpenCode | This extension |
|---|---|---|
| Default fallback | "*": "allow" (permissive) |
"*": "ask" (least privilege) |
.env file protection |
Built-in read rules deny/ask .env files |
No built-in rules; user configures with the cross-cutting path surface or per-tool path patterns (see porting guide) |
Cross-cutting path gate |
No equivalent — .env protection is per-tool only |
path surface denies/asks across all tools and bash at once; a path deny cannot be overridden by a per-tool allow |
| OpenCode-only surfaces | lsp, question, webfetch, websearch, todowrite, doom_loop |
Not applicable — Pi does not expose these tools or events |
| File mutation surfaces | edit covers edit, write, apply_patch |
Separate write and edit surfaces |
| Search/discovery surfaces | glob, grep, list |
find, grep, ls (Pi tool names) |
mcp surface |
Not a documented permission surface | First-class with server/tool-level granularity |
| Top-level string shorthand | "permission": "allow" sets all surfaces |
Not supported; must use an object |
| Per-agent config location | agent key in config JSON or YAML frontmatter |
YAML frontmatter in agent .md files only |
| Config file paths | ~/.config/opencode/opencode.json |
config/pi-permission-policy.jsonc plus config/pi-permission-hard-guards.jsonc inside the installed bundle |
| Subagent prompt forwarding | Not documented | ask policies work in non-UI subagent contexts |
| Infrastructure auto-allow | N/A | Read-only tools to Pi infra dirs bypass the gate |
| Permission review log | No equivalent documented | Writes decisions to a JSONL audit log |
Notable Differences Explained
Default Fallback: allow vs ask
OpenCode defaults to permissive — most tools work without configuration.
This extension defaults to least privilege — omitting "*" gives you "ask" for everything.
If you want OpenCode-like permissiveness:
{
"permission": {
"*": "allow",
"external_directory": "ask"
}
}
File Mutation Surfaces
OpenCode unifies all file writes under a single edit permission.
This extension exposes Pi's actual tool names: write (create/overwrite) and edit (targeted replacement).
To replicate OpenCode's unified behavior, set both to the same action:
{
"permission": {
"write": "ask",
"edit": "ask"
}
}
MCP Surface (Pi-Only)
This extension provides a first-class mcp permission surface with granular server and tool-level control:
{
"permission": {
"mcp": {
"*": "ask",
"mcp_status": "allow",
"myServer:*": "ask",
"dangerousServer": "deny"
}
}
}
OpenCode does not expose MCP as a configurable permission surface.
Bash Path Extraction
Both systems use web-tree-sitter + tree-sitter-bash to parse shell commands into an AST for external_directory path detection, but the extraction strategies differ significantly:
OpenCode only extracts paths from a hardcoded allowlist of file-manipulating commands (rm, cp, mv, mkdir, touch, chmod, chown, cat, plus PowerShell equivalents).
Commands not in the list — including sed, awk, grep — get no path extraction at all.
For allowlisted commands, all non-flag positional arguments are assumed to be paths.
This extension extracts path candidates from all commands generically, then applies additional intelligence:
- A
PATTERN_FIRST_COMMANDSmap understands flag arity forsed,awk,grep,rg, and similar tools, distinguishing inline patterns/scripts from file arguments to avoid false positives. - Redirect destinations (
> /path/to/file) are extracted. - Heredoc bodies, comments, and variable assignments are skipped.
The result is broader coverage (paths detected in any command, not just a curated list) with fewer false positives on pattern-first commands (no spurious prompts for sed regexes or grep patterns that happen to contain /).
Porting an OpenCode Config
Before (OpenCode)
{
"$schema": "https://opencode.ai/config.json",
"permission": {
"*": "allow",
"bash": {
"*": "ask",
"git *": "allow",
"npm *": "allow",
"rm *": "deny"
},
"edit": {
"*": "ask",
"src/*.ts": "allow"
},
"external_directory": {
"~/projects/*": "allow"
}
}
}
After (this extension)
{
"$schema": "https://raw.githubusercontent.com/gotgenes/pi-packages/main/packages/pi-permission-system/schemas/permissions.schema.json",
"permission": {
"*": "allow",
"bash": {
"*": "ask",
"git *": "allow",
"npm *": "allow",
"rm *": "deny"
},
"write": "ask",
"edit": "ask",
"external_directory": {
"*": "ask",
"~/projects/*": "allow"
}
}
}
Key Translation Steps
-
Replace
"permission": "allow"(top-level string) with"permission": { "*": "allow" }. -
Split
editinto separatewriteandeditentries if you need different policies for create vs. modify. If not, set both to the same action. -
Rename search surfaces:
glob→find,list→ls. -
Add
.envrules manually if you relied on OpenCode's built-in protection. Thepathsurface is the recommended approach — it covers all tools and bash in one rule:{ "permission": { "path": { "*": "allow", "*.env": "deny", "*.env.*": "deny", "*.env.example": "allow" } } }Alternatively, use per-tool patterns if you only need to protect specific tools (e.g.,
read):{ "permission": { "read": { "*": "allow", "*.env": "deny", "*.env.*": "deny", "*.env.example": "allow" } } } -
Remove OpenCode-only surfaces (
lsp,question,webfetch,websearch,todowrite,doom_loop) — they have no effect in this extension. -
Add
mcprules if you use MCP servers — OpenCode has no equivalent, so this is new configuration.