Local memory
Save findings, decisions and rules for agents to recall, without an account.
Prerequisites
Section titled “Prerequisites”- The Blop CLI (Quickstart). Memory commands work without a running collector.
What is stored
Section titled “What is stored”memory.db sits beside the telemetry store (blop status prints its path). It holds authored nodes and read-only folder projections, not captured telemetry:
- Kinds:
entity,document,finding,decision,ruleorprocedure. - Authored revisions: every authored change makes a new immutable revision; writes must name the revision they expect. Markdown projection retains only its current indexed snapshot.
- Relations and sources: typed node links and supporting trace/session references. Unsourced nodes are claims, not evidence.
Opening memory never uploads anything. To share knowledge with a team, see Organization memory.
Add and read memory
Section titled “Add and read memory”blop memory add --kind decision --title "Round two probe" --body "the flags work"blop memory search --text "Round two probe"Default ID: local: plus lowercase SHA-256 of exact UTF-8 JSON.stringify([title, body]).
Identical retries preserve revisions. See blop help memory add.
-
Write the change as JSON:
{"type": "add","id": "note:checkout-timeout","scope": "project","projectId": "my-app","expectedRevision": 0,"content": {"kind": "finding","title": "Checkout times out under load","body": "POST /api/pay exceeds 5 s when the payment stub is cold."}} -
Add it:
Terminal window blop memory add --input add.json --json -
Find it again:
Terminal window blop memory search --text checkout --project my-app --json
| Command | Purpose |
|---|---|
blop memory search --text <text> | Exact text search in titles and bodies, in stable node-ID order |
blop memory get <node-id> | One node; --revision N for an older one, --body-offset and --body-length for long bodies |
blop memory history <node-id> | Revision list with previews |
blop memory neighbors <node-id> | Recorded relations |
blop memory context --text <text> | A bounded brief for an agent |
blop memory edit, patch, retire, restore, purge | Change a node with an --input JSON file |
blop memory skills list, skills get <id> | Saved procedures |
blop memory index | Build vectors for search by meaning |
Read commands take --json and return bounded pages; follow the returned --cursor. Coding agents connected over MCP get the same reads as read-only tools (Connect a coding agent); writes always go through the CLI.
Attach Markdown knowledge
Section titled “Attach Markdown knowledge”No account, collector, model or network: Attachment/indexing never rewrite authoritative Markdown:
blop memory markdown init ./knowledge # Optional template; never overwrites.blop memory markdown attach ./knowledge --json # Save attachment ID.blop memory markdown index <attachment-id> --jsonblop memory search --text checkout --jsonblop memory get <node-id> --jsonblop memory neighbors <node-id> --jsonblop memory context --text checkout --jsonblop memory markdown list --jsonblop memory markdown detach <attachment-id> --jsonReindex after edits/deletes; replacement is atomic. Detach removes retrieval/vectors,
not files or authored assertions. Missing endpoints hide relations; restored IDs
recover original approval provenance. memory index remains optional vector/model
indexing. --project configures attachment scope only on markdown attach;
unrelated flags, including --dry-run, fail.
Identity and authority
Section titled “Identity and authority”- Arbitrary layouts with
.md,.mdownor.markdownwork without frontmatter. Optional scalarid: checkout-policypreserves note identity across renames; duplicate IDs fail. Without an ID, rename means delete/add. - Whole notes and ATX/Setext heading sections are addressable. Anchors lowercase
Unicode letters/numbers, retain
_/-, remove other punctuation and replace whitespace with-. Duplicates receive the first unused numeric suffix; heading edits/reordering may change section IDs. - Relative Markdown/reference-style links and
[[relative/path#Heading]]create unapprovedreferences, not causal assertions. Wikilinks may omit.md; no global basename matching. Code creates no links. Unresolved/external links produce warnings; URLs, images and HTML are never fetched/executed. - Projections are unapproved documents. Frontmatter grants no policy, guards,
scope or upload permission. Edit source and reindex; authored mutations fail.
Publication copies one selected
snapshot, never syncs. Projection
historyis empty;get --revisionaddresses current only, otherwisenull.
Reads preserve node/page envelopes and include path/section/hash/snapshot,
indexing time and freshness: indexed-snapshot means last successful scan,
not live filesystem freshness; last-scan-failed labels retained prior content.
There is no watcher. Local CLI/MCP assessment is explicitly not_configured,
not “assessed without findings.” MCP exposes no Markdown writes; its existing
collector health announcement contains no note content.
Safety and evidence
Section titled “Safety and evidence”Initialization requires Linux with accessible /proc/self/fd; other platforms
return markdown_init_unsupported, never unsafe pathname writes. Directory handles
anchor exclusive creation against symlink swaps. Attach/index reject symlink
roots/ancestors and exclude child symlinks. Hidden entries, node_modules, dist,
build, vendor, coverage, secrets and config are ignored. .blopignore
accepts literal relative prefixes with # comments, not globs.
Limits: 100,000 bytes/file, 16,000,000 bytes/scan, 20,000 entries, depth 32,
10,000 nodes, 200 link occurrences/file (including whole-note copies),
100 attachments. Paths cap at 1,024 characters; headings at 512. Exact citations
allow 1,029-character sourceId (path: prefix) and 1,537-character path
(path + # + heading), without truncation. Invalid/oversized sources or detected
concurrent changes preserve the prior snapshot; successful empty scans remove it.
Scan checks are not locks; pause concurrent writers.
Optional frontmatter sources uses the existing reference contract:
---sources: - namespace: otlp:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa sourceId: "1111111111111111" recordedAt: "2026-11-06T00:00:00.000Z" plane: runtime accessibility: unknown---This addresses an exact trace+span; otlp.trace with a trace ID addresses the
trace. opencode:<encoded-session-id> keeps exact source-ID semantics. Only
existence metadata is read: present is local-only, missing is unavailable;
absent stores/tables, unknown namespaces or unverifiable hash/revision constraints
are unknown. Existence is not verification. No hosted run or upload is implied.
Browse memory in the Inspector
Section titled “Browse memory in the Inspector”Open /inspector?view=memory on the collector, for example http://127.0.0.1:27811/inspector?view=memory&project=my-app&q=checkout. The view is read-only. Filter with project, q (text), kind, status (active or retired) and semantic=1 (rank by meaning).
Search by meaning
Section titled “Search by meaning”blop memory indexSearch by meaning needs an index you build explicitly. The first index or search downloads a local embedding model and caches it; your notes and queries are never uploaded. Reindex after changes: a stale index state means vectors cover older revisions. If the index is not ready, search falls back to exact text. Similarity is not evidence, and ranking never creates a relation.
Delete memory
Section titled “Delete memory”Retire a node to hide it from search while keeping its history:
echo '{"type":"retire","nodeId":"note:checkout-timeout","expectedRevision":1}' > retire.jsonblop memory retire --input retire.jsonrestore brings a retired revision back. To erase a node’s content, revisions and index entries, purge it at its current revision:
echo '{"type":"purge","nodeId":"note:checkout-timeout","expectedRevision":2}' > purge.jsonblop memory purge --input purge.jsonA purged ID cannot be reused. Purging is logical deletion: database write-ahead pages and backups are not erased at once. Telemetry is deleted separately, with blop delete.
Check it worked
Section titled “Check it worked”blop memory get note:checkout-timeout --json returns the node with its revision, and null after a purge.
- Skills: instructions your agent loads for a task.
- Organization memory: share memory with your team.