npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

pi-verdict

v0.12.0

Published

A minimal permission gate for Pi in the style of Claude Code's auto mode

Readme

pi-verdict

English | 简体中文

License: MIT npm pi extension

pi-verdict 是 pi 的 Claude Code 风格的 Auto mode 式的极简权限门禁:每次工具调用执行前先过检查——放行、拦截,或先问你。

  • 只有2k行左右的极简代码
  • 内置危险规则与你的 allow/deny 规则以零延迟先行裁决明确情形
  • 其余交给携带会话上下文的模型分类器
  • 任何不确定或失败一律 fail-closed, 绝不静默放行
  • 自我保护: 防止被窥探和篡改

问题

pi 没有内置的逐次权限确认——每次工具调用都以 pi 进程自身的权限直接执行(pi 安全文档)。

pi-verdict 补上这道缺失的门禁, 由模型基于上下文和你的意图判定是否可以运行.

为什么是三态

verdict 是裁决,不是开关。 本品类的分类器大多只输出二值 allow/block。三态有意义的地方在:ask 把真正含糊的动作转交人类确认(非交互会话中降级为 deny),「不确定」永远不会静默变成「放行」——目标是安全的自动化而非最大的自动化:审批疲劳与静默危险执行都是危险。

设计原则

  • Fail closed——不确定产生摩擦,绝不产生许可。
  • 确定性 floor 先于 AI——硬 deny 永不被分类器或用户 allow 规则覆盖。
  • 语义优先于语法——分类器判定的是动作做什么可能会产生什么安全影响,而不是命令有多长。
  • 是判断,不是证明——分类器的 allow 是有依据的判断;floor 的存在正因为它仅此而已。
  • 最小化可信输入——transcript 不含工具结果(#22),分类器零路径明文(ADR-0002)。
  • 规范化身份——词法 + realpath 双形匹配;「看起来在项目内」的路径不因此被信任(#20/#21)。
  • 门禁守护自身——任何配置都关不掉的自保护层(ADR-0001)。
  • 是权限门禁,不是沙箱——请在上面叠加 OS 级隔离;本门禁不替代它。

完整表述见 docs/security-principles.md:

截图

演示:受保护路径 ask 被拒绝

Automode Status Ask Permission

快速开始

# 从 npm 安装(pi):
pi install npm:pi-verdict

# 从 npm 安装(oh-my-pi / omp):
omp plugin install npm:pi-verdict

# 或直接从源码 —— 试用一次
pi --extension ./extensions/pi-verdict.ts

宿主

pi-verdict 同时支持 pi 与 oh-my-pi(omp)——扩展按自身安装位置自锚定到所在宿主的目录树,双宿主并存的机器上跟随扩展副本自身的位置。omp 18 下分类器的模型调用经 pi-ai compat API 降级(仍然 fail-closed)。细节见 docs/configuration.md。

| | pi | omp | |---|---|---| | 安装 | pi install npm:pi-verdict | omp plugin install npm:pi-verdict | | 扩展副本 | ~/.pi/agent/extensions/ | ~/.omp/plugins/node_modules/pi-verdict/(omp 18.1+;≤18.0 在 agent/ 下) | | 用户规则 | ~/.pi/agent/config/pi-verdict.json | ~/.omp/agent/config/pi-verdict.json | | 凭据文件(S0 硬 deny) | ~/.pi/agent/auth.json | ~/.omp/agent/auth.json |

  • /automode —— 显示当前状态:开/关
  • /automode on
  • /automode off
  • ctrl+shift+a —— 静默切换主开关(footer 始终显示为唯一反馈;键位可经 toggleShortcut 重绑或禁用)
  • footer 恒显 auto mode on(绿色)/ auto mode off(黄色)

| 配置 | 默认 | 说明 | |---|---|---| | --auto-mode / --no-auto-mode | 开 | 总开关 | | --auto-mode-model provider/id | 会话模型 | 分类器模型(默认"自省") | | --auto-mode-debug | 关 | 全量裁决通知 | | PI_AUTO_MODE_MODEL | — | 模型配置的环境变量形式 | | PI_AUTO_MODE_DEBUG=1 | 关 | 调试的环境变量形式(flag 优先) |

用户自定义规则(~/.pi/agent/config/pi-verdict.json)

{
  "allow": ["^ls\\b", "^git (status|log|diff)\\b"],
  "deny":  ["rm ", "docker ", "^/etc/"],
  "denyPaths": [
    "~/.ssh/",
    "~/.profile",
    "~/.gnupg",
    "~/.mc",
    "~/.kube",
    "~/.zshrc",
    "~/.bashrc"
  ],
  "ignoreTools": [
    "todo",
    "ask_user_question",
    "memory_write",
    "memory_search"
  ],
  "builtinDenyFloor": true,
  "classifierModel": null,
  "toggleShortcut": "ctrl+shift+a",
  "audit": false,
  "notifyAllows": false,
  "classifierMinConfidence": null,
  "classifierFallbackModel": null,
  "classifierFallbackMode": "enforce"
}
  • allow/deny 为 JS 正则数组;deny 优先于 allow,两者都优先于分类器
  • denyPaths 是你声明受保护的普通路径列表:触碰触发终局 ask 由你裁决(非交互降级 deny);分类器只被告知路径存在,路径明文永不出本机。grep/find/ls 按整个搜索范围比较:省略 path(pi 默认:当前目录)或传入位于声明路径之上的父目录,同样触发 ask。全新安装会预填一份入门列表(~/.ssh/、~/.gnupg、~/.mc、shell rc/profile 文件)
  • ignoreTools 列出规则未覆盖的工具(todo、web_search、MCP/自定义工具):直接放行、零模型调用;列出已覆盖工具(bash/read/write/edit/grep/find/ls/powershell)的条目无效:它们仍受 deny floor 与你的 allow/deny 规则约束,自保护层也永远先行。全新安装会预填一份入门列表(todo、ask_user_question、memory_write、memory_search——来自项目 1265 条生产审计的观察) 注意:被豁免的工具失去分类器对 denyPaths 的存在性话术警戒(未覆盖工具本就不进路径提取器)
  • builtinDenyFloor: false 整体关闭内置危险/路径拦截(风险自担;下方自保护层永远开启)
  • classifierModel 指定分类器模型,如 "zai/glm-5.3-flash:low"(支持思考后缀;缺省 = 会话模型且显式关思考)
  • classifierModel: "typesafe/jev-latest" 启用随包的 jev 决策适配器——灰区裁决经 TypeSafe jev 完成(默认 OpenRouter,或 PI_VERDICT_JEV_TRANSPORT=typesafe 直连官方 API);实验性质,详见 ADR-0003
  • audit: true 把每次灰区裁决(发给分类器的完整转录、其原始响应、解析出的裁决)以 JSONL 记录到 ~/.pi/agent/verdicts/<sessionId>.jsonl——按会话一分文件,保留最近 20 个。交互式 ask 还会记录你的应答(userAnswer ground truth,确认结束后落盘),protected-path ask 也入审计(#62);规则 allow/deny 仍不入。仅存本机且全保真(受保护路径明文可能出现——永不出本机;ADR-0002 边界注);agent 对该目录读写双拒。开启时 /automode 会显示审计状态与路径
  • notifyAllows: true 对每次 classifier 放行发通知(reason + action 行——如 jev 的概率分解);默认 false 保持放行静默。机械放行(你自己的 allow 规则、protected-path 确认)永不通知;两开关同开时通知只出现一次
  • classifierMinConfidence(可选,ADR-0004)设定置信地板:低于它的 jev 裁决被降级——配置了 classifierFallbackModel 则级联(enforce,默认 = 第二层全权裁决,但降级的 deny 与 ask 永不被自动放宽为 allow——fail-closed 未产生任何裁决,其获救裁决照常生效;shadow = 只记录意见、由你裁决——/automode 会提示激活开关),否则直接问你。不低于地板时第一层自主。天然搭配:jev 打头 + haiku/flash 级兜底

没有内置白名单——每一条「永远放行」声明都归你(为什么)。完整参考:docs/configuration.md。

Jev 决策后端(实验性——ADR-0003)

  1. 安装含适配器的版本( v0.8 及以上): pi install npm:pi-verdict
  2. 选一条 transport(两条走同一 decisions wire 契约):
  • OpenRouter(默认): pi 内执行 /login openrouter,或 shell 里 export OPENROUTER_API_KEY=sk-or-v1...
  • TypeSafe 直连(官方 v1 API): 在 console.typesafe.ai 自助发 key,然后 export TYPESAFE_API_KEY=apikey_... 并 export PI_VERDICT_JEV_TRANSPORT=typesafe
  1. 把分类器指到 jev(新会话生效)
  • 持久:在 pi 之外编辑 ~/.pi/agent/config/pi-verdict.json 并设置 { "classifierModel": "typesafe/jev-latest" }
  • 或者临时试一把:PI_AUTO_MODE_MODEL=typesafe/jev-latest pi

限制:

  • Transport: OpenRouter decisions(默认)或 TypeSafe 直连——TypeSafe 侧单次成本显示 $0(其 API 不返回 cost)
  • 宿主:仅支持pi。omp 上该设置会警告并回退会话模型。也绝不能选作会话主模型(不生成文本,选中即警告)
  • 逃生口:PI_VERDICT_JEV_URL 可覆盖当前 transport 的端点(OpenRouter 侧为 alpha 接口)

jev 的校准 confidence 正是置信地板的判定依据——搭配第二层使用("classifierMinConfidence", "classifierFallbackModel"),让低置信调用交给更深的模型而非直接生效(ADR-0004)。

自保护(门禁守护自身——ADR-0001)

门禁自身的文件——配置与扩展安装副本——仅用户可改:门禁之内的写入一律硬 deny(读放行);你的编辑器修改不经门禁,最近的同构先例是 sudoers 必须经 visudo。

  • 不可经任何配置关闭——builtinDenyFloor: false 与用户 allow 规则都动不了这一层
  • 变更检测作纵深兜底:受保护文件在 session_start 快照、每次裁决前复核——扩展副本被改 → 自动还原 + 本会话 fail-closed;配置被改 → 一次明确的双选确认(差分处置的完整语义见 ADR-0001)

需要 pi ≥ 0.84。交互与非交互(-p/json/rpc)会话均支持;非交互模式下 ask 降级为 deny。


与品类对比

| | 三态裁决 | 分类器携带上下文 | fail 方向 | 运行时依赖 | |---|---|---|---|---| | pi-verdict | ✅ allow / ask / deny | ✅ 近期用户意图 + 工具调用 | closed(异常/超时/违约 → deny;非交互 ask → deny) | 0 | | @czottmann/pi-automode | 规则三态,分类器二态 | ✅ 预算化 transcript | closed | 1 | | @zhushanwen/pi-permission | ✅(outcome) | ❌ 单轮无上下文 | closed(→ ask) | 4 | | @gotgenes/pi-permission-system | ✅ 纯确定性 | —(无内置分类器) | closed | 3 |

完整全景:research/pi-permission-landscape.md · 与最近架构亲缘的收敛分析:research/pi-automode-convergence.md。

诚实地说:pi-automode 与 pi-verdict 在架构上已收敛(deny floor → 用户规则 → 分类器,fail-closed——见收敛分析)。这里仍然不同的是:分类器能说 ask(运行时人工介入,而非仅由规则预声明)、内置 floor 可以关(builtinDenyFloor——用户主权)、任何配置都关不掉的自保护层(ADR-0001——门禁完整性)、零依赖的可通读单文件(仍刻意单文件)、以及测量的习惯——本仓库每个设计决策都有随库研究背书。

管线

tool_call
  │
  ├─ 0. 自保护层(ADR-0001;不可经任何配置关闭)
  │     ├─ write/edit/bash 触碰门禁自身文件 → deny;读放行
  │     └─ 变更检测:每次裁决前复核 →
  │         自动还原 + fail-closed,或一次保留/还原确认
  │
  ├─ 1. 规则层(确定性,零延迟)
  │     ├─ 内置 deny floor:bash 危险正则 + 路径敏感度 S0–S5
  │     ├─ 用户规则:deny 优先于 allow
  │     ├─ denyPaths(ADR-0002):受保护路径 → 终局 ask,先于用户 allow;
  │     │   分类器只见存在性话术
  │     ├─ ignoreTools:用户声明的未覆盖工具 → 直接放行,零模型调用
  │     └─ 无内置白名单 —— 「永远放行」的声明由你自己做
  │
  ├─ 2. 灰区 → 模型分类器(默认继承会话模型 —— "自省")
  │     ├─ 输入:CC 风格 <transcript> —— 近期用户意图 + 工具调用,
  │     │        待审动作固定在末尾
  │     └─ 输出契约:<verdict>allow|ask|deny</verdict> 前缀锚定
  │
  └─ 3. 三态裁决
        ├─ allow → 放行
        ├─ deny  → 拦截,理由回传 agent
        └─ ask   → 人工确认;非交互模式降级为 deny

fail-closed:分类器异常 / 超时(25s)/ 输出违反契约 → 拦截,绝不静默放行。

证据驱动,不靠直觉

这里的设计决策用测量收敛,实验记录随仓库发布:

状态与限制

  • 设计上无内置白名单(见绕过测试与用户规则);allow 配置为空时大多数命令进分类器 —— 延迟敏感可 --auto-mode-model 指向轻量模型
  • 路径敏感度 floor 只作用于文件类工具:bash 命令串仅匹配危险正则——cat ~/.ssh/id_rsa 走分类器而非确定性 S0 拦截(文件工具拼写 read ~/.ssh/id_rsa 会拦截)
  • Windows 下内置 floor 仅覆盖 bash 形态模式——PowerShell 原生危险命令(Remove-Item -Recurse -Force、Invoke-Expression、Set-ExecutionPolicy 等)依赖分类器兜底(fail-closed)
  • AGENTS.md 未作为降权意图证据传入分类器(Claude Code 有此设计)
  • 并行灰区调用串行裁决
  • 自省意味着会话模型亲自裁决 —— 若延迟/成本敏感,用 --auto-mode-model 指向轻量模型(开放问题见 issue tracker)
  • denyPaths 的 bash 提取是 token 级(ADR-0002):命令替换、base64 内嵌路径、外部脚本内容不产生命中信号——这些调用回落到分类器的存在性话术警戒。MCP 与自定义工具完全绕过提取器(其灰区裁决仍带话术)。路径归一化亦为基础档(ADR-0002):经符号链接目录写入尚不存在的目标不重建真实形、不产生命中——该间接路径同样由话术警戒覆盖(祖先重建档只适用于自保护层与路径敏感度 floor,不适用 denyPaths)。诚实表述,与自保护子串正则同例:确定性层可被混淆——这正是命中交由你裁决而非静默决定的原因
  • denyPaths 的 bash token 不含空格:声明路径本身含空格时,bash 拼写无法被提取器识别——cat "/path with space/x" 被拆成两个 token 永不命中(文件类工具仍命中,其路径不经 token 化)。glob 覆盖基名末段(denyPaths: ["/proj/personal"] 时 cat /proj/pers*)同样漏过——基名自身从未字面出现。经 shell 发起的递归搜索在两种拼写下都漏过——不带路径参数(默认搜 cwd,如裸 rg foo)或带父目录参数(rg foo <声明路径的父目录>):无参命令根本不产生 token,带参时 bash token 只做单向比较;同一形状经 grep/find/ls 工具发起则由双向子树比较覆盖。三个洞与上述替换/base64 一样回落到分类器的存在性话术
  • 自保护 bash 匹配是子串正则——可被混淆绕过;变更检测兜底覆盖会话内绕过,跨会话基线(启动时哈希比对与变更确认,含升级 UX)按 ADR-0001 为二期
  • dev checkout(从仓库而非 <agentDir>/extensions/ 运行扩展)不受自保护——下一个正常会话加载的安装副本只在其自身会话的门禁内受保护

verdict 不是沙箱。 它在 pi 进程内裁决工具调用;不能遏制恶意代码、不能防护被攻陷的进程、不守护手工 ! shell 逃逸。需要隔离请用操作系统级沙箱。

命名:三态**裁决(verdict)**是核心概念。UX 保留 /automode —— 模式概念上溯 Claude Code 的 auto mode,本项目亦借鉴了其 transcript 设计。

开发

bun install
bun run typecheck
bun test          # 离线桩测试:自保护 / 变更检测 / deny floor / 用户规则 / denyPaths / 绕过回归 / 分类器重试 / 命令 / toggle 快捷键

Issue tracker 与决策记录在 GitHub issues(「地图」issue #1 为索引)。

许可

MIT