Cursor
One command installs project-level hooks (VCS + cloud-agent compatible), always-on rules, and the memorylayer skill. Cursor enforces recall-before-read, loads priority memories directly from SQLite, and runs the WCM cognitive cycle (THINK / LEARN / VERIFY / SLEEP) — automatically.
Setup
Run from your project root (where you want hooks committed to git). MCP config stays global; hooks install into .cursor/ in the repo:
memorylayer namespace set <project-name> # recommended
memorylayer setup --ide cursor --yes.cursor/hooks.json in place and migrates away legacy user-level entries from ~/.cursor/hooks.jsonto avoid double-firing hooks..cursor/hooks.json and .cursor/hooks/*to version control — Cursor cloud agents load project hooks from the repo. See the Cursor hooks docs.What gets installed
Setup installs four components: (1) project hooks + registration, (2) global MCP entry, (3) always-apply rules, (4) skill reference.
| File | Tag | Purpose |
|---|---|---|
| .cursor/hooks/memorylayer_common.js | [hook] | Shared lib — namespace resolution, session flags, scenario + vocab hints |
| .cursor/hooks/memorylayer_db_helper.js | [hook] | Shared lib — direct sqlite3 reads (priority memories, BM25 search) |
| .cursor/hooks/memorylayer_session_start.js | [hook] | sessionStart — MEMORYLAYER_NAMESPACE env + WCM bootstrap + domain file hints |
| .cursor/hooks/memorylayer_before_submit_prompt.js | [hook] | beforeSubmitPrompt — staged workflow + SQLite priority memories every turn |
| .cursor/hooks/memorylayer_pre_tool_use.js | [hook] | preToolUse — denies Read/Grep/Glob/Shell until recall/code MCP runs |
| .cursor/hooks/memorylayer_mark_used.js | [hook] | postToolUse (MCP:recall|code) — lifts preToolUse deny gate |
| .cursor/hooks/memorylayer_post_tool_use.js | [hook] | postToolUse — recall-first + error lifecycle reminders |
| .cursor/hooks/memorylayer_post_tool_use_failure.js | [hook] | postToolUseFailure — error memory lifecycle |
| .cursor/hooks/memorylayer_subagent.js | [hook] | subagentStart/Stop — BM25 memory seed + capture reminder |
| .cursor/hooks/memorylayer_pre_compact.js | [hook] | preCompact — flush + consolidate({ ripple }) before context trim |
| .cursor/hooks.json | [hook] | Registers 9 hook events with matchers (project-level) |
| ~/.cursor/mcp.json | [mcp] | Global memorylayer MCP server (stdio) |
| .cursor/rules/memorylayer.mdc | [rules] | alwaysApply rules — WCM cognitive cycle + recall-first |
| ~/.agents/skills/memorylayer/SKILL.md | [skill] | Global /memorylayer skill reference |
| .cursor/skills/memorylayer/SKILL.md | [skill] | Project copy of skill reference |
Hook lifecycle
Cursor hooks use JSON stdin/stdout (see Cursor's hooks spec). MemoryLayer maps Claude Code's lifecycle to Cursor's nearest equivalents. The diagram below shows the cognitive flow — every session compounds on the last.
Cursor vs Claude Code
Cursor's hook API differs in a few important ways. MemoryLayer adapts rather than forcing Claude-parity where it would cause bugs:
- Project hooks — installed to
.cursor/in the repo (not~/.cursor/hooks/), so cloud agents and teammates get the same behavior - No PostCompact —
beforeSubmitPromptre-loads priority memories on every turn to compensate - No Stop hook — Cursor's
stoponly acceptsfollowup_message, which re-triggers a full agent loop; skipped intentionally - No SessionEnd injection — fire-and-forget only; consolidation is prompted via
preCompactand rules instead - preToolUse deny — real
permission: "deny"on Read/Grep/Glob/Shell (retry always allowed after one denial)
How each hook works
sessionStart
Fires when a new Agent/Composer session starts. Returns{ env, additional_context }:
- Sets
MEMORYLAYER_NAMESPACEenv for all subsequent hooks in the session - Injects WCM bootstrap (THINK / LEARN / VERIFY / SLEEP)
- Auto-detects
.domainfiles under.claude/domains/ordomains/and hintsdomain({ action: "load" })
beforeSubmitPrompt
Fires before each prompt is sent (matcher: UserPromptSubmit). This is the main cognitive driver — equivalent to Claude's UserPromptSubmit:
- Resets per-turn enforcement flags (memory must be consulted fresh each turn)
- Loads priority
[rule][constraint][guide]memories directly from SQLite (cross-namespace) - Ingest guard — git SHA check; skips
code(ingest)when codebase unchanged - Scenario routing — caller/import, symbol lookup, investigation, error/fix, verify claims
- Vocabulary index hints when
memorylayer indexwas run
preToolUse
Matcher: Read|Grep|Glob|Shell|Write|Edit. The first Read, Grep,Glob, or Shell call each turn returnspermission: "deny" unlessrecall or code MCP already ran. One retry is always allowed — no deadlock when memory is empty.
postToolUse (mark_used)
Matcher: MCP:recall|MCP:code. Sets the session flag that lifts the preToolUse deny gate for the rest of the turn.
postToolUse (reminders)
Fires after all tools. Injects agent_message reminders for error lifecycle (after edits) and recall-first (after direct reads).
postToolUseFailure
Captures tool failures into the error memory lifecycle:[error][open] → [error][fixed][solution], one memory per error.
preCompact
Cursor has no PostCompact event. preCompact prompts flush +consolidate({ action: "ripple" }) (WCM hippocampal replay) before context is trimmed. The next beforeSubmitPrompt re-anchors priority memories automatically.
subagentStart & subagentStop
subagentStart seeds the subagent with BM25-matched memory content from SQLite (queried against its task description). Always permission: allow— spawning isn't the risky action. subagentStop reminds to capture findings viaremember(), verify(), andconsolidate().
Cursor rules
The managed block in .cursor/rules/memorylayer.mdc hasalwaysApply: true. Key sections mirror the WCM cognitive cycle:
WCM cognitive cycle — use these every session:
THINK → recall({ query, explore: true })
LEARN → remember({ content, namespace })
VERIFY → verify({ text: "<claims>", domain? })
SLEEP → consolidate({ action: "ripple", namespace })
Before reading files:
recall({ query, namespace }) FIRST
Only Read if recall returns answer_kind="empty"Namespace setup
Namespace resolves from ~/.memorylayer/namespaces.json(directory-scoped, most specific path wins) or the global default file.sessionStart exports it as MEMORYLAYER_NAMESPACE.
memorylayer namespace set my-project
memorylayer namespace get
memorylayer setup --ide cursor --yesmemorylayer setup --remove --ide cursor --yes to uninstall project hooks, rules, and skill — without touching other .cursor/ config.