@ccask/pi-safety-gate

pi 扩展:执行前判定高危操作——危险直接拦、拿不准的弹窗确认、只读与当前工作目录内写入直接放行(规则分层 + 小模型判定)

Packages

Package details

extension

Install @ccask/pi-safety-gate from npm and Pi will load the resources declared by the package manifest.

$ pi install npm:@ccask/pi-safety-gate
Package
@ccask/pi-safety-gate
Version
0.1.4
Published
Sep 16, 2026
Downloads
329/mo · 24/wk
Author
ccask
License
MIT
Types
extension
Size
81.9 KB
Dependencies
0 dependencies · 1 peer
Pi manifest JSON
{
  "extensions": [
    "./index.ts"
  ]
}

Security note

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

README

safety-gate — 执行前判定高危操作

给 pi 加一道"执行前检查":AI 每次调用工具前先判风险。 日常操作不打扰;明显不可逆的直接不执行;AI 觉得可疑的才弹窗问你。

四层结构(v0.1.3 起)

层 内容 行为
免问层 只读命令/工具、受信目录内写入、你加的白名单、只读抓取公开网页 直接执行(不调模型)
分类器层 其余全部:shell 命令、项目外写入、联网与浏览器抓取、发布、删库、强推、脚本、改动 pi 自身配置 AI 判 allow → 执行;判 block → 弹窗问你(本次允许 / 本会话允许同类 / 拒绝)
ask 层 你在 extraAskRules 里显式写的动作 弹窗,AI 无权取消
deny 层 只有两类:格式化磁盘/写裸设备、删根目录或家目录或盘符根 不执行,不问

与旧版(≤0.1.2)的差别

  • 旧版的 14 条"要确认"规则(强推、发布、脚本执行、删保护路径、提权…)不再直接弹窗,改为作为提示送给 AI 参考
  • 硬拦从 7 类缩到 2 类(删系统目录、清空日志、改 pi 自身配置都改走"AI 判定 + 弹窗")
  • 新增:浏览器/联网工具(fetch_content、web_search 等)纳入判定;公开 URL 的只读抓取免问,内网地址要问
  • 新增:模型判 block 时可以弹窗让你决定(askOnBlock,默认开;关掉则静默不执行)

日常表现

  • ls、git status、项目内改文件、网页搜索 → 静默执行
  • npm publish、git push --force、删系统目录、跑未知脚本 → AI 判定后弹窗(问的时候会写清 AI 的理由)
  • mkfs、rm -rf /、rm -rf ~ → 直接不执行,把关卡理由交回给模型

弹窗里三个选项:本次允许 / 本会话允许同类 / 拒绝。拒绝后同一操作在一轮内不会反复问。

被拦截时怎么放行:要么在弹窗里点允许,要么下一句话明确授权("发布吧""这次允许删"),模型会带授权重试,AI 看到你的原话就会放行。

文件放哪

程序(随代码走):

index.ts  cmd.ts  rules.ts  classify.ts  config.ts  audit.ts
rules.default.json   内置规则表(deny 2 条 / 提示若干 / 免问命令 / 路径与域名边界)
tests/               规则用例,改完规则跑一遍

数据(config.json 和 logs/):

  • 直接把本目录当扩展用(~/.pi/agent/extensions/safety-gate/)→ 数据就地存放
  • 作为安装的包(npm / git)→ 数据自动改放 ~/.pi/agent/safety-gate/
  • 环境变量 SAFETY_GATE_HOME 可强制指定

/safety config 会打印实际路径。

受信范围

启动 pi 时的当前目录永远自动受信。trusted.paths 用来补充额外目录(例如 ~/.pi/agent,这样 AI 写自己的记录文件不再需要确认)。

常用命令

  • /safety — 看当前规则、模式、路径
  • /safety test <命令> — 试判(不执行)
  • /safety allow|block|ask <文字> — 加白/加黑/加必问,立即生效
  • /safety stats — 看历史判定(哪些被拦、你当时怎么选)
  • /safety mode off|rules|auto — 切换模式
  • /safety export <目录> — 导出干净副本(不含配置与日志)

配置要点(config.json)

  • mode:off(全关)/ rules(只跑规则,未命中即放行)/ auto(规则 + AI)
  • classifier:判定模型,默认 deepseek/deepseek-flash(复用 pi 已登录凭据)
  • askOnBlock:AI 判 block 时是否弹窗(false = 静默不执行)
  • allowExceptions:inProjectWrites / readOnlyCommands / declaredDependencies / readOnlyWebFetch 四个免问开关
  • trusted.paths / trusted.domains / trusted.gitRemotes:受信目录、域名、远程仓库
  • extraAllowRules / extraBlockRules / extraAskRules:自定义规则(普通文字即可,子串匹配)
  • removeRules:按 id 关掉不认可的内置规则
  • protectedPaths:额外保护的重要路径
  • askTools:某个扩展工具也必须问

改完保存即生效;改了代码需要 /reload 或重启。

改完规则跑一遍测试

pi --no-session --no-extensions -e ~/.pi/agent/extensions/safety-gate/tests/run.ts -p ok

结果在 tests/last-result.json(failed 为 0 即全过)。用例在 tests/rule-cases.ts。

安装 / 发布

别人安装(npm 上的包名是作用域包):

pi install npm:@ccask/pi-safety-gate

自己发布:

npm login                       # 或已配置 token
cd <本目录>
npm publish                     # package.json 已声明 publishConfig.access=public

发布前自检:npm pack --dry-run(不应出现 config.json、logs/、tests/last-result.json)。

边界(能力所限)

  • 只看得到命令本身:bash foo.sh 里是什么、curl | sh 拉下来什么,只能标记"不确定"并交给 AI 判
  • 无法改写命令,只能"放行 / 不执行 / 问"
  • AI 判定会出错:出错时一律偏向"要问",且失败/超时不会静默放行
  • 这是降低事故概率,不是沙箱。真隔离靠容器 + 备份

停用 / 卸载

  • 临时:/safety mode off
  • 完全:删掉本目录
  • 注意:删目录会连 config.json 与 logs/ 一起删掉,先 /safety export 备份