Persistent Memory
Spettro can remember short facts and preferences across sessions. Memory lives in two plain-Markdown files:
| Scope | File | Contents |
|---|---|---|
| user | ~/.spettro/memory.md |
Preferences that apply everywhere (style, language, workflow). |
| project | <repo>/.spettro/memory.md |
Facts specific to one repository (conventions, commands, layout). |
At session start the combined content of both files is appended to every
agent's system prompt as a # Memory section, so saved preferences are
honored automatically. Project facts are injected before user facts,
recently-used facts first.
Fact metadata
Each bullet carries an HTML-comment tail that is invisible in rendered Markdown and stripped before prompt injection:
- prefers table-driven tests <!-- id:m-a1b2c3 added:2026-07-23 used:2026-07-23 -->
id— stable short hash of the fact text, used by/memory curateops.added— date the fact was first saved.used— bumped when the same fact is saved again or curation confirms it.
Legacy bare bullets (no comment) stay valid; they are stamped automatically the first time the file is rewritten (a dedupe bump or a curation op). The files remain hand-editable Markdown — edit freely, the tail is optional.
The save-memory tool
Agents with the save-memory tool (default: coding, ask, code) can
persist a fact when you ask them to remember something:
{"fact": "prefers table-driven tests", "scope": "project"}
fact— one short line (max 500 chars).scope—user(default) orproject.
Saving is dedup-aware:
- Exact duplicate (same text after normalization) — nothing is appended;
the existing fact's
used:date is bumped. - Near-duplicate or likely contradiction (high token overlap or same
leading phrase, e.g. "prefers tabs" vs "prefers spaces") — the new fact is
routed to the review inbox as a supersede candidate instead of being
appended. Resolve it with
/memory review: approving replaces the old fact with the new one; discarding keeps the old fact. - Otherwise the fact is appended with fresh metadata.
The /memory command
| Command | Effect |
|---|---|
/memory or /memory show |
Print both memory files, their paths, and the pending inbox count. |
/memory edit [user|project] |
Open the file in $EDITOR (default vi). |
/memory clear [user|project|all] |
Erase saved memory (default: all). |
/memory mine [n] |
Scan up to n (default 10) recent saved sessions of this project in the background and draft candidate memories into the review inbox. |
/memory review |
Open the review inbox dialog. |
/memory curate [user|project|all] |
One LLM pass over the saved facts proposing merges, rewrites, and deletions; each op is applied only after you approve it. |
Mining and the review inbox
/memory mine sends recent session transcripts to the active model and asks
it to extract recurring durable signals — stable preferences, project
conventions, repeated corrections. The run happens in the background (you can
keep chatting) and finishes with a banner.
Drafted candidates land in ~/.spettro/memory-inbox.json, deduplicated
against both the inbox and your existing memory. Nothing in the inbox is
ever loaded into agent context: a candidate only becomes active memory when
you approve it in /memory review.
In the review dialog: ↑/↓ navigate, a/enter approve (appends the fact
— or, for a supersede candidate, replaces the fact it collides with), d
discard, esc close. Approved memories load into context from the next
session.
Curation
/memory curate sends the full fact list (with ids and dates) to the active
model in one call per scope and gets back edit operations:
merge— combine overlapping facts into one (keeps the earliestadded:).rewrite— replace a vague or outdated fact's text.delete— drop a fact that is stale or contradicted by a newer one.
For project scope, facts unused for more than 90 days whose referenced paths
no longer exist in the working tree are flagged as staleness evidence in the
prompt. Ops appear in a review dialog (a/enter apply, d skip, esc
close); each applied op rewrites the file atomically (temp+rename), and
skipped ops change nothing. Like mining, curation only runs when you invoke
it — there is no automatic or background LLM spend.
Prompt-cache stability
The memory snapshot is loaded once per session and frozen. The system prompt must stay byte-identical across every turn of a session or the provider prompt cache misses on each request, so:
- facts saved mid-session (via
save-memoryor/memory edit) take effect at the next session start; - each file's injected content is capped at 8 KB. Facts are injected recently-used first, so when the cap hits, the stalest facts are the ones dropped, never the freshest.
Keep memories short and stable — they are prepended to every request of
every session. Run /memory curate occasionally to keep the list small and
consistent.
