用 hooks.json 给会话和工具调用挂上自定义拦截规则
29.9/100
综合分
0
GitHub 星标
—
npm 周下载
—/5
用户评分
数据截至 2026/10/25 · 周下载取自 npm 全网(含 CI / 镜像),非本站安装数;综合分由星标、活跃度与兼容性检查合成。
安装命令 · 需先装 dsh CLI 引擎
dsh plugin --profile web add hongjunt50-afk/dsh-hooks该包不可直接 npm 安装,改从 GitHub 源安装(明细见下方安装检查)
状态速览
判定依据:实装验证 · 静态安装检查 · 自动扫描 · 仓库维护状态信任档位:仅索引
是什么
dsh 原生插件 · security
装得上吗
本站尚未做安装检查
安全吗
本站尚未对该插件做风险分级
暂未覆盖,不等同于无风险
还在维护吗
活跃:最近一次提交在 7 天前
档位由哪些信号合成
本站实装验证(真实安装 L4 覆盖全站;L5 为运行时冒烟或实机截图,覆盖范围小于 L4) · 验证所用 dsh 版本 · 静态安装检查 · 风险分级 · 仓库维护状态。 下方各区块是它的证据明细。
社区实装还没有人打卡 · 装过的第一个就是你
安全扫描自动 · 静态分析源码v2.7.0🔵 扫描:含敏感能力尚无人工评估展开查看扫描说明与证据 ↓
安全扫描自动 · 静态分析源码
v2.7.0静态扫描发现插件具备触达本地系统的能力:执行外部命令、读写/删除本地文件、读取剪贴板或密钥类环境变量(至少其一)。这是能力清单,不是危险判定——具体能力项与证据见下方,安装前请自行判断是否需要。
可执行外部命令读写/删除本地文件发起外部网络请求
查看扫描证据(共 28 处,展示前 26 条)
- 读取本地文件lib/index.js:132
if (!file || !existsSync(file)) return {} - 读取本地文件lib/index.js:135
raw = JSON.parse(readFileSync(file, 'utf8')) - 读取本地文件lib/index.js:167
return candidates.find((p) => existsSync(p)) ?? '' - 执行外部命令来自配置/变量lib/index.js:180
child = spawn(entry.command, { - 读取本地文件lib/index.js:377
if (!configFile || !existsSync(configFile)) return 'missing' - 读取本地文件lib/index.js:378
const st = statSync(configFile) - 读取本地文件lib/index.js:716
const text = existsSync(configFile) ? readFileSync(configFile, 'utf8') : '' - 写入本地文件lib/index.js:735
if (!existsSync(dir)) mkdirSync(dir, { recursive: true }) - 写入本地文件lib/index.js:737
writeFileSync(tmp, text, 'utf8') - 写入本地文件lib/index.js:738
renameSync(tmp, configFile) - 发起网络请求client.js:104
const res = await fetch(API + qs, { headers: { accept: 'application/json' } }) - 发起网络请求client.js:111
const res = await fetch(API, { - 读取本地文件_client_smoke.mjs:61
const src = readFileSync(new URL('./client.js', import.meta.url), 'utf8') - 读取本地文件_doc_test.mjs:24
const src = readFileSync(new URL('./client.js', import.meta.url), 'utf8') - 写入本地文件_smoke.mjs:59
writeFileSync(file, source, 'utf8') - 写入本地文件_smoke.mjs:67
writeFileSync( - 删除本地文件递归_smoke.mjs:245
rmSync(dir, { recursive: true, force: true }) - 读取本地文件_sync_test.mjs:3
const src = readFileSync('lib/index.js', 'utf8') - 写入本地文件_sync_test.mjs:22
writeFileSync(configFile, JSON.stringify({ hooks: { - 读取本地文件_sync_test.mjs:29
if (!configFile || !existsSync(configFile)) return 'missing' - 读取本地文件_sync_test.mjs:30
const st = statSync(configFile) - 写入本地文件_sync_test.mjs:58
writeFileSync(configFile, JSON.stringify({ hooks: { - 写入本地文件_sync_test.mjs:69
writeFileSync(configFile, '{ broken json', 'utf8') - 删除本地文件_sync_test.mjs:76
unlinkSync(configFile) - 写入本地文件_sync_test.mjs:82
writeFileSync(configFile, JSON.stringify({ hooks: { Stop: [{ command: 'node b.mjs' }] } }), 'utf8') - 删除本地文件_sync_test.mjs:86
unlinkSync(configFile)
扫描于 2026/10/31(1 天前) · 范围 入口闭包 + 发布文件清单 · 来源 GitHub 仓库
静态扫描只反映源码中出现的调用,不构成安全背书;人工评估与自动扫描相互独立、互不覆盖。
给这个插件打分还没有人投票↓
用户评分
还没有人投票,来当第一个
README
由 DeepSeek 最新模型翻译生成@dsh-external/dsh-hooks
给 DeepSeek Harness 补上通用钩子能力:用 Claude Code 风格的 hooks.json 声明「什么事件 → 跑哪个命令」,插件负责投喂 JSON、解析退出码与 stdout 决策,再把结果翻译成 DSH 的原生动作。
同一个钩子脚本,Claude Code 和 DSH 都能直接跑,不用改一行。
为什么需要它
DSH 有完整的拦截缝隙(工具调用前后、每个 step、回合收尾),但没有 Claude Code 那种「外部命令式」钩子——想加一条「禁止递归删除」「改完文件提醒跑测试」「收尾前自省」的小规则,就得写一个 Cordis 插件。这个包把那层胶水补上,规则退化成几行脚本。
展开完整文档(README 剩余 1 节)
@dsh-external/dsh-hooks
给 DeepSeek Harness 补上通用钩子能力:用 Claude Code 风格的 hooks.json 声明「什么事件 → 跑哪个命令」,插件负责投喂 JSON、解析退出码与 stdout 决策,再把结果翻译成 DSH 的原生动作。
同一个钩子脚本,Claude Code 和 DSH 都能直接跑,不用改一行。
为什么需要它
DSH 有完整的拦截缝隙(工具调用前后、每个 step、回合收尾),但没有 Claude Code 那种「外部命令式」钩子——想加一条「禁止递归删除」「改完文件提醒跑测试」「收尾前自省」的小规则,就得写一个 Cordis 插件。这个包把那层胶水补上,规则退化成几行脚本。
事件映射
| hooks.json 事件 | DSH 原生事件 | 能做什么 |
| SessionStart | agent/created | 注入 |
| UserPromptSubmit | agent/pre-step | 注入 / 拦下这条提示 |
| PreToolUse | tools/pre-execute | 放行 / 拒绝工具调用 |
| PostToolUse | tools/post-execute | 注入 |
| Stop | agent/turn-stopping | 注入(带次数上限,防自锁) |
安装
dsh plugin install /path/to/dsh-hooks
或直接放进配置档:
git clone <this repo> ~/.dsh/profiles/desktop/node_modules/@dsh-external/dsh-hooks
并在 ~/.dsh/profiles/desktop/cordis.patch.yml 里加上:
- insert:
- id: dsh-hooks
name: "@dsh-external/dsh-hooks"
config:
configFile: "F:/AI/hooks/hooks.json"
配置
{
"hooks": {
"PreToolUse": [
// 字符串 = 只要命令 "node /abs/path/guard.mjs", // 对象 = 完整写法 { "matcher": "pwsh|shell", // 正则匹配工具名,空或 "" 表示全部 "command": "node /abs/path/guard.mjs", "timeoutMs": 10000, // 默认 30000 "cwd": "F:/AI" // 默认进程 cwd } ] } }
插件配置项:
| 键 | 默认 | 说明 |
| configFile | 自动探测 | 配置文件路径(绝对,或相对进程 cwd) |
| hooks | — | 内联配置,同名事件替换文件配置 |
| disabled | false | 置 true 则完全不注册监听 |
| stopBlockLimit | 1 | 同一轮最多被 Stop 拦几次,防死循环 |
| debug | false | 每次派发打印一行结果到日志 |
没配 configFile 时按顺序找第一个存在的:
1. $DSH_HOME/hooks/hooks.json
2. ~/.dsh/hooks/hooks.json
3. <cwd>/.dsh-hooks.json
所以最常见的情况什么都不用配,把 hooks.json 放到 ~/.dsh/hooks/ 就行。
配置支持热重载:在设置页里增删启停或保存会立刻生效;用外部编辑器改文件,下次打开设置页(或任何一次 GET)会自动发现 mtime/size 变化并重读,也不用重启。
外部改坏了 JSON 时会保留上一份能用的配置继续跑,只在页面上报错,不会让钩子集体失效。
界面
装上之后有两处 UI:
① 消息下方工具栏的 🪝
每条助手消息底部的复制/点赞那排里会多一个 🪝。存过钩子运行记录的消息上它高亮,点开就是这个会话里触发过的钩子列表:事件名、命令、耗时、退出码、被注入或拦下的结果。
浮层用 position: fixed 定位,不会被子消息容器裁掉。
② 设置 → 钩子
五个事件一张卡,每张卡下面逐条列钩子,每条能单独停用(○/●)或删除(✕),底部「+ 添加钩子」填命令、匹配工具、超时就能加。改动即时落盘生效,没有单独的保存按钮。
页面下方是配置文件原文编辑器,保存前校验 JSON,写坏不会落盘。
两个界面都走 /dsh-hooks-api(只监听回环地址)。
命令契约
与 Claude Code 一致:
| 情况 | 含义 |
| stdin | 一行 JSON,含 hook_event_name / session_id / cwd 及事件字段 |
| exit 0 + stdout JSON | 决策对象(见下) |
| exit 0 + stdout 纯文本 | 当作要注入的上下文 |
| exit 2 | 阻断,stderr 作为理由 |
| 其他非零 | 非阻断错误,只记日志 |
决策对象的三种写法(都支持):
// 1. 新式:按事件给专用字段 { "hookSpecificOutput": { "additionalContext": "注入的文本" } } { "hookSpecificOutput": { "permissionDecision": "deny", "permissionDecisionReason": "理由" } }
// 2. 旧式:通用阻断 { "decision": "block", "reason": "理由" }
// 3. 通用叫停 { "continue": false, "stopReason": "理由" }
各事件收到的字段:
| 事件 | payload 附加字段 |
| SessionStart | source:startup / resume / clear / compact |
| UserPromptSubmit | prompt |
| PreToolUse / PostToolUse | tool_name、tool_input;Post 另带 tool_response: { isError, text } |
| Stop | stop_hook_active(true = 这次是拦截后重入) |
安全边界
- 钩子输出视为不可信数据:注入时包上下界声明,并 {{ → { {(宿主 system prompt 做变量插值,裸 {{ 会让整轮请求 throw)。
- 子代理会话不跑钩子,避免委派指令污染上下文、重复计费。
- 失败不冒泡:命令不存在、超时、非零退出都只记日志,绝不影响会话。
- Stop 有上限:默认同一轮最多拦 1 次,钩子写错不会死循环。
- 零宿主 import:只依赖 node: 内置模块,宿主升级不会因 @deepseek-ai/ 路径变化而炸。
示例
examples/ 下五个可直接用的脚本,覆盖全部五个事件:
- greet.mjs — SessionStart 注入固定约定
- recall.mjs — 用户提到关键词时补上下文
- guard-danger.mjs — 拦 rm -rf /、git push --force、DROP TABLE
- after-edit.mjs — 改完文件提醒跑校验
- stop-nudge.mjs — 收尾前自省提醒
examples/hooks.json 是配套配置模板。
自检
node _smoke.mjs # 18 项:五个事件、全部决策分支、防自锁、子代理隔离、转义容错
node _client_smoke.mjs # 13 项:client 半边的槽位注册与渲染结构
node _doc_test.mjs # 23 项:配置文本解析与往返保真
node _sync_test.mjs # 10 项:外部改配置的指纹检测与坏文件降级
四个脚本都不依赖宿主,直接 node 跑。_smoke.mjs 用 mock 的 ctx 走通五个事件,断言注册了几个监听、每个决策分支返回什么。
lib/index.js(Host 半边)改完要重启桌面端。client.js(UI)通常不用:宿主有 client 侧的 bundle 热重载通道,实测改完 client.js 等几秒刷新界面即生效。
若发现改动没出现,重启桌面端一定解决。
与官方桥接包的区别
官方有 @deepseek-ai/dsh-hooks-claude-code(同思路,更完整)。这个包是和它独立发展的最小实现,差别在:
- 零宿主 import(官方包 import 了 @deepseek-ai/cordis / dsh-llm / dsh-hook-protocol,在 profile 下可能解析不到)
- 同时支持新旧两套决策协议
- Stop 内置次数上限
如果你的环境能正常解析那些包,用官方包更省事;如果装不上,这个包是替代品。
许可
MIT预览分享卡片长什么样 ↓
分享 · DeepSeek Harness Hub
hongjunt50-afk/dsh-hooks
用 hooks.json 给会话和工具调用挂上自定义拦截规则
相关插件 · 安全 / 权限
智能体逆向工程morluto/rea
用智能体逆向工程任何东西,从应用行为到原生二进制。
★ 415,267已汉化DSH
73.3
智能体集群框架ruvnet/ruflo
面向 Claude Code 与 Codex 的智能体元基座meta-harness。
★ 80,414已汉化MCP
71.9
WorkBuddy 模型接入corrinehu/dsh-workbuddy-connect
2026 年 10 月 20 日起,WorkBuddy…
★ 1,604已汉化DSH
71.7
破甲一键通z91772524-ai/pojia-next
十五个 AI…
★ 967已汉化DSH
71.6
AI 代理虚拟终端strukto-ai/mirage
Mirage 是给 AI 智能体用的虚拟终端:一层 shell,统管数据、命令行和运行时。Unix…
★ 3,756已汉化DSH
70.8
Agent 操作层agentic-os-org/ANOLISA
ANOLISA(Agentic Nexus Operating Layer & Interface System Architecture)|智能体操作系统,带运行时、安全、可观测性,以及 Tokenless 响应压缩,降低 token 用量与成本。
★ 649已汉化DSH
70.7