II.
Page JSON
Structured · livepage:docs-agent-mux-tutorials-hooks
Hooks json
Inspect the normalized record payload exactly as the atlas UI reads it.
{
"id": "page:docs-agent-mux-tutorials-hooks",
"_kind": "Page",
"_file": "wiki/docs/agent-mux/tutorials/hooks.md",
"_cluster": "wiki",
"attributes": {
"nodeKind": "Page",
"sourcePath": "docs/agent-mux/tutorials/hooks.md",
"sourceKind": "repo-docs",
"title": "Hooks",
"displayName": "Hooks",
"slug": "docs/agent-mux/tutorials/hooks",
"articlePath": "wiki/docs/agent-mux/tutorials/hooks.md",
"article": "\n# Hooks\n\nHooks let you observe and intercept agent activity at well-defined points without modifying the adapter.\n\n## Lifecycle points\n\n| Hook | Fires |\n| ------------- | ------------------------------------------------------ |\n| `PreToolUse` | Before a tool call is dispatched. Can deny or rewrite. |\n| `PostToolUse` | After a tool call returns. Can annotate or redact. |\n| `Stop` | When the run terminates (done, error, or cancelled). |\n\nThe set mirrors Claude Code's native hooks; agent-mux normalizes them across adapters.\n\n## Registering\n\n```ts\nawait client.run({\n agent: 'claude',\n prompt: 'Do stuff',\n hooks: {\n PreToolUse: async (ctx) => {\n if (ctx.tool === 'Bash' && /rm -rf/.test(ctx.input.command)) {\n return { decision: 'deny', reason: 'destructive command' };\n }\n return { decision: 'allow' };\n },\n PostToolUse: async (ctx) => {\n console.log('[tool]', ctx.tool, ctx.durationMs, 'ms');\n },\n Stop: async (ctx) => {\n console.log('[done]', ctx.reason);\n },\n },\n});\n```\n\nCLI users can register hooks via `~/.amux/hooks/*.js` or per-project `.amux/hooks/`. Run `amux hooks list` to see what's active.\n\n## Virtual hooks\n\nAdapters whose underlying CLI doesn't natively expose hooks get **virtual hooks**: agent-mux interposes in the event stream and fires the same `PreToolUse` / `PostToolUse` handlers based on parsed `tool_call_start` / `tool_call_result` events. The effect is best-effort — denial may arrive after the call has already been issued.\n\nAdapters with native hook support (e.g. Claude Code) get real interception.\n\n## Return shape\n\n```ts\ntype HookDecision =\n | { decision: 'allow' }\n | { decision: 'deny'; reason: string }\n | { decision: 'rewrite'; input: unknown };\n```\n\nSee [Hooks reference](../reference/15-hooks.md) for the full context object and examples.\n",
"documents": []
},
"outgoingEdges": [],
"incomingEdges": []
}