← d3dev

Cursor Hooks — Agent Activity Logging to MongoDB


https://docs.cursor.com/agent/hooks
cursorhooksloggingmongodbagent-trackingobservability

Cursor Hooks — Agent Activity Logging to MongoDB

Metadata

FieldValue
Linkhttps://docs.cursor.com/agent/hooks
Tagscursor, hooks, logging, mongodb, agent-tracking, observability
Date2026-02-25

Sam's TLDR;

Cursor hooks are shell scripts triggered at key points in the agent lifecycle. They're configured per-project in .cursor/hooks.json. There's no global hooks.json — it's per-project only. To get "everywhere automatically" logging, the best approach is a zsh chpwd hook that auto-installs the config whenever you cd into a git repo. The hooks receive JSON on stdin with context (tool name, command, etc.) and can log to Mongo via our existing logger.js.

Key Points

Available Hook Types

HookWhenstdin DataCan Control?
sessionStartNew agent sessionSession metadataSet env vars, inject context
sessionEndSession endsSession metadataInformational
beforeSubmitPromptBefore user prompt sentPrompt textCan modify/block
preToolUseBefore tool runsTool name, input argsBlock with {"decision":"block"}
postToolUseAfter tool completesTool name, output, exit codeInformational
afterFileEditAfter agent edits fileFile path, changesInformational
afterTabFileEditAfter tab-complete editFile pathInformational
beforeShellExecutionBefore shell commandCommand stringCan block
stopAgent about to stopSession contextAuto-continue with {"followup_message":"..."}
preCompactBefore context compactionContext metadataInformational
subagentStartSubagent spawnsAgent name, taskInformational
subagentStopSubagent finishesAgent name, resultInformational

Hook Config Format

``json

{

"version": 1,

"hooks": {

"sessionStart": [

{

"command": ".cursor/hooks/session-start.sh",

"timeout": 5

}

],

"preToolUse": [

{

"command": ".cursor/hooks/pre-tool-use.sh",

"matcher": "Shell|Write|Edit",

"timeout": 5

}

],

"stop": [

{

"command": ".cursor/hooks/stop.sh",

"timeout": 10,

"loop_limit": 3

}

]

}

}

`

Hook Entry Fields

FieldRequiredDescription
commandYesShell command or script path
matcherNoRegex to filter by tool name (e.g. "Shell\Write")
timeoutNoSeconds before hook is killed
loop_limitNoMax iterations for stop hooks (prevents infinite loops)

Full Summary

How Hooks Work

  • Cursor reads .cursor/hooks.json from the project root when an agent session starts
  • At each lifecycle event, matching hooks fire in order
  • Each hook runs as a subprocess — it receives JSON on stdin and returns JSON on stdout
  • Hooks that produce no stdout or invalid JSON are treated as no-ops
  • preToolUse hooks MUST return {"decision": "allow"} or {"decision": "block", "reason": "..."} — no output = allow
  • stop hooks can return {"followup_message": "..."} to auto-continue the agent
  • Multiple hooks can be registered for the same event — they run sequentially
  • The "Everywhere Automatically" Problem

    Cursor hooks are strictly per-project. The .cursor/hooks.json must exist in each project's root. There is no ~/.cursor/hooks.json global config. Three approaches:

    Approach 1: zsh chpwd hook (recommended)

    Add a function to ~/.zshrc that checks for a .git directory and auto-creates .cursor/hooks.json if missing. Zero friction — it just works when you cd anywhere.

    Approach 2: Git template directory

    Set git config --global init.templateDir ~/.git-template and put .cursor/hooks.json in the template. Only works for new repos (git init/clone).

    Approach 3: Cursor Plugin (future)

    Cursor 2.5 introduced the plugin marketplace. A plugin could theoretically install hooks globally. Not available for custom use yet.

    What To Track

    For full agent observability:

    WhatHookGives You
    All user promptsbeforeSubmitPromptEvery question asked across all projects
    All shell commandspreToolUse (matcher: Shell)Terminal command audit trail
    All file changesafterFileEditWhich files agents modify
    Session lifecyclesessionStart + sessionEndSession duration, project context
    Subagent activitysubagentStart + subagentStopBackground agent tracking
    Agent completionsstopWhen/why agents finish

    Real-World Examples Found

    Sources