Skip to content

Hooks

Two hooks implement the engine. Both are installed to ~/.claude/leopold/hooks/ and wired into settings.json by install.sh. Both are no-ops unless a run is active, so they are safe to leave installed in every session.

stop-continuity.sh — the Stop hook

Runs when the agent finishes a turn. Contract: read JSON on stdin; print {"decision":"block","reason":"..."} to keep going, or exit 0 to allow the stop.

flowchart TD
    In["Stop event (JSON on stdin)"] --> Active{run active?}
    Active -- no --> Allow([exit 0 · allow stop])
    Active -- yes --> Kill{STOP file?}
    Kill -- yes --> Allow
    Kill -- no --> Budget{budget / failures hit?}
    Budget -- yes --> Allow
    Budget -- no --> Plan{open plan items?}
    Plan -- no --> Allow
    Plan -- yes --> Block["increment iteration ·<br/>block · re-inject continue"]

Fail-open: any unexpected error allows the stop. Continuity is best-effort; halting is always safe.

guard-irreversible.sh — the PreToolUse hook

Runs before every tool call. Contract: read JSON on stdin; print a hookSpecificOutput with permissionDecision: "deny" to block, or exit 0 to allow. It only adds denials; it never loosens Claude Code's own permissions.

See the policy table in Guardrails.

Settings wiring

{
  "hooks": {
    "Stop": [
      { "hooks": [ { "type": "command", "command": "~/.claude/leopold/hooks/stop-continuity.sh" } ] }
    ],
    "PreToolUse": [
      { "matcher": "Bash|Edit|Write|MultiEdit|NotebookEdit",
        "hooks": [ { "type": "command", "command": "~/.claude/leopold/hooks/guard-irreversible.sh" } ] }
    ]
  }
}

Event log

Both hooks append structured events to .leopold/events.jsonl (turn_start, stop, guard_block), which /leopold-status reads.