前言¶
在 DeepSeek Harness(DSH)里,很多流程需要挂在具体事件上:工具调用前拦截、工具调用后记录、用户提交时补检查、会话开始或结束时写状态。若这些逻辑散落在各个脚本里,后续排查和迁移都会比较麻烦。
dsh-hooks-plugin 提供 Claude Code 风格的 hooks:在智能体 / 工具生命周期事件上运行 shell 命令,配置来自 .dsh/hooks.json。
这是什么¶
dsh-hooks-plugin 由 KYinCode 维护,采用 MIT 许可证。它为 DSH 增加一个 hooks 入口,让开发者在项目、预设或全局层面配置事件响应命令。
核心定位如下:
在 DSH 的 agent / tool 生命周期事件上运行 shell 命令;
配置使用 .dsh/hooks.json;
JSON 结构延续 Claude Code hooks 形状。
核心功能¶
四层配置¶
hooks 配置按目录生命周期管理,支持四层来源:
全局:~/.dsh/hooks.json
预设:<preset-dir>/hooks.json
项目:<项目根>/.dsh/hooks.json
项目本地:.dsh/hooks.local.json
项目配置改动后会自动重新加载,不需要重启。
v1 接线事件¶
v1 实际接线以下事件:
PreToolUse
PostToolUse
PostToolUseFailure
UserPromptSubmit
SessionStart
SessionEnd
Stop
SubagentEnd
其中 PreToolUse 支持通过 stdout 输出 deny 决策。deny 时会出现官方工具失败卡片,模型会看到类似这样的内容:
Error: <reason>
hook 类型与字段¶
v1 实现 command 与 http 型 hook;prompt / agent 型 hook v1 不做。
hook 公共字段包括:
if
timeout
statusMessage
once
command 型可配置:
command
shell
async
asyncRewake
http 型可配置:
url
headers
allowedEnvVars
配置结构使用 matcher[] + hooks[]:
{
"<Event>": [
{
"matcher": "<模式>",
"hooks": []
}
]
}
子代理触发¶
子代理默认会触发 hooks,输入载荷会携带:
agent_id
agent_type
delegation_depth
如果需要关闭子代理触发,可以配置:
{
"subagents": false
}
热重载与热升级¶
项目配置改动会自动重新加载,无需重启。
如果安装了 dsh-hot-installer,升级插件后可以免重启当场生效:
dsh plugin --profile web add dsh-hooks-plugin@<新版本>
最近记录与日志¶
每条 hook 记录会写入最近记录文件:
recent.jsonl
默认限 200 条,可用环境变量调整:
DSH_HOOKS_RECENT_MAX
文件日志位于:
~/.dsh/logs/dsh-hooks/dsh-hooks.log
默认超过 1 MiB 自动滚动,可用环境变量调整:
DSH_HOOKS_MAX_LOG_BYTES
最近记录接口:
GET /dsh-hooks/recent
安装与启用¶
npm 安装:
dsh plugin --profile web add dsh-hooks-plugin
若使用本地 tarball,可先打包,再把生成的 tarball 交给 dsh 安装:
npm pack
dsh plugin --profile web add ./<npm pack 生成的 dsh-hooks-plugin tarball>
安装后新会话自动生效;已有存活会话也会生效。进程重启后继续旧会话,会随 agent 重建自动重新接线。
插件对运行环境有 peerDependencies 要求:
{
"peerDependencies": {
"@deepseek-ai/cordis": "^4.0.1",
"@deepseek-ai/dsh-shell": "^0.1.0-rc.6",
"@deepseek-ai/dsh-subprocess": "^0.1.0-rc.6",
"react": "^18.2.0"
}
}
典型用法¶
在工具调用前触发命令¶
在项目根创建:
<项目根>/.dsh/hooks.json
示例配置如下:
{
"PreToolUse": [
{
"matcher": "Read|Write|Edit",
"hooks": [
{
"type": "command",
"command": "echo hook triggered",
"timeout": 5
}
]
}
]
}
这条配置会在 Read、Write、Edit 工具调用前运行:
echo hook triggered
用 PreToolUse 对私有路径 deny¶
示例中对 Read 事件配置条件过滤:
{
"PreToolUse": [
{
"matcher": "Read",
"hooks": [
{
"type": "command",
"command": "node -e \"process.stdout.write(JSON.stringify({hookSpecificOutput:{hookEventName:'PreToolUse',permissionDecision:'deny',permissionDecisionReason:'blocked'}}))\"",
"if": "Read(*private*)",
"timeout": 5
}
]
}
]
}
当 Read 命中 *private* 条件时,hook 通过 stdout 输出 deny 决策。PreToolUse 决策 deny 时,会出现官方工具失败卡片,模型会看到 Error: <reason>。
命令 hook 的 stdin / stdout¶
命令 hook 从 stdin 读取单行 JSON 输入。常见字段包括:
{
"session_id": "...",
"cwd": "...",
"hook_event_name": "PreToolUse",
"tool_name": "read",
"tool_input": {
"path": "..."
},
"tool_use_id": "..."
}
如果是子代理触发,还会包含:
{
"agent_id": "...",
"agent_type": "...",
"delegation_depth": 0
}
命令 hook 通过 stdout 输出 JSON 决策。hookSpecificOutput 可包含:
{
"hookSpecificOutput": {
"hookEventName": "PreToolUse",
"permissionDecision": "deny",
"permissionDecisionReason": "blocked",
"additionalContext": "..."
}
}
开发验证与查看¶
运行测试:
node --test test/
查看文件日志:
~/.dsh/logs/dsh-hooks/dsh-hooks.log
查看最近记录:
GET /dsh-hooks/recent
安装后可以先加载自动注册技能:
skill dsh-hooks-authoring
深度配置查看安装包内文档:
docs/CONFIGURATION.md
适用场景与注意¶
适合以下场景:
在工具调用前做拦截或检查;
在工具调用后做审计、记录或后续动作;
在会话开始、结束、用户提交等事件上运行固定流程;
为项目、预设或全局配置不同层级的 hooks;
在 DSH 中保持 Claude Code hooks 风格的 JSON 配置体验。
需要注意:
hooks 会执行 shell 命令,会以当前 dsh 进程权限运行;
安装前应检查源码与 MIT 许可证;
配置的生命周期等于它所在目录的生命周期;
若某预设报 Cannot find package,通常需手动移除对应行或删除预设目录;
v1 不做 prompt / agent 型 hook;
parseHookConfig 会拒绝未知类型;
不做卸载生命周期、悬空行提醒、会话级配置档、PreCompact / PostCompact、设置页;
不注入 CLAUDE_PROJECT_DIR、CLAUDE_PLUGIN_ROOT 等 CC 专属环境变量;
不做 ${CLAUDE_PLUGIN_ROOT}、CLAUDE_PLUGIN_OPTION_*、CLAUDE_ENV_FILE 等机制。
DSH 内部决策直接消费 waterfall 返回值。stdout JSON 是命令 hook 表达决策的协议手段,不是按 Claude Code 输出解析。
链接¶
社区目录页(独立站点,不等同于 DeepSeek 或幻方的官方应用商店):
https://www.skillhub.cn/plugins/KYinCode/dsh-hooks-plugin
GitHub:
https://github.com/KYinCode/dsh-hooks-plugin