Lifecycle Hooks
July 26, 2026 · View on GitHub
Status: Active
Scope: current-state
Last reviewed: 2026-07-26
Owner: ax-code runtime
Lifecycle hooks let you run shell commands on agent events without rebuilding the runtime. They complement permission rules and the isolation sandbox: hooks are deterministic side effects (“always format”, “never force-push”), while prompts remain advisory.
Events
| Event | When | Can block? |
|---|---|---|
| PreToolUse | Before a tool executes | Yes (blockOnFailure: true) |
| PostToolUse | After a tool completes | No |
| Stop | When a session turn completes (packs may run on stop via automation) | No |
| UserPromptSubmit | When a user prompt is submitted, before the message is persisted | Yes (blockOnFailure: true) |
| PreCompact | Before session compaction runs (args: { auto, overflow }) | No |
| SubagentStop | When a task subagent finishes (args: { agent, status }) | No |
These names map to AX Code’s internal plugin triggers (tool.execute.before / tool.execute.after) plus session-level prompt, compaction, subagent, and stop hooks. Synthetic continuation prompts (internal agentRouting: "preserve" prompts) do not fire UserPromptSubmit.
Enable packs
Project hooks and plugins execute repository-controlled code, so .ax-code/hooks.json, .ax-code/plugin/, and project-configured plugins are disabled by default. After reviewing them, opt in outside the repository when starting AX Code:
AX_CODE_TRUST_PROJECT_CONFIG=1 ax-code
Then create .ax-code/hooks.json in your project:
{
"packs": ["format-after-edit", "block-force-push", "require-tests-on-stop", "protect-env-files", "log-bash-commands"]
}
Official packs (≥5)
| Pack | Events | Description |
|---|---|---|
format-after-edit | PostToolUse | Reminds the agent to format after edits |
block-force-push | PreToolUse | Blocks git push --force / -f |
require-tests-on-stop | Stop | Reminds to verify after mutations |
protect-env-files | PreToolUse | Warns when tools touch .env |
log-bash-commands | PreToolUse | Logs bash commands for audit |
Custom hooks:
{
"hooks": [
{
"event": "PreToolUse",
"matcher": "bash",
"command": "echo running bash",
"blockOnFailure": false
}
]
}
Environment variables available to hook commands:
HOOK_EVENT— PreToolUse | PostToolUse | Stop | UserPromptSubmit | PreCompact | SubagentStopHOOK_TOOL— tool idHOOK_SESSION_IDHOOK_ARGS_JSON— JSON tool argumentsHOOK_ARGS_STDIN=1— the complete JSON arguments are always available on stdin;HOOK_ARGS_JSONis empty for payloads larger than 32 KiBHOOK_PACK— pack name when applicable
Relationship to isolation
Hooks do not replace the sandbox. Use:
- App isolation for portable write/network boundaries
- OS isolation (the default
"auto"backend) for kernel-enforced bash sandboxing when available - Hooks for policy side-effects and hard blocks like force-push
See Sandbox Mode and SECURITY.md.