threadkeeper 0.4.0__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 (91) hide show
  1. threadkeeper-0.4.0/LICENSE +21 -0
  2. threadkeeper-0.4.0/PKG-INFO +351 -0
  3. threadkeeper-0.4.0/README.md +317 -0
  4. threadkeeper-0.4.0/pyproject.toml +70 -0
  5. threadkeeper-0.4.0/setup.cfg +4 -0
  6. threadkeeper-0.4.0/tests/test_adapters.py +556 -0
  7. threadkeeper-0.4.0/tests/test_brief_sections.py +208 -0
  8. threadkeeper-0.4.0/tests/test_core_memory.py +40 -0
  9. threadkeeper-0.4.0/tests/test_curator.py +323 -0
  10. threadkeeper-0.4.0/tests/test_delegated_search.py +267 -0
  11. threadkeeper-0.4.0/tests/test_dialectic.py +429 -0
  12. threadkeeper-0.4.0/tests/test_error_paths.py +54 -0
  13. threadkeeper-0.4.0/tests/test_extract_daemon.py +373 -0
  14. threadkeeper-0.4.0/tests/test_i18n_multilang.py +158 -0
  15. threadkeeper-0.4.0/tests/test_identity.py +78 -0
  16. threadkeeper-0.4.0/tests/test_lessons.py +136 -0
  17. threadkeeper-0.4.0/tests/test_missed_spawns.py +159 -0
  18. threadkeeper-0.4.0/tests/test_nudges.py +440 -0
  19. threadkeeper-0.4.0/tests/test_process_health.py +258 -0
  20. threadkeeper-0.4.0/tests/test_shadow_review.py +327 -0
  21. threadkeeper-0.4.0/tests/test_skill_hint.py +185 -0
  22. threadkeeper-0.4.0/tests/test_skill_use_parser.py +374 -0
  23. threadkeeper-0.4.0/tests/test_skill_watcher.py +202 -0
  24. threadkeeper-0.4.0/tests/test_skills.py +612 -0
  25. threadkeeper-0.4.0/tests/test_spawn_budget.py +179 -0
  26. threadkeeper-0.4.0/tests/test_spawn_hint.py +215 -0
  27. threadkeeper-0.4.0/tests/test_spawn_slim.py +127 -0
  28. threadkeeper-0.4.0/tests/test_threads.py +71 -0
  29. threadkeeper-0.4.0/tests/test_tools_smoke.py +95 -0
  30. threadkeeper-0.4.0/tests/test_vec_search.py +209 -0
  31. threadkeeper-0.4.0/threadkeeper/__init__.py +8 -0
  32. threadkeeper-0.4.0/threadkeeper/_mcp.py +6 -0
  33. threadkeeper-0.4.0/threadkeeper/_setup.py +299 -0
  34. threadkeeper-0.4.0/threadkeeper/adapters/__init__.py +40 -0
  35. threadkeeper-0.4.0/threadkeeper/adapters/_hook_helpers.py +72 -0
  36. threadkeeper-0.4.0/threadkeeper/adapters/base.py +152 -0
  37. threadkeeper-0.4.0/threadkeeper/adapters/claude_code.py +178 -0
  38. threadkeeper-0.4.0/threadkeeper/adapters/claude_desktop.py +128 -0
  39. threadkeeper-0.4.0/threadkeeper/adapters/codex.py +259 -0
  40. threadkeeper-0.4.0/threadkeeper/adapters/copilot.py +195 -0
  41. threadkeeper-0.4.0/threadkeeper/adapters/gemini.py +169 -0
  42. threadkeeper-0.4.0/threadkeeper/adapters/vscode.py +144 -0
  43. threadkeeper-0.4.0/threadkeeper/brief.py +735 -0
  44. threadkeeper-0.4.0/threadkeeper/config.py +216 -0
  45. threadkeeper-0.4.0/threadkeeper/curator.py +390 -0
  46. threadkeeper-0.4.0/threadkeeper/db.py +474 -0
  47. threadkeeper-0.4.0/threadkeeper/embeddings.py +232 -0
  48. threadkeeper-0.4.0/threadkeeper/extract_daemon.py +125 -0
  49. threadkeeper-0.4.0/threadkeeper/helpers.py +101 -0
  50. threadkeeper-0.4.0/threadkeeper/i18n.py +342 -0
  51. threadkeeper-0.4.0/threadkeeper/identity.py +237 -0
  52. threadkeeper-0.4.0/threadkeeper/ingest.py +507 -0
  53. threadkeeper-0.4.0/threadkeeper/lessons.py +170 -0
  54. threadkeeper-0.4.0/threadkeeper/nudges.py +257 -0
  55. threadkeeper-0.4.0/threadkeeper/process_health.py +202 -0
  56. threadkeeper-0.4.0/threadkeeper/review_prompts.py +207 -0
  57. threadkeeper-0.4.0/threadkeeper/search_proxy.py +160 -0
  58. threadkeeper-0.4.0/threadkeeper/server.py +55 -0
  59. threadkeeper-0.4.0/threadkeeper/shadow_review.py +358 -0
  60. threadkeeper-0.4.0/threadkeeper/skill_watcher.py +96 -0
  61. threadkeeper-0.4.0/threadkeeper/spawn_budget.py +246 -0
  62. threadkeeper-0.4.0/threadkeeper/tools/__init__.py +2 -0
  63. threadkeeper-0.4.0/threadkeeper/tools/concepts.py +111 -0
  64. threadkeeper-0.4.0/threadkeeper/tools/consolidate.py +222 -0
  65. threadkeeper-0.4.0/threadkeeper/tools/core_memory.py +109 -0
  66. threadkeeper-0.4.0/threadkeeper/tools/correlation.py +116 -0
  67. threadkeeper-0.4.0/threadkeeper/tools/curator.py +121 -0
  68. threadkeeper-0.4.0/threadkeeper/tools/dialectic.py +359 -0
  69. threadkeeper-0.4.0/threadkeeper/tools/dialog.py +131 -0
  70. threadkeeper-0.4.0/threadkeeper/tools/distill.py +184 -0
  71. threadkeeper-0.4.0/threadkeeper/tools/extract.py +411 -0
  72. threadkeeper-0.4.0/threadkeeper/tools/graph.py +183 -0
  73. threadkeeper-0.4.0/threadkeeper/tools/invariants.py +177 -0
  74. threadkeeper-0.4.0/threadkeeper/tools/lessons.py +110 -0
  75. threadkeeper-0.4.0/threadkeeper/tools/missed_spawns.py +142 -0
  76. threadkeeper-0.4.0/threadkeeper/tools/peers.py +579 -0
  77. threadkeeper-0.4.0/threadkeeper/tools/pickup.py +148 -0
  78. threadkeeper-0.4.0/threadkeeper/tools/probes.py +251 -0
  79. threadkeeper-0.4.0/threadkeeper/tools/process_health.py +90 -0
  80. threadkeeper-0.4.0/threadkeeper/tools/session.py +34 -0
  81. threadkeeper-0.4.0/threadkeeper/tools/shadow_review.py +106 -0
  82. threadkeeper-0.4.0/threadkeeper/tools/skills.py +856 -0
  83. threadkeeper-0.4.0/threadkeeper/tools/spawn.py +871 -0
  84. threadkeeper-0.4.0/threadkeeper/tools/style.py +44 -0
  85. threadkeeper-0.4.0/threadkeeper/tools/threads.py +299 -0
  86. threadkeeper-0.4.0/threadkeeper.egg-info/PKG-INFO +351 -0
  87. threadkeeper-0.4.0/threadkeeper.egg-info/SOURCES.txt +89 -0
  88. threadkeeper-0.4.0/threadkeeper.egg-info/dependency_links.txt +1 -0
  89. threadkeeper-0.4.0/threadkeeper.egg-info/entry_points.txt +2 -0
  90. threadkeeper-0.4.0/threadkeeper.egg-info/requires.txt +10 -0
  91. threadkeeper-0.4.0/threadkeeper.egg-info/top_level.txt +1 -0
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 thread-keeper contributors
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,351 @@
1
+ Metadata-Version: 2.4
2
+ Name: threadkeeper
3
+ Version: 0.4.0
4
+ Summary: Persistent working memory across agentic CLI sessions — CLI-agnostic MCP server for Claude Code/Desktop, Codex, Gemini, Copilot, VS Code.
5
+ Author: thread-keeper contributors
6
+ License: MIT
7
+ Project-URL: Homepage, https://github.com/po4erk91/thread-keeper
8
+ Project-URL: Repository, https://github.com/po4erk91/thread-keeper
9
+ Project-URL: Issues, https://github.com/po4erk91/thread-keeper/issues
10
+ Project-URL: Documentation, https://github.com/po4erk91/thread-keeper#readme
11
+ Project-URL: Changelog, https://github.com/po4erk91/thread-keeper/releases
12
+ Keywords: mcp,model-context-protocol,claude,codex,gemini,copilot,memory,agents,self-improving,skills
13
+ Classifier: Development Status :: 4 - Beta
14
+ Classifier: License :: OSI Approved :: MIT License
15
+ Classifier: Operating System :: MacOS
16
+ Classifier: Operating System :: POSIX :: Linux
17
+ Classifier: Programming Language :: Python :: 3.11
18
+ Classifier: Programming Language :: Python :: 3.12
19
+ Classifier: Programming Language :: Python :: 3.13
20
+ Classifier: Topic :: Software Development :: Libraries :: Python Modules
21
+ Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
22
+ Requires-Python: >=3.11
23
+ Description-Content-Type: text/markdown
24
+ License-File: LICENSE
25
+ Requires-Dist: mcp>=1.0.0
26
+ Provides-Extra: semantic
27
+ Requires-Dist: sentence-transformers>=2.2.0; extra == "semantic"
28
+ Requires-Dist: numpy>=1.24.0; extra == "semantic"
29
+ Requires-Dist: sqlite-vec>=0.1.9; extra == "semantic"
30
+ Provides-Extra: dev
31
+ Requires-Dist: pytest>=8.0; extra == "dev"
32
+ Requires-Dist: pytest-cov>=5.0; extra == "dev"
33
+ Dynamic: license-file
34
+
35
+ # thread-keeper
36
+
37
+ [![tests](https://github.com/po4erk91/thread-keeper/actions/workflows/test.yml/badge.svg)](https://github.com/po4erk91/thread-keeper/actions/workflows/test.yml)
38
+ [![Python](https://img.shields.io/badge/python-3.11%2B-blue)](https://www.python.org/downloads/)
39
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](LICENSE)
40
+ [![CLIs](https://img.shields.io/badge/CLIs-Claude%20%7C%20Codex%20%7C%20Gemini%20%7C%20Copilot%20%7C%20VS%20Code-green)](#multi-cli-integration)
41
+
42
+ A local MCP server that holds **persistent working memory across agentic CLI
43
+ sessions** — Claude Code, Claude Desktop, OpenAI Codex (CLI + desktop),
44
+ Google Gemini, GitHub Copilot, and every MCP-aware VS Code extension share
45
+ one SQLite store, one set of threads, one learning loop, one user model.
46
+
47
+ The brief format is dense — structural tags, opaque IDs, ~6 KB per
48
+ session-start injection. Optimized for agent consumption, not human reading.
49
+
50
+ ---
51
+
52
+ ## Why
53
+
54
+ Today every agent CLI starts cold. Context dies at session boundaries.
55
+ Skills you taught Claude don't transfer to Codex. Threads you closed in
56
+ yesterday's Gemini chat are invisible to today's Copilot.
57
+
58
+ thread-keeper is the substrate underneath:
59
+
60
+ - **One memory store** — threads, notes, verbatim quotes, dialectic claims
61
+ about you. Survives session, restart, CLI swap.
62
+ - **One learning loop (hermes-style)** — closed threads with rich content
63
+ spawn a background reviewer that appends lessons to
64
+ `~/.threadkeeper/lessons.md`. Every CLI's per-user instructions file
65
+ references this path, so the same procedural knowledge surfaces in
66
+ Claude Code, Codex, Gemini, and Copilot. Claude-specific
67
+ `~/.claude/skills/*/SKILL.md` is an optional secondary output when
68
+ frontmatter auto-triggering adds value.
69
+ - **Cross-session signaling** — broadcast / whisper / inbox / wait between
70
+ concurrent sessions across different CLIs.
71
+
72
+ ---
73
+
74
+ ## Quickstart
75
+
76
+ The shortest path — **PyPI + pipx** (recommended):
77
+
78
+ ```bash
79
+ pipx install 'threadkeeper[semantic]' && thread-keeper-setup
80
+ ```
81
+
82
+ `thread-keeper-setup` detects every CLI you have installed (Claude
83
+ Code / Claude Desktop / Codex CLI + desktop / Gemini / Copilot / VS
84
+ Code), registers the MCP server in each one's config, copies hooks to
85
+ `~/.threadkeeper/hooks/`, and writes a managed instructions block into
86
+ each CLI's per-user instructions file (`CLAUDE.md` / `AGENTS.md` /
87
+ `GEMINI.md` / `copilot-instructions.md` — Claude Desktop and VS Code
88
+ have no global instructions file, so that step is skipped for them).
89
+
90
+ Restart your CLI of choice. The SessionStart hook injects a brief on
91
+ first message; no manual `brief()` call required.
92
+
93
+ ### Alternative installs
94
+
95
+ If you don't have `pipx` and don't want to install it:
96
+
97
+ ```bash
98
+ # uv (Rust-fast Python tool runner) — no clone, single binary on PATH
99
+ uv tool install 'threadkeeper[semantic]' && thread-keeper-setup
100
+
101
+ # Plain pip into a venv
102
+ python3 -m venv ~/.threadkeeper-venv
103
+ ~/.threadkeeper-venv/bin/pip install 'threadkeeper[semantic]'
104
+ ~/.threadkeeper-venv/bin/thread-keeper-setup
105
+ ```
106
+
107
+ For development (editable install from a git checkout) or to track the
108
+ bleeding edge:
109
+
110
+ ```bash
111
+ # One-liner installer — clones to ~/thread-keeper, makes a venv,
112
+ # editable-installs, wires every detected CLI. Idempotent — re-run to
113
+ # update (it git-pulls + reinstalls).
114
+ curl -fsSL https://raw.githubusercontent.com/po4erk91/thread-keeper/main/install.sh | bash -s -- --semantic
115
+
116
+ # Or fully manual
117
+ git clone https://github.com/po4erk91/thread-keeper ~/thread-keeper
118
+ cd ~/thread-keeper && python3 -m venv .venv
119
+ .venv/bin/pip install -e '.[semantic]'
120
+ .venv/bin/thread-keeper-setup
121
+ ```
122
+
123
+ To preview without writing anything:
124
+
125
+ ```bash
126
+ thread-keeper-setup --dry-run
127
+ ```
128
+
129
+ ---
130
+
131
+ ## Multi-CLI integration
132
+
133
+ | CLI | MCP config | Instructions file | Hooks | Transcripts ingested |
134
+ |---|---|---|---|---|
135
+ | Claude Code | `~/.claude.json` `mcpServers` | `~/.claude/CLAUDE.md` | `~/.claude/settings.json` `hooks` | `~/.claude/projects/**/*.jsonl` |
136
+ | Claude Desktop | `~/Library/Application Support/Claude/claude_desktop_config.json` `mcpServers` (macOS); `%APPDATA%\Claude\…` (Win); `~/.config/Claude/…` (Linux) | none (GUI-only) | not supported by the app | none — chats live in Electron IndexedDB |
137
+ | Codex (CLI + desktop) | `~/.codex/config.toml` `[mcp_servers]` (shared between CLI and `Codex.app`) | `~/.codex/AGENTS.md` | not supported | `~/.codex/sessions/**/rollout-*.jsonl` |
138
+ | Gemini | `~/.gemini/settings.json` `mcpServers` | `~/.gemini/GEMINI.md` | `~/.gemini/settings.json` `hooks` | `~/.gemini/tmp/<user>/chats/session-*.jsonl` |
139
+ | Copilot | `~/.copilot/mcp-config.json` `mcpServers` | `~/.copilot/copilot-instructions.md` | `~/.copilot/hooks.json` | `~/.copilot/session-store.db` (sqlite) |
140
+ | VS Code | `~/Library/Application Support/Code/User/mcp.json` `servers` (macOS); `%APPDATA%\Code\User\mcp.json` (Win); `~/.config/Code/User/mcp.json` (Linux) | none (per-workspace only) | not supported | none — extensions own their history |
141
+
142
+ Every CLI that produces parseable transcripts feeds the same
143
+ `dialog_messages` table with a `source` tag, so `dialog_search()` finds
144
+ matches regardless of where the conversation happened. Claude Desktop
145
+ and the VS Code adapter are the exceptions — MCP registration only;
146
+ their chats don't reach the table for now (Electron IndexedDB on the
147
+ Claude Desktop side; per-extension stores on the VS Code side).
148
+
149
+ VS Code's user-level `mcp.json` is the central host that **every
150
+ MCP-aware VS Code extension** consumes — GitHub Copilot Chat, the
151
+ Anthropic Claude IDE plugin, the OpenAI Codex IDE plugin, Continue,
152
+ Cline, … — so a single registration there reaches all of them at once.
153
+
154
+ Adding a new CLI = one file under `threadkeeper/adapters/` implementing
155
+ the `CLIAdapter` contract. See [CONTRIBUTING.md](CONTRIBUTING.md).
156
+
157
+ ---
158
+
159
+ ## Core systems
160
+
161
+ ### Spawn — primary parallelism primitive
162
+
163
+ `spawn(prompt, slim=True, role=..., visible=False, ...)` launches a child
164
+ Claude session via a `claude -p` subprocess. By default `slim=True`: the
165
+ child loads only the thread-keeper MCP, no embeddings, no third-party
166
+ servers. ~500 MB RSS versus ~1.3 GB for a full child. Heuristic for the
167
+ parent: N≥2 modular independent units of ≥5 min each = spawn signal.
168
+
169
+ A daemon measures combined child RSS every 10 s; admission control
170
+ refuses a new spawn that would exceed `THREADKEEPER_SPAWN_BUDGET_MB`
171
+ (3 GB default). Slim children that need semantic search delegate to the
172
+ parent via `search_via_parent` — no per-child copy of sentence-transformers.
173
+
174
+ ### Learning loop (hermes-style)
175
+
176
+ Four loops materialize knowledge into Anthropic-style Skill files
177
+ (`SKILL.md` under each detected CLI's skills directory — Claude's
178
+ `~/.claude/skills/`, Codex's `~/.codex/skills/`, plus the canonical
179
+ `~/.threadkeeper/skills/` mirror) with a CLI-agnostic
180
+ `~/.threadkeeper/lessons.md` fallback for CLIs that don't auto-trigger
181
+ on the Skill format (Gemini / Copilot / bare MCP clients):
182
+
183
+ - **Auto-review on close_thread** — when a closed thread is rich
184
+ (≥5 notes, ≥2 insight/move), `close_thread` spawns a slim child with
185
+ `SKILL_REVIEW_PROMPT` + the thread's notes. The prompt is rubric-form
186
+ (Q1–Q5 yes/no) with explicit positive examples for incident-vs-rule
187
+ classification. The fork also receives a "recently active skills"
188
+ block so it prefers PATCHing existing umbrellas over creating new
189
+ ones (Hermes Agent v0.12's *active-update bias*). Child appends a
190
+ lesson via `lesson_append`, optionally mirrors to
191
+ `~/.claude/skills/<name>/SKILL.md`, then closes with
192
+ `mark_skill_materialized`. Opt in with `THREADKEEPER_AUTO_REVIEW=1`.
193
+ - **Shadow-review daemon** — every `THREADKEEPER_SHADOW_REVIEW_INTERVAL_S`
194
+ seconds (default off; 15 min recommended), scans the diff of
195
+ `dialog_messages` since the last cursor across **all** CLIs. The
196
+ window filters internal review-child sessions (no self-pollution)
197
+ and strips adapter `[tool_result]` / `[tool_call]` noise — Hermes
198
+ v0.12's "clean context" rule. If ≥500 chars of meaningful signal
199
+ remain, spawns a slim observer child that decides on class-level
200
+ learning. Idempotent through `events.kind='shadow_review_pass'`.
201
+ - **Extract daemon** — every `THREADKEEPER_EXTRACT_INTERVAL_S` seconds
202
+ (default off; 10 min recommended), scans recent `dialog_messages`
203
+ with heuristic matchers (locale-aware "I want / next time / always"
204
+ patterns, headers + insight markers, bullet regularities, paraphrase
205
+ clusters via cosine ≥ 0.80) and enqueues candidates in
206
+ `extract_candidates.status='pending'` for the agent to review via
207
+ `review_candidates()` / `accept_candidate()`. The same self-pollution
208
+ filter as shadow_review excludes internal review-child sessions.
209
+ Where shadow extracts CLASS-LEVEL durable rules, extract harvests
210
+ PER-INCIDENT decision-shaped utterances — sidesteps the empirical
211
+ problem that agents focused on their primary task don't call
212
+ `note()` / `verbatim_user()` on their own.
213
+ - **Autonomous Curator** — every `THREADKEEPER_CURATOR_INTERVAL_S`
214
+ seconds (default off; 7 days recommended), spawns a slim child that
215
+ reviews the EXISTING `lessons.md` + `skill_usage` inventory and
216
+ writes `~/.threadkeeper/curator/REPORT-<isodate>.md` with KEEP /
217
+ PATCH / CONSOLIDATE / PRUNE recommendations. Pinned and
218
+ foreground-authored entries are marked `[PROTECTED]` in the
219
+ inventory so the curator never proposes destructive changes against
220
+ them. Phase 1 is advisory-only — user reviews the REPORT and
221
+ applies changes manually. Inspired by Hermes Agent v0.12's
222
+ `hermes curator` cron agent.
223
+
224
+ ### Dialectic user model
225
+
226
+ A model of you, accumulated as you use the agent. `dialectic_claim`,
227
+ `dialectic_evidence` (support / contradict / clarifying),
228
+ `dialectic_synthesis`, `dialectic_supersede`. Honcho-inspired smoothed
229
+ ratio `(s-c)/(s+c+3)` → low / medium / high / disputed confidence.
230
+ Grouped by domain (style, values, workflow, ...) in `brief()`.
231
+
232
+ ### i18n bundle
233
+
234
+ All multilingual regex and prompt fragments live in
235
+ `threadkeeper/i18n.py` — the rest of the codebase stays English-only.
236
+ Currently ships ten locales: **English, Mandarin Chinese, Hindi,
237
+ Spanish, Portuguese, French, German, Arabic, Russian, Japanese**
238
+ (~82 % of the world's speakers).
239
+
240
+ Adding a new language is a two-file PR — see [CONTRIBUTING.md](CONTRIBUTING.md).
241
+
242
+ ---
243
+
244
+ ## Configuration
245
+
246
+ The most-used env knobs (full list in `threadkeeper/config.py`):
247
+
248
+ | Knob | Default | Purpose |
249
+ |---|---|---|
250
+ | `THREADKEEPER_DB` | `~/.threadkeeper/db.sqlite` | SQLite file |
251
+ | `THREADKEEPER_AUTO_REVIEW` | "" (off) | auto-review on `close_thread` |
252
+ | `THREADKEEPER_SHADOW_REVIEW_INTERVAL_S` | 0 (off) | shadow daemon tick (s) |
253
+ | `THREADKEEPER_SHADOW_REVIEW_WINDOW_S` | 900 | sliding window for shadow scan (s) |
254
+ | `THREADKEEPER_EXTRACT_INTERVAL_S` | 0 (off) | extract daemon tick (s); 600 = 10 min recommended |
255
+ | `THREADKEEPER_EXTRACT_WINDOW_MIN` | 30 | sliding dialog window per extract pass (min) |
256
+ | `THREADKEEPER_CURATOR_INTERVAL_S` | 0 (off) | curator daemon tick (s); 604800 = 7d recommended |
257
+ | `THREADKEEPER_CURATOR_MIN_LESSONS` | 3 | min lessons before curator engages |
258
+ | `THREADKEEPER_CURATOR_DESTRUCTIVE` | "" (advisory) | when "1": curator child applies its own PATCH/PRUNE/CONSOLIDATE directly instead of writing advisory REPORT only |
259
+ | `THREADKEEPER_SPAWN_BUDGET_MB` | 3072 | combined child RSS cap (MB); 0 disables |
260
+ | `THREADKEEPER_INGEST_INTERVAL_S` | 30 | transcript ingest tick (s) |
261
+ | `THREADKEEPER_NO_EMBEDDINGS` | "" | force-disable sentence-transformers |
262
+ | `THREADKEEPER_SKILL_NUDGE_INTERVAL` | 10 | events between `skill_hint` nudges |
263
+
264
+ Persist them via `~/.claude/settings.json`'s `env` block (Claude Code) or
265
+ the equivalent env section in each CLI's config. Hot-config reload is
266
+ [tracked](https://github.com/po4erk91/thread-keeper/issues/2).
267
+
268
+ ---
269
+
270
+ ## Storage
271
+
272
+ `~/.threadkeeper/db.sqlite` (overridable via `THREADKEEPER_DB`). WAL
273
+ mode for multi-writer concurrency. Optional `notes_vec` / `dialog_vec`
274
+ HNSW indexes through `sqlite-vec` for sub-linear semantic search;
275
+ fallback to Python-side cosine when the extension is missing.
276
+
277
+ One file. Backup = `cp`. Wipe memory = `rm`.
278
+
279
+ Hooks and small runtime artifacts: `~/.threadkeeper/hooks/`.
280
+
281
+ ---
282
+
283
+ ## Verifying ingest across CLIs
284
+
285
+ ```bash
286
+ python scripts/tk_verify_ingest.py
287
+ ```
288
+
289
+ Walks every installed CLI adapter, parses recent transcripts in an
290
+ isolated tempdir DB, reports per-source message counts and any silent
291
+ parse failures. Read-only with respect to live state.
292
+
293
+ ---
294
+
295
+ ## Tests
296
+
297
+ ```bash
298
+ pip install -e '.[semantic,dev]'
299
+ python -m pytest
300
+ ```
301
+
302
+ 412 tests passing on Python 3.11 / 3.12 / 3.13 (1 skipped). CI runs
303
+ the suite on every push and PR.
304
+
305
+ ---
306
+
307
+ ## Project layout
308
+
309
+ ```
310
+ threadkeeper/
311
+ ├── server.py # MCP entry: python -m threadkeeper.server
312
+ ├── _setup.py # `thread-keeper-setup` installer
313
+ ├── config.py # env-driven defaults
314
+ ├── db.py # SQLite schema + sqlite-vec loader
315
+ ├── identity.py # session, self-cid, daemon launchers
316
+ ├── ingest.py # adapter-driven transcript ingest
317
+ ├── brief.py # render_brief / render_context
318
+ ├── shadow_review.py # autonomous learning observer
319
+ ├── i18n.py # 10 locales of regex + prompt bundles
320
+ ├── adapters/ # one file per supported CLI
321
+ │ ├── claude_code.py
322
+ │ ├── claude_desktop.py
323
+ │ ├── codex.py
324
+ │ ├── gemini.py
325
+ │ ├── copilot.py
326
+ │ └── vscode.py
327
+ └── tools/ # @mcp.tool entries — 83 of them
328
+ ├── threads.py
329
+ ├── peers.py
330
+ ├── spawn.py
331
+ ├── skills.py
332
+ └── ...
333
+ ```
334
+
335
+ Detailed map in [docs/ARCHITECTURE.md](docs/ARCHITECTURE.md).
336
+ Open work in [docs/ROADMAP.md](docs/ROADMAP.md) and the
337
+ [Issues tab](https://github.com/po4erk91/thread-keeper/issues).
338
+
339
+ ---
340
+
341
+ ## Contributing
342
+
343
+ PRs welcome — see [CONTRIBUTING.md](CONTRIBUTING.md) for the project
344
+ map, test workflow, and recipes for adding a new CLI adapter or a new
345
+ locale. Look for the `good-first-issue` label.
346
+
347
+ ---
348
+
349
+ ## License
350
+
351
+ MIT — see [LICENSE](LICENSE).