@ccask/pi-safety-gate
pi 扩展:执行前判定高危操作——危险直接拦、拿不准的弹窗确认、只读与当前工作目录内写入直接放行(规则分层 + 小模型判定)
Package details
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备份