# hooks/ — Claude Code Pre/Post-Tool Hooks

See @../../CLAUDE.md for project-wide patterns.

## What This Is
Reliability guardrails injected into Claude Code's tool pipeline. Installed into `~/.claude/settings.json` during loop startup via `install.py`.

## Hook Inventory

### PreToolUse
- **guard_done** (`mcp__peon-mcp__update_task`): Currently a no-op placeholder (test gate removed)
- **guard_pr** (`Bash` — blocks `gh pr create`): Prevents PR creation if tests not passing. Extracts task ID from branch name (`task/123` or `task-123` patterns), calls REST API to check test status. **Fails open** — allows if API unreachable or not on a task branch.

### PostToolUse
- **session_link** (`mcp__peon-mcp__next_task`): After next_task returns, links the claimed task to current session via `PUT /api/sessions/{id}`. Uses `PEON_SESSION_ID` env var; no-op if unset.
- **progress_reminder** (`*` — all tools): Every 20 tool calls, emits systemMessage reminding agent to update progress. Uses `/tmp/peon_progress_{ppid}` counter file.

## Critical Patterns
- Hooks are **synchronous subprocess calls** — must use `urllib`, not async. No access to the FastAPI event loop.
- `install.py` is idempotent: filters existing hooks by `_PEON_MARKER`, preserves user-defined hooks
- All hooks use `common.py` utilities: `get_api_url()`, `get_api_key()`, `api_request()`, `extract_task_id_from_branch()`

## Environment Variables Required
- `PEON_API_URL` — REST API base URL (default: http://127.0.0.1:8420)
- `PEON_API_KEY` — Optional API key
- `PEON_SESSION_ID` — Set by loop.py for session_link hook

## Gotchas
- Counter files at `/tmp/peon_progress_*` are never cleaned up
- guard_pr fails open by design — network issues don't block the agent
- session_link silently fails if env vars unset — no error, just skips
