ashlr

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 SessionStart hook, which Claude Code fires with source: compact right after a compaction — and which can inject context. Claude Code's PreCompact event is decision-control only (it cannot emit additionalContext), so ashlr does its post-compaction re-orientation from SessionStart instead.

SubagentStop — savings rollup after a Task finishes

Hook: hooks/subagent-stop-rollup.ts

Fires when a subagent (Task) completes. Does two things:

  1. Appends a rollup line to ~/.ashlr/session-log.jsonl recording the subagent's task ID, session ID, tokens saved, call count, and top tool.
  2. Fires genome consolidation for the current working directory — a background bun run scripts/genome-auto-consolidate.ts that 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:

VariableEffect
ASHLR_SESSION_LOG=0Skips appending to session-log.jsonl
ASHLR_GENOME_AUTO=0Skips 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:

  1. Reads final session stats — tokens saved, call count, and top tool.
  2. Appends a stop entry 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:

VariableEffect
ASHLR_SESSION_LOG=0Skips 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.

On this page