Skip to content

Claude Code hooks — the surface Argus runs on

Argus's capture and recall ride on Claude Code's hook system. This documents the hook events we rely on and can verify, how Argus uses each, and — separately, clearly quarantined — a set of additional events surfaced by 2026 web research that we could not confirm against authoritative docs and must verify before trusting.

Verification status (be honest about it): the events in §1 are confirmed by the Claude Code settings schema bundled with this CLI (the update-config reference) and by Argus's own working hooks. The events in the Appendix came from third-party blogs and a research subagent; treat them as leads, not facts, until checked against https://code.claude.com/docs/en/hooks.


1. Verified hook events

All hooks receive JSON on stdin and may return JSON on stdout. Common stdin fields: session_id, transcript_path, cwd, plus event-specific fields.

Output is wrapped in hookSpecificOutput (with hookEventName), plus top-level controls: continue (false to stop), stopReason, suppressOutput, decision ("block"), reason, and systemMessage (shown to the user).

Event Matcher Fires Key payload Can output
SessionStart startup\|resume\|compact session begins/resumes session_id, cwd, source additionalContext (injected into context)
UserPromptSubmit user submits a prompt the prompt text, session_id, cwd additionalContext (prepended), decision:block
PreToolUse tool name / mcp__srv__tool before a tool runs tool_name, tool_input permissionDecision (allow/deny/ask), permissionDecisionReason, updatedInput
PostToolUse tool name after a tool succeeds tool_name, tool_input, tool_response additionalContext, decision:block
PostToolUseFailure tool name after a tool fails tool_name, tool_input, error additionalContext
PermissionRequest tool name / rule before the permission prompt tool_name, tool_input permissionDecision
Notification notification type Claude emits a notification type, message suppressOutput
Stop Claude finishes a response session_id, transcript_path decision:block (force continue)
PreCompact auto / manual before context compaction transcript_path, trigger feedback; additionalContext
PostCompact auto / manual after compaction the compacted summary additionalContext
SessionEnd session ends session_id, transcript_path (output ignored)

Hook types (the type field)

  • command — runs a shell command; stdin JSON in, stdout JSON out. The default, most versatile; what every Argus hook uses. Supports timeout, async variants.
  • prompt — asks Claude (LLM) a yes/no; slow, non-deterministic. Tool events only.
  • agent — spawns a subagent to decide/verify; powerful, expensive. Tool events only.

Exit codes (command hooks)

  • 0 — success; parse stdout as JSON.
  • 2 — blocking error; stderr becomes the reason Claude sees.
  • other — non-blocking; logged, execution continues.

2. How Argus uses them

Argus deliberately uses a small, append-NDJSON, fail-loud set — matching the 2026 best practice (capture = no LLM on the hot path; never exit 0 silently on failure). Wired per machine in settings.json via thin wrappers in ~/.argus/bin/ that source ~/.argus/env (URL + ARGUS_CAPTURE_TOKEN) and exec the real binary.

Hook Argus wrapper Binary What it does
Stop argus-capture-hook capture-hook Capture the just-finished turn(s) → POST /capture
SessionEnd argus-capture-hook capture-hook Final capture of the session tail
PreCompact (auto) argus-capture-hook capture-hook Capture before compaction discards turns
SessionStart (startup\|resume\|compact) argus-recall-hook recall-hook -mode=context Inject project + global durable facts (deterministic, importance-ranked)
UserPromptSubmit argus-recall-hook -mode=prompt recall-hook Hybrid recall against the prompt; inject top-5 (gated: system-turn → substance → floor)

Why these and not more: capture needs the turn text (Stop/SessionEnd) and the pre-compaction window (PreCompact). Recall needs session start (SessionStart) and each user query (UserPromptSubmit). PreToolUse/PostToolUse-style capture is deliberately NOT used — tool I/O is noise for a decision/knowledge memory, and capturing it was a source of the system-turn noise we just gated out.

Reliability contract: every hook is fail-open for the session but loud on stderr — a memory hiccup can never block or pollute a session, but it never fails silently either (the anti-pattern the research explicitly named). The recall hook prints nothing to stdout and exits 0 on any problem; the capture hook logs the error.

Verify a hook is firing: for the cron-driven monitor tick the log is ~/tdarr-monitor-cron.log; for the Argus hooks, the proof is data — raw_items rows appearing per session (capture) and injections rows appearing per recall (recall). A machine whose hooks aren't installed shows no rows from that host.


3. Hook config locations & precedence

settings.json merges across scopes (later overrides earlier, but hooks accumulate): managed → user (~/.claude) → project (.claude) → local (.claude/*.local.json) → plugin → session. View active hooks with /hooks. Argus's hooks live in the user scope (the dotfiles claude/settings.json, symlinked by install.sh), so they apply across every project on a machine.


Appendix — UNVERIFIED events (do not trust without confirming)

A 2026 research subagent (sourcing third-party blogs) listed ~27 hook events. The ones not in §1 are listed here unconfirmed. Several look plausible (newer releases add events), but some smell invented (e.g. an identity_status: ALIVE/WEAK/SILENT PostCompact field appears to come from one specific blog/project, not Anthropic). Verify against the official hooks reference before building on any of these.

Claimed-but-unverified events: Setup, UserPromptExpansion, PostToolBatch, PermissionDenied, StopFailure, SubagentStart, SubagentStop, FileChanged, CwdChanged, ConfigChange, WorktreeCreate/WorktreeRemove, InstructionsLoaded, Elicitation/ElicitationResult, TaskCreated/TaskCompleted/TeammateIdle.

Claimed-but-unverified hook types: http (POST to an endpoint), mcp_tool (call an MCP tool directly). An HTTP hook type, if real, would be a cleaner transport for Argus than the wrapper-binary pattern — worth confirming; it would let capture/ recall POST straight to argus-mem.aaronbrazier.com without a local binary.

Claimed-but-unverified payload field names (the research used user_message, assistant_message, tool_output, compacted_summary, etc.; the authoritative schema uses tool_input/tool_response and a prompt field — confirm exact names before parsing them).

Action item if this matters: spend 10 minutes against the official docs to promote the real ones into §1 and delete the rest. Until then, §1 is the trustworthy set.