Settings → Hooks, cron's twin for the other end of a task: instead of a
schedule it has an event (conversation-done) + a delay, and a firing resumes
the conversation that just finished rather than spawning a new one.
Seeded with an enabled `post-task` hook (delay 1 min) whose prompt asks the
agent to save memories on the tricky parts, update README/CLAUDE.md, copy
artefacts into .ai/artefacts/, tear down worktrees and processes, and update
the changelog.
- backend/hooks.py: HookStore (/data/hooks.json — hooks + a persistent pending
queue) and a 10s HookScheduler daemon; the scheduler claims an entry off the
queue before firing, so a deploy cutover can't double-resume.
- backend/main.py: /api/hooks CRUD + /run + /prompt, read-only /api/claude-hooks
(the repo's native .claude/settings.json hooks), _enqueue_hooks on both finish
paths (exit watcher + POST /api/notify), _fire_hook, due-time preconditions.
- backend/meta.py: meta.hooks {hookId: iso} merged, not replaced — that mapping
is the once-per-hook-per-session loop guard, without which the follow-up's own
DONE would re-trigger the hook forever.
- frontend: Hooks page (delay/skip/cap controls, prompt editor, pending queue,
run history, native-hooks section), route + settings category, HookBadge on
conversation cards and detail, api/queries/SSE/optimistic wiring, mock backend
handlers + seed.
Skips cron-spawned sessions and subagent conversations by default; no transcript
cap. Native-hook editing stays out — writing .claude/settings.json from the
container is host-level code execution.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
8.5 KiB
8.5 KiB