description: "Run your existing Codex hooks.json hook config during agent runs — block prompts and tools, attach context, or force continuation — for users and maintainers of the bridge."
English | 中文
dsh-hooks-codex runs command hooks from an existing Codex hooks.json during agent runs, so prompt and tool gates work without being rewritten. It supports five Codex hook points: session start, prompt submission, before and after tool execution, and stop. Hooks can block prompts or tool calls with model-visible reasons, add conversation context, or force another agent step. Choose this package to reuse Codex command hooks in the harness; use a native plugin for behavior outside this supported subset.
Mount this package, point configPath at your hooks.json, and the hooks you already have start firing at the corresponding moments in agent runs. There is nothing else to set up before the first hook works.
Use it when you own a Codex hooks.json and its command hooks should gate prompts, tools, and turns. Skip it for behavior with no Codex equivalent: a native plugin has the full harness API, while this bridge runs only the reference tool's command-hook subset.
- name: '@deepseek-ai/dsh-hooks-codex'
config:
configPath: ./.codex/hooks.json
model: deepseek-v4
| Field | Default | Meaning |
|---|---|---|
configPath |
required | Path to a Codex hooks.json |
model |
'' |
Model name stamped on every payload (Codex includes model on each event) |
defaultTimeoutMs |
600,000 |
Per-hook timeout when a hook sets none (the Codex default) |
stderrSummaryMaxChars |
500 |
Character cap on the persisted hook/result stderr summary |
The generated configuration catalog is the exhaustive source for every accepted field.
| Your hook | When it runs | What it can do |
|---|---|---|
SessionStart |
when a session starts | attach context the model sees in that session |
UserPromptSubmit |
when the agent receives a prompt | block the prompt, or attach extra context |
PreToolUse |
before a tool runs | block the tool |
PostToolUse |
after a tool runs | block the result with feedback, or attach extra context |
Stop |
when the run is about to stop | force another step with a reason |
pwd and relative paths in your hooks refer to your project, not the server's launch directory.configPath resolves from the directory that launched the process.async: true or non-command hook is skipped with a warning.Read these pages when the package-level contract is not enough. They move from the shared protocol to the bridge design and the extension points it programs against.
SessionStart, accepted prompt, and post-tool hooks can add source-attributed context messages; a blocking Stop hook adds its reason as next-step steering.
No cost when hooks return no context. Hook text is data-dependent, logged, and resent in later conversation requests until compaction.
Append-only; newly visible content follows the reusable request prefix and does not invalidate existing KV-cache entries.
Provider-supplied reasons pass through verbatim. When absent, a denied tool becomes Error: blocked by PreToolUse hook, blocked post-tool feedback is exactly blocked by PostToolUse hook, and a blocking stop adds steering exactly continue: blocked by Stop hook; a blocked prompt is discarded with no model-visible message, ending the turn as blocked. Codex systemMessage is not surfaced.
Blocking a prompt removes that prompt's request tokens; denial or feedback adds the retained fallback or provider text; forced continuation pays another full request.
A blocked prompt sends no request and invalidates nothing. Denial, feedback, and forced-continuation context append after the reusable prefix without rewriting it.
These limits describe what your Codex hooks cannot do through this bridge yet, and where behavior differs from the reference tool. They are current package constraints, not a task backlog.
PermissionRequest, PreCompact, PostCompact, SubagentStart, and SubagentStop. Config for these events is silently dropped during parsing. The comparison baseline is Codex's official hook reference.SessionStart is partial — plain stdout and JSON additionalContext work, but the hook runs detached, so context can miss the first request.UserPromptSubmit is partial — blocking plus plain-stdout or JSON context work, but the common systemMessage and {"continue": false} controls are not enforced.PreToolUse is partial — blocking works, but additionalContext, permissionDecision: "allow", and updatedInput are ignored. Every tool is represented as tool_input: { command }, so non-shell tool arguments are not faithfully exposed to the hook.PostToolUse is partial — blocking feedback and JSON additionalContext work, but {"continue": false} is not enforced, non-shell tool arguments are reduced to { command }, and structured tool output is flattened to text in tool_response.Stop is partial — blocking forces another model turn, but stop_hook_active is always false, last_assistant_message is always null, and {"continue": false} is not enforced. An unconditionally blocking hook therefore force-continues every step unless it self-limits.model and permission_mode: "default" instead of current Codex runtime values, and transcript_path is never populated: it is always null, because the persistence seam exposes no artifact paths and the default-zstd session log is not readable by hook scripts. systemMessage is logged + warned but not surfaced, and {"continue": false} is recorded but does not apply Codex's event-specific stop behavior.configPath is parsed at load; Codex's active user, project, session, system/managed, and plugin layers, trust controls, and inline config.toml hook form are not implemented. Only synchronous command handlers run, current metadata such as statusMessage and commandWindows is ignored, and matching handlers run serially rather than with Codex's concurrent launch semantics.