What you can build
- Stop operations before they cause problems (like creating
.jsfiles in a TypeScript project) - Run linters or custom validators before files get saved
- Prevent operations that violate security policies
- Track everything for analytics or compliance
- Trigger external tools or services at the right moments
- Add context to the conversation based on what Cline is doing
Hook types
Cline supports 8 hook types that run at different points in the task lifecycle:| Hook type | When it runs |
|---|---|
TaskStart | When you start a new task |
TaskResume | When you resume an interrupted task |
TaskCancel | When you cancel a running task |
TaskComplete | When a task finishes successfully |
PreToolUse | Before Cline executes a tool (read_file, write_to_file, etc.) |
PostToolUse | After a tool execution completes |
UserPromptSubmit | When you submit a message to Cline |
PreCompact | Before Cline truncates conversation history to free up context |
Hook locations
Hooks can be stored globally or in a project workspace:- Global hooks:
~/Documents/Cline/Hooks/— applies to all projects - Project hooks:
.clinerules/hooks/in your repo — can be committed to version control
cancel: true, the operation stops.
Creating a hook
Open the Hooks tab
Click the scale icon at the bottom of the Cline panel, to the left of the model selector. Switch to the Hooks tab.
Create a new hook
Click the New hook… dropdown and select a hook type (e.g.,
PreToolUse, TaskStart).Review the hook's code
Click the pencil icon to open and edit the hook script. Cline generates a template with examples.
Platform requirements
Hook filenames are platform-specific:
- macOS/Linux: extensionless
HookName(e.g.,PreToolUse) — must be marked executable withchmod +x - Windows:
HookName.ps1PowerShell script files (e.g.,PreToolUse.ps1)
How hooks work
Hooks are executable scripts that receive JSON input via stdin and return JSON output via stdout.Input structure
Every hook receives a JSON object with common fields plus hook-specific data:| Hook type | Field | Contents |
|---|---|---|
TaskStart | taskStart | { task: string } |
TaskResume | taskResume | { task: string } |
TaskCancel | taskCancel | { task: string } |
TaskComplete | taskComplete | { task: string } |
PreToolUse | preToolUse | { tool: string, parameters: object } |
PostToolUse | postToolUse | { tool: string, parameters: object, result: string, success: boolean, durationMs: number } |
UserPromptSubmit | userPromptSubmit | { prompt: string } |
PreCompact | preCompact | { conversationLength: number, estimatedTokens: number } |
timestamp is a string (milliseconds since epoch). workspaceRoots is an array — use .workspaceRoots[0] if you need a single path.Output structure
Hooks return a JSON object to stdout:| Field | Type | Description |
|---|---|---|
cancel | boolean | If true, stops the operation |
contextModification | string | Text injected into the conversation as context for Cline |
errorMessage | string | Shown to the user if cancel is true |
Use stderr (
>&2) for debug logging. Only stdout is parsed as the hook response.Context modification
ThecontextModification field lets hooks inject information into the conversation. Context affects future AI decisions, not the current tool execution — by the time a PreToolUse hook runs, Cline has already decided what parameters to use. The injected context influences the next API request.
Useful for:
- Adding project-specific context when a task starts
- Providing validation results that Cline should consider for future steps
- Flagging that a file is auto-generated or should not be modified
Hook reference
TaskStart
TaskStart
Runs when you start a new task. Use it to log task start time, add project context, check prerequisites, or notify external systems.
TaskResume
TaskResume
Runs when you resume an interrupted task instead of
TaskStart. Use it to check for changes since the task was paused, refresh context with the latest project state, or notify that work is resuming.TaskCancel
TaskCancel
Runs when you cancel a running task. Use it to clean up temporary files or resources, notify external systems, or log cancellation for analytics. This hook cannot itself be cancelled.
TaskComplete
TaskComplete
Runs when a task completes successfully. Use it to run tests or validation after changes, generate reports or summaries, notify stakeholders, or trigger CI/CD pipelines.
PreToolUse
PreToolUse
Runs before any tool executes. This is the most powerful hook for validation and safety. The operation can be blocked by returning Example that blocks
cancel: true.Input includes the tool name and its parameters:.js files in a TypeScript project:PostToolUse
PostToolUse
Runs after a tool completes (success or failure). Use it to audit tool usage, validate results, trigger follow-up actions, or monitor performance.Input includes execution results:
PostToolUse hooks can return cancel: true to stop the task, but they cannot undo the tool execution that already happened.UserPromptSubmit
UserPromptSubmit
Runs when you send a message to Cline. Use it to log prompts for analytics, add context based on prompt content, or validate prompts.
PreCompact
PreCompact
Runs before Cline truncates conversation history to stay within context limits. Use it to archive important conversation parts before they’re removed, or log compaction events.Input includes context metrics:
Examples
TypeScript enforcement
Block creation of.js files in a TypeScript project:
Tool usage logging
Log all tool executions with timing information:Add project context on task start
Inject project-specific information when a task begins:Block writes to protected paths
Prevent Cline from modifying generated or read-only files:Troubleshooting
Hook not running?- On macOS/Linux: check that the file is executable (
chmod +x hookname) and uses extensionless naming (PreToolUse, notPreToolUse.sh) - On Windows: ensure the hook file is named
<HookName>.ps1and PowerShell is available - Verify that Hooks are enabled in Settings → Features → Enable Hooks
- Ensure output is valid JSON on a single line to stdout
- Use stderr (
>&2) for debug logging, not stdout - Check for trailing characters or newlines before the JSON
- Review the hook’s logic and test with sample input piped to the script
- Check both global and workspace hooks — both run if they exist
- Remember that if any hook returns
cancel: true, the operation is blocked