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.
- threadkeeper-0.4.0/LICENSE +21 -0
- threadkeeper-0.4.0/PKG-INFO +351 -0
- threadkeeper-0.4.0/README.md +317 -0
- threadkeeper-0.4.0/pyproject.toml +70 -0
- threadkeeper-0.4.0/setup.cfg +4 -0
- threadkeeper-0.4.0/tests/test_adapters.py +556 -0
- threadkeeper-0.4.0/tests/test_brief_sections.py +208 -0
- threadkeeper-0.4.0/tests/test_core_memory.py +40 -0
- threadkeeper-0.4.0/tests/test_curator.py +323 -0
- threadkeeper-0.4.0/tests/test_delegated_search.py +267 -0
- threadkeeper-0.4.0/tests/test_dialectic.py +429 -0
- threadkeeper-0.4.0/tests/test_error_paths.py +54 -0
- threadkeeper-0.4.0/tests/test_extract_daemon.py +373 -0
- threadkeeper-0.4.0/tests/test_i18n_multilang.py +158 -0
- threadkeeper-0.4.0/tests/test_identity.py +78 -0
- threadkeeper-0.4.0/tests/test_lessons.py +136 -0
- threadkeeper-0.4.0/tests/test_missed_spawns.py +159 -0
- threadkeeper-0.4.0/tests/test_nudges.py +440 -0
- threadkeeper-0.4.0/tests/test_process_health.py +258 -0
- threadkeeper-0.4.0/tests/test_shadow_review.py +327 -0
- threadkeeper-0.4.0/tests/test_skill_hint.py +185 -0
- threadkeeper-0.4.0/tests/test_skill_use_parser.py +374 -0
- threadkeeper-0.4.0/tests/test_skill_watcher.py +202 -0
- threadkeeper-0.4.0/tests/test_skills.py +612 -0
- threadkeeper-0.4.0/tests/test_spawn_budget.py +179 -0
- threadkeeper-0.4.0/tests/test_spawn_hint.py +215 -0
- threadkeeper-0.4.0/tests/test_spawn_slim.py +127 -0
- threadkeeper-0.4.0/tests/test_threads.py +71 -0
- threadkeeper-0.4.0/tests/test_tools_smoke.py +95 -0
- threadkeeper-0.4.0/tests/test_vec_search.py +209 -0
- threadkeeper-0.4.0/threadkeeper/__init__.py +8 -0
- threadkeeper-0.4.0/threadkeeper/_mcp.py +6 -0
- threadkeeper-0.4.0/threadkeeper/_setup.py +299 -0
- threadkeeper-0.4.0/threadkeeper/adapters/__init__.py +40 -0
- threadkeeper-0.4.0/threadkeeper/adapters/_hook_helpers.py +72 -0
- threadkeeper-0.4.0/threadkeeper/adapters/base.py +152 -0
- threadkeeper-0.4.0/threadkeeper/adapters/claude_code.py +178 -0
- threadkeeper-0.4.0/threadkeeper/adapters/claude_desktop.py +128 -0
- threadkeeper-0.4.0/threadkeeper/adapters/codex.py +259 -0
- threadkeeper-0.4.0/threadkeeper/adapters/copilot.py +195 -0
- threadkeeper-0.4.0/threadkeeper/adapters/gemini.py +169 -0
- threadkeeper-0.4.0/threadkeeper/adapters/vscode.py +144 -0
- threadkeeper-0.4.0/threadkeeper/brief.py +735 -0
- threadkeeper-0.4.0/threadkeeper/config.py +216 -0
- threadkeeper-0.4.0/threadkeeper/curator.py +390 -0
- threadkeeper-0.4.0/threadkeeper/db.py +474 -0
- threadkeeper-0.4.0/threadkeeper/embeddings.py +232 -0
- threadkeeper-0.4.0/threadkeeper/extract_daemon.py +125 -0
- threadkeeper-0.4.0/threadkeeper/helpers.py +101 -0
- threadkeeper-0.4.0/threadkeeper/i18n.py +342 -0
- threadkeeper-0.4.0/threadkeeper/identity.py +237 -0
- threadkeeper-0.4.0/threadkeeper/ingest.py +507 -0
- threadkeeper-0.4.0/threadkeeper/lessons.py +170 -0
- threadkeeper-0.4.0/threadkeeper/nudges.py +257 -0
- threadkeeper-0.4.0/threadkeeper/process_health.py +202 -0
- threadkeeper-0.4.0/threadkeeper/review_prompts.py +207 -0
- threadkeeper-0.4.0/threadkeeper/search_proxy.py +160 -0
- threadkeeper-0.4.0/threadkeeper/server.py +55 -0
- threadkeeper-0.4.0/threadkeeper/shadow_review.py +358 -0
- threadkeeper-0.4.0/threadkeeper/skill_watcher.py +96 -0
- threadkeeper-0.4.0/threadkeeper/spawn_budget.py +246 -0
- threadkeeper-0.4.0/threadkeeper/tools/__init__.py +2 -0
- threadkeeper-0.4.0/threadkeeper/tools/concepts.py +111 -0
- threadkeeper-0.4.0/threadkeeper/tools/consolidate.py +222 -0
- threadkeeper-0.4.0/threadkeeper/tools/core_memory.py +109 -0
- threadkeeper-0.4.0/threadkeeper/tools/correlation.py +116 -0
- threadkeeper-0.4.0/threadkeeper/tools/curator.py +121 -0
- threadkeeper-0.4.0/threadkeeper/tools/dialectic.py +359 -0
- threadkeeper-0.4.0/threadkeeper/tools/dialog.py +131 -0
- threadkeeper-0.4.0/threadkeeper/tools/distill.py +184 -0
- threadkeeper-0.4.0/threadkeeper/tools/extract.py +411 -0
- threadkeeper-0.4.0/threadkeeper/tools/graph.py +183 -0
- threadkeeper-0.4.0/threadkeeper/tools/invariants.py +177 -0
- threadkeeper-0.4.0/threadkeeper/tools/lessons.py +110 -0
- threadkeeper-0.4.0/threadkeeper/tools/missed_spawns.py +142 -0
- threadkeeper-0.4.0/threadkeeper/tools/peers.py +579 -0
- threadkeeper-0.4.0/threadkeeper/tools/pickup.py +148 -0
- threadkeeper-0.4.0/threadkeeper/tools/probes.py +251 -0
- threadkeeper-0.4.0/threadkeeper/tools/process_health.py +90 -0
- threadkeeper-0.4.0/threadkeeper/tools/session.py +34 -0
- threadkeeper-0.4.0/threadkeeper/tools/shadow_review.py +106 -0
- threadkeeper-0.4.0/threadkeeper/tools/skills.py +856 -0
- threadkeeper-0.4.0/threadkeeper/tools/spawn.py +871 -0
- threadkeeper-0.4.0/threadkeeper/tools/style.py +44 -0
- threadkeeper-0.4.0/threadkeeper/tools/threads.py +299 -0
- threadkeeper-0.4.0/threadkeeper.egg-info/PKG-INFO +351 -0
- threadkeeper-0.4.0/threadkeeper.egg-info/SOURCES.txt +89 -0
- threadkeeper-0.4.0/threadkeeper.egg-info/dependency_links.txt +1 -0
- threadkeeper-0.4.0/threadkeeper.egg-info/entry_points.txt +2 -0
- threadkeeper-0.4.0/threadkeeper.egg-info/requires.txt +10 -0
- 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
|
+
[](https://github.com/po4erk91/thread-keeper/actions/workflows/test.yml)
|
|
38
|
+
[](https://www.python.org/downloads/)
|
|
39
|
+
[](LICENSE)
|
|
40
|
+
[](#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).
|