审查并批准钩子脚本,按轮查看运行与拦截统计
30.7/100
综合分
1
GitHub 星标
—
npm 周下载
—/5
用户评分
数据截至 2026/10/30 · 周下载取自 npm 全网(含 CI / 镜像),非本站安装数;综合分由星标、活跃度与兼容性检查合成。
安装命令 · 需先装 dsh CLI 引擎
dsh plugin --profile web add matata2017/dsh-codex-hooks该包不可直接 npm 安装,改从 GitHub 源安装(明细见下方安装检查)
状态速览
判定依据:实装验证 · 静态安装检查 · 自动扫描 · 仓库维护状态信任档位:仅索引
是什么
dsh 原生插件 · chat
装得上吗
本站尚未做安装检查
安全吗
本站尚未对该插件做风险分级
暂未覆盖,不等同于无风险
还在维护吗
活跃:最近一次提交在 5 天前
档位由哪些信号合成
本站实装验证(真实安装 L4 覆盖全站;L5 为运行时冒烟或实机截图,覆盖范围小于 L4) · 验证所用 dsh 版本 · 静态安装检查 · 风险分级 · 仓库维护状态。 下方各区块是它的证据明细。
社区实装还没有人打卡 · 装过的第一个就是你
安全扫描自动 · 静态分析源码v2.7.0🔵 扫描:含敏感能力尚无人工评估展开查看扫描说明与证据 ↓
安全扫描自动 · 静态分析源码
v2.7.0静态扫描发现插件具备触达本地系统的能力:执行外部命令、读写/删除本地文件、读取剪贴板或密钥类环境变量(至少其一)。这是能力清单,不是危险判定——具体能力项与证据见下方,安装前请自行判断是否需要。
可执行外部命令读写/删除本地文件
查看扫描证据(共 25 处,展示前 22 条)
- 读取本地文件lib/core.js:407
if (!path || !existsSync(path)) return { version: STATE_FILE_VERSION, states: {} } - 读取本地文件lib/core.js:408
return parseStateFile(readFileSync(path, 'utf8')) - 写入本地文件lib/core.js:416
mkdirSync(dirname(path), { recursive: true }) - 写入本地文件lib/core.js:423
writeFileSync(temporary, `${JSON.stringify(payload, null, 2)}\n`, 'utf8') - 写入本地文件lib/core.js:424
renameSync(temporary, path) - 读取本地文件lib/core.js:427
if (existsSync(temporary)) rmSync(temporary, { force: true }) - 删除本地文件lib/core.js:427
if (existsSync(temporary)) rmSync(temporary, { force: true }) - 读取本地文件lib/core.js:589
const text = readFileSync(path, 'utf8') - 读取本地文件lib/core.js:598
if (!existsSync(modulesDir)) return [] - 读取本地文件lib/core.js:602
if (existsSync(candidate)) found.push(candidate) - 执行外部命令固定命令lib/events.js:135
spawn('taskkill', ['/pid', String(child.pid), '/T', '/F'], { windowsHide: true }).unref() - 写入本地文件lib/events.js:187
writeFileSync(inPath, input, 'utf8') - 删除本地文件递归lib/events.js:197
rmSync(dir, { recursive: true, force: true }) - 执行外部命令来自配置/变量lib/events.js:208
child = spawn(command, { - 读取本地文件lib/events.js:247
stdout = readFileSync(outPath, 'utf8') - 读取本地文件lib/events.js:252
stderr = readFileSync(errPath, 'utf8') - 删除本地文件递归lib/events.js:257
rmSync(dir, { recursive: true, force: true }) - 写入本地文件lib/events.js:266
appendFileSync(errPath, String(error?.message ?? error), 'utf8') - 写入本地文件lib/events.js:276
appendFileSync(errPath, note, 'utf8') - 执行外部命令来自配置/变量lib/events.js:312
child = spawn(command, { - 写入本地文件lib/events.js:422
mkdirSync(dir, { recursive: true }) - 写入本地文件lib/events.js:425
writeFileSync(file, content, 'utf8')
扫描于 2026/11/3(0 天前) · 范围 入口闭包 + 发布文件清单 · 来源 GitHub 仓库
静态扫描只反映源码中出现的调用,不构成安全背书;人工评估与自动扫描相互独立、互不覆盖。
给这个插件打分还没有人投票↓
用户评分
还没有人投票,来当第一个
展开完整介绍(128 字)↓
为 DeepSeek Harness 提供 Codex 风格的钩子管理:从配置、插件和项目读取 hooks.json,每个钩子绑定一个 sha256 指纹,你批准后才会运行;输入框里有审核对话框,还有 Hooks 设置页、/hooks 命令和每轮运行统计。
README
由 DeepSeek 最新模型翻译生成dsh-codex-hooks
把 CODEX 的钩子管理方式移植到 DeepSeek Harness(dsh)。
CODEX 里每条钩子都有:一次审查、钉在指纹上的一次批准、设置页、/hooks 浏览器,还有运行统计。dsh 一样都没有——它只暴露拦截 seam,其余全空。这个插件把这一整套管理搬过来,于是 dsh 上的钩子也能按 CODEX 那套审查、批准、单独关掉、看运行情况。
配置文件是 dsh 自己的(hooks.json + dsh 事件名)——移植的是围绕钩子的那套行为,不是 CODEX 的文件格式。
English: README.md
截图
审查就发生在干活的地方:输入框工具栏一个钩子图标,有待审核时右上角一个红点:
输入框工具栏的钩子图标,待审核时红点
点开就是审查弹窗:一条钩子一行,带新建徽标,chevron 展开细节,底部以后再说 / 全部允许 / 允许所选项:
审查钩子弹窗
其余都在 设置 → Hooks 里管:按来源分组,每条带信任状态、启用开关、信任/撤销和一次性的测试:
设置页里的钩子列表、信任状态与操作
单次运行的明细在消息操作行后面。钩子统计弹窗只读一轮、标明是哪一轮,列出这一轮的执行,底部是本会话累计——没有轮次下拉,它只回答你点开它的那条消息。
展开完整文档(README 剩余 1 节)
dsh-codex-hooks
把 CODEX 的钩子管理方式移植到 DeepSeek Harness(dsh)。
CODEX 里每条钩子都有:一次审查、钉在指纹上的一次批准、设置页、/hooks 浏览器,还有运行统计。dsh 一样都没有——它只暴露拦截 seam,其余全空。这个插件把这一整套管理搬过来,于是 dsh 上的钩子也能按 CODEX 那套审查、批准、单独关掉、看运行情况。
配置文件是 dsh 自己的(hooks.json + dsh 事件名)——移植的是围绕钩子的那套行为,不是 CODEX 的文件格式。
English: README.md
截图
审查就发生在干活的地方:输入框工具栏一个钩子图标,有待审核时右上角一个红点:
输入框工具栏的钩子图标,待审核时红点
点开就是审查弹窗:一条钩子一行,带新建徽标,chevron 展开细节,底部以后再说 / 全部允许 / 允许所选项:
审查钩子弹窗
其余都在 设置 → Hooks 里管:按来源分组,每条带信任状态、启用开关、信任/撤销和一次性的测试:
设置页里的钩子列表、信任状态与操作
单次运行的明细在消息操作行后面。钩子统计弹窗只读一轮、标明是哪一轮,列出这一轮的执行,底部是本会话累计——没有轮次下拉,它只回答你点开它的那条消息。每次运行都归属于触发它的那一轮,和 CODEX 把运行绑在 turn id 上一样:匹配是精确的,日志里没有的那一轮——包括宿主重启前编号的那些——就显示 0 并给出提示,绝不拿别的轮的数字顶替。轮次只在当前会话里解析,别的会话的同名轮次不会顶替。轮次由你点的那条消息决定:收尾的那条消息精确对应它所属的那一轮,正在进行中的那一轮的消息就回答那一轮:
钩子统计弹窗:运行、拦截、失败与这一轮的执行历史
截图取自本地运行的 dsh,钩子就是 ~/.dsh/hooks.json 里那两条 echo-hook —— 和本仓库示例用的是同一份配置。
兼容性
| 插件版本 | 验证过的 dsh |
| 0.5.x | dsh 0.1.0-rc.6(开发与自测宿主,web 与 desktop) |
更新的 dsh 版本没有验证过:插件读的是 dsh 的插槽、命令与远程方法契约,宿主改掉其中任何一个,插件在跟进之前就会坏。
客户端这一半绑在四个 dsh 客户端包上 —— @deepseek-ai/dsh-client-locale、@deepseek-ai/dsh-client-ui-settings、@deepseek-ai/dsh-client-ui-commands、@deepseek-ai/dsh-client-ui-chat。前三个随 profile 一起装;dsh-client-ui-chat 提供 conversation.chat.turnTail 插槽,「点哪条消息就看哪一轮」靠的就是它,有些安装里它只存在于应用自带的 node_modules。如果消息上的钩子按钮不显示轮次,缺的就是这个包。
它到底做了什么
- 发现三个来源的 hooks.json,界面上分组显示:
- 来自配置 —— $DSH_HOME/hooks.json(默认 ~/.dsh/hooks.json)。
- 来自插件 —— 当前 profile 里自带 hooks.json 的每个包。
- 来自项目配置文件 —— 本会话碰过的 workspace 里的 <workspace>/.dsh/hooks.json(最多记 32 个)。
- 指纹:把钩子定义规范化成 JSON,再对它 UTF-8 字节做 sha256:。信任就钉在这个指纹上,所以改掉一条钩子的命令,它的信任会自动失效,不会悄悄跑新代码。
- 逐个审查信任:新钩子处于待审核;你在设置页批准当前指纹,状态存在 $DSH_HOME/hooks.state.json,同时每条钩子有独立的启用开关。
- 执行:只有既启用又可信的 command 处理器才会跑,带自己的超时、cwd、环境变量,以及 command/commandWindows 平台拆分。同一事件的同步钩子会并行启动,与 Codex 一致;结果和注入上下文仍按配置顺序合并。approval/request 钩子可以返回 {"decision":"allow"} 直接放行待审批的工具调用,或返回 deny;任何一条钩子 deny 都压过 allow。
- 注入上下文:处理器返回的 additionalContext 会追加到模型输入,适用于 agent/pre-step、tools/pre-execute、tools/post-execute、agent/created(默认上限 2500 字符)。
- 匹配:工具类 seam(tools/pre-execute、tools/post-execute、approval/request)支持 matcher:、精确名、A|B 多选或正则。
事件
| 事件 | 何时触发 | 可拦截 |
| agent/pre-step | 用户提交提示、步骤开始之前 | 可以 |
| agent/request | 模型请求发出之前 | 不可以 |
| tools/pre-execute | 工具调用执行之前 | 可以 |
| tools/post-execute | 工具调用结束之后 | 可以 |
| approval/request | 工具调用向用户申请权限之前 | 可以 |
| agent/created | 会话开始 | 不可以 |
| agent/turn-stopping | 本轮响应结束之前 | 不可以 |
| session/disposed | 会话销毁 | 不可以 |
默认超时 600 秒;session/disposed 例外(默认 1 秒,最多 3 秒),免得退出时卡住。
审查、运行记录与 /hooks
- 输入框工具栏的钩子图标 —— 输入框工具栏(权限/专家控件旁边)有一个钩子图标,待审核时右上角只有一个红点、不带数字(数字一被别处信任就会过期);点它打开审查钩子弹窗:每条钩子一行,带复选框、名称、新建徽标和 chevron,展开是来源 / Hook 类型 / 命令 / 超时;底部提示「你可以稍后在 设置 → 钩子 里更改此选项」(纯文字,dsh 没有给插件打开设置页的接口,所以不假装能跳);三个按钮是以后再说 / 全部允许 / 允许所选项。点工具图标就打开,不自动弹。批准即把当前指纹钉进 $DSH_HOME/hooks.state.json;其余情况到 设置 → Hooks 里逐个处理。
- /hooks 打开钩子浏览器 —— 第一页按事件列出 生效/已安装 计数,待审核的事件行尾带 !;第二页列出该事件的处理器,带信任状态、启用开关和信任/撤销按钮。它是标准的 dsh 斜杠命令(宿主组合了 commands 服务时注册),不会发给模型。
- 消息操作行的钩子图标 → 钩子统计弹窗 —— 助手消息的操作行有一个钩子图标,点开是统计弹窗。与 CODEX 一致,每次运行都归属触发它的那一轮,所以弹窗一次只看一轮(运行 / 拦截 / 失败,慢钩子运行中另有 运行中 计数),并标明是哪一轮,底部是本会话累计。没有轮次切换器:弹窗就回答你打开它的那条消息。运行历史列表只列这一轮的运行(形如 Completed agent/pre-step User);弹窗打开期间每 1.5 秒刷新一次。钩子输出不会打印进对话,模型只会看到处理器的 additionalContext。运行记录只放在内存里,不落盘——重载即清空,与 CODEX 相同(它的 HookStarted/HookCompleted 通知同样是瞬态的)。会话级视角看 /hooks。点某条消息就打开它所在的那一轮:DSH 给动作行插槽的只有 messageId,所以另在 conversation.chat.turnTail 上挂了一个不绘制的伴随渲染——它拿得到完整的 TurnLocation,且比同一轮的动作行先渲染——记下每条消息属于哪一轮,弹窗据此打开;认不出的消息回落到当前轮。与 CODEX 有一处刻意的差别:agent/pre-step 在 agent 循环的每一步之前触发({ turn, step }),不是每提交一次提示触发一次,所以一条 agent/pre-step 钩子在一轮里会随每次模型调用各跑一次——这就是一轮里能看到多次运行的原因;只想每轮跑一次的钩子设 firstStepOnly: true。
- 试跑 —— 设置页的测试*会用样例输入把一条钩子跑一次,报告 通过/拦截/失败 和耗时;未批准的钩子拒绝试跑。
- 浮层:所有面板都用 portal 渲到 document.body 上并固定定位,不会被输入框或消息列裁掉。
自动放行一次工具调用
approval/request 钩子可以自己决定待审批的那次调用:
{
"hooks": {
"approval/request": [{ "command": "node examples/approval-allow.mjs", "timeout": 10 }]
}
}
钩子打印 {"decision":"allow"} 就是放行这一次;打印 {"decision":"deny","reason":"…"} 是拒绝;什么都不打印就交回正常的审批提示。任一钩子 deny 压过别的钩子的 allow。
examples/approval-allow.mjs 只放行 APPROVAL_ALLOW_TOOL 指定的那个工具——把什么都放行的钩子,等于把你装钩子本来想收紧的那道提示给拆了。
安装
需要 dsh 0.1.0-rc.6 或更新版本,Node 20+。
从 GitHub
dsh plugin --profile desktop add github:matata2017/dsh-codex-hooks
或者本地开发目录,本项目就是这么用的
dsh plugin --profile desktop add /path/to/dsh-codex-hooks
装完重启 dsh 的 web/desktop 宿主,然后打开 设置 → Hooks。
配置
~/.dsh/hooks.json:
{
"version": 1,
"description": "my hooks",
"hooks": {
"agent/created": [
{
"command": "node ./examples/echo-hook.mjs agent/created",
"commandWindows": "node.exe ./examples/echo-hook.mjs agent/created",
"timeout": 15,
"statusMessage": "echo-hook: session started"
}
],
"tools/pre-execute": [
{
"matcher": "Bash",
"command": "node ./examples/echo-hook.mjs"
}
]
}
}
一条钩子一个对象:command(或 type: "mcp_tool" 加 server + tool),可选 matcher、timeout、statusMessage、additionalContextLimit、async、firstStepOnly。
firstStepOnly(仅 agent/pre-step):agent/pre-step 在一轮的每一步之前都会触发,设为 true 后这条钩子每轮只在第一步(带用户消息的那一步)运行,后续步骤连进程都不启动,统计弹窗里一轮也只记一次。适合只关心用户这条消息的钩子(记忆召回、提示改写等)。该字段计入信任哈希,加上之后要重新信任一次;不写或写 false 时哈希与以前相同。
处理器类型:只有 command 会被执行。mcp_tool、prompt、agent 可以解析、可以审查,但暂不派发——它们显示为“已安装”而不是“生效”,宁可说清楚,也不要让一条钩子静默地什么都不做。
验证状态
- node test/run-tests.mjs → 99 passed, 0 failed, 0 skipped。
- node selftest/host-e2e.mjs → 对着真实 profile 跑 20 passed, 0 failed。
- agent/pre-step 在真实 dsh 会话里跑通(前提是钩子已被信任):示例钩子每跑一步打印一行 echo-hook received event=…(它在 agent 循环的每一步之前触发,所以一次提示可能打印多行)。未信任的钩子不会执行,必须先在审查弹窗或「设置 → 钩子」里批准。
这里做不到的事
下面几条是 dsh 的边界,不是我们没写:需要一个宿主没开放的接缝。CODEX 有这些,dsh 没有,所以移植到这里为止。
- 上下文只能以 user 角色注入:agent/pre-step 收的是 UserMessage[],也没有对外的「追加 developer 消息」接口,所以 additionalContext 拿不到 developer 消息那种分量。
- 改不了工具入参:tools/pre-execute 只能 allow / deny / ask / cancel,dsh 明确排除入参改写(参数已经记日志并展示给用户)。
- 压缩、中断、模型请求这三类事件没有接缝,最接近「压缩后」的只有 agent/created 的 source: "compact"。
- mcp_tool、prompt、agent 处理器可以审查但不会执行,所以它们永远不会显示为生效。
安全
钩子以 dsh 进程的权限执行真实命令。所以信任钉在每条钩子的 sha256 指纹上:批准一条钩子=批准这一行具体的命令,任何改动都要重新批准。只启用你读过的钩子。
批准是稳的。信任状态先写临时文件再改名覆盖正式文件,写到一半被打断也不会留下半个文件让下一次读取失败;而那个会落到「刚刚替换掉它的按钮」上的点击会被忽略——刚给的信任不会在一秒后自己撤销。
License
MIT预览分享卡片长什么样 ↓
分享 · DeepSeek Harness Hub
matata2017/dsh-codex-hooks
审查并批准钩子脚本,按轮查看运行与拦截统计
相关插件 · 对话 / 记忆
上下文中枢oceanbase/powercontext
上下文跟着工作走 —— 跨会话、跨智能体、跨人。
★ 1,487已汉化DSH
73
智能体记忆库plastic-labs/honcho
Honcho 是记忆基础设施,用来构建有状态的智能体。这些智能体能理解不断变化的人、智能体、群组、项目和想法。
★ 7,894已汉化DSH
71.7
长程智能体控制面loopx-project/loopx
给 Agent 一个目标,让工作持续向前。
★ 6,358已汉化DSH
71.3
智能体上下文数据库volcengine/OpenViking
给 AI 智能体用的上下文数据库
★ 41,379已汉化DSH
71.3
长效机器人团队Fei2411/DS-Bot
DS Bot 是一个基于 DeepSeek Harness简称 dsh的 bot 插件,插件将 dsh 改造为 bot…
★ 5,084已汉化DSH
71.1
可携带记忆层EverMind-AI/EverOS
为什么选择 EverOS
★ 13,778已汉化DSH
71.1
这是你的仓库?认领条目