clawmem 0.13.0 → 0.15.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (40) hide show
  1. package/AGENTS.md +165 -677
  2. package/CLAUDE.md +4 -747
  3. package/README.md +20 -191
  4. package/SKILL.md +157 -711
  5. package/docs/clawmem-architecture.excalidraw +2415 -0
  6. package/docs/clawmem-architecture.png +0 -0
  7. package/docs/clawmem_hero.jpg +0 -0
  8. package/docs/concepts/architecture.md +413 -0
  9. package/docs/concepts/composite-scoring.md +133 -0
  10. package/docs/concepts/hooks-vs-mcp.md +156 -0
  11. package/docs/concepts/multi-vault.md +71 -0
  12. package/docs/contributing.md +101 -0
  13. package/docs/guides/cloud-embedding.md +134 -0
  14. package/docs/guides/hermes-plugin.md +187 -0
  15. package/docs/guides/inference-services.md +144 -0
  16. package/docs/guides/multi-vault-config.md +84 -0
  17. package/docs/guides/openclaw-plugin.md +306 -0
  18. package/docs/guides/setup-hooks.md +146 -0
  19. package/docs/guides/setup-mcp.md +76 -0
  20. package/docs/guides/systemd-services.md +332 -0
  21. package/docs/guides/upgrading.md +566 -0
  22. package/docs/internals/entity-resolution.md +135 -0
  23. package/docs/internals/graph-traversal.md +85 -0
  24. package/docs/internals/intent-search-pipeline.md +103 -0
  25. package/docs/internals/query-pipeline.md +100 -0
  26. package/docs/introduction.md +104 -0
  27. package/docs/quickstart.md +158 -0
  28. package/docs/reference/cli.md +195 -0
  29. package/docs/reference/configuration.md +101 -0
  30. package/docs/reference/mcp-tools.md +336 -0
  31. package/docs/reference/rest-api.md +204 -0
  32. package/docs/troubleshooting.md +330 -0
  33. package/package.json +2 -1
  34. package/src/clawmem.ts +60 -0
  35. package/src/health/rerank-golden.json +54 -0
  36. package/src/health/rerank-health.ts +150 -0
  37. package/src/mcp.ts +20 -1
  38. package/src/memory.ts +2 -0
  39. package/src/search-utils.ts +35 -4
  40. package/src/store.ts +115 -22
@@ -0,0 +1,135 @@
1
+ # Entity resolution
2
+
3
+ ClawMem extracts named entities from documents during A-MEM enrichment, resolves them to canonical forms, and tracks co-occurrences to power entity-aware retrieval.
4
+
5
+ ## Extraction
6
+
7
+ Each document is passed to the LLM (QMD query expansion model by default) with a prompt requesting named entities as JSON. The LLM returns `(name, type)` pairs from a fixed type vocabulary:
8
+
9
+ `person`, `project`, `service`, `tool`, `concept`, `org`, `location`
10
+
11
+ Entities pass through quality filters before storage:
12
+ - Document titles are rejected (Levenshtein similarity > 0.85 against the doc's own title)
13
+ - Names longer than 60 characters are rejected (likely titles or sentence fragments)
14
+ - Template placeholders and heading labels are blocklisted
15
+ - Location entities are validated against lexical patterns (IP addresses, VM identifiers, short geographic names) — long non-geographic names typed as location are rejected
16
+
17
+ ## Canonical resolution
18
+
19
+ When an entity is extracted, ClawMem checks whether a matching entity already exists in the vault. Resolution uses FTS5 candidate lookup followed by Levenshtein fuzzy matching (threshold 0.75, lowered to 0.65 for person names).
20
+
21
+ Resolution is **type-agnostic within compatibility buckets**. Two entities with the same name but different types will merge if their types belong to the same bucket:
22
+
23
+ | Bucket | Types | Rationale |
24
+ |--------|-------|-----------|
25
+ | `person` | person | People should never merge with non-people |
26
+ | `org` | org | Organizations are distinct from other categories |
27
+ | `location` | location | Geographic entities kept separate |
28
+ | `tech` | project, service, tool, concept | LLMs frequently assign these inconsistently for the same entity across documents |
29
+
30
+ Cross-bucket merges are always rejected. "Andrea" as a person will never merge with "Andrea" as a project, even if both exist in the vault.
31
+
32
+ Unknown types (if you customize the extraction prompt) default to their own isolated bucket — they won't false-merge with anything.
33
+
34
+ ### How merging works
35
+
36
+ When a new entity is extracted and a canonical match is found in the same bucket:
37
+ 1. The existing entity's `mention_count` is incremented
38
+ 2. The new mention is recorded against the existing entity's ID
39
+ 3. No new `entity_nodes` row is created
40
+
41
+ When no match is found, a new entity node is created with ID format `vault:type:normalized_name`.
42
+
43
+ ### Extending the type vocabulary
44
+
45
+ The extraction prompt and bucket map live in `src/entity.ts`. To add domain-specific types:
46
+
47
+ 1. Add the type to the prompt's type list
48
+ 2. Add it to `ENTITY_BUCKETS` with a bucket assignment:
49
+
50
+ ```typescript
51
+ const ENTITY_BUCKETS: Record<string, string> = {
52
+ person: 'person',
53
+ org: 'org',
54
+ location: 'location',
55
+ project: 'tech',
56
+ service: 'tech',
57
+ tool: 'tech',
58
+ concept: 'tech',
59
+ // Domain extensions:
60
+ statute: 'legal',
61
+ regulation: 'legal', // statutes and regulations can merge
62
+ drug: 'medical',
63
+ condition: 'medical', // or keep them separate with distinct buckets
64
+ };
65
+ ```
66
+
67
+ Types not listed in `ENTITY_BUCKETS` automatically form their own single-type bucket.
68
+
69
+ ## Co-occurrences
70
+
71
+ When multiple entities are extracted from the same document, all pairs are recorded in `entity_cooccurrences`. This powers:
72
+ - The entity graph channel in `query` (conditional 1-hop entity walk from seed results)
73
+ - Entity-aware MPFP meta-path patterns (`[entity, semantic]`)
74
+ - `getEntityGraphNeighbors()` for discovering related documents through shared entities
75
+
76
+ ## Entity edges
77
+
78
+ Document-to-document edges with `relation_type='entity'` are created in `memory_relations` when two documents share entities. Edge weight is computed using IDF-based specificity:
79
+
80
+ - **Rare entities** (appearing in few documents) produce higher-weight edges
81
+ - **Ubiquitous entities** (appearing in many documents) produce low-weight edges that fall below the creation threshold
82
+
83
+ This prevents common entities (e.g., a project name mentioned in every doc) from creating noise edges between unrelated documents, while allowing rare entities to establish meaningful connections even as the sole shared entity.
84
+
85
+ ## Enrichment lifecycle
86
+
87
+ Entity extraction runs as part of the A-MEM `postIndexEnrich()` pipeline during indexing. Each document's enrichment is tracked via `entity_enrichment_state` (input hash of title + body). Documents are only re-extracted when their content changes.
88
+
89
+ To force re-extraction after upgrading ClawMem:
90
+
91
+ ```bash
92
+ clawmem reindex --enrich
93
+ ```
94
+
95
+ This processes all documents through the full enrichment pipeline regardless of whether content changed.
96
+
97
+ ## Model quality and entity extraction
98
+
99
+ Entity extraction quality scales directly with LLM capability. The default QMD query expansion model (1.7B parameters) is optimized for query expansion, not structured extraction — it can mistype entities, echo prompt examples, or extract document titles as entities. The quality filters in the pipeline catch most of these, but a more capable model produces cleaner extractions with fewer filter rejections.
100
+
101
+ **Options for better entity extraction:**
102
+
103
+ ### Option 1: Use a larger local model
104
+
105
+ Point `CLAWMEM_LLM_URL` at a more capable model for all LLM tasks (query expansion + entity extraction + A-MEM notes):
106
+
107
+ ```bash
108
+ # Example: use a 7B+ model instead of QMD 1.7B
109
+ CLAWMEM_LLM_URL=http://localhost:8091 \
110
+ CLAWMEM_LLM_MODEL=your-7b-model \
111
+ clawmem reindex --enrich
112
+ ```
113
+
114
+ Trade-off: query expansion is already well-served by QMD — a larger model is slower for the same task with marginal gains. Entity extraction benefits more.
115
+
116
+ ### Option 2: Use a cloud API
117
+
118
+ Point the LLM at a cloud endpoint for higher-quality extraction. Any OpenAI-compatible `/v1/chat/completions` endpoint works:
119
+
120
+ ```bash
121
+ # Example: use an OpenAI-compatible API
122
+ CLAWMEM_LLM_URL=https://api.example.com/v1 \
123
+ CLAWMEM_LLM_MODEL=gpt-5.4-mini \
124
+ clawmem reindex --enrich
125
+ ```
126
+
127
+ Trade-off: cloud API calls have per-token costs. With 261 documents at ~2000 tokens each, a full re-enrichment is roughly 500K input tokens.
128
+
129
+ ### Option 3: Accept the default and rely on filters
130
+
131
+ The quality filters (title rejection, length limits, blocklist, location validation, type-agnostic canonical resolution) compensate for most small-model weaknesses. For many vaults, the default QMD model with filters produces adequate entity graphs. Run `reindex --enrich` after upgrading ClawMem to benefit from improved filters.
132
+
133
+ ### Recommendation
134
+
135
+ For vaults where entity graph quality matters (large corpora, cross-document discovery, ENTITY intent queries), use a 7B+ model or cloud API for the initial `reindex --enrich` pass. The watcher's incremental enrichment can continue with the default QMD model — individual document additions are less sensitive to extraction quality than bulk corpus enrichment.
@@ -0,0 +1,85 @@
1
+ # Graph traversal in ClawMem
2
+
3
+ ClawMem maintains a multi-graph of relationships between documents in the `memory_relations` table. These edges let agents trace chains of reasoning across documents — answering questions like "why did we decide X", "what caused Y", and "what else supports Z" that keyword and vector search alone can't handle.
4
+
5
+ Most edges are created automatically during indexing (A-MEM link generation) and after each response (causal inference from decision-extractor). The `build_graphs` tool adds temporal backbone and bulk semantic edges for vaults with sparse A-MEM coverage. You don't need to manage the graph manually under normal use.
6
+
7
+ ## Edge types
8
+
9
+ | Type | Meaning | Direction |
10
+ |------|---------|-----------|
11
+ | `semantic` | Topically related (cosine similarity or LLM-assessed) | Bidirectional |
12
+ | `supporting` | One document supports/reinforces another | Directional |
13
+ | `contradicts` | One document contradicts another | Directional |
14
+ | `causal` | One event/decision caused or led to another | Directional |
15
+ | `temporal` | Creation-order adjacency | Directional |
16
+
17
+ ## How edges are created
18
+
19
+ | Source | Edge types | Trigger |
20
+ |--------|-----------|---------|
21
+ | **A-MEM `generateMemoryLinks()`** | semantic, supporting, contradicts | Indexing (new docs only). LLM-assessed confidence + reasoning. Requires embeddings for neighbor discovery. |
22
+ | **A-MEM `inferCausalLinks()`** | causal | Post-response (`decision-extractor`). Links between `_clawmem/agent/observations/` docs. |
23
+ | **Beads `syncBeadsIssues()`** | causal, supporting, semantic | `beads_sync` MCP tool or watcher. Maps dependency types: `blocks→causal`, `discovered-from→supporting`, `relates-to→semantic`. |
24
+ | **`buildTemporalBackbone()`** | temporal | `build_graphs` MCP tool (manual). Creation-order edges between all active docs. |
25
+ | **`buildSemanticGraph()`** | semantic | `build_graphs` MCP tool (manual). Pure cosine similarity between embeddings. |
26
+
27
+ ### SPO knowledge graph (entity_triples)
28
+
29
+ Separate from `memory_relations`, the `entity_triples` table stores structured Subject-Predicate-Object facts with temporal validity (`valid_from`/`valid_to`). Triples are emitted by the observer LLM as `<triples>` blocks alongside `<facts>`, parsed and validated by `parseObservationXml` against a tight canonical predicate vocabulary, then persisted by `decision-extractor` using canonical `vault:type:slug` entity IDs via `ensureEntityCanonical`.
30
+
31
+ **Eligible observation types** for triple extraction: decision, preference, milestone, problem, discovery, feature. Observation types `bugfix`, `change`, `refactor` are excluded as secondary safety net.
32
+
33
+ **Canonical predicate vocabulary** (parser rejects anything outside this set): `adopted`, `migrated_to`, `deployed_to`, `runs_on`, `replaced`, `depends_on`, `integrates_with`, `uses`, `prefers`, `avoids`, `caused_by`, `resolved_by`, `owned_by`. The `prefers` and `avoids` predicates store their object as a literal (not resolved to an entity).
34
+
35
+ **Entity type inheritance** is ambiguity-safe via `resolveEntityTypeExact`: if exactly one active entity in the vault shares the name, its type is inherited; zero matches or multiple matches (cross-bucket ambiguity) default to `concept`.
36
+
37
+ **Provenance**: each triple's `source_doc_id` points at the persisted observation document it was extracted from. Triples for observations whose doc insert failed are naturally skipped because the extractor iterates the `ObservationWithDoc` array.
38
+
39
+ Query via the `kg_query(entity)` MCP tool — accepts either an entity name (resolved via `searchEntities`) or a canonical ID in `vault:type:slug` form. This is not used by `adaptiveTraversal()` — it serves a different purpose (structured entity lookup vs document graph traversal).
40
+
41
+ ### Edge collision
42
+
43
+ Both `generateMemoryLinks()` and `buildSemanticGraph()` insert `semantic` edges. The primary key is `(source_id, target_id, relation_type)` — first writer wins (`INSERT OR IGNORE`). A-MEM edges take precedence if they exist.
44
+
45
+ ## Adaptive traversal
46
+
47
+ `adaptiveTraversal()` performs multi-hop beam search:
48
+
49
+ 1. Start from anchor nodes (top search results)
50
+ 2. At each hop, expand outbound edges (all types) and inbound edges (semantic + entity only)
51
+ 3. Score candidates by:
52
+ - Edge weight (confidence)
53
+ - Cosine similarity to the query embedding
54
+ - Decay by depth
55
+ 4. Beam selection: keep top `beamWidth` candidates per hop
56
+ 5. Budget cap: stop after visiting `budget` total nodes
57
+
58
+ ### Traversal asymmetry
59
+
60
+ | Direction | Edge types traversed |
61
+ |-----------|---------------------|
62
+ | Outbound (source→target) | All: semantic, supporting, contradicts, causal, temporal |
63
+ | Inbound (target→source) | Only: semantic, entity |
64
+
65
+ This is intentional — temporal and causal edges are directional by nature.
66
+
67
+ ## When to run build_graphs
68
+
69
+ - After **bulk ingestion** (many new docs at once) — adds temporal backbone and fills semantic gaps
70
+ - When `intent_search` returns **weak or incomplete results** and you suspect graph sparsity
71
+ - Do NOT run after every reindex — A-MEM creates per-doc links automatically for new docs
72
+
73
+ ## When to run find_causal_links
74
+
75
+ Use after `intent_search` to walk the full causal chain from a specific document:
76
+
77
+ ```
78
+ # 1. Find the anchor
79
+ intent_search("why did we switch to PostgreSQL")
80
+ # → top result: decisions/2026-02-15-db-migration.md (#a1b2c3)
81
+
82
+ # 2. Trace the chain
83
+ find_causal_links(docid="#a1b2c3", direction="both", depth=5)
84
+ # → shows what caused this decision and what it caused
85
+ ```
@@ -0,0 +1,103 @@
1
+ # Intent search pipeline
2
+
3
+ The `intent_search` MCP tool classifies query intent and uses graph traversal to find causal chains across AI agent memory that keyword and vector search alone can't reach.
4
+
5
+ ## Pipeline stages
6
+
7
+ ```
8
+ User Query
9
+
10
+
11
+ Intent Classification (LLM)
12
+ │ → WHY, WHEN, ENTITY, or WHAT
13
+ │ (or force_intent override)
14
+
15
+
16
+ Baseline Search
17
+ │ BM25 + Vector in parallel
18
+
19
+
20
+ Intent-Weighted RRF
21
+ │ WHY → boost vector [1.0, 1.5]
22
+ │ WHEN → boost BM25 [1.5, 1.0]
23
+ │ Other → balanced [1.0, 1.0]
24
+
25
+
26
+ Graph Traversal (WHY/ENTITY only)
27
+ │ Multi-hop beam search over memory_relations
28
+ │ Outbound: all edge types
29
+ │ Inbound: semantic + entity only
30
+ │ Budget: 30 nodes, depth: 2, beam: 5
31
+ │ Scores normalized to [0,1]
32
+
33
+
34
+ Cross-Encoder Reranking
35
+ │ 200 chars/doc context
36
+ │ File-keyed score join
37
+
38
+
39
+ Position-Aware Blending
40
+ │ origWeight · upstream score + (1 − origWeight) · rerank
41
+ │ origWeight = 0.75 (top 3), 0.60 (mid), 0.40 (tail)
42
+ │ (intent_search keeps this curve; the query tool uses blendRerank instead)
43
+
44
+
45
+ Composite Scoring
46
+
47
+
48
+ Results (with intent + confidence metadata)
49
+ ```
50
+
51
+ ## Intent types
52
+
53
+ | Intent | Signal | Graph traversal | RRF weighting |
54
+ |--------|--------|----------------|---------------|
55
+ | WHY | "why did", "what caused", "reason for", "decided to" | Yes | Boost vector |
56
+ | WHEN | "when did", "first/last occurrence", timeline | No | Boost BM25 |
57
+ | ENTITY | Named component/person/service needing cross-doc linkage | Yes | Balanced |
58
+ | WHAT | General factual | No | Balanced |
59
+
60
+ ## Graph traversal
61
+
62
+ When intent is WHY or ENTITY, the pipeline runs `adaptiveTraversal()`:
63
+
64
+ 1. Anchors on top 10 search results
65
+ 2. Traverses `memory_relations` edges:
66
+ - **Outbound** (source→target): semantic, supporting, contradicts, causal, temporal
67
+ - **Inbound** (target→source): semantic and entity only
68
+ 3. Beam search with query embedding as relevance signal
69
+ 4. Discovered nodes are hydrated from the database and merged with search results
70
+ 5. Scores are normalized to [0, 1] before merging
71
+
72
+ ## Graph edge sources
73
+
74
+ | Source | Edge types | How populated |
75
+ |--------|-----------|--------------|
76
+ | A-MEM `generateMemoryLinks()` | semantic, supporting, contradicts | During indexing (new docs) |
77
+ | A-MEM `inferCausalLinks()` | causal | Post-response (decision-extractor) |
78
+ | Beads `syncBeadsIssues()` | causal, supporting, semantic | `beads_sync` or watcher |
79
+ | `buildTemporalBackbone()` | temporal | `build_graphs` (manual) |
80
+ | `buildSemanticGraph()` | semantic | `build_graphs` (manual) |
81
+
82
+ ## Differences from query
83
+
84
+ | Aspect | `query` | `intent_search` |
85
+ |--------|---------|-----------------|
86
+ | Query expansion | Yes | No |
87
+ | Intent hint | Manual (`intent` param) | Auto-detected |
88
+ | Rerank context | 4000 chars/doc | 200 chars/doc |
89
+ | Graph traversal | No | Yes (WHY/ENTITY) |
90
+ | MMR diversity | Yes | No |
91
+ | `compact` param | Yes | No |
92
+ | `collection` filter | Yes | No |
93
+ | Best for | General recall | Causal chains spanning docs |
94
+
95
+ ## When to use
96
+
97
+ Use `intent_search` **directly** (not as a fallback from query) when:
98
+ - The question starts with "why"
99
+ - You need to trace decision chains
100
+ - You're asking about entity relationships across documents
101
+ - You need temporal context ("when did this change")
102
+
103
+ For WHEN queries, start with `enable_graph_traversal=false` (BM25-biased). Fall back to `query()` if recall drifts.
@@ -0,0 +1,100 @@
1
+ # Query pipeline
2
+
3
+ The `query` MCP tool runs the full hybrid retrieval pipeline, combining BM25, vector search, query expansion, and cross-encoder reranking in a single call.
4
+
5
+ ## Pipeline stages
6
+
7
+ ```
8
+ User Query + optional intent hint
9
+
10
+
11
+ BM25 Probe
12
+ │ Top hit score >= 0.85 with gap >= 0.15?
13
+ │ (disabled when intent is provided)
14
+ ├── YES → Skip expansion, use BM25 results directly
15
+
16
+
17
+ Query Expansion (LLM)
18
+ │ Generates text variants (lex/vec/hyde)
19
+ │ Intent steers the expansion prompt
20
+
21
+
22
+ Parallel Search (typed routing)
23
+ │ BM25(original) + Vector(original) ← original fans out to both
24
+ │ + BM25(lex expansions) ← lex → BM25 only
25
+ │ + Vector(vec/hyde expansions) ← vec/hyde → vector only
26
+
27
+
28
+ Reciprocal Rank Fusion (k=60)
29
+ │ Original query lists get 2x positional weight
30
+ │ Expanded query lists get 1x weight
31
+ │ Top candidateLimit results (default 30)
32
+
33
+
34
+ Intent-Aware Chunk Selection
35
+ │ Intent terms at 0.5x weight
36
+ │ Query terms at 1.0x weight
37
+
38
+
39
+ Cross-Encoder Reranking
40
+ │ 4000 char context per doc
41
+ │ Intent prepended to rerank query
42
+ │ Chunk dedup (identical texts share single call)
43
+ │ Batch cap = 4
44
+
45
+
46
+ Rerank / RRF Blend (blendRerank)
47
+ │ 0.9 · reranker + 0.1 · normalized-RRF tiebreaker
48
+ │ Reranker is the dominant signal; can promote a doc over RRF #1
49
+ │ Falls back to pure RRF order if the reranker is unavailable / degenerate
50
+ │ (no score above RERANK_DEGENERATE_FLOOR ≈ 1e-4); emits a rate-limited warning on fallback
51
+ │ (the reranker-health guard surfaces this — see `clawmem doctor` / `clawmem rerank-health`)
52
+
53
+
54
+ Composite Scoring
55
+ │ (relevance * 0.70 + recency * 0.15 + confidence * 0.15) ← query-tuned weights (v0.13.0)
56
+ │ recency-intent queries instead use 0.10 / 0.70 / 0.20
57
+ │ × quality multiplier × co-activation boost
58
+
59
+
60
+ MMR Diversity Filter
61
+ │ Jaccard bigram similarity > 0.6 → demoted
62
+
63
+
64
+ Results
65
+ ```
66
+
67
+ ## Key parameters
68
+
69
+ | Parameter | Effect | Default |
70
+ |-----------|--------|---------|
71
+ | `intent` | Steers 5 stages: expansion, reranking, chunk selection, snippet extraction, bypass | — |
72
+ | `candidateLimit` | How many candidates reach reranking | 30 |
73
+ | `compact` | Snippet vs full content output | true |
74
+ | `collection` | Filter by collection (comma-separated) | all |
75
+
76
+ ## BM25 strong-signal bypass
77
+
78
+ When the top BM25 hit scores >= 0.85 and the gap to the second hit is >= 0.15, the pipeline skips query expansion entirely. This is a fast path for queries with obvious keyword matches.
79
+
80
+ The bypass is disabled when `intent` is provided — intent implies the query is ambiguous, so keyword confidence alone is insufficient.
81
+
82
+ ## Query expansion
83
+
84
+ The LLM generates lex (keyword), vec (semantic), and hyde (hypothetical answer) variants of the query, each carried as a typed `ExpandedQuery`. Variants are **routed by type**: `lex` expansions are searched on BM25 only, `vec` and `hyde` on vector only. The original query is the only leg that fans out to *both* backends. All legs are searched in parallel and fused; the original query's two lists receive 2x weight in RRF, ensuring it anchors the ranking.
85
+
86
+ Routing by type matters because a keyword expansion ("auth token refresh") is useless to a dense vector model, and a hypothetical-answer passage (hyde) is mostly stopword noise to BM25. Searching every variant on both backends — the earlier behavior — fed each leg the input it handles worst, diluting RRF with low-quality lists.
87
+
88
+ ## Chunk selection
89
+
90
+ For reranking, each document's content is windowed into overlapping chunks. Chunks are scored by overlap with query terms (1.0x weight) and intent terms (0.5x weight). The best chunk per document is sent to the cross-encoder.
91
+
92
+ ## When to use query vs alternatives
93
+
94
+ | Tool | Cost | When |
95
+ |------|------|------|
96
+ | `search` | 0 GPU calls | Known exact terms, spot-check |
97
+ | `vsearch` | 1 GPU call | Conceptual, don't know vocabulary |
98
+ | `query` | 3+ GPU calls | General recall, unsure which signal matters |
99
+ | `intent_search` | Hybrid + graph | Why/entity chains, temporal queries |
100
+ | `query_plan` | Hybrid + decomposition | Multi-topic queries |
@@ -0,0 +1,104 @@
1
+ # ClawMem overview
2
+
3
+ ClawMem is an open-source memory engine for Claude Code and AI agents. It runs on-device, giving agents persistent and searchable memory that survives across sessions, compactions, and runtime boundaries. The system integrates via Claude Code hooks, an MCP server (works with any MCP-compatible client including OpenClaw), or a native OpenClaw memory plugin (`kind: memory`, v0.10.0+).
4
+
5
+ ## What it does
6
+
7
+ - **Indexes** markdown documents into a local SQLite vault with full-text search (BM25) and vector embeddings
8
+ - **Retrieves** relevant context automatically via hooks or on-demand via MCP tools / REST API
9
+ - **Scores** results using composite scoring (relevance, recency, confidence, quality, co-activation)
10
+ - **Tracks** decisions, handoffs, and session history across conversations
11
+ - **Traverses** causal and semantic graphs to answer "why" and "what led to" questions
12
+
13
+ ## Architecture
14
+
15
+ ```
16
+ Agent (Claude Code / OpenClaw / any MCP client)
17
+
18
+ ├── Hooks (automatic, ~90% of retrieval)
19
+ │ ├── context-surfacing → injects <vault-context> on every prompt
20
+ │ ├── decision-extractor → extracts observations after each response
21
+ │ ├── handoff-generator → summarizes sessions for continuity
22
+ │ ├── feedback-loop → reinforces referenced memories
23
+ │ ├── precompact-extract → preserves state before context compaction
24
+ │ ├── curator-nudge → surfaces maintenance suggestions
25
+ │ └── postcompact-inject → re-injects authoritative context after compaction
26
+
27
+ ├── MCP Tools (agent-initiated, ~10%)
28
+ │ ├── memory_retrieve → auto-routing entry point
29
+ │ ├── query / search / vsearch / intent_search / query_plan
30
+ │ ├── get / multi_get / find_similar / find_causal_links / timeline
31
+ │ ├── memory_pin / memory_snooze / memory_forget
32
+ │ └── lifecycle / vault / maintenance tools
33
+
34
+ └── REST API (optional, for non-MCP clients)
35
+ ├── POST /retrieve → mirrors memory_retrieve
36
+ ├── POST /search → direct mode selection
37
+ └── GET/POST endpoints → documents, lifecycle, graphs
38
+
39
+
40
+
41
+ SQLite Vault (WAL mode)
42
+ ├── documents + content (FTS5 index)
43
+ ├── vectors (vec0 extension)
44
+ ├── memory_relations (causal, semantic, temporal, supporting edges)
45
+ ├── sessions + usage tracking
46
+ └── hook_dedupe (heartbeat suppression)
47
+
48
+
49
+
50
+ GPU Services (llama-server)
51
+ ├── :8088 — Embedding (EmbeddingGemma-300M default, zembed-1 SOTA upgrade)
52
+ ├── :8089 — LLM (qmd-query-expansion-1.7B)
53
+ └── :8090 — Reranker (qwen3-reranker-0.6B default, zerank-2 seq-cls sidecar SOTA upgrade)
54
+ ```
55
+
56
+ ## Key design principles
57
+
58
+ 1. **Local-first** — all data stays on your machine in a single SQLite file. No cloud dependencies unless you opt into cloud embedding.
59
+ 2. **Fail-open** — every hook and search path degrades gracefully. A failed GPU call returns BM25-only results, not an error.
60
+ 3. **Dual-mode** — the same vault is shared between Claude Code hooks and OpenClaw's memory plugin. Both runtimes read and write the same memory.
61
+ 4. **Progressive disclosure** — agents see compact results first (`compact=true`), then fetch full content only when needed. Minimizes context window usage.
62
+ 5. **Zero-config default** — a single vault with `clawmem bootstrap` gets you running. Multi-vault, cloud embedding, and profiles are opt-in.
63
+
64
+ ## Building a rich context field
65
+
66
+ A filesystem-based context engine is only as useful as what you put into the filesystem. If your vault contains a handful of sparse memory files, the retrieval pipeline has little to work with — BM25 won't find relevant terms, vector search has few neighbors to compare, and graph traversal has no edges to follow.
67
+
68
+ The agents that get the most from ClawMem are the ones with rich, diverse collections. Index broadly:
69
+
70
+ | Content type | Example | Why it helps |
71
+ |-------------|---------|-------------|
72
+ | Memory files | `MEMORY.md`, session logs | Captures what happened and what was decided |
73
+ | Research outputs | Analysis notes, comparison docs | Gives the agent domain knowledge it would otherwise lack |
74
+ | Decision records | Architecture decisions, tradeoffs | Lets the agent understand *why*, not just *what* |
75
+ | Learnings and antipatterns | Post-mortems, things to avoid | Prevents repeated mistakes across sessions |
76
+ | Domain expertise | Reference docs, runbooks, SOPs | Provides stable context that rarely changes |
77
+ | Project notes | Status updates, meeting notes, specs | Keeps the agent current on project state |
78
+
79
+ A practical starting point: configure each project collection to index every `.md` file in the project (`pattern: "**/*.md"`). The composite scoring system handles the rest — decisions and hubs never decay, progress notes fade after 45 days, and the quality multiplier rewards well-structured documents over flat text dumps.
80
+
81
+ ### Document structure matters
82
+
83
+ How you write documents affects how well they score. The [quality multiplier](concepts/composite-scoring.md#quality-multiplier-07---13) ranges from 0.7x (penalty) to 1.3x (boost) based on headings, lists, decision keywords, and frontmatter. Five well-structured decision documents with clear headings will consistently outscore fifty single-paragraph notes.
84
+
85
+ ### Keep code out of the vault
86
+
87
+ ClawMem indexes prose, not code. Source files (`.ts`, `.py`, `.go`, etc.) are excluded by design — BM25 and vector models trained on natural language perform poorly on code syntax, and code retrieval needs AST-aware, symbol-level tools (call graphs, definitions, references). Document your technical decisions and architecture in markdown. Let the code live in version control and use a dedicated code search tool for code retrieval.
88
+
89
+ ## Integrations
90
+
91
+ | Runtime | Integration | How | Services needed |
92
+ |---------|------------|-----|-----------------|
93
+ | Claude Code | Hooks + MCP stdio | `clawmem setup hooks` + `clawmem setup mcp` | watcher + embed timer |
94
+ | OpenClaw | Memory plugin + REST API | `clawmem setup openclaw` (requires OpenClaw v2026.4.11+) | watcher + embed timer + `clawmem serve` |
95
+ | Any MCP client | MCP stdio | Add to MCP config | watcher + embed timer |
96
+ | Web / scripts | REST API | `clawmem serve` | watcher + embed timer + `clawmem serve` |
97
+
98
+ All integrations share the same SQLite vault. The [watcher](guides/systemd-services.md#watcher-service) keeps the index fresh, the [embed timer](guides/systemd-services.md#embed-timer) maintains vector embeddings, and the [REST API](reference/rest-api.md) serves OpenClaw agent tools. GPU servers are optional — `node-llama-cpp` provides in-process fallback (Metal on Apple Silicon, Vulkan where available, CPU as last resort). Fast with GPU acceleration; significantly slower on CPU-only. The [curator agent](../agents/clawmem-curator.md) handles periodic maintenance on demand.
99
+
100
+ ## Next steps
101
+
102
+ - [Quickstart](quickstart.md) — install and bootstrap in 5 minutes
103
+ - [Concepts](concepts/architecture.md) — understand vaults, collections, and scoring
104
+ - [MCP Tools Reference](reference/mcp-tools.md) — full tool reference with examples