Files
my-pi/pi-permission-system/docs/opencode-compatibility.md
T
云服务部-叶林立andDevin <158243242+devin-ai-integration[bot]@users.noreply.github.com> 2aa1be0b54 feat: 组合包配置以包内 config/ 为唯一来源,并新增受保护写入人工审批
配置统一:权限策略、硬防御、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>
2026-10-20 01:05:31 -07:00

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_COMMANDS map understands flag arity for sed, 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

  1. Replace "permission": "allow" (top-level string) with "permission": { "*": "allow" }.

  2. Split edit into separate write and edit entries if you need different policies for create vs. modify. If not, set both to the same action.

  3. Rename search surfaces: glob → find, list → ls.

  4. Add .env rules manually if you relied on OpenCode's built-in protection. The path surface 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"
        }
      }
    }
    
  5. Remove OpenCode-only surfaces (lsp, question, webfetch, websearch, todowrite, doom_loop) — they have no effect in this extension.

  6. Add mcp rules if you use MCP servers — OpenCode has no equivalent, so this is new configuration.