Create Hook
You (the lead) do the work. Do not dispatch sub-agents.
Type: Utility skill (procedural, no agentic lead or sub-agents).
Adds a Cursor lifecycle hook: a script that runs when a specific agent event fires. Hooks are project-level only (.cursor/hooks/ and .cursor/hooks.json).
1. Choose the lifecycle event
Register the hook under one of these keys in hooks.json:
| Event | When it runs |
|---|---|
stop | When the agent stops (end of turn) |
afterFileEdit | After the agent edits a file |
afterAgentResponse | After the agent sends a response |
beforeSubmitPrompt | Before the user's prompt is submitted |
beforeReadFile / afterShellExecution / etc. | See Cursor docs for full list |
2. Add the script
- Path:
.cursor/hooks/<name>.js(or.shif shell). Use a clear name (e.g.memory-reminder.js,on-stop.js). - Runtime: Node.js is typical; command in
hooks.jsonis run with Cursor's working directory set so thatnode hooks/<name>.jsresolves (run from.cursor). - Input: The hook receives a single JSON object on stdin. Read it like this:
javascript1let input = ""; 2process.stdin.setEncoding("utf8"); 3process.stdin.on("data", (chunk) => { 4 input += chunk; 5}); 6process.stdin.on("end", () => { 7 const payload = JSON.parse(input); 8 const roots = payload.workspace_roots || [process.cwd()]; 9 const root = path.resolve(roots[0]); // repo root 10 // ... use root for paths like path.join(root, '.cursor', 'next-step.md') 11});
- Payload: Often includes
workspace_roots(array of repo roots). Use the first root as the project root for paths. Event-specific payloads may includefile_path,prompt, etc. - Output: Hook can write files (e.g.
.cursor/next-step.md), log to stderr, or exit; avoid writing to stdout if the protocol expects JSON there. - Shebang: Start Node scripts with
#!/usr/bin/env node.
3. Register in hooks.json
- Path:
.cursor/hooks.json - Format:
json1{ 2 "version": 1, 3 "hooks": { 4 "stop": [ 5 { "command": "node hooks/on-stop.js" }, 6 { "command": "node hooks/my-new-hook.js" } 7 ] 8 } 9}
- Append to the array for the chosen event; do not remove existing hooks unless the user asks to replace them.
Checklist
- Script created under
.cursor/hooks/<name>.js(or.sh) - Script reads JSON from stdin and uses
workspace_rootsfor repo root when needed - Entry added to
.cursor/hooks.jsonunder the correct event key - Command is
node hooks/<name>.js(or./hooks/<name>.sh); path is relative to.cursor
Reference
- Existing hooks in this repo:
.cursor/hooks/on-stop.js,.cursor/hooks/after-file-edit.js,.cursor/hooks/memory-reminder.js— use them as patterns for stdin handling andpath.join(root, ...). - Project memory (
.cursor/memory.md) notes that new hooks should be added under.cursor/hooks/and registered in.cursor/hooks.json.