Automatic hooks
The two lifecycle hooks ashlr installs — SubagentStop and Stop — what each one does, and the env toggles that control them.
ashlr installs two Claude Code lifecycle hooks automatically. They run in the background and require no configuration. This page describes what each one does and how to tune or disable them.
Why no PreCompact hook? Re-orientation after a context compaction is handled by the
SessionStarthook, which Claude Code fires withsource: compactright after a compaction — and which can inject context. Claude Code'sPreCompactevent is decision-control only (it cannot emitadditionalContext), so ashlr does its post-compaction re-orientation fromSessionStartinstead.
SubagentStop — savings rollup after a Task finishes
Hook: hooks/subagent-stop-rollup.ts
Fires when a subagent (Task) completes. Does two things:
- Appends a rollup line to
~/.ashlr/session-log.jsonlrecording the subagent's task ID, session ID, tokens saved, call count, and top tool. - Fires genome consolidation for the current working directory — a background
bun run scripts/genome-auto-consolidate.tsthat keeps the genome fresh after the subagent's changes.
SubagentStop is a decision-control event in Claude Code, so the hook emits no context of its own — the rollup is recorded to the session log.
Env toggles:
| Variable | Effect |
|---|---|
ASHLR_SESSION_LOG=0 | Skips appending to session-log.jsonl |
ASHLR_GENOME_AUTO=0 | Skips the background genome consolidation |
Stop — session finalization
Hook: hooks/stop-accounting.ts
Fires on the Claude Code Stop event (the end of each assistant turn). Complements the SessionEnd GC path with an idempotency guard: before writing, it reads the last three lines of session-log.jsonl and skips if a session_end or stop entry for this session already exists within the last 60 seconds.
What it does:
- Reads final session stats — tokens saved, call count, and top tool.
- Appends a
stopentry to~/.ashlr/session-log.jsonl.
Stop is a decision-control event in Claude Code — it cannot emit additionalContext — so the hook surfaces nothing inline. Per-session savings are shown in the status line and via /ashlr-savings.
Env toggles:
| Variable | Effect |
|---|---|
ASHLR_SESSION_LOG=0 | Skips the log append |
Session log location
Both hooks write to ~/.ashlr/session-log.jsonl. Each line is a JSON object with at minimum ts, event, and session fields. See Stats schema for the full shape.
All hooks are fire-and-forget safe
Every hook is written to the contract: never throws, always exits 0. A hook failure writes a note to ~/.ashlr/hook-errors.jsonl via _hook-errors.ts and then exits cleanly — it never blocks the session.