feat: add mempalace-recall skill and optional Cursor recall rule
Ports the OpenClaw "search before answering" protocol to the Cursor and Claude plugin surfaces so the agent reads the palace before answering about past work, people, projects, or prior decisions instead of guessing from model memory. - integrations/shared/recall-protocol.md: single source of truth for the recall protocol, referenced by the skill and the rule so they cannot drift. - skills/mempalace-recall/SKILL.md: recall-only skill (the mempalace skill keeps setup/mine/status); cross-linked from the ops skill. - rules/mempalace-recall.mdc: plugin recall rule, alwaysApply: false so it only fires on recall-relevant turns and never adds MCP latency to greenfield work. - examples/cursor/rules/: opt-in copies for non-plugin users, including an aggressive alwaysApply: true variant documented with its latency tradeoff. - .claude-plugin/skills/mempalace-recall/SKILL.md: Claude plugin parity. - tests: assert the recall skill and rules/ discovery layout; the shipped rule must be alwaysApply: false. - docs: .cursor-plugin/README.md and the cursor-hooks guide now describe the three layers of recall (hook + skill + rule). The Antigravity plugin mirror lands as a follow-up on the antigravity branch, where .antigravity-plugin/ exists. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
parent
c420a9f66c
commit
24ad98df8c
|
|
@ -0,0 +1,60 @@
|
|||
---
|
||||
name: mempalace-recall
|
||||
description: Recall protocol for MemPalace — search the palace before answering about past work, prior decisions, people, or projects. Use when the user asks what was decided, what happened before, who someone is, what was discussed last time, or anything that may already be filed in their memory palace.
|
||||
allowed-tools: Bash
|
||||
---
|
||||
|
||||
# MemPalace Recall
|
||||
|
||||
Search-before-answer protocol for MemPalace. Read the user's memory
|
||||
palace before answering anything that may already be filed there,
|
||||
instead of guessing from model memory. This complements the `mempalace`
|
||||
skill (install / mine / status); this one covers recall only.
|
||||
|
||||
## Step 0 — Verify MemPalace is available
|
||||
|
||||
```bash
|
||||
mempalace --version
|
||||
```
|
||||
|
||||
If the `mempalace_*` MCP tools are not available, tell the user the
|
||||
server is not connected and point them at the `mempalace` skill or
|
||||
`/init`. Do not silently fall back to answering from model memory.
|
||||
|
||||
## When to recall
|
||||
|
||||
Search the palace **before answering** whenever the user asks about
|
||||
something that may be filed:
|
||||
|
||||
- Past work or prior decisions — "what did we decide / try / do?"
|
||||
- A person, project, or entity — "who is …", "what is …"
|
||||
- An earlier session — "remember when …", "last time …"
|
||||
- A preference, fact, or relationship that could have changed over time
|
||||
|
||||
Skip recall for pure greenfield work with no memory relevance (renaming
|
||||
a variable, fixing a typo). Recall is question-driven, not reflexive.
|
||||
|
||||
## Protocol
|
||||
|
||||
1. Before responding about people / projects / past events / prior
|
||||
decisions: call `mempalace_search` first. Use `mempalace_kg_query`
|
||||
for relational or time-bound facts.
|
||||
2. If unsure about a fact: say "let me check the palace" and query.
|
||||
3. Return the drawer's **verbatim** text — never summarize or paraphrase
|
||||
stored content.
|
||||
4. After a substantive session, record continuity with
|
||||
`mempalace_diary_write` (skip if a background hook already saved).
|
||||
5. When a fact changes: `mempalace_kg_invalidate` the old fact, then
|
||||
`mempalace_kg_add` the new one.
|
||||
|
||||
## Unhappy paths
|
||||
|
||||
- **Empty results** — say the palace has nothing on this; do not invent
|
||||
an answer. Offer to widen the search or file the new information.
|
||||
- **MCP error / server down** — surface the error, suggest `mempalace
|
||||
status` or re-running `/init`; never fall back to guessing.
|
||||
- **Conflicting facts** — trust the knowledge graph's time-valid answer;
|
||||
invalidate-then-add rather than overwriting silently.
|
||||
|
||||
The canonical protocol, shared across all MemPalace integrations, lives
|
||||
in `integrations/shared/recall-protocol.md`.
|
||||
|
|
@ -1,6 +1,6 @@
|
|||
# MemPalace Cursor Plugin
|
||||
|
||||
A Cursor IDE plugin that gives your agent a persistent memory system. Auto-registers the `mempalace-mcp` server (19 MCP tools), ships 5 slash commands, and provides one model-invocable skill that guides the agent through setup, mining, and search.
|
||||
A Cursor IDE plugin that gives your agent a persistent memory system. Auto-registers the `mempalace-mcp` server (19 MCP tools), ships 5 slash commands, two model-invocable skills (setup/mining/search and a recall protocol), and an optional recall rule.
|
||||
|
||||
> Hooks (auto-save + session-start memory recall) are shipped separately under `hooks/cursor/` so the plugin is safe to install in any Cursor workspace without touching the agent loop. See [Hooks](#hooks-optional) below.
|
||||
|
||||
|
|
@ -49,6 +49,30 @@ This installs the `mempalace` package via `uv tool` or `pip`, initializes a pala
|
|||
|
||||
> Cursor commands are global, not plugin-namespaced — that's why each slug is prefixed with `mempalace-` rather than appearing as `/help`, `/init`, etc. This keeps them collision-free with built-in or other-plugin commands.
|
||||
|
||||
## Skills
|
||||
|
||||
Two model-invocable skills ship at the plugin root under `skills/`:
|
||||
|
||||
| Skill | What it does |
|
||||
|-------|--------------|
|
||||
| `mempalace` | Setup, mining, status, and the dynamic `mempalace instructions` CLI. |
|
||||
| `mempalace-recall` | Search-before-answer protocol — makes the agent read the palace before answering about past work, people, projects, or prior decisions instead of guessing. |
|
||||
|
||||
Cursor surfaces these automatically when a request matches their description, or you can attach them explicitly.
|
||||
|
||||
## Recall rule (optional)
|
||||
|
||||
The plugin also ships a Cursor rule at the plugin root under `rules/mempalace-recall.mdc`:
|
||||
|
||||
```yaml
|
||||
description: When the user asks about past work, prior decisions, people, ... call mempalace_search before answering ...
|
||||
alwaysApply: false
|
||||
```
|
||||
|
||||
It is `alwaysApply: false` on purpose — Cursor loads it only when its matcher judges the turn recall-relevant, so it never fires on unrelated coding work and never adds MCP latency to greenfield tasks. The rule, the `mempalace-recall` skill, and the `sessionStart` hook all reference the same canonical protocol in [`integrations/shared/recall-protocol.md`](../integrations/shared/recall-protocol.md).
|
||||
|
||||
Want recall forced into **every** conversation regardless of context? Copy the aggressive `alwaysApply: true` variant from [`examples/cursor/rules/`](../examples/cursor/rules/README.md) into `~/.cursor/rules/`. That is a deliberate, heavier opt-in, not a default.
|
||||
|
||||
## MCP Server
|
||||
|
||||
This plugin ships `mcp.json` at the plugin root, so Cursor auto-loads the `mempalace-mcp` server on plugin install:
|
||||
|
|
|
|||
|
|
@ -0,0 +1,58 @@
|
|||
# Cursor Rules — MemPalace recall
|
||||
|
||||
Optional [Cursor rules](https://cursor.com/docs/rules) that make the
|
||||
agent search MemPalace before answering questions about past work,
|
||||
people, projects, or prior decisions.
|
||||
|
||||
These are for users who install MemPalace **without** the Cursor plugin
|
||||
(or who want recall behaviour in a specific project). If you installed
|
||||
the [Cursor plugin](../../../.cursor-plugin/README.md), it already ships
|
||||
the `alwaysApply: false` rule at the plugin root — you do not need to
|
||||
copy anything.
|
||||
|
||||
## Which file to use
|
||||
|
||||
| File | `alwaysApply` | Fires when | Use when |
|
||||
|------|---------------|------------|----------|
|
||||
| [`mempalace-recall.mdc`](mempalace-recall.mdc) | `false` | Cursor's matcher decides the turn is recall-relevant (from the rule `description`) | **Recommended.** Recall without paying for the rule on unrelated work. |
|
||||
| [`mempalace-recall-always.mdc`](mempalace-recall-always.mdc) | `true` | Every conversation in scope, every turn | You want recall guaranteed in context and accept the cost. |
|
||||
|
||||
The always-on variant is heavier: it sits in context on every turn and
|
||||
makes the agent more eager to call `mempalace_search`, which adds MCP
|
||||
latency and works against MemPalace's "memory should feel instant"
|
||||
budget. Prefer the `false` variant unless you specifically want recall
|
||||
forced into every conversation. Pick **one** of the two — do not install
|
||||
both.
|
||||
|
||||
## Install
|
||||
|
||||
User scope (every workspace) — copy into `~/.cursor/rules/`:
|
||||
|
||||
```bash
|
||||
mkdir -p ~/.cursor/rules
|
||||
cp examples/cursor/rules/mempalace-recall.mdc ~/.cursor/rules/
|
||||
```
|
||||
|
||||
Project scope (this repo only) — copy into `.cursor/rules/`:
|
||||
|
||||
```bash
|
||||
mkdir -p .cursor/rules
|
||||
cp examples/cursor/rules/mempalace-recall.mdc .cursor/rules/
|
||||
```
|
||||
|
||||
For the aggressive variant, copy `mempalace-recall-always.mdc` instead
|
||||
(only one of the two). Then reload Cursor:
|
||||
<kbd>Cmd</kbd>-<kbd>Shift</kbd>-<kbd>P</kbd> → **Developer: Reload Window**.
|
||||
|
||||
## How recall is delivered
|
||||
|
||||
Recall ships in three orthogonal layers — install any combination:
|
||||
|
||||
| Layer | What it does | Where |
|
||||
|-------|--------------|-------|
|
||||
| `sessionStart` hook | Injects wing-scoped recall context once per new chat | [`hooks/cursor/`](../../../hooks/cursor/) |
|
||||
| `mempalace-recall` skill | Full search-before-answer protocol, model-invoked or attached | [`skills/mempalace-recall/`](../../../skills/mempalace-recall/) |
|
||||
| Recall rule (these files) | Nudges search-before-answer on recall-relevant turns | here, or the plugin root `rules/` |
|
||||
|
||||
All three reference the same canonical protocol in
|
||||
[`integrations/shared/recall-protocol.md`](../../../integrations/shared/recall-protocol.md).
|
||||
|
|
@ -0,0 +1,25 @@
|
|||
---
|
||||
description: Always-on MemPalace recall — search the palace before answering about past work, people, projects, or prior decisions.
|
||||
alwaysApply: true
|
||||
---
|
||||
|
||||
# MemPalace recall (always on)
|
||||
|
||||
This is the aggressive variant of the recall rule: `alwaysApply: true`
|
||||
loads it into every conversation in scope, on every turn, regardless of
|
||||
whether Cursor's matcher thinks recall is relevant.
|
||||
|
||||
Before answering anything that may already be in the user's memory
|
||||
palace — past work, prior decisions, a person, a project, or "what did
|
||||
we do / decide / discuss last time?" — search the palace first:
|
||||
|
||||
1. Call `mempalace_search` with a short keyword query. Use
|
||||
`mempalace_kg_query` for relational or time-bound facts.
|
||||
2. Quote the drawer's **verbatim** text. Never summarize or paraphrase
|
||||
stored content.
|
||||
3. If results are empty, say so — do not invent an answer. If the MCP
|
||||
server is unavailable, surface the error; do not fall back to guessing.
|
||||
|
||||
Even with this rule always loaded, only actually call the tools when the
|
||||
question touches memory. Do not search on pure greenfield work
|
||||
(renaming a variable, fixing a typo).
|
||||
|
|
@ -0,0 +1,20 @@
|
|||
---
|
||||
description: When the user asks about past work, prior decisions, people, projects, or events that may be filed in MemPalace, call mempalace_search (or mempalace_kg_query for relational or time-bound facts) before answering from model memory. Return stored content verbatim; never guess when the palace might know.
|
||||
alwaysApply: false
|
||||
---
|
||||
|
||||
# MemPalace recall
|
||||
|
||||
Before answering anything that may already be in the user's memory
|
||||
palace — past work, prior decisions, a person, a project, or "what did
|
||||
we do / decide / discuss last time?" — search the palace first:
|
||||
|
||||
1. Call `mempalace_search` with a short keyword query. Use
|
||||
`mempalace_kg_query` for relational or time-bound facts.
|
||||
2. Quote the drawer's **verbatim** text. Never summarize or paraphrase
|
||||
stored content.
|
||||
3. If results are empty, say so — do not invent an answer. If the MCP
|
||||
server is unavailable, surface the error; do not fall back to guessing.
|
||||
|
||||
Skip recall for pure greenfield work with no memory relevance (renaming
|
||||
a variable, fixing a typo). Recall is question-driven, not reflexive.
|
||||
|
|
@ -0,0 +1,92 @@
|
|||
# MemPalace Recall Protocol
|
||||
|
||||
The canonical "search before answering" protocol shared across every
|
||||
MemPalace integration (Cursor, Antigravity, Claude Code, Codex,
|
||||
OpenClaw). This file is the single source of truth — skills and rules
|
||||
should link here rather than restating the protocol, so the rule never
|
||||
drifts from the skill.
|
||||
|
||||
The protocol exists to honour MemPalace's foundational promise:
|
||||
**100% recall, verbatim, never guess.** When the palace might hold the
|
||||
answer, the agent must read the palace before answering from model
|
||||
memory.
|
||||
|
||||
## When to recall
|
||||
|
||||
Search the palace **before answering** whenever the user asks about
|
||||
anything that may already be filed:
|
||||
|
||||
- Past work, prior decisions, or "what did we do / decide / try?"
|
||||
- A person, project, or entity ("who is …", "what is …")
|
||||
- Something that happened in an earlier session ("remember when …",
|
||||
"last time …", "the thing we discussed")
|
||||
- A preference, fact, or relationship that could have changed over time
|
||||
|
||||
If the question is pure greenfield work with no memory relevance (e.g.
|
||||
"rename this variable", "fix this typo"), do not search — recall is
|
||||
question-driven, not reflexive.
|
||||
|
||||
## The protocol
|
||||
|
||||
1. **On wake-up** (if a session-start hook is installed, honour its
|
||||
`additional_context`): scope recall to the wing inferred from the
|
||||
workspace, then continue.
|
||||
2. **Before responding** about people, projects, past events, or prior
|
||||
decisions: call `mempalace_search` first. For relational or temporal
|
||||
facts ("who reported to whom in March", "what was true then"), call
|
||||
`mempalace_kg_query` instead or as well.
|
||||
3. **If unsure** about a fact (name, age, relationship, preference): say
|
||||
"let me check the palace" and query. Wrong is worse than slow.
|
||||
4. **Return verbatim.** Quote the drawer's exact stored words. Never
|
||||
summarize, paraphrase, or lossy-compress what the palace returns —
|
||||
that is the whole point of the system.
|
||||
5. **After a substantive session**, record continuity with
|
||||
`mempalace_diary_write` (background hooks may already do this — do not
|
||||
double-file).
|
||||
6. **When a fact changes**, call `mempalace_kg_invalidate` on the old
|
||||
fact, then `mempalace_kg_add` for the new one.
|
||||
|
||||
## Tool selection
|
||||
|
||||
| You need | Tool |
|
||||
|---|---|
|
||||
| Find any memory by meaning | `mempalace_search` (start here) |
|
||||
| Relational / time-bound facts about an entity | `mempalace_kg_query` |
|
||||
| The chronological story of an entity | `mempalace_kg_timeline` |
|
||||
| Recent session continuity | `mempalace_diary_read` |
|
||||
| Which wings / rooms exist (when scope unknown) | `mempalace_list_wings`, `mempalace_list_rooms` |
|
||||
| Record this session | `mempalace_diary_write` |
|
||||
|
||||
`mempalace_search` takes a short natural-language `query` (keywords or a
|
||||
question — not a system prompt or pasted conversation) plus optional
|
||||
`wing` / `room` filters and `limit` (default 5).
|
||||
|
||||
## Unhappy paths
|
||||
|
||||
- **Empty results.** Say the palace has nothing on this; do not invent an
|
||||
answer to fill the gap. Offer to widen the search (drop the wing
|
||||
filter) or to file the new information.
|
||||
- **MCP unavailable / tool error.** Surface the error plainly and suggest
|
||||
the user verify the server (`mempalace status`, or re-run install).
|
||||
Do not silently fall back to guessing from model memory.
|
||||
- **Stale or conflicting facts.** Prefer the knowledge graph's
|
||||
time-valid answer; if a fact has changed, invalidate the old one and
|
||||
add the new one rather than overwriting context silently.
|
||||
|
||||
## Anti-patterns
|
||||
|
||||
- Answering about past work, people, or decisions from model memory when
|
||||
the palace might know — search first.
|
||||
- Paraphrasing or summarizing stored content instead of quoting it
|
||||
verbatim.
|
||||
- Searching reflexively on every turn, including pure greenfield coding
|
||||
with no memory relevance.
|
||||
- Pasting the full conversation or a system prompt into the `query`
|
||||
argument — keep queries short and keyword-driven.
|
||||
|
||||
## See also
|
||||
|
||||
- [`integrations/openclaw/SKILL.md`](../openclaw/SKILL.md) — the original
|
||||
full-protocol skill this is distilled from.
|
||||
- MemPalace design principles (verbatim, local-first, never summarize):
|
||||
<https://github.com/MemPalace/mempalace>
|
||||
|
|
@ -0,0 +1,23 @@
|
|||
---
|
||||
description: When the user asks about past work, prior decisions, people, projects, or events that may be filed in MemPalace, call mempalace_search (or mempalace_kg_query for relational or time-bound facts) before answering from model memory. Return stored content verbatim; never guess when the palace might know.
|
||||
alwaysApply: false
|
||||
---
|
||||
|
||||
# MemPalace recall
|
||||
|
||||
Before answering anything that may already be in the user's memory
|
||||
palace — past work, prior decisions, a person, a project, or "what did
|
||||
we do / decide / discuss last time?" — search the palace first:
|
||||
|
||||
1. Call `mempalace_search` with a short keyword query. Use
|
||||
`mempalace_kg_query` for relational or time-bound facts.
|
||||
2. Quote the drawer's **verbatim** text. Never summarize or paraphrase
|
||||
stored content.
|
||||
3. If results are empty, say so — do not invent an answer. If the MCP
|
||||
server is unavailable, surface the error; do not fall back to guessing.
|
||||
|
||||
Skip recall for pure greenfield work with no memory relevance (renaming
|
||||
a variable, fixing a typo). Recall is question-driven, not reflexive.
|
||||
|
||||
Full protocol: `integrations/shared/recall-protocol.md`. Deeper guidance:
|
||||
the `mempalace-recall` skill.
|
||||
|
|
@ -0,0 +1,112 @@
|
|||
---
|
||||
name: mempalace-recall
|
||||
description: "Recall protocol for MemPalace — search the palace before answering about past work, people, projects, or prior decisions. Apply when the user asks what was decided, what happened before, who someone is, what was discussed last time, or anything that may already be filed in their memory palace; or when mempalace-recall is invoked. Complements the mempalace setup skill and requires the mempalace-mcp server."
|
||||
---
|
||||
|
||||
# MemPalace Recall
|
||||
|
||||
Search-before-answer protocol for MemPalace. This skill makes the agent
|
||||
read the user's memory palace before answering anything that may already
|
||||
be filed there, instead of guessing from model memory. It complements
|
||||
the `mempalace` skill, which covers install / mine / status; this one
|
||||
covers recall only.
|
||||
|
||||
## Step 0 — Verify MemPalace is available
|
||||
|
||||
Before relying on recall, confirm MemPalace is installed and reachable:
|
||||
|
||||
- Official release page: <https://github.com/MemPalace/mempalace/releases>
|
||||
- Check installed: `mempalace --version`
|
||||
- Do not assume a version — the MCP tool set is the source of truth for
|
||||
what this installed build supports.
|
||||
|
||||
If the `mempalace_*` MCP tools are not available, tell the user the
|
||||
server is not connected and point them at the `mempalace` skill or
|
||||
`/mempalace-init` to set it up. Do not silently fall back to answering
|
||||
from model memory.
|
||||
|
||||
## Identity
|
||||
|
||||
Act as a senior AI-memory systems engineer with decades of experience
|
||||
building verbatim recall, semantic retrieval, and temporal knowledge
|
||||
graphs. Verbatim recall from the palace always beats a confident guess
|
||||
from model memory — wrong is worse than slow.
|
||||
|
||||
## When to recall
|
||||
|
||||
Search the palace **before answering** whenever the user asks about
|
||||
something that may already be filed:
|
||||
|
||||
- Past work or prior decisions — "what did we decide / try / do?"
|
||||
- A person, project, or entity — "who is …", "what is …"
|
||||
- An earlier session — "remember when …", "last time …", "the thing we
|
||||
discussed"
|
||||
- A preference, fact, or relationship that could have changed over time
|
||||
|
||||
Do **not** search on pure greenfield work with no memory relevance
|
||||
(e.g. "rename this variable", "fix this typo"). Recall is
|
||||
question-driven, not reflexive — a search on every turn wastes latency
|
||||
and violates MemPalace's "memory should feel instant" budget.
|
||||
|
||||
## Protocol
|
||||
|
||||
1. On wake-up, if a session-start hook injected `additional_context`,
|
||||
honour its wing scoping.
|
||||
2. Before responding about people / projects / past events / prior
|
||||
decisions: call `mempalace_search` first. Use `mempalace_kg_query`
|
||||
for relational or time-bound facts.
|
||||
3. If unsure about a fact: say "let me check the palace" and query.
|
||||
4. Return the drawer's **verbatim** text. Never summarize or paraphrase
|
||||
stored content — quoting the exact words is the point of the system.
|
||||
5. After a substantive session, record continuity with
|
||||
`mempalace_diary_write` (skip if a background hook already saved).
|
||||
6. When a fact changes: `mempalace_kg_invalidate` the old fact, then
|
||||
`mempalace_kg_add` the new one.
|
||||
|
||||
The full canonical protocol — shared verbatim with the Cursor recall
|
||||
rule and the other integrations — lives in
|
||||
[`integrations/shared/recall-protocol.md`](../../integrations/shared/recall-protocol.md).
|
||||
|
||||
## Tool selection
|
||||
|
||||
| You need | Tool |
|
||||
|---|---|
|
||||
| Find any memory by meaning | `mempalace_search` (start here) |
|
||||
| Relational / time-bound facts about an entity | `mempalace_kg_query` |
|
||||
| The chronological story of an entity | `mempalace_kg_timeline` |
|
||||
| Recent session continuity | `mempalace_diary_read` |
|
||||
| Which wings / rooms exist (scope unknown) | `mempalace_list_wings`, `mempalace_list_rooms` |
|
||||
| Record this session | `mempalace_diary_write` |
|
||||
|
||||
`mempalace_search` takes a short natural-language `query` (keywords or a
|
||||
question — not a system prompt or pasted conversation) plus optional
|
||||
`wing` / `room` filters and `limit` (default 5).
|
||||
|
||||
## Unhappy paths
|
||||
|
||||
- **Empty results.** Say the palace has nothing on this; do not invent an
|
||||
answer. Offer to widen the search (drop the `wing` filter) or to file
|
||||
the new information.
|
||||
- **MCP error / server down.** Surface the error and suggest the user
|
||||
run `mempalace status` or re-run `/mempalace-init`. Never fall back to
|
||||
guessing.
|
||||
- **Conflicting facts.** Trust the knowledge graph's time-valid answer;
|
||||
invalidate-then-add rather than overwriting silently.
|
||||
|
||||
## Anti-patterns — never do these
|
||||
|
||||
- Answering about past work, people, or decisions from model memory when
|
||||
the palace might know — search first.
|
||||
- Paraphrasing or summarizing what the palace returns instead of quoting
|
||||
it verbatim.
|
||||
- Searching on every turn, including greenfield tasks with no memory
|
||||
relevance.
|
||||
- Pasting the whole conversation or a system prompt into the `query`
|
||||
argument — keep queries short and keyword-driven.
|
||||
|
||||
## Official References
|
||||
|
||||
- MemPalace: <https://github.com/MemPalace/mempalace>
|
||||
- MemPalace releases: <https://github.com/MemPalace/mempalace/releases>
|
||||
- Cursor Skills documentation: <https://cursor.com/docs/skills>
|
||||
- Agent Skills specification: <https://agentskills.io/specification>
|
||||
|
|
@ -33,6 +33,13 @@ Where `<command>` is one of: `help`, `init`, `mine`, `search`, `status`.
|
|||
|
||||
Run the appropriate instructions command, then follow the returned instructions step by step.
|
||||
|
||||
## Recalling past work
|
||||
|
||||
This skill covers setup, mining, and status. For questions about past
|
||||
work, prior decisions, or people that may already be filed in the
|
||||
palace, prefer the **`mempalace-recall`** skill — it enforces
|
||||
search-before-answer so the agent reads the palace instead of guessing.
|
||||
|
||||
## Cursor-specific notes
|
||||
|
||||
- The `mempalace-mcp` server is auto-registered by this plugin. Once installed, all 19 MemPalace MCP tools (`mempalace_search`, `mempalace_add_drawer`, `mempalace_diary_write`, `mempalace_check_duplicate`, `mempalace_diary_read`, etc.) are available to the agent without any further configuration.
|
||||
|
|
|
|||
|
|
@ -47,6 +47,7 @@ README_PATH = PLUGIN_DIR / "README.md"
|
|||
# directories at the plugin root; .cursor-plugin/ symlinks back to these.
|
||||
SKILLS_DIR = REPO_ROOT / "skills"
|
||||
COMMANDS_DIR = REPO_ROOT / "commands"
|
||||
RULES_DIR = REPO_ROOT / "rules"
|
||||
|
||||
# The slugs we promise to ship. The README's "Available Slash Commands"
|
||||
# table is the user-facing contract; if you add/remove a command,
|
||||
|
|
@ -291,6 +292,13 @@ class TestSkills:
|
|||
def test_mempalace_skill_exists(self):
|
||||
assert (SKILLS_DIR / "mempalace" / "SKILL.md").is_file()
|
||||
|
||||
def test_mempalace_recall_skill_exists(self):
|
||||
"""The recall skill is the search-before-answer half of the
|
||||
plugin (the ``mempalace`` skill covers setup/mine/status). If it
|
||||
goes missing, recall silently regresses to model-memory guessing.
|
||||
"""
|
||||
assert (SKILLS_DIR / "mempalace-recall" / "SKILL.md").is_file()
|
||||
|
||||
def test_each_skill_has_valid_frontmatter(self):
|
||||
"""Every SKILL.md must declare ``name`` (kebab-case) and a
|
||||
non-empty ``description``. Skills missing these fields silently
|
||||
|
|
@ -327,6 +335,66 @@ class TestSkills:
|
|||
)
|
||||
|
||||
|
||||
# ── rules/ ──────────────────────────────────────────────────────────
|
||||
|
||||
|
||||
class TestRules:
|
||||
"""The plugin ships an optional recall rule at the plugin root under
|
||||
``rules/``. Like skills and commands, rules are discovered from a
|
||||
real directory at the plugin root (the repo root), not from inside
|
||||
``.cursor-plugin/``.
|
||||
"""
|
||||
|
||||
def test_rules_dir_exists(self):
|
||||
assert RULES_DIR.is_dir(), "rules/ missing at repo root"
|
||||
|
||||
def test_rules_dir_is_real_not_symlink(self):
|
||||
assert not RULES_DIR.is_symlink(), (
|
||||
"rules/ must be a real directory, not a symlink — "
|
||||
"Cursor does not follow symlinks for local-plugin discovery"
|
||||
)
|
||||
|
||||
def test_recall_rule_exists(self):
|
||||
assert (RULES_DIR / "mempalace-recall.mdc").is_file()
|
||||
|
||||
def test_each_rule_has_valid_frontmatter(self):
|
||||
"""Every ``.mdc`` rule must declare a non-empty ``description``
|
||||
(Cursor's matcher reads it to decide relevance) and a boolean
|
||||
``alwaysApply``. A rule missing ``description`` never auto-applies.
|
||||
"""
|
||||
rule_files = list(RULES_DIR.glob("*.mdc"))
|
||||
assert rule_files, f"{RULES_DIR} must contain at least one .mdc rule"
|
||||
for rule_path in rule_files:
|
||||
text = rule_path.read_text(encoding="utf-8")
|
||||
meta, body = _parse_frontmatter(text)
|
||||
ctx = f"{rule_path.relative_to(REPO_ROOT)}"
|
||||
assert meta, f"{ctx}: missing YAML frontmatter"
|
||||
assert isinstance(meta.get("description"), str) and meta["description"], (
|
||||
f"{ctx}: 'description' must be a non-empty string"
|
||||
)
|
||||
assert isinstance(meta.get("alwaysApply"), bool), (
|
||||
f"{ctx}: 'alwaysApply' must be a boolean"
|
||||
)
|
||||
assert body.strip(), f"{ctx}: body must not be empty"
|
||||
|
||||
def test_shipped_recall_rule_is_not_always_apply(self):
|
||||
"""The plugin-shipped recall rule must be ``alwaysApply: false``.
|
||||
|
||||
An always-on rule loads on every turn in every workspace the
|
||||
plugin touches, adding MCP latency to unrelated work and fighting
|
||||
MemPalace's "memory should feel instant" budget. The aggressive
|
||||
``alwaysApply: true`` variant is an opt-in shipped only under
|
||||
examples/, never wired into the default plugin bundle.
|
||||
"""
|
||||
meta, _ = _parse_frontmatter(
|
||||
(RULES_DIR / "mempalace-recall.mdc").read_text(encoding="utf-8")
|
||||
)
|
||||
assert meta.get("alwaysApply") is False, (
|
||||
"the plugin-shipped recall rule must be alwaysApply: false; "
|
||||
"the always-on variant belongs in examples/cursor/rules/"
|
||||
)
|
||||
|
||||
|
||||
# ── commands/ ───────────────────────────────────────────────────────
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -21,6 +21,28 @@ system is configured per-user/per-project (in `~/.cursor/hooks.json`),
|
|||
not per-plugin.
|
||||
:::
|
||||
|
||||
## Three layers of recall
|
||||
|
||||
The `sessionStart` wake hook is one of three orthogonal ways MemPalace
|
||||
gets the agent to read the palace before answering. Install any
|
||||
combination — they reinforce each other and all reference the same
|
||||
canonical protocol in
|
||||
[`integrations/shared/recall-protocol.md`](https://github.com/MemPalace/mempalace/blob/develop/integrations/shared/recall-protocol.md).
|
||||
|
||||
| Layer | Fires | Scope | Get it from |
|
||||
|-------|-------|-------|-------------|
|
||||
| **`sessionStart` hook** | Once per new conversation | Injects wing-scoped recall context up front | The hooks on this page |
|
||||
| **`mempalace-recall` skill** | When a request matches its description, or when attached | Full search-before-answer protocol | The [Cursor plugin](https://github.com/MemPalace/mempalace/blob/main/.cursor-plugin/README.md) (`skills/`) |
|
||||
| **Recall rule** | When Cursor's matcher judges the turn recall-relevant | A short nudge to search first | The plugin (`rules/mempalace-recall.mdc`, `alwaysApply: false`) or [`examples/cursor/rules/`](https://github.com/MemPalace/mempalace/blob/develop/examples/cursor/rules/README.md) |
|
||||
|
||||
The hook is the only layer that fires *automatically and exactly once*
|
||||
per chat. The skill and rule are demand-driven: they kick in when the
|
||||
user actually asks about past work, people, or prior decisions, and stay
|
||||
out of the way on greenfield coding. For recall forced into every
|
||||
conversation, copy the `alwaysApply: true` variant from
|
||||
`examples/cursor/rules/` into `~/.cursor/rules/` — a heavier, deliberate
|
||||
opt-in.
|
||||
|
||||
## What They Do
|
||||
|
||||
| Hook | When It Fires | What Happens |
|
||||
|
|
|
|||
Loading…
Reference in New Issue