# LazyClaude Hooks

LazyClaude hooks translate the LazyClaude prompt workflow into Claude Code hook
events while keeping execution local and bounded.

## Hook Events

| Event | Runner | Purpose |
| --- | --- | --- |
| `SessionStart` | `plugins/lazyclaude/bin/lazyclaude-hook.js session-start` | Adds a compact rules-loaded context line. |
| `UserPromptSubmit` | `plugins/lazyclaude/bin/lazyclaude-hook.js user-prompt-submit` | Detects ultrawork prompts and injects workflow context. |
| `PostToolUse` | `plugins/lazyclaude/bin/lazyclaude-hook.js post-tool-use` | Reminds the session to run post-edit checks. |
| `PostCompact` | `plugins/lazyclaude/bin/lazyclaude-hook.js post-compact` | Resets compacted rule context after summarization. |

## ULW Trigger Phrases

The `UserPromptSubmit` hook activates on any of these phrases:

```text
ulw
ultrawork
$ulw-plan
/ulw-plan
/lazyclaude:ulw-plan
$ulw-loop
/ulw-loop
/lazyclaude:ulw-loop
$start-work
/start-work
/lazyclaude:start-work
```

When a trigger is present, the hook returns additional context containing
`ULTRAWORK MODE ENABLED` and a visible `LazyClaude ULW hook active` system
message. That context is guidance for Claude Code; it is not executed as a
command. The guidance tells Claude to treat plain `ulw` as
`/lazyclaude:ulw-loop` / `Skill(ulw-loop)` semantics before ordinary task
execution.

LazyClaude follows the LazyClaude goal pattern as model-facing run context, not
as slash-command injection. If Claude Code exposes the native goal surface, the
guidance tells Claude to inspect `get_goal`, call `create_goal` only when no
matching goal is active, and delay `update_goal` until verified completion or a
genuine blocker. It may also point Claude toward the user-visible `/goal`
surface, but it does not auto-type `/goal` or send slash command text.

If goal tools are unavailable or not exposed in the running Claude Code session,
the hook context keeps the local evidence ledger authoritative. It may suggest
`/goal <completion condition>` before long execution, but it should not repeat
fallback chatter on every ULW turn.

For broad work, the same context ports the LazyClaude model-facing principle to
Claude Code's exposed orchestration surfaces: if `Workflow` is available, call
the `Workflow` tool before serial execution and bind every lane to evidence and
cleanup. If isolated edits need a model-facing worktree lane, use
`EnterWorktree`; when only the CLI surface is available, the actionable launch
form is `claude --worktree <short-name> --tmux`.

Plain `ulw` therefore activates hook context, not a visible Skill tool call.
For a visible LazyClaude command/skill invocation, use the namespaced Claude
Code commands. The shorter slash aliases above are also recognized by the prompt
hook so they route to the same discipline instead of falling through to plain
`ulw` loop activation:

```text
/lazyclaude:ulw-loop <goal>
/lazyclaude:ulw-plan <planning brief>
/lazyclaude:start-work plans/lazyclaude-retrofit.md
```

These are real Claude Code command files in `plugins/lazyclaude/commands/`.

## Safety

Hooks parse JSON from stdin and return JSON to Claude Code. The hook does not
execute prompt text and does not echo prompt text into the returned context. The
ultrawork detector returns constant workflow guidance, so a prompt cannot become
a shell command through the hook response.

## Local Smoke

Run the hook fixture directly:

```bash
node plugins/lazyclaude/bin/lazyclaude-hook.js user-prompt-submit < fixtures/hooks/user-prompt-ultrawork.json
```

Reload local plugin metadata in Claude Code after hook edits:

```text
/reload-plugins
```
