DeepSHPlugins
hooks-adapter 项目预览
GITHUB / COMMUNITY PROJECT

hooks-adapter

生态与开发JavaScriptMIT

把 Claude Code、Codex、opencode 配置里声明的 hooks 原样复用到 dsh,执行 shell、webhook、oracle、proxy 四类 handler,零运行时依赖。

2 StarsJohnXu22786 更新时间 2026-08-17
访问 GitHub 仓库
hooks-adapter 项目预览

项目介绍

中文

把 Claude Code、Codex、opencode 配置里声明的 hooks 原样复用到 dsh,执行 shell、webhook、oracle、proxy 四类 handler,零运行时依赖。

English

Reuses hooks declared in Claude Code, Codex and opencode configs on dsh, executing shell, webhook, oracle and proxy handlers with zero runtime dependencies.

项目信息与收录信号

快照 2026-09-11
作者 / 组织
JohnXu22786
仓库
JohnXu22786/hooks-adapter
GitHub Stars
2
Forks
0
开发语言
JavaScript
许可证
MIT
最近推送
2026-08-17
Manifest
数据中检测到声明

公开仓库不自动等于可商用;许可证与当前兼容性以原项目文档为准。Manifest 和数据评分不构成安装安全认证。

数据评分

54/ 100
维护活跃
83
文档与实用信息
85
生态关注度
14
安装便捷信号
75
项目声明信号
100

README 含完整安装与使用说明;关注度尚低(2)。

评分来自已有数据快照的五维模型,仅作浏览参考,不是实际使用评测或安全检测结论。

安装与使用

所有项目资料与许可均以对应 GitHub 仓库为准。

dsh plugin --profile web add github:JohnXu22786/hooks-adapter

复制命令不会自动执行。请先阅读仓库文档,确认环境要求与许可证。

项目截图

仓库 README

GitHub 原文

已保存的仓库文档快照;文档抓取时间未记录,可能与上方目录介绍处于不同版本。安装前请核对当前仓库说明。

简体中文

hooks-adapter

A hooks configuration compatibility layer for DeepSeek Harness (dsh): it reads existing hooks config files from mainstream agent harnesses (such as the hooks declarations in .claude/settings.json, .codex/hooks.json, and the hooks section of opencode.json), maps their lifecycle events to dsh extension points, and executes four kinds of handlers — shell / webhook / oracle / proxy — so the same hooks config can be reused as-is across different harnesses.

  • Zero runtime dependencies (Node ≥ 18, pure ESM + JSDoc types)
  • Config is read-only, not migrated: your existing hooks declarations stay unchanged
  • All four handler kinds supported: command execution, HTTP callbacks, LLM evaluation, subagent delegation
  • Timeout control, failure degradation policy, and friendly config validation (validate subcommand)
  • Three integration modes: dsh plugin (Cordis apply), stdio JSON-lines protocol (any host), one-shot CLI
hooks-adapter/
├── package.json        # dsh bundle manifest (dsh.bundle + exports)
├── cordis.patch.yml    # composite package layer: inserts this plugin into the plugin tree
├── dsh/plugin.js       # dsh entry: Cordis plugin (name + apply(ctx, config))
├── lib/                # runtime core (usable independently of dsh)
│   ├── index.js        # CLI entry + programmatic API exports
│   ├── events.js       # canonical event catalog + four-dialect mapping table + matcher semantics
│   ├── discover.js     # config file discovery (global/project/local)
│   ├── parse.js        # four-dialect parsers (all go through diagnostics, never throw)
│   ├── config.js       # runtime assembly: merging, disableAllHooks, defaults
│   ├── contract.js     # stdin JSON contract construction + response decoding + decision folding
│   ├── execute.js      # four-kind handler executor + timeout + process tree cleanup
│   ├── dispatch.js     # dispatch pipeline: matcher matching, ordered execution, blockable constraints
│   └── serve.js        # stdio JSON-lines protocol server
├── docs/               # config formats, event mapping, contract, integration notes, CLI guide
├── examples/           # four-dialect example configs + local mock LLM
└── test/               # node:test tests (111 items)

What It Can Do

Declare hooks in .claude/settings.json (no matter which harness you wrote them for) and they keep working in dsh:

{
  "hooks": {
    "PreToolUse": [
      {
        "matcher": "Bash",
        "hooks": [
          { "type": "command", "command": "guard.sh", "timeout": 10 }
        ]
      }
    ],
    "Stop": [
      { "hooks": [ { "type": "command", "command": "notify-send done" } ] }
    ]
  }
}

Config files must be strict JSON (no comments); see examples/ for complete four-dialect examples.

  • PreToolUse → interception point before tool execution: handler exit code 2 / JSON decision: "block" will block the tool call (or turn it into ask for human confirmation)
  • PostToolUse / PostToolUseFailure → after tool execution (mutually exclusive triggers): reject the write-back as result feedback, append context
  • UserPromptSubmit / SessionStart / Stop / SubagentStart / SubagentStop / SessionEnd → inject context, reject prompts, force the model to continue
  • Notification / PreCompact → triggered manually or via the stdio protocol

The four handler kinds (the type field in config follows each harness's conventions; normalized internally):

Config typeInternal kindBehaviorDefault timeout
commandshellspawn a shell process, feed the JSON contract on stdin600s
httpwebhookPOST JSON to a URL, the response body is the decision600s
promptoraclecall an LLM endpoint to evaluate, {ok:false} rejects30s
agent / subagentproxydelegate to a subagent runner (configurable command)60s

Quick Start

Mode one: dsh plugin (recommended)

# From a directory containing this plugin checkout
dsh plugin --profile demo add ./hooks-adapter
dsh --profile demo

After loading, the plugin automatically discovers hooks configs in project and user directories (see below). You can also override the config line in the profile's cordis.patch.yml:

- replace:
    - id: hooks-adapter
      config:
        configPath: /abs/path/to/hooks.json   # pin a single file (skip discovery)
        discover: false
        llm: { baseUrl: "https://api.example.com/v1", model: "eval-small" }
        proxy: { command: "dsh run --quiet" }

Integration details: docs/INTEGRATION.md.

Installing in DSH

Install directly from the GitHub repository with the dsh plugin command:

dsh plugin --profile demo add github:JohnXu22786/hooks-adapter

The package is a dsh bundle (dsh.bundle.patch → cordis.patch.yml); once added, it inserts itself into the plugin tree and automatically discovers hooks configs on the next dsh run. Remove it with:

dsh plugin --profile demo remove hooks-adapter

Mode two: stdio protocol (any host)

echo '{"op":"ping"}' | node lib/index.js listen --config hooks.json
echo '{"op":"dispatch","event":"PreToolUse","payload":{"tool_name":"Bash","tool_input":{}}}' | node lib/index.js listen

Protocol details: docs/CONTRACT.md.

Mode three: one-shot CLI

node lib/index.js validate            # check all discoverable configs, exit code 0/1
node lib/index.js run --event PreToolUse --payload payload.json
node lib/index.js dump                # print the merged effective config
node lib/index.js list                # list discovered config files

Where the Config Comes From

Auto-discovered and merged in order (later files append groups for same-named events; disableAllHooks follows the most specific file):

OrderFileDialect
1~/.claude/settings.jsonclaude
2~/.codex/hooks.jsoncodex
3~/.config/opencode/opencode.jsonopencode
4~/.config/hooks-adapter/hooks.jsonnative
5<project>/.claude/settings.jsonclaude
6<project>/.codex/hooks.jsoncodex
7<project>/opencode.jsonopencode
8<project>/.dsh-hooks.jsonnative
9<project>/.claude/settings.local.jsonclaude
  • Environment variables HOOKS_ADAPTER_CONFIG (same as --config) and HOOKS_ADAPTER_HOME (same as --home)
  • Any missing file is silently skipped; if an existing file has issues, it only produces diagnostics, it never blocks startup
  • Config file format details: docs/CONFIG.md

Event Mapping

Every harness's event names map to a set of canonical events (session:start, tool:before, ...), which then bind to dsh extension points:

Canonical eventclaude dialectcodex dialectopencode dialectdsh extension point
session:startSessionStartSessionStartsession.createdagent/session-start
session:endSessionEndSessionEndsession.deletedsession/disposed
prompt:submitUserPromptSubmitUserPromptSubmitchat.messageagent/pre-step
tool:beforePreToolUsePreToolUsetool.execute.beforetools/pre-execute
tool:afterPostToolUse / PostToolUseFailurePostToolUsetool.execute.aftertools/post-execute
turn:stopStopStopsession.idleagent/turn-stopping
subagent:startSubagentStartSubagentStarttool.execute.before.subagentsubagent/start
subagent:endSubagentStopSubagentStoptool.execute.after.subagentsubagent/end
noticeNotificationNotificationnotificationmanual / stdio
compact:beforePreCompact—experimental.session.compactingmanual / stdio

Full semantics (blockability, matcher rules, payload fields): docs/EVENTS.md.

Contract

  • stdin JSON: session_id, transcript_path, cwd, hook_event_name, permission_mode + event fields (tool_name/tool_input/tool_use_id/tool_response/prompt/source ...)
  • Exit codes: 0 = allow (when stdout is JSON, the decision is parsed from it); 2 = block (stderr is the reason); any other non-zero = non-blocking error
  • stdout JSON: decision, continue/stopReason, systemMessage, hookSpecificOutput.permissionDecision (allow/deny/ask), additionalContext, updatedInput; oracle answers {ok: true|false, reason}
  • Multi-hook folding: deny > ask > allow; any continue:false stops; context accumulates in hook order
  • Details and the stdio protocol: docs/CONTRACT.md

Testing

node --test

(The default test-discovery mode runs all 111 tests; helper scripts live in test-support/ and are not mistaken for tests.)

License

Released under the MIT License.

使用前核对

安装步骤、兼容版本与授权范围以原项目当前文档为准。Stars 和评分是快照中的导航信号。

安装与排错 · 项目问题反馈

同类项目