Quick Start
The following example demonstrates how to use a Hook to block dangerous commands — automatically preventing execution when the Agent attempts to runrm -rf.
Step 1: Create the script
~/.qoder/settings.json:
rm -rf. The Hook will block the execution and notify the Agent.
Configuration
Configuration File Locations
Hook configuration is loaded from the following three files. All three levels are merged and executed together:Configuration Format
| Field | Required | Description |
|---|---|---|
type | Yes | Hook type. Use "command" for shell scripts and shell commands. |
command | Yes | The shell command to execute |
timeout | No | Timeout in seconds. Command hooks default to 600 seconds. |
matcher | No | Match condition; matches all if omitted |
Matcher Rules
matcher filters the scope of hook triggers. Different events match different fields (see individual event descriptions).
| Syntax | Meaning | Example |
|---|---|---|
Omitted or "*" | Match all | All tools trigger |
| Exact value | Exact match | "Bash" matches only the Bash tool |
| separated | Match multiple values | "Write|Edit" matches Write or Edit |
| Regular expression | Regex match | "mcp__.*" matches all MCP tools |
Writing Hook Scripts
Hook scripts receive JSON input via stdin and control behavior through exit codes and stdout. This section describes the common input/output format for all events. Additional fields specific to commonly used events are described in Common Events.Input
Hook scripts receive JSON data via stdin. All events include the following common fields:| Field | Description |
|---|---|
session_id | Current session ID |
transcript_path | Path to the current transcript file |
cwd | Current working directory |
hook_event_name | Name of the triggered event |
permission_mode | Current permission mode, when available |
agent_id | Current agent ID, when available |
agent_type | Current agent type, when available |
jq:
Output
Hooks control behavior through exit codes and stdout. Exit code determines the basic behavior: 0 for success, 2 for blocking (stderr content is injected into the conversation, only effective for events that support blocking), other values are non-blocking errors. stdout JSON (parsed only when exit code is 0) provides fine-grained control for some events — see individual event descriptions for supported fields. stdout is ignored when exit code is non-zero.Environment Variables
The following environment variables are available when hook scripts execute:| Variable | Description |
|---|---|
QODER_PROJECT_DIR | Working directory of the current project |
Common Events
Commonly used Hook events include the following. Qoder CLI may emit additional lifecycle events for advanced workflows.SessionStart
Triggered when a session starts. matcher field: Session source| matcher value | Trigger scenario |
|---|---|
startup | New session started |
resume | Existing session resumed |
compact | After context compaction completes |
SessionEnd
Triggered when a session ends. matcher field: End reason| matcher value | Trigger scenario |
|---|---|
prompt_input_exit | User exits input (Ctrl+D, etc.) |
other | Other reasons |
UserPromptSubmit
Triggered after the user submits a prompt, before the Agent begins processing it. Additional input fields:PreToolUse
Triggered before tool execution. Can block tool execution. matcher field: Tool name (e.g.Bash, Write, Edit, Read, Glob, Grep; MCP tool names like mcp__server__tool)
Additional input fields:
PostToolUse
Triggered after a tool executes successfully. matcher field: Tool name Additional input fields:PostToolUseFailure
Triggered after a tool execution fails. matcher field: Tool name Additional input fields:Stop
Triggered when the Agent finishes responding (main Agent, with no pending tool calls). Can prevent the Agent from stopping and let it continue working. Preventing the Agent from stopping: exit code 2; stderr content is injected into the conversation as a message, and the Agent continues working.SubagentStart / SubagentStop
Triggered when a sub-agent starts and completes. SubagentStop is similar to Stop and can prevent the sub-agent from stopping. matcher field: Agent type name Additional input fields:PreCompact
Triggered before context compaction. matcher field: Trigger method| matcher value | Trigger scenario |
|---|---|
manual | User manually runs /compact |
auto | Automatically triggered when context window is full |
Notification
Triggered on notification events (permission requests, task completion, etc.). matcher field: Notification type| matcher value | Trigger scenario |
|---|---|
permission | Permission request notification |
result | Agent result notification |
PermissionRequest
Triggered when a tool requires user authorization to execute. matcher field: Tool name Additional input fields:Practical Examples
Desktop Notifications
Pop up a desktop notification when the Agent completes a task or requires authorization. Script~/.qoder/hooks/notify.sh (macOS):
Auto-Lint After Writing Files
Automatically run lint checks every time the Agent writes or edits a file. Script${project}/.qoder/hooks/auto-lint.sh:
PostToolUse, matcher Write|Edit, command .qoder/hooks/auto-lint.sh.
Keep the Agent Working
When the Agent stops, check whether there are unfinished tasks; if so, inject a message to keep the Agent working. Script~/.qoder/hooks/check-continue.sh:
Stop, command ~/.qoder/hooks/check-continue.sh.