Bundle
dsh-hooks-pack
One-click Claude Code & Codex hooks for DeepSeek Harness: auto-discovers your existing hooks config and runs it on the harness interception points via the official bridge plugins
- Source
- chenzhi-clude
- stars
- 1 stars
- License
- MIT
- Updated
- Updated 5 days ago
Readme
# dsh-hooks-pack
One-click **Claude Code & Codex hooks** for [DeepSeek Harness](https://github.com/deepseek-ai/deepseek-harness).
Already have a `hooks.json` from Claude Code or Codex? Install this pack and those hooks run inside DSH — no code, no config editing. No hooks yet? Copy the bundled starter pack and you have dangerous-command guarding plus a full tool-call audit log in one minute.
The heavy lifting is done by the official bridge plugins (`@deepseek-ai/dsh-hooks-claude-code`, `@deepseek-ai/dsh-hooks-codex`, shared protocol `@deepseek-ai/dsh-hook-protocol`). This pack adds what a manual setup is missing:
1. **Auto-discovery** — probes the standard locations for your existing hook configs.
2. **One row** — a single bundle mounts both dialects on the host plane.
3. **Safe idle** — with no config found anywhere it registers nothing; installing never changes agent behavior by itself.
## Install
From the plugin market UI: search **dsh-hooks-pack** → install.
Or with the CLI:
```sh
dsh plugin --profile web add github:REPLACE_ME/dsh-hooks-pack
# or from npm once published:
dsh plugin --profile web add dsh-hooks-pack
```
Restart the profile (or reload the web app) afterwards.
## What gets discovered
| Dialect | Probed locations (first hit wins) |
|---|---|
| Claude Code | `$CLAUDE_CONFIG_DIR/hooks.json` → `~/.claude/hooks.json` → `~/.claude/settings.json` (only if it has a `hooks` key) |
| Codex | `$CODEX_HOME/hooks.json` → `~/.codex/hooks.json` |
Explicit paths win over discovery:
```yaml
# your profile's cordis.patch.yml
- id: hooks-pack
name: dsh-hooks-pack
config:
claude:
configPath: D:/my-hooks/claude-hooks.json
codex:
configPath: D:/my-hooks/codex-hooks.json
```
## Supported hook points
Via the official bridges (command hooks only):
- Claude Code dialect: `SessionStart`, `UserPromptSubmit`, `PreToolUse`, `PostToolUse`, `Stop`, `SubagentStart`, `SubagentStop`
- Codex dialect: `PreToolUse`, `PostToolUse`, `SessionStart`, `UserPromptSubmit`, `Stop`
`deny` / `ask` decisions, blocking feedback, and `additionalContext` injection all work; see each bridge README for the exact per-event payload and output contract.
## Hook output format
Decisions must use Claude Code's **structured** form — top-level `permissionDecision` is ignored:
```json
{
"hookSpecificOutput": {
"hookEventName": "PreToolUse",
"permissionDecision": "deny",
"permissionDecisionReason": "blocked by policy X"
}
}
```
`hookEventName` must name the firing event (`PreToolUse`, `SessionStart`, …) or the event-scoped fields are discarded. Exit code 2 also blocks, with stderr as the reason.
## Starter pack
`examples/claude-hooks.example.json` ships two ready-made hooks:
- **guard-dangerous** (`PreToolUse` on shell tools): blocks `rm -rf`, force pushes, `Remove-Item -Recurse -Force`, disk formatting, fork bombs, …
- **audit-log** (`PostToolUse` on everything): appends every tool call to `~/.dsh-hooks-audit.jsonl`
Enable them:
```sh
# 1. copy the examples somewhere stable
xcopy /E /I <profile-node-modules>\dsh-hooks-pack\examples %USERPROFILE%\dsh-hooks-examples\
# 2. point your hooks file at it
copy %USERPROFILE%\dsh-hooks-examples\claude-hooks.example.json %USERPROFILE%\.claude\hooks.json
# 3. edit that file, replacing <ABS-PATH> with %USERPROFILE%\dsh-hooks-examples
```
## Config reference
| Key | Type | Default | Meaning |
|---|---|---|---|
| `executionMode` | string | `direct` | Hook execution backend: `direct` = in-process spawn (cmd.exe /c on Windows, /bin/sh -c elsewhere) with full user rights, matching Claude Code semantics, one log line per invocation; `shim` = legacy `ctx.shell` + sandboxPolicy shim (only for special requirements) |
| `auditFile` | string | — | Optional absolute path of an append-only audit file; one line per hook invocation (timestamp / exit code / duration / command head) |
| `autoDiscover` | boolean | `true` | Probe standard locations when no explicit path is given |
| `claude.configPath` | string | discovered | Explicit Claude Code config file |
| `claude.pluginRoot` | string | — | Replaces `${CLAUDE_PLUGIN_ROOT}` in commands |
| `claude.projectDir` | string | session cwd | Replaces `${CLAUDE_PROJECT_DIR}` and sets the env var |
| `claude.defaultTimeoutMs` | number | 600000 | Per-hook timeout when the hook sets none |
| `codex.configPath` | string | discovered | Explicit Codex config file |
| `codex.model` | string | — | Model name stamped on Codex payloads |
## v0.1.1 critical fix: silent no-op on Windows
**Symptom**: the plugin loads fine, config looks right, the host boots — but hooks never execute. Guards stop guarding, audit lines never appear, and nothing errors anywhere.
**Root cause**: the protocol runner executes every hook through the sandboxed shell chain behind `ctx.shell`, folding ANY executor failure into a neutral "allow" (fail-open). On some Windows deployments that chain never manages to spawn the user's hook command ⇒ every hook silently no-ops.
**Fix**: a new `direct` execution backend, now the default — the command string is spawned in-process, bypassing the sandbox/shell resolution chain entirely. Spawn failures are reported as stderr text and logged instead of being swallowed as throws; every invocation logs `hooks-pack[direct]: exit=N duration :: command-head`, with optional persistent `auditFile`. Component tests in `examples/test/test-direct-shell.mjs` cover 5 behaviors (execute / stdin passthrough / timeout kill / ENOENT must-not-throw / audit).
**Upgrade**: run `dsh plugin --profile web add <this-package-path>` and restart the host (link installs follow workspace code automatically). Set `executionMode: 'shim'` to restore the old behavior.
## Known limitations
Inherited from the official bridges: only shell-form command hooks run (`http`/`mcp_tool`/`prompt` handlers are skipped with a warning); config is read once at process load, so project-local `hooks.json` per-session discovery is not available yet; some newer Claude Code events are not mapped. See the bridges' READMEs for the complete lists.
In `direct` mode Windows runs commands through cmd.exe — complex quoting of embedded double quotes is limited exactly like Claude Code on Windows; put complex logic into a `.cmd`/`.mjs` file and invoke it instead.
## Compatibility
Tested against DeepSeek Harness `0.1.0-rc.7` with bridge packages `0.1.0-rc.7`. The dependency range also accepts `0.1.1-rc.1` for newer deployments.
## License
MIT
Install
dsh plugin --profile web add github:chenzhi-clude/dsh-hooks-pack
Profile: web
With the hub plugin installed, ask your agent to install it by name — it resolves the same plan shown here.
dsh plugin --profile web add github:stvlynn/dsh.fish#path:packages/dsh-plugin-hub
install dsh-hooks-pack from the hub
- This source has no pinned commit, so a later push upstream changes what installs. Prefer pinning a commit.