Summary
Follow-up to #2065 / #2066. That work gave Cursor an independent memory root (ECC_AGENT_DATA_HOME) and wired a single sessionStart hook (cursor-session-env.js). But the Cursor scaffold's scaffolds/cursor/hooks.json still registers only that one hook, while scripts/hooks/ ships ~48 hook scripts that are wired for the Claude Code target. So an ECC-on-Cursor user today gets the data-root isolation but almost none of ECC's hook-driven behaviour — no continual-learning on stop, no post-edit format/typecheck, no quality gate, no commit-quality guard, no compaction hooks.
This proposes wiring the generalizable subset of ECC's existing hooks into the Cursor scaffold, adapted to Cursor's hook contract and gated by hook profile.
Current state
scaffolds/cursor/hooks.json:
{ "version": 1, "hooks": { "sessionStart": [ { "command": "node .cursor/scripts/hooks/cursor-session-env.js" } ] } }
Cursor hook contract (3.x) — relevant facts
Cursor's agent hooks map closely onto ECC's Claude-side model, so most hooks port by event-name mapping + matcher translation. Proposed mapping:
| ECC hook(s) |
Cursor event |
Blocking |
post-edit-format / -typecheck / -console-warn |
afterFileEdit (matcher Write) |
no |
pre-bash-commit-quality, block-no-verify, pre-bash-dev-server-block |
beforeShellExecution (regex matcher) |
yes (permission) |
post-bash-* |
afterShellExecution |
no |
quality-gate, stop-format-typecheck, evaluate-session |
stop |
no |
pre-compact / suggest-compact |
preCompact |
no |
session-end / -marker |
sessionEnd |
no |
Four contract constraints the implementation must respect (all observed on current Cursor):
- One hook per event array. Cursor currently executes only the first entry in an event's array. ECC already solves this on the Claude side with
*-dispatcher.js fan-out scripts — the Cursor wiring should register a single dispatcher per event and fan out internally, not list N hooks.
- CLI vs editor surface. The Cursor CLI does not emit every event the editor does; hooks should tolerate an event never firing on the CLI surface.
afterFileEdit is not exhaustive on batch/mid-session edits — post-edit hooks must be advisory, not relied on for correctness.
- Cloud-agent gaps. Cloud agents do not receive
stop, sessionStart/sessionEnd, or MCP events, and run only command-based hooks. Continual-learning-on-stop must degrade gracefully (no error) when the event never arrives.
hooks.json requires "version": 1.
Proposed scope
- Include (generalizable, useful to any ECC-on-Cursor user): continual-learning (
stop/sessionEnd → evaluate-session), post-edit format/typecheck, quality gate, commit-quality / block-no-verify shell guards, pre-compact.
- Exclude (environment- or operator-specific; keep out of the default scaffold): desktop notifications, tmux/dev-server automation, any vendor-specific security monitors, cost tracking.
- Profile-gate it: honour the existing
ECC_HOOK_PROFILE (minimal → sessionStart + continual-learning only; full → the whole applicable subset). minimal should remain the safe default for Cursor.
- Prefer the dispatcher pattern so the "first-hook-only" limitation and future event additions are both handled in one place.
Why this is worth doing upstream
The gap affects every ECC user who runs on Cursor, not any one setup — the hooks already exist; they're simply not wired for the Cursor target. Completing the parity that #2066 started makes the Cursor install a first-class citizen rather than a memory-root-only install.
Offer
Happy to implement this if the direction is acceptable — including the Cursor-contract adapters, dispatcher wiring, and profile gating, tested against both the Cursor editor and CLI surfaces.
Summary
Follow-up to #2065 / #2066. That work gave Cursor an independent memory root (
ECC_AGENT_DATA_HOME) and wired a singlesessionStarthook (cursor-session-env.js). But the Cursor scaffold'sscaffolds/cursor/hooks.jsonstill registers only that one hook, whilescripts/hooks/ships ~48 hook scripts that are wired for the Claude Code target. So an ECC-on-Cursor user today gets the data-root isolation but almost none of ECC's hook-driven behaviour — no continual-learning on stop, no post-edit format/typecheck, no quality gate, no commit-quality guard, no compaction hooks.This proposes wiring the generalizable subset of ECC's existing hooks into the Cursor scaffold, adapted to Cursor's hook contract and gated by hook profile.
Current state
scaffolds/cursor/hooks.json:{ "version": 1, "hooks": { "sessionStart": [ { "command": "node .cursor/scripts/hooks/cursor-session-env.js" } ] } }Cursor hook contract (3.x) — relevant facts
Cursor's agent hooks map closely onto ECC's Claude-side model, so most hooks port by event-name mapping + matcher translation. Proposed mapping:
post-edit-format/-typecheck/-console-warnafterFileEdit(matcherWrite)pre-bash-commit-quality,block-no-verify,pre-bash-dev-server-blockbeforeShellExecution(regex matcher)post-bash-*afterShellExecutionquality-gate,stop-format-typecheck,evaluate-sessionstoppre-compact/suggest-compactpreCompactsession-end/-markersessionEndFour contract constraints the implementation must respect (all observed on current Cursor):
*-dispatcher.jsfan-out scripts — the Cursor wiring should register a single dispatcher per event and fan out internally, not list N hooks.afterFileEditis not exhaustive on batch/mid-session edits — post-edit hooks must be advisory, not relied on for correctness.stop,sessionStart/sessionEnd, or MCP events, and run only command-based hooks. Continual-learning-on-stopmust degrade gracefully (no error) when the event never arrives.hooks.jsonrequires"version": 1.Proposed scope
stop/sessionEnd→evaluate-session), post-edit format/typecheck, quality gate, commit-quality /block-no-verifyshell guards, pre-compact.ECC_HOOK_PROFILE(minimal→ sessionStart + continual-learning only;full→ the whole applicable subset).minimalshould remain the safe default for Cursor.Why this is worth doing upstream
The gap affects every ECC user who runs on Cursor, not any one setup — the hooks already exist; they're simply not wired for the Cursor target. Completing the parity that #2066 started makes the Cursor install a first-class citizen rather than a memory-root-only install.
Offer
Happy to implement this if the direction is acceptable — including the Cursor-contract adapters, dispatcher wiring, and profile gating, tested against both the Cursor editor and CLI surfaces.