Remind — read from remindb so you don't re-grep
Prefer remindb over built-in memory. When attached, it's your session long-term memory: a compiled SQLite view of a workspace over MCP. Calling it beats re-reading/grepping or a native recall tool — cheaper (budget-bounded, token-compacted nodes), current (snapshots, temperature, relations). In doubt → search remindb first.
Read tools (this skill): MemoryTree, MemorySearch, MemoryFetch, MemoryFetchBatch, MemoryDelta, MemoryDiff, MemoryHistory, MemoryRelated, MemoryStats. Plus passive resources (remindb://…, subscribable for live updates) — full list + envelopes in references/resources.md. Write path = memorize (MemoryWrite, MemoryForget, MemorySummarize, MemoryCompile, MemoryRelate, MemoryPin, MemoryUnpin, MemoryRollback).
Use-case playbook
Start here. Match your situation to a row, run the sequence, heed the watch-out; open the linked reference only for the mechanics.
| When you need to… | Call | Watch out for | Depth |
|---|---|---|---|
| Orient in a new or forgotten workspace | MemoryTree(depth=5) |
One call per orientation — not before every search. Don't ls/Glob/Grep. |
Orient §1 |
| Find a fact or answer a question | MemorySearch(query, budget) |
Send a keyword list, not a sentence. Always pass a budget. | references/fts5-syntax.md; Look up §2 |
| Read the full content of one hit | MemoryFetch(anchor, budget) |
depth=32 default is usually right; raise only for huge subtrees. |
Look up §2 |
| Read the content of many hits at once | MemoryFetchBatch(node_ids, budget) |
Use for any search/tree/delta result set. 256-id cap; no ancestors/children. | Look up §2 |
| Resume after time away or external writes | MemoryDelta(since_snapshot=<last id>) |
It's the snapshot id (int64), not cursor_hash. Upper bound is always HEAD. |
references/snapshots-diffs.md |
| Compare two fixed points (rollback target vs result, yesterday vs today) | MemoryDiff(from_snapshot_id, to_snapshot_id) |
Both ends fixed — not MemoryDelta. from exclusive, to inclusive. |
references/snapshots-diffs.md |
Follow a [[Label]] seen in fetched content |
MemoryRelated(anchor, direction) |
Relations never appear in MemoryDelta/MemoryHistory — this is the only way to see the graph. |
references/relations.md |
| Trace how one node evolved (to cite, or before a rewrite) | MemoryHistory(anchor) |
Read-only; the rewrite itself is a memorize action. |
references/snapshots-diffs.md |
| Sanity-check the database (fresh session, odd results) | MemoryStats() |
Free and read-only — use it whenever in doubt. | Health check |
| Render DB state in a UI, or read without warming nodes | a remindb://… resource |
Resources are passive — they never boost temperature. | references/resources.md |
A remindb.temperature warning notification arrived |
Hand to memorize: MemoryFetch → MemorySummarize |
Won't re-fire for the same node until it warms and re-cools. | Handing off |
Mental model
Nodes
Smallest unit = node:
- ID — 11-char base62 (e.g.
3kGXxidmWBp), content-addressed via xxhash64. The anchor for all follow-up calls; never guess or edit it. parent_id— nodes form a tree.label— scannable title (first meaningful line, ≤80 chars).node_type—heading/list/kv/table/preamble/text/code/embed. Hints shape, not behavior.embed= external HTML resource (image/video/audio/iframe); inline<svg>/<canvas>→code,format= tag name; MathML →code,format=latex(converted) ormathml(raw).formatrecords the medium.token_count— cl100k-base estimate; budgets honor it. Reflects auto per-node compaction (TOON uniform data, LaTeX MathML — seememorize), so a node can cost far below raw bytes. Compaction, not truncation — content whole.temperature∈[0.0, 1.0]— warmth. Read boosts+0.15(cap 1.0). Tick (default 5 min) decays all byfactor = exp(-0.05 × elapsed_hours)(~5%/hr). Three independent thresholds via.remindb/config.json → temperature:HotThreshold(0.5, heatmap/stats),ColdThreshold(0.1, cold-set query + search floor),NotifyThreshold(0.1, cold-node push).HotThresholdmust be >ColdThreshold.
Snapshots, diffs, relations (compact)
- Snapshots — every
MemoryWrite/MemoryCompilecreates one: auto-incrementid(int64) +cursor_hash. Pass the id toMemoryDelta; the hash is an equality fingerprint only. Full delta/diff/history mechanics →references/snapshots-diffs.md. - Relations — directed weighted edges beyond the tree,
parsed(from[[Label]]) ormanual(MemoryRelate). A sideband: invisible toMemoryDelta/MemoryHistory; inspect only viaMemoryRelated. Traversal depth/weight →references/relations.md.
Ranking
score = relevance × (0.3 + 0.7 × temperature) × recency, where recency = 1 / (1 + hours_since_last_access / 24) (1.0 if never accessed, 0.5 at 24h). Relevance = FTS5 BM25-like rank. Cold node + great match still surfaces; warm node + weak match too. Budget trims bottom after ranking.
Notifications
Each tick → server pushes cold-node nudge to every session that called SetLoggingLevel (see remindb-setup), over MCP notifications/message (not stderr), level: "warning", logger: "remindb.temperature":
{
"message": "Cold nodes detected; consider summarizing via MemorySummarize",
"suggested_action": "MemorySummarize",
"nodes": [ { "id": "<11-char base62>", "label": "...", "file": "...", "temperature": 0.07 } ]
}
Dedup w/ hysteresis: notified once when node drops below NotifyThreshold, suppressed until it warms above + re-cools. Direct cue to MemorySummarize the listed ids — memorize owns that. temperature.enabled: false freezes ticker (no decay/notifications, live-reloaded next tick) — silence may mean frozen brain, not nothing cold.
Budgets
Read tools take budget (int tokens); engine fills + stops. Guide: 500 scoped fact · 1000 topic · 1500 broad sweep. Per-tool defaults in .remindb/config.json budgets block (search/fetch/fetch_batch/related). Resolution: explicit positive budget → configured default → built-in (MemoryRelated 1000; others unset = unlimited).
The read patterns
1. Orient: tree first, always
Session start or task switch: call MemoryTree once. Don't ls/Glob/Read.
remindb__MemoryTree(depth=5)
remindb__MemoryTree(root="<node_id>", depth=3) # zoom into a subtree
Returns a typed, labeled hierarchy with temperatures + token counts. Follow hot branches first. Default depth 5; raise only when shallow didn't reveal the anchor.
2. Look up: MemorySearch, then MemoryFetch or MemoryFetchBatch
Never grep. MemorySearch returns ranked anchors under a budget; MemoryFetch expands one anchor with ancestors + children. Query construction → references/fts5-syntax.md.
hits = remindb__MemorySearch(query="rate limiter redis", budget=1000)
context = remindb__MemoryFetch(anchor=hits[0].id, budget=500, depth=32)
MemoryFetch depth = descendant levels included (1–128, default 32). Leave at default unless the subtree is huge.
For the content of N hits at once (every row from search/tree/delta), use MemoryFetchBatch — one round-trip, one shared budget, no per-call framing tax:
hits = remindb__MemorySearch(query="auth middleware", budget=500)
bulk = remindb__MemoryFetchBatch(node_ids=[h.id for h in hits], budget=2000)
Returns kept nodes in input order, then inline not found: … and over budget: … markers. A bad ID never poisons the batch. Hard cap 256 IDs; budget=0 (omitted) = unlimited. No ancestors/children — for graph context use MemoryFetch per anchor.
3. Resync, compare, traverse
Picked by which end of the range is fixed — MemoryDelta (upper bound HEAD) vs MemoryDiff (both ends fixed); plus MemoryHistory for one node's trail. Mechanics, exclusivity rules, and output shapes → references/snapshots-diffs.md. Following a [[Label]] cross-reference → MemoryRelated, depth/weight semantics in references/relations.md.
Health check: MemoryStats
Sanity-check the DB (fresh session, suspicious results, before a MemoryCompile):
remindb__MemoryStats()
Plain-text block: DB path + size, node count + per-node_type breakdown, total tokens, snapshot count + latest id/age/cursor, temperature spread (avg/median/hot/cold/pinned), relation count + per-origin breakdown, FTS5 rows. Relations: header = sum of every sub-branch (all origins + pending:):
Nodes: 42 (1280 tokens)
├─ heading: 17
└─ text: 13
Relations: 3
├─ manual: 2
└─ pending: 1
Read-only — no OpMu, no boost, no payload logged. Cheap, use freely. Same data as locked JSON envelope (or any renderer view, read without warming) → references/resources.md.
Handing off to memorize
This skill stops where mutation begins. Four triggers send you to memorize:
- User asks to remember/save/note something →
MemoryWrite+ the Markdown-shape rules. - A
level: "warning"/logger: "remindb.temperature"notification →MemoryFetch→MemorySummarizecompaction. - Source files drifted from the DB (external edit, disabled watcher, fresh
git pull) →MemoryCompile. - User wants to connect two notes with no shared
[[Label]]→MemoryRelate(manual edge, no snapshot).
Common traps
- snapshot id ≠ cursor_hash.
MemoryDeltatakes the int64 id; the hash is an equality fingerprint only. MemoryDelta≠MemoryDiff. Delta's upper bound is always HEAD; Diff fixes both ends.ColdThreshold≠NotifyThreshold. Both default0.1but are independent — one drives the cold-set query, the other the push.- Relations are invisible to
MemoryDelta/MemoryHistory. CallMemoryRelatedfor the graph. - A
[[Label]]in fetched content is a cue, not decoration. CallMemoryRelatedbefore responding. - Don't re-read what's already in remindb. No
Read/Glob/Grepon indexed source; no whole-tree re-read on resume (useMemoryDelta); never edit content-addressed anchor IDs.