Skip to content

Hooks

Hooks run at agent lifecycle events (session start, before shell, after file edit, and more). You declare them once; capa translates each hook into the provider-specific config shape and tags its entries as capa:<id> so install/clean stay surgical.

Edit hooks in the capabilities file, or use the CLI:

Terminal window
capa add --hook --id audit-shell --on beforeShell --command 'date >> ~/.capa/audit.log'
capa add --hook --id greet --on sessionStart --type prompt --prompt 'Remember project conventions.'
capa install

See CLI: add for source flags (--source, --command, --prompt, --type).

FieldNotes
idStable id → capa:<id> in provider configs
onCanonical event (beforeShell, afterFileEdit, …) or provider-scoped (cursor:beforeShellExecution)
typecommand (default) or prompt
command / promptInline body when you do not use source
sourceinline, remote, github, gitlab, or local (path in the project)
matcher, timeout, failClosed, sequential, providersOptional controls; failClosed is Cursor-oriented today

Canonical events include sessionStart, sessionEnd, userPromptSubmit, beforeTool, afterTool, afterToolFailure, beforeShell, afterShell, beforeFileRead, afterFileEdit, beforeMcpCall, afterMcpCall, subagentStart, subagentStop, preCompact, and stop.

hooks:
- id: audit-shell
description: Timestamp every shell invocation
on: beforeShell
command: 'date >> ~/.capa/audit.log'
timeout: 5
- id: block-rm-rf
on: cursor:beforeShellExecution
matcher: 'rm -rf *'
failClosed: true
command: 'echo "blocked" && exit 1'
- id: log-bash-commands
on: beforeShell
source:
type: local
path: scripts/log-bash.sh

Non-local sources are materialized under ~/.capa/hooks/<projectId>/. source.type: local references your project file in place (no copy; capa clean will not delete it).

capa installs hooks only for providers that support them (for example Cursor → .cursor/hooks.json, Claude Code → .claude/settings.json). Unsupported providers get a warning and are skipped — install does not fail.