clawmem 0.5.0 → 0.6.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.
- package/AGENTS.md +23 -5
- package/CLAUDE.md +23 -5
- package/README.md +18 -7
- package/SKILL.md +14 -3
- package/package.json +1 -1
- package/src/clawmem.ts +115 -0
- package/src/consolidation.ts +312 -1
- package/src/hooks/decision-extractor.ts +92 -0
- package/src/hooks/session-bootstrap.ts +102 -29
- package/src/llm.ts +120 -16
- package/src/mcp.ts +148 -0
- package/src/memory.ts +5 -3
- package/src/store.ts +155 -2
package/AGENTS.md
CHANGED
|
@@ -250,7 +250,7 @@ ClawMem hooks handle ~90% of retrieval automatically. Agent-initiated MCP calls
|
|
|
250
250
|
| `postcompact-inject` | SessionStart (compact) | 1200 tokens | re-injects authoritative context after compaction: precompact state (600) + recent decisions (400) + antipatterns (150) + vault context (200) → `<vault-postcompact>` |
|
|
251
251
|
| `curator-nudge` | SessionStart | 200 tokens | surfaces curator report actions, nudges when report is stale (>7 days) |
|
|
252
252
|
| `precompact-extract` | PreCompact | — | extracts decisions, file paths, open questions → writes `precompact-state.md` to auto-memory. Query-aware decision ranking. Reindexes auto-memory collection. |
|
|
253
|
-
| `decision-extractor` | Stop | — | LLM extracts observations → `_clawmem/agent/observations/`, infers causal links, detects contradictions
|
|
253
|
+
| `decision-extractor` | Stop | — | LLM extracts observations → `_clawmem/agent/observations/`, infers causal links, detects contradictions, extracts SPO triples from decision/preference/milestone/problem facts. Background consolidation worker synthesizes deductive observations from related facts (Phase 3, every ~15 min). |
|
|
254
254
|
| `handoff-generator` | Stop | — | LLM summarizes session → `_clawmem/agent/handoffs/` |
|
|
255
255
|
| `feedback-loop` | Stop | — | tracks referenced notes → boosts confidence, records usage relations + co-activations between co-referenced docs, tracks utility signals (surfaced vs referenced ratio for lifecycle automation) |
|
|
256
256
|
|
|
@@ -307,9 +307,15 @@ All other retrieval is handled by Tier 2 hooks. Do NOT call MCP tools speculativ
|
|
|
307
307
|
4. Chain tracing → find_causal_links(docid, direction="both", depth=5)
|
|
308
308
|
Traverses causal edges between _clawmem/agent/observations/ docs (from decision-extractor).
|
|
309
309
|
|
|
310
|
-
5.
|
|
310
|
+
5. Entity facts → kg_query(entity, as_of?, direction?)
|
|
311
|
+
Structured SPO triples with temporal validity. Different from intent_search:
|
|
312
|
+
- kg_query: "what does ClawMem relate to?" → returns structured facts (subject-predicate-object)
|
|
313
|
+
- intent_search: "why did we choose ClawMem?" → returns documents with causal reasoning
|
|
314
|
+
Use kg_query for entity lookup, intent_search for causal chains.
|
|
311
315
|
|
|
312
|
-
6.
|
|
316
|
+
6. Memory debugging → memory_evolution_status(docid)
|
|
317
|
+
|
|
318
|
+
7. Temporal context → timeline(docid, before=5, after=5, same_collection=false)
|
|
313
319
|
Shows what was created/modified before and after a document.
|
|
314
320
|
Use after search to understand chronological neighborhood.
|
|
315
321
|
```
|
|
@@ -327,6 +333,9 @@ All other retrieval is handled by Tier 2 hooks. Do NOT call MCP tools speculativ
|
|
|
327
333
|
- `timeline(docid, before=5, after=5, same_collection=false)` — temporal neighborhood around a document. Progressive disclosure: search → timeline → get. Supports same-collection scoping and session correlation.
|
|
328
334
|
- `list_vaults()` — show configured vault names and paths. Empty in single-vault mode (default).
|
|
329
335
|
- `vault_sync(vault, content_root, pattern?, collection_name?)` — index markdown from a directory into a named vault. Restricted-path validation rejects sensitive directories (`/etc/`, `/root/`, `.ssh`, `.env`, `credentials`, etc.).
|
|
336
|
+
- `kg_query(entity, as_of?, direction?)` — query the SPO knowledge graph for an entity's relationships. Returns temporal triples with validity windows. USE THIS for "what does X relate to?", "what was true about X in January?". Uses entity resolution for lookup.
|
|
337
|
+
- `diary_write(entry, topic?, agent?)` — write a diary entry. USE PROACTIVELY in non-hooked environments (Hermes, Gemini, plain MCP) for recording important events and decisions. Do NOT use in Claude Code (hooks handle this automatically).
|
|
338
|
+
- `diary_read(last_n?, agent?)` — read recent diary entries.
|
|
330
339
|
|
|
331
340
|
### Multi-Vault
|
|
332
341
|
|
|
@@ -355,6 +364,8 @@ Pin, snooze, and forget are **manual MCP tools** — not automated. The agent sh
|
|
|
355
364
|
- Do NOT forget memories to "clean up" — let confidence decay and contradiction detection handle it naturally.
|
|
356
365
|
- Do NOT run `build_graphs` after every reindex — A-MEM creates per-doc links automatically. Only after bulk ingestion or when `intent_search` returns weak graph results.
|
|
357
366
|
- Do NOT run `clawmem mine` autonomously — it is a bulk ingestion command (same category as `update`/`reindex`). Suggest it to the user when they mention old conversation exports, but let them run it. Bulk import has disk/embedding cost implications that need user consent.
|
|
367
|
+
- Do NOT use `diary_write` in Claude Code — hooks (`decision-extractor`, `handoff-generator`) capture this automatically. Diary is for non-hooked environments only (Hermes, Gemini, plain MCP clients).
|
|
368
|
+
- Do NOT use `kg_query` for causal "why" questions — use `intent_search` or `memory_retrieve`. `kg_query` returns structured entity facts (SPO triples), not reasoning chains.
|
|
358
369
|
|
|
359
370
|
## Tool Selection (one-liner)
|
|
360
371
|
|
|
@@ -436,7 +447,7 @@ compositeScore = (0.10 × searchScore + 0.70 × recencyScore + 0.20 × confidenc
|
|
|
436
447
|
|
|
437
448
|
| Content Type | Half-Life | Effect |
|
|
438
449
|
|--------------|-----------|--------|
|
|
439
|
-
| decision, preference, hub | ∞ | Never decay |
|
|
450
|
+
| decision, deductive, preference, hub | ∞ | Never decay |
|
|
440
451
|
| antipattern | ∞ | Never decay — accumulated negative patterns persist |
|
|
441
452
|
| project | 120 days | Slow decay |
|
|
442
453
|
| research | 90 days | Moderate decay |
|
|
@@ -445,7 +456,7 @@ compositeScore = (0.10 × searchScore + 0.70 × recencyScore + 0.20 × confidenc
|
|
|
445
456
|
| handoff | 30 days | Fast — recent matters most |
|
|
446
457
|
|
|
447
458
|
Half-lives extend up to 3× for frequently-accessed memories (access reinforcement decays over 90 days).
|
|
448
|
-
Attention decay: non-durable types (handoff, progress, conversation, note, project) lose 5% confidence per week without access. Decision/preference/hub/research/antipattern are exempt.
|
|
459
|
+
Attention decay: non-durable types (handoff, progress, conversation, note, project) lose 5% confidence per week without access. Decision/deductive/preference/hub/research/antipattern are exempt.
|
|
449
460
|
|
|
450
461
|
## Indexing & Graph Building
|
|
451
462
|
|
|
@@ -488,6 +499,7 @@ The `memory_relations` table is populated by multiple independent sources:
|
|
|
488
499
|
| `buildSemanticGraph()` | semantic | `build_graphs` MCP tool (manual) | Pure cosine similarity. PK collision: `INSERT OR IGNORE` means A-MEM semantic edges take precedence if they exist first. |
|
|
489
500
|
| Entity co-occurrence graph | entity | A-MEM enrichment (indexing) | LLM entity extraction → quality filters (title/length/blocklist/location validation) → type-agnostic canonical resolution within compatibility buckets (person, org, location, tech=project/service/tool/concept) → `entity_mentions` + `entity_cooccurrences` tables. Entity edges use IDF-based specificity scoring. Feeds ENTITY intent queries and MPFP `[entity, semantic]` patterns. |
|
|
490
501
|
| `consolidated_observations` | supporting | Consolidation worker (background) | 3-tier consolidation: facts → observations → mental models. Observations track `proof_count`, `trend` (STABLE/STRENGTHENING/WEAKENING/STALE), and source links. |
|
|
502
|
+
| Deductive synthesis | supporting | Consolidation worker Phase 3 (background, every ~15 min) | Combines 2-3 related recent observations (decision/preference/milestone/problem, last 7 days) into `content_type='deductive'` documents with `source_doc_ids` provenance. First-class searchable docs with ∞ half-life. |
|
|
491
503
|
|
|
492
504
|
**Edge collision:** Both `generateMemoryLinks()` and `buildSemanticGraph()` insert `relation_type='semantic'`. PK is `(source_id, target_id, relation_type)` — first writer wins.
|
|
493
505
|
|
|
@@ -564,6 +576,12 @@ Symptom: "Local model download blocked" error
|
|
|
564
576
|
→ llama-server endpoint unreachable while CLAWMEM_NO_LOCAL_MODELS=true.
|
|
565
577
|
→ Fix: Start the llama-server instance. Or set CLAWMEM_NO_LOCAL_MODELS=false for in-process fallback.
|
|
566
578
|
|
|
579
|
+
Symptom: "[generate] Remote LLM in cooldown, falling back to in-process generation"
|
|
580
|
+
→ Remote LLM server had a transport failure (ECONNREFUSED/ETIMEDOUT). ClawMem set a 60s cooldown
|
|
581
|
+
and is using local node-llama-cpp. Remote will be retried after cooldown expires.
|
|
582
|
+
→ Not an error if you expect local fallback. If you want remote only: ensure llama-server is running,
|
|
583
|
+
or set CLAWMEM_NO_LOCAL_MODELS=true to get null instead of slow local inference.
|
|
584
|
+
|
|
567
585
|
Symptom: Query expansion always fails / returns garbage
|
|
568
586
|
→ On CPU-only systems, in-process inference is significantly slower and less reliable. Systems with GPU acceleration (Metal/Vulkan) handle these models well in-process.
|
|
569
587
|
→ Fix: Run llama-server on a GPU. Even a low-end NVIDIA card handles 1.7B models.
|
package/CLAUDE.md
CHANGED
|
@@ -250,7 +250,7 @@ ClawMem hooks handle ~90% of retrieval automatically. Agent-initiated MCP calls
|
|
|
250
250
|
| `postcompact-inject` | SessionStart (compact) | 1200 tokens | re-injects authoritative context after compaction: precompact state (600) + recent decisions (400) + antipatterns (150) + vault context (200) → `<vault-postcompact>` |
|
|
251
251
|
| `curator-nudge` | SessionStart | 200 tokens | surfaces curator report actions, nudges when report is stale (>7 days) |
|
|
252
252
|
| `precompact-extract` | PreCompact | — | extracts decisions, file paths, open questions → writes `precompact-state.md` to auto-memory. Query-aware decision ranking. Reindexes auto-memory collection. |
|
|
253
|
-
| `decision-extractor` | Stop | — | LLM extracts observations → `_clawmem/agent/observations/`, infers causal links, detects contradictions
|
|
253
|
+
| `decision-extractor` | Stop | — | LLM extracts observations → `_clawmem/agent/observations/`, infers causal links, detects contradictions, extracts SPO triples from decision/preference/milestone/problem facts. Background consolidation worker synthesizes deductive observations from related facts (Phase 3, every ~15 min). |
|
|
254
254
|
| `handoff-generator` | Stop | — | LLM summarizes session → `_clawmem/agent/handoffs/` |
|
|
255
255
|
| `feedback-loop` | Stop | — | tracks referenced notes → boosts confidence, records usage relations + co-activations between co-referenced docs, tracks utility signals (surfaced vs referenced ratio for lifecycle automation) |
|
|
256
256
|
|
|
@@ -307,9 +307,15 @@ All other retrieval is handled by Tier 2 hooks. Do NOT call MCP tools speculativ
|
|
|
307
307
|
4. Chain tracing → find_causal_links(docid, direction="both", depth=5)
|
|
308
308
|
Traverses causal edges between _clawmem/agent/observations/ docs (from decision-extractor).
|
|
309
309
|
|
|
310
|
-
5.
|
|
310
|
+
5. Entity facts → kg_query(entity, as_of?, direction?)
|
|
311
|
+
Structured SPO triples with temporal validity. Different from intent_search:
|
|
312
|
+
- kg_query: "what does ClawMem relate to?" → returns structured facts (subject-predicate-object)
|
|
313
|
+
- intent_search: "why did we choose ClawMem?" → returns documents with causal reasoning
|
|
314
|
+
Use kg_query for entity lookup, intent_search for causal chains.
|
|
311
315
|
|
|
312
|
-
6.
|
|
316
|
+
6. Memory debugging → memory_evolution_status(docid)
|
|
317
|
+
|
|
318
|
+
7. Temporal context → timeline(docid, before=5, after=5, same_collection=false)
|
|
313
319
|
Shows what was created/modified before and after a document.
|
|
314
320
|
Use after search to understand chronological neighborhood.
|
|
315
321
|
```
|
|
@@ -327,6 +333,9 @@ All other retrieval is handled by Tier 2 hooks. Do NOT call MCP tools speculativ
|
|
|
327
333
|
- `timeline(docid, before=5, after=5, same_collection=false)` — temporal neighborhood around a document. Progressive disclosure: search → timeline → get. Supports same-collection scoping and session correlation.
|
|
328
334
|
- `list_vaults()` — show configured vault names and paths. Empty in single-vault mode (default).
|
|
329
335
|
- `vault_sync(vault, content_root, pattern?, collection_name?)` — index markdown from a directory into a named vault. Restricted-path validation rejects sensitive directories (`/etc/`, `/root/`, `.ssh`, `.env`, `credentials`, etc.).
|
|
336
|
+
- `kg_query(entity, as_of?, direction?)` — query the SPO knowledge graph for an entity's relationships. Returns temporal triples with validity windows. USE THIS for "what does X relate to?", "what was true about X in January?". Uses entity resolution for lookup.
|
|
337
|
+
- `diary_write(entry, topic?, agent?)` — write a diary entry. USE PROACTIVELY in non-hooked environments (Hermes, Gemini, plain MCP) for recording important events and decisions. Do NOT use in Claude Code (hooks handle this automatically).
|
|
338
|
+
- `diary_read(last_n?, agent?)` — read recent diary entries.
|
|
330
339
|
|
|
331
340
|
### Multi-Vault
|
|
332
341
|
|
|
@@ -355,6 +364,8 @@ Pin, snooze, and forget are **manual MCP tools** — not automated. The agent sh
|
|
|
355
364
|
- Do NOT forget memories to "clean up" — let confidence decay and contradiction detection handle it naturally.
|
|
356
365
|
- Do NOT run `build_graphs` after every reindex — A-MEM creates per-doc links automatically. Only after bulk ingestion or when `intent_search` returns weak graph results.
|
|
357
366
|
- Do NOT run `clawmem mine` autonomously — it is a bulk ingestion command (same category as `update`/`reindex`). Suggest it to the user when they mention old conversation exports, but let them run it. Bulk import has disk/embedding cost implications that need user consent.
|
|
367
|
+
- Do NOT use `diary_write` in Claude Code — hooks (`decision-extractor`, `handoff-generator`) capture this automatically. Diary is for non-hooked environments only (Hermes, Gemini, plain MCP clients).
|
|
368
|
+
- Do NOT use `kg_query` for causal "why" questions — use `intent_search` or `memory_retrieve`. `kg_query` returns structured entity facts (SPO triples), not reasoning chains.
|
|
358
369
|
|
|
359
370
|
## Tool Selection (one-liner)
|
|
360
371
|
|
|
@@ -436,7 +447,7 @@ compositeScore = (0.10 × searchScore + 0.70 × recencyScore + 0.20 × confidenc
|
|
|
436
447
|
|
|
437
448
|
| Content Type | Half-Life | Effect |
|
|
438
449
|
|--------------|-----------|--------|
|
|
439
|
-
| decision, preference, hub | ∞ | Never decay |
|
|
450
|
+
| decision, deductive, preference, hub | ∞ | Never decay |
|
|
440
451
|
| antipattern | ∞ | Never decay — accumulated negative patterns persist |
|
|
441
452
|
| project | 120 days | Slow decay |
|
|
442
453
|
| research | 90 days | Moderate decay |
|
|
@@ -445,7 +456,7 @@ compositeScore = (0.10 × searchScore + 0.70 × recencyScore + 0.20 × confidenc
|
|
|
445
456
|
| handoff | 30 days | Fast — recent matters most |
|
|
446
457
|
|
|
447
458
|
Half-lives extend up to 3× for frequently-accessed memories (access reinforcement decays over 90 days).
|
|
448
|
-
Attention decay: non-durable types (handoff, progress, conversation, note, project) lose 5% confidence per week without access. Decision/preference/hub/research/antipattern are exempt.
|
|
459
|
+
Attention decay: non-durable types (handoff, progress, conversation, note, project) lose 5% confidence per week without access. Decision/deductive/preference/hub/research/antipattern are exempt.
|
|
449
460
|
|
|
450
461
|
## Indexing & Graph Building
|
|
451
462
|
|
|
@@ -488,6 +499,7 @@ The `memory_relations` table is populated by multiple independent sources:
|
|
|
488
499
|
| `buildSemanticGraph()` | semantic | `build_graphs` MCP tool (manual) | Pure cosine similarity. PK collision: `INSERT OR IGNORE` means A-MEM semantic edges take precedence if they exist first. |
|
|
489
500
|
| Entity co-occurrence graph | entity | A-MEM enrichment (indexing) | LLM entity extraction → quality filters (title/length/blocklist/location validation) → type-agnostic canonical resolution within compatibility buckets (person, org, location, tech=project/service/tool/concept) → `entity_mentions` + `entity_cooccurrences` tables. Entity edges use IDF-based specificity scoring. Feeds ENTITY intent queries and MPFP `[entity, semantic]` patterns. |
|
|
490
501
|
| `consolidated_observations` | supporting | Consolidation worker (background) | 3-tier consolidation: facts → observations → mental models. Observations track `proof_count`, `trend` (STABLE/STRENGTHENING/WEAKENING/STALE), and source links. |
|
|
502
|
+
| Deductive synthesis | supporting | Consolidation worker Phase 3 (background, every ~15 min) | Combines 2-3 related recent observations (decision/preference/milestone/problem, last 7 days) into `content_type='deductive'` documents with `source_doc_ids` provenance. First-class searchable docs with ∞ half-life. |
|
|
491
503
|
|
|
492
504
|
**Edge collision:** Both `generateMemoryLinks()` and `buildSemanticGraph()` insert `relation_type='semantic'`. PK is `(source_id, target_id, relation_type)` — first writer wins.
|
|
493
505
|
|
|
@@ -564,6 +576,12 @@ Symptom: "Local model download blocked" error
|
|
|
564
576
|
→ llama-server endpoint unreachable while CLAWMEM_NO_LOCAL_MODELS=true.
|
|
565
577
|
→ Fix: Start the llama-server instance. Or set CLAWMEM_NO_LOCAL_MODELS=false for in-process fallback.
|
|
566
578
|
|
|
579
|
+
Symptom: "[generate] Remote LLM in cooldown, falling back to in-process generation"
|
|
580
|
+
→ Remote LLM server had a transport failure (ECONNREFUSED/ETIMEDOUT). ClawMem set a 60s cooldown
|
|
581
|
+
and is using local node-llama-cpp. Remote will be retried after cooldown expires.
|
|
582
|
+
→ Not an error if you expect local fallback. If you want remote only: ensure llama-server is running,
|
|
583
|
+
or set CLAWMEM_NO_LOCAL_MODELS=true to get null instead of slow local inference.
|
|
584
|
+
|
|
567
585
|
Symptom: Query expansion always fails / returns garbage
|
|
568
586
|
→ On CPU-only systems, in-process inference is significantly slower and less reliable. Systems with GPU acceleration (Metal/Vulkan) handle these models well in-process.
|
|
569
587
|
→ Fix: Run llama-server on a GPU. Even a low-end NVIDIA card handles 1.7B models.
|
package/README.md
CHANGED
|
@@ -176,7 +176,7 @@ ClawMem integrates via hooks (`settings.json`) and an MCP stdio server. Hooks ha
|
|
|
176
176
|
|
|
177
177
|
```bash
|
|
178
178
|
clawmem setup hooks # Install lifecycle hooks (SessionStart, UserPromptSubmit, Stop, PreCompact)
|
|
179
|
-
clawmem setup mcp # Register MCP server in ~/.claude.json (
|
|
179
|
+
clawmem setup mcp # Register MCP server in ~/.claude.json (31 tools)
|
|
180
180
|
```
|
|
181
181
|
|
|
182
182
|
**Automatic (90%):** `context-surfacing` injects relevant memory on every prompt. `postcompact-inject` re-injects state after compaction. `decision-extractor`, `handoff-generator`, `feedback-loop` capture session state on stop.
|
|
@@ -203,7 +203,7 @@ Disable OpenClaw's native memory and `memory-lancedb` auto-recall/capture to avo
|
|
|
203
203
|
openclaw config set agents.defaults.memorySearch.extraPaths "[]"
|
|
204
204
|
```
|
|
205
205
|
|
|
206
|
-
**Alternative:** OpenClaw agents can also use ClawMem's MCP server directly (`clawmem setup mcp`), with or without hooks. This gives full access to all
|
|
206
|
+
**Alternative:** OpenClaw agents can also use ClawMem's MCP server directly (`clawmem setup mcp`), with or without hooks. This gives full access to all 31 MCP tools but bypasses OpenClaw's ContextEngine lifecycle, so you lose token budget awareness, native compaction orchestration, and the `afterTurn()` message pipeline. The ContextEngine plugin is recommended for new OpenClaw setups; MCP is available as an additional or standalone integration.
|
|
207
207
|
|
|
208
208
|
#### Hermes Agent
|
|
209
209
|
|
|
@@ -310,9 +310,9 @@ ClawMem uses three `llama-server` (llama.cpp) instances for neural inference. Al
|
|
|
310
310
|
| LLM | 8089 | [qmd-query-expansion-1.7B-q4_k_m](https://huggingface.co/tobil/qmd-query-expansion-1.7B-gguf) | ~2.2GB | Intent classification, query expansion, A-MEM |
|
|
311
311
|
| Reranker | 8090 | [qwen3-reranker-0.6B-Q8_0](https://huggingface.co/ggml-org/Qwen3-Reranker-0.6B-Q8_0-GGUF) | ~1.3GB | Cross-encoder reranking (query, intent_search) |
|
|
312
312
|
|
|
313
|
-
The `bin/clawmem` wrapper defaults to `localhost:8088/8089/8090`. If a server is unreachable, ClawMem
|
|
313
|
+
The `bin/clawmem` wrapper defaults to `localhost:8088/8089/8090`. If a server is unreachable (transport error like ECONNREFUSED/ETIMEDOUT), ClawMem sets a 60-second cooldown and falls back to in-process inference via `node-llama-cpp` (auto-downloads the QMD native models on first use, uses Metal/Vulkan/CPU depending on hardware). HTTP errors (400/500) and user-cancelled requests do not trigger cooldown — the remote server is retried normally on the next call. With GPU acceleration the fallback is fast; on CPU-only it is significantly slower. ClawMem always works either way, but **if you're running dedicated GPU servers, use [systemd services](docs/guides/systemd-services.md) to ensure they stay up**.
|
|
314
314
|
|
|
315
|
-
To prevent
|
|
315
|
+
To prevent fallback and fail fast instead, set `CLAWMEM_NO_LOCAL_MODELS=true`.
|
|
316
316
|
|
|
317
317
|
#### Remote GPU (optional)
|
|
318
318
|
|
|
@@ -473,7 +473,7 @@ llama-server -m Qwen3-Reranker-0.6B-Q8_0.gguf \
|
|
|
473
473
|
|
|
474
474
|
### MCP Server
|
|
475
475
|
|
|
476
|
-
ClawMem exposes
|
|
476
|
+
ClawMem exposes 31 MCP tools via the [Model Context Protocol](https://modelcontextprotocol.io) and an optional HTTP REST API. Any MCP-compatible client or HTTP client can use it.
|
|
477
477
|
|
|
478
478
|
**Claude Code (automatic):**
|
|
479
479
|
|
|
@@ -678,7 +678,7 @@ clawmem doctor Full health check
|
|
|
678
678
|
clawmem status Quick index status
|
|
679
679
|
```
|
|
680
680
|
|
|
681
|
-
## MCP Tools (
|
|
681
|
+
## MCP Tools (31)
|
|
682
682
|
|
|
683
683
|
Registered by `clawmem setup mcp`. Available to any MCP-compatible client.
|
|
684
684
|
|
|
@@ -715,6 +715,7 @@ Registered by `clawmem setup mcp`. Available to any MCP-compatible client.
|
|
|
715
715
|
|---|---|
|
|
716
716
|
| `build_graphs` | Build temporal and/or semantic graphs from document corpus |
|
|
717
717
|
| `find_causal_links` | Trace decision chains: "what led to X", "how we got from A to B". Follow up `intent_search` with this tool on a top result to walk the full causal chain. Traverses causes / caused_by / both up to N hops with depth-annotated reasoning. |
|
|
718
|
+
| `kg_query` | Query the SPO knowledge graph: "what does X relate to?", "what was true about X when?". Returns temporal entity-relationship triples with validity windows. Uses entity resolution for lookup. |
|
|
718
719
|
| `memory_evolution_status` | Show how a document's A-MEM metadata evolved over time |
|
|
719
720
|
| `timeline` | Show the temporal neighborhood around a document — what was created/modified before and after it. Progressive disclosure: search → timeline (context) → get (full content). Supports same-collection scoping and session correlation. |
|
|
720
721
|
|
|
@@ -731,6 +732,13 @@ Registered by `clawmem setup mcp`. Available to any MCP-compatible client.
|
|
|
731
732
|
| `list_vaults` | Show configured vault names and paths. Empty in single-vault mode. |
|
|
732
733
|
| `vault_sync` | Index markdown from a directory into a named vault. Restricted-path validation rejects sensitive directories. |
|
|
733
734
|
|
|
735
|
+
### Agent Diary
|
|
736
|
+
|
|
737
|
+
| Tool | Description |
|
|
738
|
+
|---|---|
|
|
739
|
+
| `diary_write` | Write a diary entry. Use for recording important events, decisions, or observations in environments without hook support. Stored as searchable memories. |
|
|
740
|
+
| `diary_read` | Read recent diary entries. Filter by agent name. |
|
|
741
|
+
|
|
734
742
|
### Memory Management & Lifecycle
|
|
735
743
|
|
|
736
744
|
| Tool | Description |
|
|
@@ -815,6 +823,7 @@ For WHY and ENTITY queries, the search pipeline expands results through the memo
|
|
|
815
823
|
| Type | Half-life | Baseline | Notes |
|
|
816
824
|
|---|---|---|---|
|
|
817
825
|
| `decision` | ∞ | 0.85 | Never decays |
|
|
826
|
+
| `deductive` | ∞ | 0.85 | Never decays — cross-session derived insights with source provenance |
|
|
818
827
|
| `preference` | ∞ | 0.80 | Never decays — user preferences are durable facts |
|
|
819
828
|
| `hub` | ∞ | 0.80 | Never decays |
|
|
820
829
|
| `antipattern` | ∞ | 0.75 | Never decays — accumulated negative patterns persist |
|
|
@@ -827,7 +836,7 @@ For WHY and ENTITY queries, the search pipeline expands results through the memo
|
|
|
827
836
|
| `progress` | 45 days | 0.50 | |
|
|
828
837
|
| `note` | 60 days | 0.50 | Default |
|
|
829
838
|
|
|
830
|
-
Content types are inferred from frontmatter or file path patterns. Half-lives extend up to 3× for frequently-accessed memories (access reinforcement, decays over 90 days). Non-durable types (handoff, progress, conversation, note, project) lose 5% confidence per week without access (attention decay). Decision/preference/hub/research/antipattern are exempt.
|
|
839
|
+
Content types are inferred from frontmatter or file path patterns. Half-lives extend up to 3× for frequently-accessed memories (access reinforcement, decays over 90 days). Non-durable types (handoff, progress, conversation, note, project) lose 5% confidence per week without access (attention decay). Decision/deductive/preference/hub/research/antipattern are exempt.
|
|
831
840
|
|
|
832
841
|
**Quality scoring:** Each document gets a `quality_score` (0.0–1.0) computed during indexing based on length, structure (headings, lists), decision/correction keywords, and frontmatter richness. Applied as `qualityMultiplier = 0.7 + 0.6 × qualityScore` (range: 0.7× penalty to 1.3× boost).
|
|
833
842
|
|
|
@@ -1111,7 +1120,9 @@ Built on the shoulders of:
|
|
|
1111
1120
|
- [Engram](https://github.com/Gentleman-Programming/engram) — observation dedup window, topic-key upsert pattern, temporal timeline navigation, duplicate metadata scoring signals
|
|
1112
1121
|
- [Hermes Agent](https://github.com/NousResearch/hermes-agent) — MemoryProvider plugin integration, memory nudge system (periodic lifecycle tool prompting)
|
|
1113
1122
|
- [Hindsight](https://github.com/vectorize-io/hindsight) — entity resolution, MPFP graph traversal, temporal extraction, 3-tier consolidation, observation invalidation, 4-way parallel retrieval
|
|
1123
|
+
- [Honcho](https://github.com/plastic-labs/honcho) — deductive observation synthesis patterns, surprisal-based anomaly scoring concept, embed-state self-healing, retrieval separation (raw vs derived)
|
|
1114
1124
|
- [MAGMA](https://arxiv.org/abs/2501.13956) — multi-graph memory agent
|
|
1125
|
+
- [MemPalace](https://github.com/milla-jovovich/mempalace) — conversation import patterns, broadened observation taxonomy (preference/milestone/problem), session-bootstrap synthesis
|
|
1115
1126
|
- [memory-lancedb-pro](https://github.com/CortexReach/memory-lancedb-pro) — retrieval gate, length normalization, MMR diversity, access reinforcement algorithms
|
|
1116
1127
|
- [OpenViking](https://github.com/volcengine/OpenViking) — query decomposition patterns, collection-scoped retrieval, transaction-safe indexing
|
|
1117
1128
|
- [QMD](https://github.com/tobi/qmd) — search backend (BM25 + vectors + RRF + reranking)
|
package/SKILL.md
CHANGED
|
@@ -242,9 +242,15 @@ Once escalated, route by query type:
|
|
|
242
242
|
4. Chain tracing -> find_causal_links(docid, direction="both", depth=5)
|
|
243
243
|
Traverses causal edges between _clawmem/agent/observations/ docs.
|
|
244
244
|
|
|
245
|
-
5.
|
|
245
|
+
5. Entity facts -> kg_query(entity, as_of?, direction?)
|
|
246
|
+
Structured SPO triples with temporal validity. Different from intent_search:
|
|
247
|
+
- kg_query: "what does ClawMem relate to?" -> returns structured facts (subject-predicate-object)
|
|
248
|
+
- intent_search: "why did we choose ClawMem?" -> returns documents with causal reasoning
|
|
249
|
+
Use kg_query for entity lookup, intent_search for causal chains.
|
|
246
250
|
|
|
247
|
-
6.
|
|
251
|
+
6. Memory debugging -> memory_evolution_status(docid)
|
|
252
|
+
|
|
253
|
+
7. Temporal context -> timeline(docid, before=5, after=5, same_collection=false)
|
|
248
254
|
Shows what was created/modified before and after a document.
|
|
249
255
|
Use after search to understand chronological neighborhood.
|
|
250
256
|
```
|
|
@@ -277,6 +283,9 @@ Once escalated, route by query type:
|
|
|
277
283
|
| `timeline` | Temporal neighborhood around a document — what was modified before/after. Progressive disclosure: search → timeline → get. Supports same-collection scoping and session correlation. |
|
|
278
284
|
| `list_vaults` | Show configured vault names and paths. Empty in single-vault mode. |
|
|
279
285
|
| `vault_sync` | Index markdown from a directory into a named vault. Restricted-path validation rejects sensitive directories. |
|
|
286
|
+
| `kg_query` | Query SPO knowledge graph for entity relationships with temporal validity. Uses entity resolution. |
|
|
287
|
+
| `diary_write` | Write diary entry. Use proactively in non-hooked environments. Do NOT use in Claude Code. |
|
|
288
|
+
| `diary_read` | Read recent diary entries. Filter by agent name. |
|
|
280
289
|
| `lifecycle_status` | Document lifecycle statistics: active, archived, forgotten, pinned, snoozed counts and policy summary. |
|
|
281
290
|
| `lifecycle_sweep` | Run lifecycle policies: archive stale docs. Defaults to dry_run (preview only). |
|
|
282
291
|
| `lifecycle_restore` | Restore auto-archived documents. Filter by query, collection, or all. Does NOT restore manually forgotten docs. |
|
|
@@ -442,7 +451,7 @@ compositeScore = (0.10 x searchScore + 0.70 x recencyScore + 0.20 x confidenceSc
|
|
|
442
451
|
|
|
443
452
|
| Content Type | Half-Life | Effect |
|
|
444
453
|
|--------------|-----------|--------|
|
|
445
|
-
| decision, preference, hub | infinity | Never decay |
|
|
454
|
+
| decision, deductive, preference, hub | infinity | Never decay |
|
|
446
455
|
| antipattern | infinity | Never decay — accumulated negative patterns persist |
|
|
447
456
|
| project | 120 days | Slow decay |
|
|
448
457
|
| research | 90 days | Moderate decay |
|
|
@@ -567,6 +576,8 @@ When `decision-extractor` detects a new decision contradicting an old one, the o
|
|
|
567
576
|
- Do NOT forget memories to "clean up" — let confidence decay and contradiction detection handle it.
|
|
568
577
|
- Do NOT run `build_graphs` after every reindex — A-MEM creates per-doc links automatically.
|
|
569
578
|
- Do NOT run `clawmem mine` autonomously — it is a bulk ingestion command. Suggest it to the user when they mention old conversation exports, but let them run it.
|
|
579
|
+
- Do NOT use `diary_write` in Claude Code — hooks capture this automatically. Diary is for non-hooked environments only (Hermes, Gemini, plain MCP).
|
|
580
|
+
- Do NOT use `kg_query` for causal "why" questions — use `intent_search` or `memory_retrieve`. `kg_query` returns structured entity facts (SPO triples), not reasoning chains.
|
|
570
581
|
|
|
571
582
|
---
|
|
572
583
|
|
package/package.json
CHANGED
package/src/clawmem.ts
CHANGED
|
@@ -410,6 +410,9 @@ async function cmdEmbed(args: string[]) {
|
|
|
410
410
|
|
|
411
411
|
const fragments = splitDocument(body, frontmatter);
|
|
412
412
|
const docStart = Date.now();
|
|
413
|
+
const prevTotalFragments = totalFragments;
|
|
414
|
+
const prevFailedFragments = failedFragments;
|
|
415
|
+
let seq0Succeeded = false;
|
|
413
416
|
console.error(` [${docIdx + 1}/${hashes.length}] ${basename(path)} (${fragments.length} frags, ${body.length} chars)`);
|
|
414
417
|
|
|
415
418
|
if (isCloudEmbed) {
|
|
@@ -463,6 +466,7 @@ async function cmdEmbed(args: string[]) {
|
|
|
463
466
|
result.model, new Date().toISOString(), frag.type, frag.label ?? undefined, canId
|
|
464
467
|
);
|
|
465
468
|
totalFragments++;
|
|
469
|
+
if (seq === 0) seq0Succeeded = true;
|
|
466
470
|
} else {
|
|
467
471
|
failedFragments++;
|
|
468
472
|
}
|
|
@@ -491,6 +495,7 @@ async function cmdEmbed(args: string[]) {
|
|
|
491
495
|
result.model, new Date().toISOString(), frag.type, frag.label ?? undefined, canId
|
|
492
496
|
);
|
|
493
497
|
totalFragments++;
|
|
498
|
+
if (seq === 0) seq0Succeeded = true;
|
|
494
499
|
if (seq === 0 || (seq + 1) % 5 === 0 || seq === fragments.length - 1) {
|
|
495
500
|
console.error(` frag ${seq + 1}/${fragments.length} (${frag.type}) ${fragMs}ms [${text.length} chars]`);
|
|
496
501
|
}
|
|
@@ -505,6 +510,18 @@ async function cmdEmbed(args: string[]) {
|
|
|
505
510
|
}
|
|
506
511
|
}
|
|
507
512
|
|
|
513
|
+
// Track embed state per document — seq=0 (primary) must succeed for synced status
|
|
514
|
+
const docFragsOk = totalFragments - prevTotalFragments;
|
|
515
|
+
const docFragsFail = failedFragments - prevFailedFragments;
|
|
516
|
+
if (seq0Succeeded) {
|
|
517
|
+
s.markEmbedSynced(hash);
|
|
518
|
+
} else if (docFragsOk === 0 && docFragsFail > 0) {
|
|
519
|
+
s.markEmbedFailed(hash, "all fragments failed");
|
|
520
|
+
} else {
|
|
521
|
+
// seq=0 failed but some later fragments succeeded — mark failed so seq=0 gets retried
|
|
522
|
+
s.markEmbedFailed(hash, "primary fragment (seq=0) failed");
|
|
523
|
+
}
|
|
524
|
+
|
|
508
525
|
embedded++;
|
|
509
526
|
const docMs = Date.now() - docStart;
|
|
510
527
|
const elapsed = ((Date.now() - batchStart) / 1000).toFixed(0);
|
|
@@ -1868,6 +1885,9 @@ async function main() {
|
|
|
1868
1885
|
case "curate":
|
|
1869
1886
|
await cmdCurate(subArgs);
|
|
1870
1887
|
break;
|
|
1888
|
+
case "diary":
|
|
1889
|
+
await cmdDiary(subArgs);
|
|
1890
|
+
break;
|
|
1871
1891
|
case "help":
|
|
1872
1892
|
case "--help":
|
|
1873
1893
|
case "-h":
|
|
@@ -2207,6 +2227,99 @@ interface CuratorReport {
|
|
|
2207
2227
|
actions: string[];
|
|
2208
2228
|
}
|
|
2209
2229
|
|
|
2230
|
+
async function cmdDiary(args: string[]) {
|
|
2231
|
+
const subCmd = args[0];
|
|
2232
|
+
const subArgs = args.slice(1);
|
|
2233
|
+
|
|
2234
|
+
switch (subCmd) {
|
|
2235
|
+
case "write": {
|
|
2236
|
+
const { values, positionals } = parseArgs({
|
|
2237
|
+
args: subArgs,
|
|
2238
|
+
options: {
|
|
2239
|
+
topic: { type: "string", short: "t", default: "general" },
|
|
2240
|
+
agent: { type: "string", short: "a", default: "user" },
|
|
2241
|
+
},
|
|
2242
|
+
allowPositionals: true,
|
|
2243
|
+
});
|
|
2244
|
+
|
|
2245
|
+
const entry = positionals.join(" ");
|
|
2246
|
+
if (!entry) die("Usage: clawmem diary write <entry text> [-t topic] [-a agent-name]");
|
|
2247
|
+
|
|
2248
|
+
const s = getStore();
|
|
2249
|
+
const now = new Date();
|
|
2250
|
+
const dateStr = now.toISOString().slice(0, 10);
|
|
2251
|
+
const timeStr = now.toISOString().slice(11, 19).replace(/:/g, "");
|
|
2252
|
+
const ms = String(now.getMilliseconds()).padStart(3, "0");
|
|
2253
|
+
const diaryPath = `diary/${dateStr}-${timeStr}${ms}-${values.topic}.md`;
|
|
2254
|
+
const body = [
|
|
2255
|
+
"---",
|
|
2256
|
+
`title: "${entry.slice(0, 80).replace(/"/g, '\\"')}"`,
|
|
2257
|
+
`content_type: note`,
|
|
2258
|
+
`tags: [diary, ${values.topic}]`,
|
|
2259
|
+
`domain: "${values.agent}"`,
|
|
2260
|
+
"---",
|
|
2261
|
+
"",
|
|
2262
|
+
entry,
|
|
2263
|
+
].join("\n");
|
|
2264
|
+
|
|
2265
|
+
const result = s.saveMemory({
|
|
2266
|
+
collection: "_clawmem",
|
|
2267
|
+
path: diaryPath,
|
|
2268
|
+
title: entry.slice(0, 80),
|
|
2269
|
+
body,
|
|
2270
|
+
contentType: "note",
|
|
2271
|
+
confidence: 0.7,
|
|
2272
|
+
semanticPayload: `${diaryPath}::${entry}`,
|
|
2273
|
+
});
|
|
2274
|
+
|
|
2275
|
+
console.log(`${c.green}✓${c.reset} Diary entry saved (${result.action}, doc #${result.docId})`);
|
|
2276
|
+
break;
|
|
2277
|
+
}
|
|
2278
|
+
|
|
2279
|
+
case "read": {
|
|
2280
|
+
const { values } = parseArgs({
|
|
2281
|
+
args: subArgs,
|
|
2282
|
+
options: {
|
|
2283
|
+
last: { type: "string", short: "n", default: "10" },
|
|
2284
|
+
agent: { type: "string", short: "a" },
|
|
2285
|
+
},
|
|
2286
|
+
allowPositionals: false,
|
|
2287
|
+
});
|
|
2288
|
+
|
|
2289
|
+
const limit = parseInt(values.last || "10", 10);
|
|
2290
|
+
const s = getStore();
|
|
2291
|
+
|
|
2292
|
+
const rows = s.db.prepare(`
|
|
2293
|
+
SELECT d.id, d.path, d.title, d.modified_at as modifiedAt, d.domain,
|
|
2294
|
+
c.doc as body
|
|
2295
|
+
FROM documents d
|
|
2296
|
+
JOIN content c ON c.hash = d.hash
|
|
2297
|
+
WHERE d.active = 1 AND d.collection = '_clawmem' AND d.path LIKE 'diary/%'
|
|
2298
|
+
${values.agent ? "AND d.domain = ?" : ""}
|
|
2299
|
+
ORDER BY d.modified_at DESC
|
|
2300
|
+
LIMIT ?
|
|
2301
|
+
`).all(...(values.agent ? [values.agent, limit] : [limit])) as any[];
|
|
2302
|
+
|
|
2303
|
+
if (rows.length === 0) {
|
|
2304
|
+
console.log("No diary entries found.");
|
|
2305
|
+
break;
|
|
2306
|
+
}
|
|
2307
|
+
|
|
2308
|
+
console.log(`${c.bold}Diary${c.reset} (${rows.length} entries)\n`);
|
|
2309
|
+
for (const row of rows) {
|
|
2310
|
+
const agent = row.domain ? ` [${row.domain}]` : "";
|
|
2311
|
+
console.log(`${c.dim}${row.modifiedAt.slice(0, 16)}${c.reset}${agent} ${row.title}`);
|
|
2312
|
+
}
|
|
2313
|
+
break;
|
|
2314
|
+
}
|
|
2315
|
+
|
|
2316
|
+
default:
|
|
2317
|
+
console.log(`Usage:
|
|
2318
|
+
clawmem diary write <entry> [-t topic] [-a agent] Write diary entry
|
|
2319
|
+
clawmem diary read [-n limit] [-a agent] Read recent entries`);
|
|
2320
|
+
}
|
|
2321
|
+
}
|
|
2322
|
+
|
|
2210
2323
|
async function cmdCurate(_args: string[]) {
|
|
2211
2324
|
const s = getStore();
|
|
2212
2325
|
const report: CuratorReport = {
|
|
@@ -2422,6 +2535,8 @@ ${c.bold}Intelligence:${c.reset}
|
|
|
2422
2535
|
clawmem reflect [days] Cross-session pattern analysis
|
|
2423
2536
|
clawmem consolidate [--dry-run] Merge duplicate low-confidence docs
|
|
2424
2537
|
clawmem curate Automated maintenance (health, sweep, dedup, hygiene)
|
|
2538
|
+
clawmem diary write <entry> [-t topic] Write a diary entry (for non-hooked environments)
|
|
2539
|
+
clawmem diary read [-n N] [-a agent] Read recent diary entries
|
|
2425
2540
|
|
|
2426
2541
|
${c.bold}Integration:${c.reset}
|
|
2427
2542
|
clawmem mcp Start stdio MCP server
|