name: create-hook description: >- Create Cursor hooks. Use when you want to create a hook, write hooks.json, add hook scripts, or automate behavior around agent events.
Creating Cursor Hooks
Create hooks when you want Cursor to run custom logic before or after agent events. Hooks are scripts or prompt-based checks that exchange JSON over stdin/stdout and can observe, block, modify, or follow up on behavior.
When the user asks for a hook, don't stop at describing the format. Gather the missing requirements, then create or update the hook files directly.
Gather Requirements
Before you write anything, determine:
- Scope: Should this be a project hook or a user hook?
- Trigger: Which event should run the hook?
- Behavior: Should it audit, deny/allow, rewrite input, inject context, or continue a workflow?
- Implementation: Should it be a command hook (script) or a prompt hook?
- Filtering: Does it need a matcher so it only runs for certain tools, commands, or subagent types?
- Safety: Should failures fail open or fail closed?
Infer these from the conversation when possible. Only ask for the missing pieces.
Choose the Right Location
- Project hooks:
.cursor/hooks.jsonand.cursor/hooks/* - User hooks:
~/.cursor/hooks.jsonand~/.cursor/hooks/*
Path behavior matters:
- Project hooks run from the project root, so use paths like
.cursor/hooks/my-hook.sh - User hooks run from
~/.cursor/, so use paths like./hooks/my-hook.shorhooks/my-hook.sh
Prefer project hooks when the behavior should be shared with the repository and checked into version control.
Choose the Hook Event
Use the narrowest event that matches the user's goal.
Common Agent events
sessionStart,sessionEnd: set up or audit a sessionpreToolUse,postToolUse,postToolUseFailure: work across all toolssubagentStart,subagentStop: control or continue Task/subagent workflowsbeforeShellExecution,afterShellExecution: gate or audit terminal commandsbeforeMCPExecution,afterMCPExecution: gate or audit MCP tool callsbeforeReadFile,afterFileEdit: control file reads or post-process editsbeforeSubmitPrompt: validate prompts before they are sentpreCompact: observe context compactionstop: handle agent completionafterAgentResponse,afterAgentThought: track agent output or reasoning
Tab events
beforeTabFileRead: control file access for inline completionsafterTabFileEdit: post-process edits made by Tab
Quick event chooser
- Block or approve shell commands ->
beforeShellExecution - Audit shell output ->
afterShellExecution - Format files after edits ->
afterFileEdit - Block or rewrite a specific tool call ->
preToolUse - Add follow-up context after a tool succeeds ->
postToolUse - Control whether subagents can run ->
subagentStart - Chain subagent loops ->
subagentStop - Check prompts for secrets or policy violations ->
beforeSubmitPrompt - Protect MCP calls ->
beforeMCPExecution
Hooks File Format
Create a hooks.json file with schema version 1:
{
"version": 1,
"hooks": {
"afterFileEdit": [
{
"command": ".cursor/hooks/format.sh"
}
]
}
}
Each hook definition can include:
command: shell command or script pathtype:"command"or"prompt"(defaults to"command")timeout: timeout in secondsmatcher: filter for when the hook runsfailClosed: block the action when the hook crashes, times out, or returns invalid JSONloop_limit: mainly forstopandsubagentStopfollow-up loops
Matchers
Use matchers to avoid running the hook on every event.
preToolUse/postToolUse/postToolUseFailure: match on tool type such asShell,Read,Write,Task, or MCP tools inMCP: ...formsubagentStart/subagentStop: match on subagent type such asgeneralPurpose,explore, orshellbeforeShellExecution/afterShellExecution: match on the full shell command stringbeforeReadFile: match on tool type such asReadorTabReadafterFileEdit: match on tool type such asWriteorTabWritebeforeSubmitPrompt: matches the valueUserPromptSubmit
Important matcher warning:
- Matchers use JavaScript-style regular expressions, not POSIX/grep syntax
- Do not use POSIX classes like
[[:space:]]; use JavaScript equivalents like\s - If the matcher is at all tricky, start by getting the hook working without one or with a very simple matcher, then tighten it after the hook is confirmed to load and fire
If the user wants a hook for only one risky command family, prefer script-side filtering for the first working version and add a matcher afterward only if it is simple and clearly correct.
Command Hooks
Command hooks are the default. They receive JSON on stdin and can return JSON on stdout.
Before using a command hook, verify that every executable it depends on will actually run in the hook environment:
- the script itself has a valid shebang and is executable
- any helper binary it calls is already installed and on
$PATH - if the script depends on tools like
jq,python3,node, or repo-local CLIs, verify that explicitly before finishing
Do not assume a binary exists just because it is common on your machine.
Minimal project-level example
{
"version": 1,
"hooks": {
"beforeShellExecution": [
{
"command": ".cursor/hooks/approve-network.sh",
"matcher": "curl|wget|nc ",
"failClosed": true
}
]
}
}
#!/bin/bash
input=$(cat)
command=$(echo "$input" | jq -r '.command // empty')
if [[ "$command" =~ curl|wget|nc ]]; then
echo '{
"permission": "ask",
"user_message": "This command may make a network request. Please review it before continuing.",
"agent_message": "A hook flagged this shell command as a possible network call."
}'
exit 0
fi
echo '{ "permission": "allow" }'
exit 0
Important behavior:
- Exit code
0: success - Exit code
2: block the action, same as returning deny - Other non-zero exit codes: fail open by default unless
failClosed: true
Always make hook scripts executable after creating them.
Prompt Hooks
Prompt hooks are useful when the policy is easier to describe than to script.
{
"version": 1,
"hooks": {
"beforeShellExecution": [
{
"type": "prompt",
"prompt": "Does this command look safe to execute? Only allow read-only operations. Here is the hook input: $ARGUMENTS",
"timeout": 10
}
]
}
}
Use prompt hooks for lightweight policy decisions. Prefer command hooks when the logic must be deterministic or when the user needs exact, auditable behavior.
Event Output Cheat Sheet
Use the event's supported output fields only.
preToolUse: can returnpermission,user_message,agent_message, andupdated_inputpostToolUse: can returnadditional_context; for MCP tools it can also returnupdated_mcp_tool_outputsubagentStart: can returnpermissionanduser_messagesubagentStop: can returnfollowup_messagebeforeShellExecution/beforeMCPExecution: can returnpermission,user_message, andagent_message
When the user wants to rewrite a tool call, prefer preToolUse. When they want to gate only shell commands, prefer beforeShellExecution.
Implementation Workflow
- Pick the correct location and event
- Create or update the correct
hooks.jsonfile - Start with no matcher or the simplest safe matcher
- Create the script under the matching hooks directory
- Read stdin JSON and implement the required behavior
- Make the script executable
- Verify any helper executables the script uses are installed and on
$PATH - Trigger the relevant action to test the hook
- Verify behavior in Cursor's Hooks settings tab or the Hooks output channel
If you are editing an existing hooks setup, preserve unrelated hooks and only change the minimum necessary entries.
Validation and Troubleshooting
- Cursor watches
hooks.jsonand reloads on save - If hooks still do not load, restart Cursor
- Double-check relative paths:
- project hooks -> relative to the project root
- user hooks -> relative to
~/.cursor/
- If the hook does not appear to load at all, suspect matcher/config parsing first; remove the matcher and confirm the base hook works before tightening it
- If the script runs external commands, verify each one is installed and reachable from the hook process with
command -vor equivalent - If the hook should block on failure, set
failClosed: true - If a command hook should intentionally block, returning exit code
2is valid
Final Checklist
- Used the correct hook location and path style
- Chose the narrowest correct event
- Added a matcher when appropriate
- Returned only fields supported by that hook event
- Made the script executable
- Tested the hook by triggering the real event
- Checked the Hooks tab or Hooks output channel if debugging was needed
Overview
create-hook: a free, copy-ready skill on OpenRuna. Create Cursor hooks. Use when you want to create a hook, write hooks.json, add hook scripts, or automate behavior around agent events.
What this skill does
Reach for "create-hook" whenever you need a reliable skill for real work across ChatGPT, Claude, Gemini, and Cursor. Create Cursor hooks. Use when you want to create a hook, write hooks.json, add hook scripts, or automate behavior around agent events. It is catalogued next to similar resources on OpenRuna, so the rest of the toolkit you need is close by. Copy it into your assistant of choice and sharpen the result with a couple of follow-up turns.
Use cases
- Combine it with related tools and prompts in the same OpenRuna category to build an end-to-end workflow.
- Reach for it during planning or review sessions when you want consistent, AI-assisted structure.
- Use "create-hook" when you need a repeatable skill for professional work without rewriting instructions every time.
- Hand "create-hook" to a new teammate so their skill output matches your team's quality bar from day one.
Example output
Running this skill produces output shaped like the source material below: # Creating Cursor Hooks Create hooks when you want Cursor to run custom logic before or after agent events. Hooks are scripts or prompt-based checks that exchange JSON over stdin/stdout and can observe, block, modify, or follow up on behavior. When the user asks for a hook, don't stop at describing the format. Gather the missing requirements, then create or update the hook files directly. ## Gather Requirements Before you write anything, determine: 1. **Scope**: Should this be a project hook or a user hook? 2. **Trigger**: Which event should run the hook? 3. **Behavior**: Should it audit,… Results vary by model and temperature; treat the first response as a draft and refine it with follow-up prompts.
Tips by platform
Claude
With Claude, drop this skill into Project knowledge so every chat in the project inherits it. Ask Claude to restate the goal first, then run — it catches edge cases early.
ChatGPT
For ChatGPT, save this skill as a Custom Instruction or a saved prompt so it is one click away. Add your specifics in a follow-up rather than editing the original.
Cursor
In Cursor, lift the key instructions from this skill into .cursorrules or a SKILL.md file, then reference it in Agent mode with @ mentions. Keep the title in a comment so teammates can find it on OpenRuna.
Frequently asked questions
- What is "create-hook"?
- It is a skill listed on OpenRuna — Create Cursor hooks. Use when you want to create a hook, write hooks.json, add hook scripts, or automate behavior around agent events. You can copy and adapt it for ChatGPT, Claude, Cursor, or any other AI assistant.
- Is "create-hook" free to use?
- Most OpenRuna resources are open or CC0-licensed. Check the license shown on this page before commercial use; premium collections are clearly marked as such.
- How do I get the best results from this skill?
- Replace any placeholders, add your project context, and ask the model to confirm its assumptions first. Iterate over 2–3 follow-up turns rather than expecting a perfect first response.
- Does "create-hook" work with both Claude and ChatGPT?
- Yes — it is model-agnostic text, so it runs on Claude, ChatGPT, Gemini, and Cursor. The tips on this page cover each of those assistants specifically.
- Where can I find resources related to "create-hook"?
- Scroll to the Related resources section on this page, or open the matching category hub on OpenRuna to find connected prompts, tools, agents, and datasets in the same topic area.
Related resources
- Tool
v0 Prompts and Tools — ReadFile
Reads file contents intelligently - returns complete files when small, paginated chunks, or targeted chunks when large based on your query. **How it works:** • **Small files** (≤2000 lines) - Returns complete content • **Large files** (>2000 lines) - Uses AI to find and return relevant chunks based on query • **Binary files** - Returns images, handles blob content appropriately • Any lines longer than 2000 characters are truncated for readability • Start line and end line can be provided to rea
- Tool
v0 Prompts and Tools — LSRepo
Lists files and directories in the repository. Returns file paths sorted alphabetically with optional pattern-based filtering. Common use cases: • Explore repository structure and understand project layout • Find files in specific directories (e.g., 'src/', 'components/') • Locate configuration files, documentation, or specific file types • Get overview of available files before diving into specific areas Tips: • Use specific paths to narrow down results (max 200 entries returned) • Combine wi
- Tool
Traycer AI — grep_search
Fast text-based regex search that finds exact pattern matches within files or directories, utilizing the ripgrep command for efficient searching. Results will be formatted in the style of ripgrep and can be configured to include line numbers and content. To avoid overwhelming output, the results are capped at 50 matches. Use the include patterns to filter the search scope by file type or specific paths. This is best for finding exact text matches or regex patterns. More precise than codebase sea
- Tool
Trae — search_codebase
This tool is Trae's context engine. It: 1. Takes in a natural language description of the code you are looking for; 2. Uses a proprietary retrieval/embedding model suite that produces the highest-quality recall of relevant code snippets from across the codebase; 3. Maintains a real-time index of the codebase, so the results are always up-to-date and reflects the current state of the codebase; 4. Can retrieve across different programming languages; 5. Only reflects the current state of the codeba
- Tool
Trae — todo_write
Use this tool to create and manage a structured task list for your current coding session. This helps you track progress, organize complex tasks, and demonstrate thoroughness to the user. It also helps the user understand the progress of the task and overall progress of their requests.
- Tool
Same.dev — task_agent
Launches a highly capable task agent in the USER's workspace. Usage notes: 1. When the agent is done, it will return a report of its actions. This report is also visible to USER, so you don't have to repeat any overlapping information. 2. Each agent invocation is stateless and doesn't have access to your chat history with USER. You will not be able to send additional messages to the agent, nor will the agent be able to communicate with you outside of its final report. Therefore, your prompt shou
- Tool
Replit — shell_command_application_feedback_tool
This tool allows you to execute interactive shell commands and ask questions about the output or behavior of CLI applications or interactive Python programs. ## Rules of usage: 1. Provide clear, concise interactive commands to execute and specific questions about the results or interaction. 2. Ask one question at a time about the interactive behavior or output. 3. Focus on interactive functionality, user input/output, and real-time behavior. 4. Specify the exact command to run, including any ne
- Tool
Replit — str_replace_editor
Custom editing tool for viewing, creating and editing files * State is persistent across command calls and discussions with the user * If `path` is a file, `view` displays the result of applying `cat -n`. If `path` is a directory, `view` lists non-hidden files and directories up to 2 levels deep * The `create` command cannot be used if the specified `path` already exists as a file * If a `command` generates a long output, it will be truncated and marked with `<response clipped>` * The `undo_edi
