loop-memory 0.4.1__tar.gz → 0.4.2__tar.gz

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 (126) hide show
  1. {loop_memory-0.4.1 → loop_memory-0.4.2}/PKG-INFO +166 -33
  2. {loop_memory-0.4.1 → loop_memory-0.4.2}/README.md +165 -32
  3. {loop_memory-0.4.1 → loop_memory-0.4.2}/loop_memory.egg-info/PKG-INFO +166 -33
  4. {loop_memory-0.4.1 → loop_memory-0.4.2}/pyproject.toml +1 -1
  5. {loop_memory-0.4.1 → loop_memory-0.4.2}/tests/test_repo_framing.py +89 -0
  6. {loop_memory-0.4.1 → loop_memory-0.4.2}/LICENSE +0 -0
  7. {loop_memory-0.4.1 → loop_memory-0.4.2}/loop_memory/__init__.py +0 -0
  8. {loop_memory-0.4.1 → loop_memory-0.4.2}/loop_memory/backends/__init__.py +0 -0
  9. {loop_memory-0.4.1 → loop_memory-0.4.2}/loop_memory/backends/embedding.py +0 -0
  10. {loop_memory-0.4.1 → loop_memory-0.4.2}/loop_memory/backends/sentence_embedder.py +0 -0
  11. {loop_memory-0.4.1 → loop_memory-0.4.2}/loop_memory/backends/vector_store.py +0 -0
  12. {loop_memory-0.4.1 → loop_memory-0.4.2}/loop_memory/cli/__init__.py +0 -0
  13. {loop_memory-0.4.1 → loop_memory-0.4.2}/loop_memory/cli/_common.py +0 -0
  14. {loop_memory-0.4.1 → loop_memory-0.4.2}/loop_memory/cli/commands/__init__.py +0 -0
  15. {loop_memory-0.4.1 → loop_memory-0.4.2}/loop_memory/cli/commands/cognitive.py +0 -0
  16. {loop_memory-0.4.1 → loop_memory-0.4.2}/loop_memory/cli/commands/diag.py +0 -0
  17. {loop_memory-0.4.1 → loop_memory-0.4.2}/loop_memory/cli/commands/graph.py +0 -0
  18. {loop_memory-0.4.1 → loop_memory-0.4.2}/loop_memory/cli/commands/hooks.py +0 -0
  19. {loop_memory-0.4.1 → loop_memory-0.4.2}/loop_memory/cli/commands/read.py +0 -0
  20. {loop_memory-0.4.1 → loop_memory-0.4.2}/loop_memory/cli/commands/serve.py +0 -0
  21. {loop_memory-0.4.1 → loop_memory-0.4.2}/loop_memory/cli/commands/write.py +0 -0
  22. {loop_memory-0.4.1 → loop_memory-0.4.2}/loop_memory/cli/main.py +0 -0
  23. {loop_memory-0.4.1 → loop_memory-0.4.2}/loop_memory/engine/__init__.py +0 -0
  24. {loop_memory-0.4.1 → loop_memory-0.4.2}/loop_memory/engine/loop.py +0 -0
  25. {loop_memory-0.4.1 → loop_memory-0.4.2}/loop_memory/engine/reflect.py +0 -0
  26. {loop_memory-0.4.1 → loop_memory-0.4.2}/loop_memory/examples/__init__.py +0 -0
  27. {loop_memory-0.4.1 → loop_memory-0.4.2}/loop_memory/examples/demo.py +0 -0
  28. {loop_memory-0.4.1 → loop_memory-0.4.2}/loop_memory/export/__init__.py +0 -0
  29. {loop_memory-0.4.1 → loop_memory-0.4.2}/loop_memory/export/memory_md.py +0 -0
  30. {loop_memory-0.4.1 → loop_memory-0.4.2}/loop_memory/graph/__init__.py +0 -0
  31. {loop_memory-0.4.1 → loop_memory-0.4.2}/loop_memory/graph/build.py +0 -0
  32. {loop_memory-0.4.1 → loop_memory-0.4.2}/loop_memory/graph/extract.py +0 -0
  33. {loop_memory-0.4.1 → loop_memory-0.4.2}/loop_memory/ingest/__init__.py +0 -0
  34. {loop_memory-0.4.1 → loop_memory-0.4.2}/loop_memory/ingest/loader.py +0 -0
  35. {loop_memory-0.4.1 → loop_memory-0.4.2}/loop_memory/ingest/pipeline.py +0 -0
  36. {loop_memory-0.4.1 → loop_memory-0.4.2}/loop_memory/jobs/__init__.py +0 -0
  37. {loop_memory-0.4.1 → loop_memory-0.4.2}/loop_memory/jobs/cognitive.py +0 -0
  38. {loop_memory-0.4.1 → loop_memory-0.4.2}/loop_memory/jobs/compact.py +0 -0
  39. {loop_memory-0.4.1 → loop_memory-0.4.2}/loop_memory/jobs/consolidate.py +0 -0
  40. {loop_memory-0.4.1 → loop_memory-0.4.2}/loop_memory/jobs/contradiction.py +0 -0
  41. {loop_memory-0.4.1 → loop_memory-0.4.2}/loop_memory/jobs/evolution.py +0 -0
  42. {loop_memory-0.4.1 → loop_memory-0.4.2}/loop_memory/jobs/graph.py +0 -0
  43. {loop_memory-0.4.1 → loop_memory-0.4.2}/loop_memory/jobs/llm_compact_pass.py +0 -0
  44. {loop_memory-0.4.1 → loop_memory-0.4.2}/loop_memory/jobs/llm_consolidate.py +0 -0
  45. {loop_memory-0.4.1 → loop_memory-0.4.2}/loop_memory/jobs/scheduler.py +0 -0
  46. {loop_memory-0.4.1 → loop_memory-0.4.2}/loop_memory/llm/__init__.py +0 -0
  47. {loop_memory-0.4.1 → loop_memory-0.4.2}/loop_memory/llm/base.py +0 -0
  48. {loop_memory-0.4.1 → loop_memory-0.4.2}/loop_memory/llm/openai_adapter.py +0 -0
  49. {loop_memory-0.4.1 → loop_memory-0.4.2}/loop_memory/llm/providers.py +0 -0
  50. {loop_memory-0.4.1 → loop_memory-0.4.2}/loop_memory/mcp/__init__.py +0 -0
  51. {loop_memory-0.4.1 → loop_memory-0.4.2}/loop_memory/memory/__init__.py +0 -0
  52. {loop_memory-0.4.1 → loop_memory-0.4.2}/loop_memory/memory/types.py +0 -0
  53. {loop_memory-0.4.1 → loop_memory-0.4.2}/loop_memory/privacy/__init__.py +0 -0
  54. {loop_memory-0.4.1 → loop_memory-0.4.2}/loop_memory/privacy/private.py +0 -0
  55. {loop_memory-0.4.1 → loop_memory-0.4.2}/loop_memory/privacy/redact.py +0 -0
  56. {loop_memory-0.4.1 → loop_memory-0.4.2}/loop_memory/py.typed +0 -0
  57. {loop_memory-0.4.1 → loop_memory-0.4.2}/loop_memory/sdk.py +0 -0
  58. {loop_memory-0.4.1 → loop_memory-0.4.2}/loop_memory/sdk_extensions.py +0 -0
  59. {loop_memory-0.4.1 → loop_memory-0.4.2}/loop_memory/security/__init__.py +0 -0
  60. {loop_memory-0.4.1 → loop_memory-0.4.2}/loop_memory/security/secrets.py +0 -0
  61. {loop_memory-0.4.1 → loop_memory-0.4.2}/loop_memory/serve/__init__.py +0 -0
  62. {loop_memory-0.4.1 → loop_memory-0.4.2}/loop_memory/serve/app.py +0 -0
  63. {loop_memory-0.4.1 → loop_memory-0.4.2}/loop_memory/serve/handlers.py +0 -0
  64. {loop_memory-0.4.1 → loop_memory-0.4.2}/loop_memory/serve/routes/_shared.py +0 -0
  65. {loop_memory-0.4.1 → loop_memory-0.4.2}/loop_memory/serve/routes/admin.py +0 -0
  66. {loop_memory-0.4.1 → loop_memory-0.4.2}/loop_memory/serve/routes/cognitive.py +0 -0
  67. {loop_memory-0.4.1 → loop_memory-0.4.2}/loop_memory/serve/routes/export.py +0 -0
  68. {loop_memory-0.4.1 → loop_memory-0.4.2}/loop_memory/serve/routes/graph.py +0 -0
  69. {loop_memory-0.4.1 → loop_memory-0.4.2}/loop_memory/serve/routes/insights.py +0 -0
  70. {loop_memory-0.4.1 → loop_memory-0.4.2}/loop_memory/serve/routes/memories.py +0 -0
  71. {loop_memory-0.4.1 → loop_memory-0.4.2}/loop_memory/serve/routes/sessions.py +0 -0
  72. {loop_memory-0.4.1 → loop_memory-0.4.2}/loop_memory/serve/routes/system.py +0 -0
  73. {loop_memory-0.4.1 → loop_memory-0.4.2}/loop_memory/serve/routes/wiki.py +0 -0
  74. {loop_memory-0.4.1 → loop_memory-0.4.2}/loop_memory/serve/static/__init__.py +0 -0
  75. {loop_memory-0.4.1 → loop_memory-0.4.2}/loop_memory/serve/static/index.html +0 -0
  76. {loop_memory-0.4.1 → loop_memory-0.4.2}/loop_memory/serve/watcher.py +0 -0
  77. {loop_memory-0.4.1 → loop_memory-0.4.2}/loop_memory/storage/__init__.py +0 -0
  78. {loop_memory-0.4.1 → loop_memory-0.4.2}/loop_memory/storage/retrieval.py +0 -0
  79. {loop_memory-0.4.1 → loop_memory-0.4.2}/loop_memory/storage/sqlite_store.py +0 -0
  80. {loop_memory-0.4.1 → loop_memory-0.4.2}/loop_memory/wiki/__init__.py +0 -0
  81. {loop_memory-0.4.1 → loop_memory-0.4.2}/loop_memory/wiki/backfill.py +0 -0
  82. {loop_memory-0.4.1 → loop_memory-0.4.2}/loop_memory/wiki/classifier.py +0 -0
  83. {loop_memory-0.4.1 → loop_memory-0.4.2}/loop_memory/wiki/prompts.py +0 -0
  84. {loop_memory-0.4.1 → loop_memory-0.4.2}/loop_memory/wiki/scope.py +0 -0
  85. {loop_memory-0.4.1 → loop_memory-0.4.2}/loop_memory.egg-info/SOURCES.txt +0 -0
  86. {loop_memory-0.4.1 → loop_memory-0.4.2}/loop_memory.egg-info/dependency_links.txt +0 -0
  87. {loop_memory-0.4.1 → loop_memory-0.4.2}/loop_memory.egg-info/entry_points.txt +0 -0
  88. {loop_memory-0.4.1 → loop_memory-0.4.2}/loop_memory.egg-info/requires.txt +0 -0
  89. {loop_memory-0.4.1 → loop_memory-0.4.2}/loop_memory.egg-info/top_level.txt +0 -0
  90. {loop_memory-0.4.1 → loop_memory-0.4.2}/setup.cfg +0 -0
  91. {loop_memory-0.4.1 → loop_memory-0.4.2}/tests/test_admin_ingest_route.py +0 -0
  92. {loop_memory-0.4.1 → loop_memory-0.4.2}/tests/test_agent_memory_api.py +0 -0
  93. {loop_memory-0.4.1 → loop_memory-0.4.2}/tests/test_agent_memory_sdk.py +0 -0
  94. {loop_memory-0.4.1 → loop_memory-0.4.2}/tests/test_auth_token_rotate.py +0 -0
  95. {loop_memory-0.4.1 → loop_memory-0.4.2}/tests/test_cli_v7.py +0 -0
  96. {loop_memory-0.4.1 → loop_memory-0.4.2}/tests/test_cli_version.py +0 -0
  97. {loop_memory-0.4.1 → loop_memory-0.4.2}/tests/test_contradictions.py +0 -0
  98. {loop_memory-0.4.1 → loop_memory-0.4.2}/tests/test_evolution.py +0 -0
  99. {loop_memory-0.4.1 → loop_memory-0.4.2}/tests/test_evolution_quality.py +0 -0
  100. {loop_memory-0.4.1 → loop_memory-0.4.2}/tests/test_expanduser.py +0 -0
  101. {loop_memory-0.4.1 → loop_memory-0.4.2}/tests/test_export_ask.py +0 -0
  102. {loop_memory-0.4.1 → loop_memory-0.4.2}/tests/test_graph.py +0 -0
  103. {loop_memory-0.4.1 → loop_memory-0.4.2}/tests/test_ingest.py +0 -0
  104. {loop_memory-0.4.1 → loop_memory-0.4.2}/tests/test_llm_consolidator.py +0 -0
  105. {loop_memory-0.4.1 → loop_memory-0.4.2}/tests/test_llm_fingerprint_not_persisted.py +0 -0
  106. {loop_memory-0.4.1 → loop_memory-0.4.2}/tests/test_llm_providers.py +0 -0
  107. {loop_memory-0.4.1 → loop_memory-0.4.2}/tests/test_llm_test_endpoint.py +0 -0
  108. {loop_memory-0.4.1 → loop_memory-0.4.2}/tests/test_loop.py +0 -0
  109. {loop_memory-0.4.1 → loop_memory-0.4.2}/tests/test_mcp.py +0 -0
  110. {loop_memory-0.4.1 → loop_memory-0.4.2}/tests/test_memories_pagination.py +0 -0
  111. {loop_memory-0.4.1 → loop_memory-0.4.2}/tests/test_openclaw_loader.py +0 -0
  112. {loop_memory-0.4.1 → loop_memory-0.4.2}/tests/test_reflection.py +0 -0
  113. {loop_memory-0.4.1 → loop_memory-0.4.2}/tests/test_score_api.py +0 -0
  114. {loop_memory-0.4.1 → loop_memory-0.4.2}/tests/test_scoring_v2.py +0 -0
  115. {loop_memory-0.4.1 → loop_memory-0.4.2}/tests/test_secrets.py +0 -0
  116. {loop_memory-0.4.1 → loop_memory-0.4.2}/tests/test_serve_app.py +0 -0
  117. {loop_memory-0.4.1 → loop_memory-0.4.2}/tests/test_serve_handlers.py +0 -0
  118. {loop_memory-0.4.1 → loop_memory-0.4.2}/tests/test_session_order.py +0 -0
  119. {loop_memory-0.4.1 → loop_memory-0.4.2}/tests/test_store.py +0 -0
  120. {loop_memory-0.4.1 → loop_memory-0.4.2}/tests/test_summarization.py +0 -0
  121. {loop_memory-0.4.1 → loop_memory-0.4.2}/tests/test_universal_memory.py +0 -0
  122. {loop_memory-0.4.1 → loop_memory-0.4.2}/tests/test_vector_store.py +0 -0
  123. {loop_memory-0.4.1 → loop_memory-0.4.2}/tests/test_watcher.py +0 -0
  124. {loop_memory-0.4.1 → loop_memory-0.4.2}/tests/test_wiki_classifier.py +0 -0
  125. {loop_memory-0.4.1 → loop_memory-0.4.2}/tests/test_wiki_export_escape.py +0 -0
  126. {loop_memory-0.4.1 → loop_memory-0.4.2}/tests/test_wiki_prompts.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: loop-memory
3
- Version: 0.4.1
3
+ Version: 0.4.2
4
4
  Summary: A general-purpose, local memory system for every AI agent you run. Loop Memory auto-captures conversations from Codex / Claude / Hermes / OpenClaw, scores them by importance × recency × usage × feedback, distils them into a curated wiki, and serves everything from a single web UI.
5
5
  Author: Loop Memory contributors <loop-memory@users.noreply.github.com>
6
6
  License-Expression: MIT
@@ -66,6 +66,40 @@ Dynamic: license-file
66
66
 
67
67
  ---
68
68
 
69
+ > **What's new in 0.4.1** — CLI dispatch hardened so every subcommand's
70
+ > `--help` / `--version` exits 0 cleanly (no more `ValueError: unknown
71
+ > source: '--help'` on a zero-deps install). Added a static
72
+ > `COMMAND_HELP` table guarded by 10 new regression cases in
73
+ > `tests/test_cli_version.py`, plus GitHub `About` / README lead now
74
+ > surface for "agent loop" searches.
75
+ > [Full changelog →](CHANGELOG.md)
76
+
77
+ ---
78
+
79
+ ## Table of contents
80
+
81
+ - [What it does](#what-it-does)
82
+ - [Install](#install)
83
+ - [Quickstart](#quickstart)
84
+ - [Why Loop Memory vs. every other agent-memory project](#why-loop-memory-vs-every-other-agent-memory-project)
85
+ - [Architecture & docs](#architecture--docs)
86
+ - [After install: 30-second setup](#after-install-30-second-setup)
87
+ - [Auto-capture (after every conversation)](#auto-capture-after-every-conversation)
88
+ - [Dashboard + Evolution consolidator](#dashboard--evolution-consolidator-看板--进化式蒸馏)
89
+ - [Auto-feedback into every LLM client](#auto-feedback-into-every-llm-client-反哺)
90
+ - [Web UI](#web-ui)
91
+ - [Programmatic use](#programmatic-use)
92
+ - [The four-stage loop](#the-four-stage-loop)
93
+ - [Project layout](#project-layout)
94
+ - [Security & auth token](#security--auth-token)
95
+ - [Wiki scope auto-classification](#wiki-scope-auto-classification)
96
+ - [FAQ & troubleshooting](#faq--troubleshooting)
97
+ - [Run the tests](#run-the-tests)
98
+ - [Using distilled knowledge in your clients](#using-distilled-knowledge-in-your-clients)
99
+ - [License](#license)
100
+
101
+ ---
102
+
69
103
  ## What it does
70
104
 
71
105
  **Loop Memory** gives every agent you use a single, persistent brain
@@ -108,6 +142,21 @@ via MCP / hooks]
108
142
 
109
143
  *One loop, many agents, one evolving wiki.*
110
144
 
145
+ **Supported agents:**
146
+
147
+ | Agent | Capture path | Hook shipped? | Notes |
148
+ | -------------- | ----------------------------------- | :-----------: | ----- |
149
+ | Codex CLI | `~/.codex/sessions/*.json` | ✅ | MCP + SessionStart auto-wired by `install-hooks` |
150
+ | Claude Code | `~/.claude/**/*.jsonl` | ✅ | MCP + SessionStart auto-wired by `install-hooks` |
151
+ | Hermes | `~/.hermes/**/*.jsonl` | ✅ | MCP + SessionStart auto-wired by `install-hooks` |
152
+ | OpenClaw/clawx | `~/.openclaw/agents/main/sessions` + `workspace/memory/*.md` | ✅ | watcher only (no MCP yet); `openclaw-setup` enables launchd |
153
+ | Anything else | any on-disk transcript dir | — | use `loop-memory hook --source <name> --watch <dir>` (see [docs/auto-capture.md](docs/auto-capture.md)) |
154
+
155
+ The shipped hooks are the four popular agents we maintain in-tree.
156
+ The generic watcher CLI is the supported extension point for every
157
+ other agent — Aider, Cursor, Copilot, Cline, Continue, Goose, your
158
+ own home-grown CLI, anything that drops JSON/JSONL on disk.
159
+
111
160
  ---
112
161
 
113
162
  ## Install
@@ -229,6 +278,7 @@ flavors:
229
278
  | Claude Code | `loop-memory hook --source claude --watch ~/.claude` |
230
279
  | Hermes | `loop-memory hook --source hermes --watch ~/.hermes` |
231
280
  | OpenClaw (clawx) | `loop-memory hook --source openclaw --watch ~/.openclaw/agents/main/sessions` — also ingests `workspace/memory/*.md` daily logs |
281
+ | Anything else (Aider, Cursor, Copilot, Cline, Continue, Goose, …) | `loop-memory hook --source <name> --watch <path/to/transcripts>` — see [docs/auto-capture.md](docs/auto-capture.md) for loader requirements |
232
282
 
233
283
  Three of these in a `tmux` session, or persisted via launchd, keeps
234
284
  your memory store fresh without any clicks. Run `loop-memory
@@ -335,6 +385,34 @@ User signals close the loop:
335
385
  - Every `recall()` / search bumps `recall_count` on the returned
336
386
  rows so the next Stage-1 ranks them higher.
337
387
 
388
+ ### Cognitive sleep (v7)
389
+
390
+ `loop-memory cognitive-sleep [--apply]` runs an **auditable cleanup
391
+ pass** over the store:
392
+
393
+ - Surfaces contradictions between memories (e.g. "user prefers X"
394
+ vs. "user prefers Y") so you can resolve them in one click rather
395
+ than chasing them across sessions.
396
+ - Drops items that are below the configurable floor (`min_score`) and
397
+ older than the floor age.
398
+ - Merges near-duplicate memories (cosine ≥ 0.95 with `MergeableBy` rules).
399
+ - Emits a full audit row per action — visible in the Dashboard →
400
+ **Audit** tab and reachable via the MCP `audit` tool, so every
401
+ byte the consolidator ever touches is traceable.
402
+
403
+ Dry-run by default; pass `--apply` to commit.
404
+
405
+ ### Knowledge graph
406
+
407
+ `loop-memory graph-rebuild` extracts entities from every distilled
408
+ wiki page and every long-term memory, then materialises a typed
409
+ relation graph:
410
+
411
+ - Visible as the **Knowledge graph** globe tab in the web UI.
412
+ - Queryable via the MCP `subgraph` and `remember_edge` tools.
413
+ - Re-built by the Evolution Consolidator's Stage-5 evolution memo, so
414
+ the graph evolves alongside the wiki.
415
+
338
416
  ## Auto-feedback into every LLM client (反哺)
339
417
 
340
418
  Distilled knowledge is only useful if your LLM tools can actually
@@ -391,21 +469,6 @@ configuration, scheduling, language switching, and light/dark themes.
391
469
 
392
470
  ---
393
471
 
394
- ## Time-weighted scoring
395
-
396
- Every memory carries a `score ∈ [0, 1]` recomputed from:
397
-
398
- ```
399
- score = 0.35 · importance + 0.65 · recency
400
- recency = ½ ^ (age / half_life)
401
- ```
402
-
403
- `half_life` defaults to 30 days, configurable via
404
- `consolidate(half_life_days=...)`. The UI shows the score as a
405
- percentage; use `?min_score=0.85` to see only high-relevance memories.
406
-
407
- ---
408
-
409
472
  ## Programmatic use
410
473
 
411
474
  ```python
@@ -459,26 +522,35 @@ Even though v0.2 is built around local storage, the original
459
522
  ```
460
523
  loop_memory/
461
524
  loop_memory/
525
+ cli/main.py # CLI entrypoint + COMMAND_HELP table + `--version`
526
+ ingest/ # Codex / Claude / Hermes / OpenClaw / generic loaders
527
+ wiki/ # distillation, classifier, scope auto-promotion
528
+ graph/ # entity extraction + knowledge-graph build
529
+ jobs/ # consolidate / evolve / cognitive-sleep / scheduler / contradiction / graph
530
+ llm/ # provider protocol + OpenAI / Anthropic / Ollama / rule-based
531
+ backends/ # embedding (hashing / sentence-transformers) + vector store (memory / chroma)
532
+ storage/ # SQLite-backed MemoryStore + migrations
533
+ privacy/ # <private> stripping + regex redaction
534
+ security/ # Keychain / 0600-file secrets wrapper
535
+ mcp/ # stdio JSON-RPC MCP server
536
+ serve/ # FastAPI app, watcher, web UI (Timeline / Dashboard / Wiki / Graph)
537
+ export/ # markdown + v7 portable bundle export/import
538
+ sdk.py # four-verb stable API: remember / recall / forget / feedback
539
+ sdk_extensions.py # optional high-level helpers (graph edges, wiki pages)
540
+ engine/loop.py # Retrieve → Generate → Reflect → Store loop
462
541
  memory/types.py # MemoryItem + 4 tiers
463
- backends/embedding.py # BaseEmbedder, HashingEmbedder, IdentityEmbedder
464
- backends/vector_store.py # VectorStore protocol + InMemory / Chroma
465
- backends/sentence_embedder.py # optional sentence-transformers
466
- llm/base.py # LLMClient protocol + EchoLLM + helpers
467
- llm/openai_adapter.py # optional OpenAI client
468
- engine/loop.py # the Retrieve → Generate → Reflect → Store loop
469
- engine/reflect.py # reflection & summarization passes
470
- storage/sqlite_store.py # persistent SQLite-backed MemoryStore
471
- ingest/loader.py # CodexLoader, ClaudeLoader, HermesLoader
472
- ingest/pipeline.py # session → MemoryStore
473
- jobs/consolidate.py # background rescore + GC + dedupe
474
- serve/app.py # FastAPI app for the local web UI
475
- serve/static/index.html # the page
476
- serve/watcher.py # filesystem watcher for auto-capture
477
- cli/main.py # CLI entrypoint (chat / stats / ingest / consolidate / serve / hook)
478
542
  examples/demo.py # runnable, zero-API-key demo
479
543
  py.typed
480
- tests/ # 92 unit tests, zero deps
481
- docs/auto-capture.md # launchd / systemd / cron recipes
544
+ tests/ # 475 unit tests across memory / SDK / serve / CLI / scripts
545
+ docs/
546
+ auto-capture.md # launchd / systemd / cron recipes
547
+ architecture.md # layered view + 5-stage evolution pipeline
548
+ api.md # HTTP API reference
549
+ agent-memory-api.md # four-verb SDK / HTTP / MCP contract
550
+ universal-agent-memory.md # v7 graph memory + cognitive sleep + bundles
551
+ providers.md # LLM provider reference
552
+ settings.md # settings table + secrets file
553
+ weekly-research-automation.md # how the project auto-evolves from upstream research
482
554
  ```
483
555
 
484
556
  ---
@@ -560,6 +632,67 @@ classifier is local and makes no model or network request on a wiki write.
560
632
 
561
633
  ---
562
634
 
635
+ ## FAQ & troubleshooting
636
+
637
+ **Q: `pip install loop-memory` succeeds but `loop-memory serve` says `ModuleNotFoundError: No module named 'fastapi'`.**
638
+ A: `fastapi` is the optional `[serve]` extra. Install it explicitly:
639
+ `pip install 'loop-memory[serve]'` (or `'loop-memory[all]'` for everything).
640
+
641
+ **Q: My `~/.codex/sessions/` is empty / nothing appears in the UI.**
642
+ A: Run `loop-memory doctor` — it prints per-source paths, last-seen
643
+ mtime, and whether the watcher is running. Then check
644
+ `loop-memory hook --source codex --watch ~/.codex/sessions` is alive
645
+ in another shell (or via launchd — see [docs/auto-capture.md](docs/auto-capture.md)).
646
+
647
+ **Q: Distillation never finishes / wiki stays empty.**
648
+ A: You need an LLM provider configured. Open the web UI → ⚙ Model,
649
+ pick a provider, paste an API key, and click **Save**. Then either
650
+ wait for the scheduler or hit **� Run now**. Zero-deps installs ship
651
+ with a rule-based provider as a placeholder so the loop never blocks
652
+ on a missing key.
653
+
654
+ **Q: `loop-memory install-hooks` warns that the token file already exists.**
655
+ A: That's expected — it's idempotent. To force a rewrite, delete the
656
+ target files (`~/.codex/config.toml`, `~/.claude/mcp.json`,
657
+ `~/.hermes/mcp.json`) and re-run. The tool also refuses to touch
658
+ non-loop-memory config keys.
659
+
660
+ **Q: How big can the SQLite store get before I should worry?**
661
+ A: Practical floor: 100k memories / 10k wiki pages stays under ~80 MB
662
+ and `recall()` returns in <100 ms. The Evolution Consolidator is
663
+ designed to keep the wiki tight (~hundreds of pages) rather than let
664
+ it grow unbounded. Run `loop-memory cognitive-sleep --apply` weekly
665
+ to drop the long tail.
666
+
667
+ **Q: Can I sync the store across machines?**
668
+ A: The SQLite file is git-friendly and copy-friendly. The `MEMORY.md`
669
+ + graph + memories + metadata **bundle** (`loop-memory export
670
+ <dir>`) is a portable v7 artefact you can commit, share, or
671
+ back-up. There is no first-class sync daemon — by design — so the
672
+ local-first guarantee is never violated.
673
+
674
+ **Q: Is there a hosted / cloud version?**
675
+ A: No. Loop Memory is MIT-licensed and 100% local; the SQLite file
676
+ lives under `~/.loop_memory/`. The web UI is bound to loopback by
677
+ default; binding to `0.0.0.0` prints a security warning and requires
678
+ an auth token.
679
+
680
+ **Q: Where do secrets / API keys live?**
681
+ A: Two places. Provider keys you set in the **⚙ Model** UI are
682
+ written to `~/.loop_memory/secrets.json` (mode 0600) via the
683
+ `loop_memory.security.secrets` wrapper, which prefers the macOS
684
+ Keychain on Darwin and falls back to the encrypted file on Linux.
685
+ The auth token used by the web UI is hashed in the SQLite settings
686
+ table — never stored in plaintext.
687
+
688
+ **Q: I see "no version" / "package not found" on the PyPI badge.**
689
+ A: shields.io pulls from a separate data source that lags PyPI by a
690
+ few minutes after a new release. Re-publish the badge warmer step
691
+ in `.github/workflows/publish.yml` to force a refresh, or wait ~30
692
+ minutes for shields.io to catch up.
693
+
694
+ ---
695
+
563
696
  ## Run the tests
564
697
 
565
698
  ```bash
@@ -22,6 +22,40 @@
22
22
 
23
23
  ---
24
24
 
25
+ > **What's new in 0.4.1** — CLI dispatch hardened so every subcommand's
26
+ > `--help` / `--version` exits 0 cleanly (no more `ValueError: unknown
27
+ > source: '--help'` on a zero-deps install). Added a static
28
+ > `COMMAND_HELP` table guarded by 10 new regression cases in
29
+ > `tests/test_cli_version.py`, plus GitHub `About` / README lead now
30
+ > surface for "agent loop" searches.
31
+ > [Full changelog →](CHANGELOG.md)
32
+
33
+ ---
34
+
35
+ ## Table of contents
36
+
37
+ - [What it does](#what-it-does)
38
+ - [Install](#install)
39
+ - [Quickstart](#quickstart)
40
+ - [Why Loop Memory vs. every other agent-memory project](#why-loop-memory-vs-every-other-agent-memory-project)
41
+ - [Architecture & docs](#architecture--docs)
42
+ - [After install: 30-second setup](#after-install-30-second-setup)
43
+ - [Auto-capture (after every conversation)](#auto-capture-after-every-conversation)
44
+ - [Dashboard + Evolution consolidator](#dashboard--evolution-consolidator-看板--进化式蒸馏)
45
+ - [Auto-feedback into every LLM client](#auto-feedback-into-every-llm-client-反哺)
46
+ - [Web UI](#web-ui)
47
+ - [Programmatic use](#programmatic-use)
48
+ - [The four-stage loop](#the-four-stage-loop)
49
+ - [Project layout](#project-layout)
50
+ - [Security & auth token](#security--auth-token)
51
+ - [Wiki scope auto-classification](#wiki-scope-auto-classification)
52
+ - [FAQ & troubleshooting](#faq--troubleshooting)
53
+ - [Run the tests](#run-the-tests)
54
+ - [Using distilled knowledge in your clients](#using-distilled-knowledge-in-your-clients)
55
+ - [License](#license)
56
+
57
+ ---
58
+
25
59
  ## What it does
26
60
 
27
61
  **Loop Memory** gives every agent you use a single, persistent brain
@@ -64,6 +98,21 @@ via MCP / hooks]
64
98
 
65
99
  *One loop, many agents, one evolving wiki.*
66
100
 
101
+ **Supported agents:**
102
+
103
+ | Agent | Capture path | Hook shipped? | Notes |
104
+ | -------------- | ----------------------------------- | :-----------: | ----- |
105
+ | Codex CLI | `~/.codex/sessions/*.json` | ✅ | MCP + SessionStart auto-wired by `install-hooks` |
106
+ | Claude Code | `~/.claude/**/*.jsonl` | ✅ | MCP + SessionStart auto-wired by `install-hooks` |
107
+ | Hermes | `~/.hermes/**/*.jsonl` | ✅ | MCP + SessionStart auto-wired by `install-hooks` |
108
+ | OpenClaw/clawx | `~/.openclaw/agents/main/sessions` + `workspace/memory/*.md` | ✅ | watcher only (no MCP yet); `openclaw-setup` enables launchd |
109
+ | Anything else | any on-disk transcript dir | — | use `loop-memory hook --source <name> --watch <dir>` (see [docs/auto-capture.md](docs/auto-capture.md)) |
110
+
111
+ The shipped hooks are the four popular agents we maintain in-tree.
112
+ The generic watcher CLI is the supported extension point for every
113
+ other agent — Aider, Cursor, Copilot, Cline, Continue, Goose, your
114
+ own home-grown CLI, anything that drops JSON/JSONL on disk.
115
+
67
116
  ---
68
117
 
69
118
  ## Install
@@ -185,6 +234,7 @@ flavors:
185
234
  | Claude Code | `loop-memory hook --source claude --watch ~/.claude` |
186
235
  | Hermes | `loop-memory hook --source hermes --watch ~/.hermes` |
187
236
  | OpenClaw (clawx) | `loop-memory hook --source openclaw --watch ~/.openclaw/agents/main/sessions` — also ingests `workspace/memory/*.md` daily logs |
237
+ | Anything else (Aider, Cursor, Copilot, Cline, Continue, Goose, …) | `loop-memory hook --source <name> --watch <path/to/transcripts>` — see [docs/auto-capture.md](docs/auto-capture.md) for loader requirements |
188
238
 
189
239
  Three of these in a `tmux` session, or persisted via launchd, keeps
190
240
  your memory store fresh without any clicks. Run `loop-memory
@@ -291,6 +341,34 @@ User signals close the loop:
291
341
  - Every `recall()` / search bumps `recall_count` on the returned
292
342
  rows so the next Stage-1 ranks them higher.
293
343
 
344
+ ### Cognitive sleep (v7)
345
+
346
+ `loop-memory cognitive-sleep [--apply]` runs an **auditable cleanup
347
+ pass** over the store:
348
+
349
+ - Surfaces contradictions between memories (e.g. "user prefers X"
350
+ vs. "user prefers Y") so you can resolve them in one click rather
351
+ than chasing them across sessions.
352
+ - Drops items that are below the configurable floor (`min_score`) and
353
+ older than the floor age.
354
+ - Merges near-duplicate memories (cosine ≥ 0.95 with `MergeableBy` rules).
355
+ - Emits a full audit row per action — visible in the Dashboard →
356
+ **Audit** tab and reachable via the MCP `audit` tool, so every
357
+ byte the consolidator ever touches is traceable.
358
+
359
+ Dry-run by default; pass `--apply` to commit.
360
+
361
+ ### Knowledge graph
362
+
363
+ `loop-memory graph-rebuild` extracts entities from every distilled
364
+ wiki page and every long-term memory, then materialises a typed
365
+ relation graph:
366
+
367
+ - Visible as the **Knowledge graph** globe tab in the web UI.
368
+ - Queryable via the MCP `subgraph` and `remember_edge` tools.
369
+ - Re-built by the Evolution Consolidator's Stage-5 evolution memo, so
370
+ the graph evolves alongside the wiki.
371
+
294
372
  ## Auto-feedback into every LLM client (反哺)
295
373
 
296
374
  Distilled knowledge is only useful if your LLM tools can actually
@@ -347,21 +425,6 @@ configuration, scheduling, language switching, and light/dark themes.
347
425
 
348
426
  ---
349
427
 
350
- ## Time-weighted scoring
351
-
352
- Every memory carries a `score ∈ [0, 1]` recomputed from:
353
-
354
- ```
355
- score = 0.35 · importance + 0.65 · recency
356
- recency = ½ ^ (age / half_life)
357
- ```
358
-
359
- `half_life` defaults to 30 days, configurable via
360
- `consolidate(half_life_days=...)`. The UI shows the score as a
361
- percentage; use `?min_score=0.85` to see only high-relevance memories.
362
-
363
- ---
364
-
365
428
  ## Programmatic use
366
429
 
367
430
  ```python
@@ -415,26 +478,35 @@ Even though v0.2 is built around local storage, the original
415
478
  ```
416
479
  loop_memory/
417
480
  loop_memory/
481
+ cli/main.py # CLI entrypoint + COMMAND_HELP table + `--version`
482
+ ingest/ # Codex / Claude / Hermes / OpenClaw / generic loaders
483
+ wiki/ # distillation, classifier, scope auto-promotion
484
+ graph/ # entity extraction + knowledge-graph build
485
+ jobs/ # consolidate / evolve / cognitive-sleep / scheduler / contradiction / graph
486
+ llm/ # provider protocol + OpenAI / Anthropic / Ollama / rule-based
487
+ backends/ # embedding (hashing / sentence-transformers) + vector store (memory / chroma)
488
+ storage/ # SQLite-backed MemoryStore + migrations
489
+ privacy/ # <private> stripping + regex redaction
490
+ security/ # Keychain / 0600-file secrets wrapper
491
+ mcp/ # stdio JSON-RPC MCP server
492
+ serve/ # FastAPI app, watcher, web UI (Timeline / Dashboard / Wiki / Graph)
493
+ export/ # markdown + v7 portable bundle export/import
494
+ sdk.py # four-verb stable API: remember / recall / forget / feedback
495
+ sdk_extensions.py # optional high-level helpers (graph edges, wiki pages)
496
+ engine/loop.py # Retrieve → Generate → Reflect → Store loop
418
497
  memory/types.py # MemoryItem + 4 tiers
419
- backends/embedding.py # BaseEmbedder, HashingEmbedder, IdentityEmbedder
420
- backends/vector_store.py # VectorStore protocol + InMemory / Chroma
421
- backends/sentence_embedder.py # optional sentence-transformers
422
- llm/base.py # LLMClient protocol + EchoLLM + helpers
423
- llm/openai_adapter.py # optional OpenAI client
424
- engine/loop.py # the Retrieve → Generate → Reflect → Store loop
425
- engine/reflect.py # reflection & summarization passes
426
- storage/sqlite_store.py # persistent SQLite-backed MemoryStore
427
- ingest/loader.py # CodexLoader, ClaudeLoader, HermesLoader
428
- ingest/pipeline.py # session → MemoryStore
429
- jobs/consolidate.py # background rescore + GC + dedupe
430
- serve/app.py # FastAPI app for the local web UI
431
- serve/static/index.html # the page
432
- serve/watcher.py # filesystem watcher for auto-capture
433
- cli/main.py # CLI entrypoint (chat / stats / ingest / consolidate / serve / hook)
434
498
  examples/demo.py # runnable, zero-API-key demo
435
499
  py.typed
436
- tests/ # 92 unit tests, zero deps
437
- docs/auto-capture.md # launchd / systemd / cron recipes
500
+ tests/ # 475 unit tests across memory / SDK / serve / CLI / scripts
501
+ docs/
502
+ auto-capture.md # launchd / systemd / cron recipes
503
+ architecture.md # layered view + 5-stage evolution pipeline
504
+ api.md # HTTP API reference
505
+ agent-memory-api.md # four-verb SDK / HTTP / MCP contract
506
+ universal-agent-memory.md # v7 graph memory + cognitive sleep + bundles
507
+ providers.md # LLM provider reference
508
+ settings.md # settings table + secrets file
509
+ weekly-research-automation.md # how the project auto-evolves from upstream research
438
510
  ```
439
511
 
440
512
  ---
@@ -516,6 +588,67 @@ classifier is local and makes no model or network request on a wiki write.
516
588
 
517
589
  ---
518
590
 
591
+ ## FAQ & troubleshooting
592
+
593
+ **Q: `pip install loop-memory` succeeds but `loop-memory serve` says `ModuleNotFoundError: No module named 'fastapi'`.**
594
+ A: `fastapi` is the optional `[serve]` extra. Install it explicitly:
595
+ `pip install 'loop-memory[serve]'` (or `'loop-memory[all]'` for everything).
596
+
597
+ **Q: My `~/.codex/sessions/` is empty / nothing appears in the UI.**
598
+ A: Run `loop-memory doctor` — it prints per-source paths, last-seen
599
+ mtime, and whether the watcher is running. Then check
600
+ `loop-memory hook --source codex --watch ~/.codex/sessions` is alive
601
+ in another shell (or via launchd — see [docs/auto-capture.md](docs/auto-capture.md)).
602
+
603
+ **Q: Distillation never finishes / wiki stays empty.**
604
+ A: You need an LLM provider configured. Open the web UI → ⚙ Model,
605
+ pick a provider, paste an API key, and click **Save**. Then either
606
+ wait for the scheduler or hit **� Run now**. Zero-deps installs ship
607
+ with a rule-based provider as a placeholder so the loop never blocks
608
+ on a missing key.
609
+
610
+ **Q: `loop-memory install-hooks` warns that the token file already exists.**
611
+ A: That's expected — it's idempotent. To force a rewrite, delete the
612
+ target files (`~/.codex/config.toml`, `~/.claude/mcp.json`,
613
+ `~/.hermes/mcp.json`) and re-run. The tool also refuses to touch
614
+ non-loop-memory config keys.
615
+
616
+ **Q: How big can the SQLite store get before I should worry?**
617
+ A: Practical floor: 100k memories / 10k wiki pages stays under ~80 MB
618
+ and `recall()` returns in <100 ms. The Evolution Consolidator is
619
+ designed to keep the wiki tight (~hundreds of pages) rather than let
620
+ it grow unbounded. Run `loop-memory cognitive-sleep --apply` weekly
621
+ to drop the long tail.
622
+
623
+ **Q: Can I sync the store across machines?**
624
+ A: The SQLite file is git-friendly and copy-friendly. The `MEMORY.md`
625
+ + graph + memories + metadata **bundle** (`loop-memory export
626
+ <dir>`) is a portable v7 artefact you can commit, share, or
627
+ back-up. There is no first-class sync daemon — by design — so the
628
+ local-first guarantee is never violated.
629
+
630
+ **Q: Is there a hosted / cloud version?**
631
+ A: No. Loop Memory is MIT-licensed and 100% local; the SQLite file
632
+ lives under `~/.loop_memory/`. The web UI is bound to loopback by
633
+ default; binding to `0.0.0.0` prints a security warning and requires
634
+ an auth token.
635
+
636
+ **Q: Where do secrets / API keys live?**
637
+ A: Two places. Provider keys you set in the **⚙ Model** UI are
638
+ written to `~/.loop_memory/secrets.json` (mode 0600) via the
639
+ `loop_memory.security.secrets` wrapper, which prefers the macOS
640
+ Keychain on Darwin and falls back to the encrypted file on Linux.
641
+ The auth token used by the web UI is hashed in the SQLite settings
642
+ table — never stored in plaintext.
643
+
644
+ **Q: I see "no version" / "package not found" on the PyPI badge.**
645
+ A: shields.io pulls from a separate data source that lags PyPI by a
646
+ few minutes after a new release. Re-publish the badge warmer step
647
+ in `.github/workflows/publish.yml` to force a refresh, or wait ~30
648
+ minutes for shields.io to catch up.
649
+
650
+ ---
651
+
519
652
  ## Run the tests
520
653
 
521
654
  ```bash