
Vestige Auto Memorise
- 1 installs
- 4 repo stars
- Updated August 2, 2026
- conorluddy/vestige
Agent skill for automatically building and maintaining agent memory and context.
About
Builds persistent memory for Claude Code agents. Used by long-running agents to preserve state and context across sessions.
- Automatic context capture
- Memory persistence layer
Vestige Auto Memorise by the numbers
- 1 all-time installs (skills.sh)
- Ranked #14,098 of 16,546 AI & Agent Building skills by installs in the Skillselion catalog
- Data as of Aug 3, 2026 (Skillselion catalog sync)
npx skills add https://github.com/conorluddy/vestige --skill vestige-auto-memoriseAdd your badge
Show developers this skill is listed on Skillselion. Paste this into your README.
| Installs | 1 |
|---|---|
| repo stars | ★ 4 |
| Last updated | August 2, 2026 |
| Repository | conorluddy/vestige ↗ |
What it does
Agent skill for automatically building and maintaining agent memory and context.
Files
Auto-memorise: fire it yourself
This is the meta-capture skill. The four vestige-record-* skills wait for an explicit cue. Auto-memorise fires proactively whenever you spot a memorable moment — and dispatches inline to the right vestige subcommand without bouncing through another skill.
The point: agentic memory only compounds if capture is automatic. If the agent waits to be told "remember this" every time, the project's accumulated context stays in the user's head — exactly the failure mode Vestige exists to fix.
When to fire (the watch list)
Fire whenever the conversation produces any of the categories below. You decide the category based on the cue, then dispatch via the matching subcommand.
| Category | Cues you watch for | Subcommand | Default importance |
|---|---|---|---|
| Decision | "we'll go with…", "let's use…", "settled —", "going with X over Y because…", "decision:", explicit ## Decision headers, you chose A over B with a stated reason | vestige decision add | 0.7 (0.85+ if architectural) |
| Preference | "I prefer…", "always…", "never…", "make sure to…", "in this project we…", "convention:", "rule:", correction the user gave that you should bake in | vestige preference add | 0.6 (0.8+ for hard rules) |
| Open question | "TBD:", "open question:", "unclear whether…", "we should figure out…", "follow-up:", "park that", ## Open Questions headers | vestige question add | 0.5 (0.8+ if blocking) |
| Aha / TIL / gotcha / smell / TODO / root cause / workaround / surprise | "TIL", "turns out…", "the reason X happens is…", "good to know:", "careful — X breaks Y", "non-obvious", "smell:", "refactor candidate", "TODO:", "the bug was…", "I had assumed X but actually Y", "hack until…" | vestige note add | 0.5 (0.6 for smells / root causes) |
Tie-breaker rule of thumb: did the conversation produce a commitment with a why? Decision. A user opinion? Preference. An unknown? Question. Anything else worth keeping? Note.
If the moment is purely conversational acknowledgement, code that's better expressed as a TODO comment in source, or a fact already encoded in the codebase — don't capture. The auto-memorise loop's value comes from precision, not volume. A noisy memory store decays faster than a sparse one.
How to invoke (categorise → dedup → dispatch)
Step 1 — Categorise
Pick one row from the table above based on the cue. If two categories overlap (a user-stated commitment with a why), prefer decision over preference; the rationale field is the tiebreaker.
Step 2 — Dedup probe
Before writing, probe for an existing memory that already says this:
vestige recall "<3-6 keywords from the moment>" --type <category> --json --limit 3Skip the capture if the top hit's score clears the threshold and its one_liner says essentially the same thing:
- Lexical-only mode (default): skip when
score >= 0.6. --hybridmode: skip whenscore >= 0.75.
If you skip, cite the existing handle: "Already recorded as `mem_…`." That's still ambient surface — short and informative.
Step 3 — Dispatch inline
Call the underlying CLI directly. Don't bounce through another skill — that just wastes turns.
Decision:
vestige decision add "<one-line decision>" \
--rationale "<the why; cite tradeoffs / alternatives / constraints>" \
--importance 0.7 \
--jsonPreference:
vestige preference add "<the preference, in the user's voice>" \
--importance 0.6 \
--jsonQuestion:
vestige question add "<framed as an actual question>" \
--importance 0.5 \
--jsonNote (aha / TIL / gotcha / smell / TODO / root cause / workaround / surprise):
vestige note add "<the fact, written so it stands alone>" \
--importance 0.5 \
--jsonWhen the moment came from a specific file, attach --source <path:line> so the captured memory traces back to inspectable evidence.
After invocation
Surface a single ambient line per capture, no more:
Recorded decision mem_01HXXXXXXXXXXXXXXXX.(Or note / preference / question for the other categories.) Don't read the body back to the user — they just said it. Don't list flags or rationale; the JSON already has them. Auto-memorise must feel like a quiet background commit, not a conversation interruption.
If you captured several memories in a single turn (e.g. a long planning discussion produced two decisions and one question), batch the surface line:
Recorded decision mem_01… , decision mem_01… , question mem_01… .What this skill must NOT do
- Never call `forget` / `restore` / `show` / `context` as the primary action. Those have their own skills.
- Never use `vestige recall` for anything other than the dedup probe in Step 2. Recall has its own skill for retrieval-driven moments.
- Never re-capture when the dedup probe finds a near-duplicate. Cite the existing handle instead.
- Never narrate the capture. No "I'll record that decision because…" — just record it and surface the one-liner.
Idempotence & dedup
The skill is idempotent by discipline — the dedup probe in Step 2 is what makes proactive auto-firing safe. Without it, every "we'll go with X" from the user produces another row. With it, the second mention is a cite, not a write.
If you ever notice the project memory has accumulated near-duplicates from earlier sessions, that's a signal the dedup threshold was too generous; tighten the score thresholds in Step 2 for the rest of the session.
Why this exists (the design rationale)
The four vestige-record-* skills are precise but require an explicit "remember this" moment in the agent's reasoning. In practice that explicit moment doesn't always happen — the conversation produces a decision and moves on, and three sessions later we re-litigate the same choice.
Auto-memorise closes that loop. It says: every memorable moment is a capture moment, and you, the agent, are the trigger. The dedup probe keeps the precision that the per-type skills give you. The categorisation table keeps you using the right memory type. The ambient one-line surface keeps the user undisturbed.
Future configurability: .vestige/config.toml will gain an auto_memorise = ["decision", "preference", "question"] knob so projects can opt out of categories that are too noisy for them. Until that ships, all four categories are on by default.
{
"skill_name": "vestige-auto-memorise",
"evals": [
{
"id": 1,
"prompt": "ok we just settled — we're going with SQLite over Redis for the rate-limit token bucket. Single-node deploy, the Redis dependency isn't worth it.",
"expected_output": "Categorise as decision. Dedup probe via vestige recall. Then vestige decision add with rationale. Surface a single line: 'Recorded decision mem_<ULID>.'",
"files": []
},
{
"id": 2,
"prompt": "TIL — rusqlite_migration::validate panics if the migration list has a numbering gap. Surprise.",
"expected_output": "Categorise as note (aha/TIL). Dedup probe. vestige note add with importance ~0.5. Surface 'Recorded note mem_<ULID>.'",
"files": []
},
{
"id": 3,
"prompt": "in this project we never use unwrap() outside of #[cfg(test)] blocks. always propagate with ?",
"expected_output": "Categorise as preference. Dedup probe. vestige preference add with importance >=0.7 (hard rule). Surface 'Recorded preference mem_<ULID>.'",
"files": []
},
{
"id": 4,
"prompt": "open question I want to keep alive: should auto-memorise default to on or off per project? leaving it open for now",
"expected_output": "Categorise as question. Dedup probe. vestige question add. Surface 'Recorded question mem_<ULID>.'",
"files": []
},
{
"id": 5,
"prompt": "the bug was that MemoryId::parse used starts_with instead of validating the ULID character set — anything beginning with 'mem_' was accepted. fixed it.",
"expected_output": "Categorise as note (root cause). Dedup probe. vestige note add with importance 0.6. Surface 'Recorded note mem_<ULID>.'",
"files": []
},
{
"id": 6,
"prompt": "this match arm in derive_representations is duplicated four times — one per MemoryType. classic refactor candidate, code smell.",
"expected_output": "Categorise as note (code smell). Dedup probe. vestige note add with importance 0.6. Surface 'Recorded note mem_<ULID>.'",
"files": []
},
{
"id": 7,
"prompt": "decision: every crate gets its own thiserror enum (CoreError, StoreError, ConfigError); anyhow only at the CLI boundary with .context(). importance high — every crate inherits.",
"expected_output": "Categorise as decision (with explicit decision keyword). vestige decision add with --rationale and --importance >=0.85. Surface 'Recorded decision mem_<ULID>.'",
"files": []
},
{
"id": 8,
"prompt": "thanks, that's helpful — let me think about it",
"expected_output": "No capture. This is conversational acknowledgement, not a memorable moment. The skill should explicitly NOT fire vestige; produce no `Recorded ...` line.",
"files": []
},
{
"id": 9,
"prompt": "TODO: write the function get_project_id_from_remote — single-line code task",
"expected_output": "No capture (or a borderline note at most). The agent should recognise this as a code task that belongs as a TODO comment in source, not as project-level memory. Strong precision here matters.",
"files": []
},
{
"id": 10,
"prompt": "careful — restoring a soft-deleted memory does not regenerate embeddings, the old embeddings stay marked stale until the next `vestige embed` run. non-obvious gotcha.",
"expected_output": "Categorise as note (gotcha). Dedup probe. vestige note add. Surface single line.",
"files": []
},
{
"id": 11,
"prompt": "I prefer integration tests against real SQLite over mocks, every time. don't mock the DB.",
"expected_output": "Categorise as preference. Dedup probe. vestige preference add. Surface single line.",
"files": []
},
{
"id": 12,
"prompt": "Long planning discussion: ok so we'll use rmcp 0.16 with stdio transport (decision) — and I want every public MCP tool to map 1:1 to a high-level core function, no raw SQL exposed (preference / rule). Also TBD whether we ship a vestige_admin tool surface in v0.5.",
"expected_output": "Three captures in one turn: vestige decision add (rmcp 0.16 stdio), vestige preference add (no raw SQL, 1:1 high-level mapping), vestige question add (vestige_admin in v0.5). Single batched surface line listing all three handles.",
"files": []
}
]
}
[
{ "query": "ok we're going with SQLite over Redis, single-node deploy doesn't need it", "should_trigger": true },
{ "query": "TIL rusqlite_migration validates numbering gaps and panics on them", "should_trigger": true },
{ "query": "I prefer integration tests against real SQLite, never mock the DB in this project", "should_trigger": true },
{ "query": "TBD: should auto-memorise default on or off per project? leaving open", "should_trigger": true },
{ "query": "the bug was MemoryId::parse using starts_with — accepted any garbage after mem_", "should_trigger": true },
{ "query": "this derive_representations match arm is duplicated 4× per MemoryType, classic smell", "should_trigger": true },
{ "query": "careful — restoring a forgotten memory leaves embeddings stale until you re-embed", "should_trigger": true },
{ "query": "convention: no unwrap() outside #[cfg(test)] in this project", "should_trigger": true },
{ "query": "I had assumed rusqlite bundled mode used the system sqlite — actually it pins to the crate's version. heads up", "should_trigger": true },
{ "query": "decision: rmcp 0.16 with stdio transport, settled. importance high", "should_trigger": true },
{ "query": "follow-up to investigate: should hybrid recall normalise scores min-max or rank-based?", "should_trigger": true },
{ "query": "thanks, that makes sense", "should_trigger": false },
{ "query": "ok cool", "should_trigger": false },
{ "query": "let me think about that for a moment", "should_trigger": false },
{ "query": "search memory for what we said about embeddings", "should_trigger": false },
{ "query": "show me mem_01H8XYZ in full", "should_trigger": false },
{ "query": "give me the project context pack", "should_trigger": false },
{ "query": "forget mem_01H8XYZ", "should_trigger": false },
{ "query": "restore mem_01H8XYZ", "should_trigger": false },
{ "query": "TODO: write the function get_project_id_from_remote", "should_trigger": false },
{ "query": "fix the failing test in vestige-store/src/lib.rs:402", "should_trigger": false },
{ "query": "what's the current SQLite version we're bundling?", "should_trigger": false }
]