threadkeeper 0.10.0__tar.gz → 0.12.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 (154) hide show
  1. {threadkeeper-0.10.0 → threadkeeper-0.12.0}/PKG-INFO +108 -84
  2. {threadkeeper-0.10.0 → threadkeeper-0.12.0}/README.md +106 -82
  3. {threadkeeper-0.10.0 → threadkeeper-0.12.0}/pyproject.toml +2 -2
  4. {threadkeeper-0.10.0 → threadkeeper-0.12.0}/tests/test_adapters.py +44 -5
  5. {threadkeeper-0.10.0 → threadkeeper-0.12.0}/tests/test_agent_status.py +50 -0
  6. {threadkeeper-0.10.0 → threadkeeper-0.12.0}/tests/test_curator.py +5 -0
  7. threadkeeper-0.12.0/tests/test_evolve_applier.py +1133 -0
  8. {threadkeeper-0.10.0 → threadkeeper-0.12.0}/tests/test_evolve_daemon.py +77 -10
  9. {threadkeeper-0.10.0 → threadkeeper-0.12.0}/tests/test_lessons.py +3 -2
  10. {threadkeeper-0.10.0 → threadkeeper-0.12.0}/tests/test_menubar_app.py +24 -0
  11. {threadkeeper-0.10.0 → threadkeeper-0.12.0}/tests/test_skills.py +1 -1
  12. {threadkeeper-0.10.0 → threadkeeper-0.12.0}/tests/test_spawn_config.py +25 -7
  13. {threadkeeper-0.10.0 → threadkeeper-0.12.0}/threadkeeper/_setup.py +14 -13
  14. {threadkeeper-0.10.0 → threadkeeper-0.12.0}/threadkeeper/adapters/__init__.py +8 -3
  15. {threadkeeper-0.10.0 → threadkeeper-0.12.0}/threadkeeper/adapters/_hook_helpers.py +1 -1
  16. threadkeeper-0.12.0/threadkeeper/adapters/antigravity.py +137 -0
  17. {threadkeeper-0.10.0 → threadkeeper-0.12.0}/threadkeeper/adapters/base.py +5 -3
  18. {threadkeeper-0.10.0 → threadkeeper-0.12.0}/threadkeeper/adapters/codex.py +2 -0
  19. {threadkeeper-0.10.0 → threadkeeper-0.12.0}/threadkeeper/adapters/vscode.py +1 -1
  20. {threadkeeper-0.10.0 → threadkeeper-0.12.0}/threadkeeper/agent_status.py +34 -10
  21. {threadkeeper-0.10.0 → threadkeeper-0.12.0}/threadkeeper/assets/macos-agent-status/README.md +8 -0
  22. threadkeeper-0.12.0/threadkeeper/assets/macos-agent-status/ThreadKeeperAgentStatus.swift +1814 -0
  23. {threadkeeper-0.10.0 → threadkeeper-0.12.0}/threadkeeper/brief.py +4 -3
  24. {threadkeeper-0.10.0 → threadkeeper-0.12.0}/threadkeeper/config.py +6 -0
  25. {threadkeeper-0.10.0 → threadkeeper-0.12.0}/threadkeeper/curator.py +19 -0
  26. threadkeeper-0.12.0/threadkeeper/evolve_applier.py +1445 -0
  27. {threadkeeper-0.10.0 → threadkeeper-0.12.0}/threadkeeper/evolve_daemon.py +98 -66
  28. {threadkeeper-0.10.0 → threadkeeper-0.12.0}/threadkeeper/identity.py +6 -4
  29. {threadkeeper-0.10.0 → threadkeeper-0.12.0}/threadkeeper/nudges.py +6 -6
  30. {threadkeeper-0.10.0 → threadkeeper-0.12.0}/threadkeeper/review_prompts.py +6 -4
  31. {threadkeeper-0.10.0 → threadkeeper-0.12.0}/threadkeeper/spawn_config.py +30 -9
  32. {threadkeeper-0.10.0 → threadkeeper-0.12.0}/threadkeeper/tools/evolve_applier.py +45 -1
  33. {threadkeeper-0.10.0 → threadkeeper-0.12.0}/threadkeeper/tools/skills.py +3 -3
  34. {threadkeeper-0.10.0 → threadkeeper-0.12.0}/threadkeeper/tools/spawn.py +1 -1
  35. {threadkeeper-0.10.0 → threadkeeper-0.12.0}/threadkeeper/tools/threads.py +2 -2
  36. {threadkeeper-0.10.0 → threadkeeper-0.12.0}/threadkeeper.egg-info/PKG-INFO +108 -84
  37. {threadkeeper-0.10.0 → threadkeeper-0.12.0}/threadkeeper.egg-info/SOURCES.txt +1 -0
  38. threadkeeper-0.10.0/tests/test_evolve_applier.py +0 -445
  39. threadkeeper-0.10.0/threadkeeper/assets/macos-agent-status/ThreadKeeperAgentStatus.swift +0 -760
  40. threadkeeper-0.10.0/threadkeeper/evolve_applier.py +0 -709
  41. {threadkeeper-0.10.0 → threadkeeper-0.12.0}/LICENSE +0 -0
  42. {threadkeeper-0.10.0 → threadkeeper-0.12.0}/setup.cfg +0 -0
  43. {threadkeeper-0.10.0 → threadkeeper-0.12.0}/tests/test_auto_update.py +0 -0
  44. {threadkeeper-0.10.0 → threadkeeper-0.12.0}/tests/test_brief_footprint.py +0 -0
  45. {threadkeeper-0.10.0 → threadkeeper-0.12.0}/tests/test_brief_sections.py +0 -0
  46. {threadkeeper-0.10.0 → threadkeeper-0.12.0}/tests/test_candidate_reviewer.py +0 -0
  47. {threadkeeper-0.10.0 → threadkeeper-0.12.0}/tests/test_config_settings.py +0 -0
  48. {threadkeeper-0.10.0 → threadkeeper-0.12.0}/tests/test_core_memory.py +0 -0
  49. {threadkeeper-0.10.0 → threadkeeper-0.12.0}/tests/test_dashboard.py +0 -0
  50. {threadkeeper-0.10.0 → threadkeeper-0.12.0}/tests/test_delegated_search.py +0 -0
  51. {threadkeeper-0.10.0 → threadkeeper-0.12.0}/tests/test_dialectic.py +0 -0
  52. {threadkeeper-0.10.0 → threadkeeper-0.12.0}/tests/test_dialectic_feed_tools.py +0 -0
  53. {threadkeeper-0.10.0 → threadkeeper-0.12.0}/tests/test_dialectic_miner.py +0 -0
  54. {threadkeeper-0.10.0 → threadkeeper-0.12.0}/tests/test_dialectic_observation_resolve.py +0 -0
  55. {threadkeeper-0.10.0 → threadkeeper-0.12.0}/tests/test_dialectic_recompute.py +0 -0
  56. {threadkeeper-0.10.0 → threadkeeper-0.12.0}/tests/test_dialectic_tier.py +0 -0
  57. {threadkeeper-0.10.0 → threadkeeper-0.12.0}/tests/test_dialectic_validator.py +0 -0
  58. {threadkeeper-0.10.0 → threadkeeper-0.12.0}/tests/test_error_paths.py +0 -0
  59. {threadkeeper-0.10.0 → threadkeeper-0.12.0}/tests/test_evolve_apply_2.py +0 -0
  60. {threadkeeper-0.10.0 → threadkeeper-0.12.0}/tests/test_evolve_apply_3.py +0 -0
  61. {threadkeeper-0.10.0 → threadkeeper-0.12.0}/tests/test_extract_daemon.py +0 -0
  62. {threadkeeper-0.10.0 → threadkeeper-0.12.0}/tests/test_extract_dedup.py +0 -0
  63. {threadkeeper-0.10.0 → threadkeeper-0.12.0}/tests/test_i18n_multilang.py +0 -0
  64. {threadkeeper-0.10.0 → threadkeeper-0.12.0}/tests/test_identity.py +0 -0
  65. {threadkeeper-0.10.0 → threadkeeper-0.12.0}/tests/test_ingest_status.py +0 -0
  66. {threadkeeper-0.10.0 → threadkeeper-0.12.0}/tests/test_memory_guard.py +0 -0
  67. {threadkeeper-0.10.0 → threadkeeper-0.12.0}/tests/test_missed_spawns.py +0 -0
  68. {threadkeeper-0.10.0 → threadkeeper-0.12.0}/tests/test_nudges.py +0 -0
  69. {threadkeeper-0.10.0 → threadkeeper-0.12.0}/tests/test_onnx_embeddings.py +0 -0
  70. {threadkeeper-0.10.0 → threadkeeper-0.12.0}/tests/test_panel.py +0 -0
  71. {threadkeeper-0.10.0 → threadkeeper-0.12.0}/tests/test_probe_daemon.py +0 -0
  72. {threadkeeper-0.10.0 → threadkeeper-0.12.0}/tests/test_process_health.py +0 -0
  73. {threadkeeper-0.10.0 → threadkeeper-0.12.0}/tests/test_search_fts_punctuation.py +0 -0
  74. {threadkeeper-0.10.0 → threadkeeper-0.12.0}/tests/test_shadow_review.py +0 -0
  75. {threadkeeper-0.10.0 → threadkeeper-0.12.0}/tests/test_skill_hint.py +0 -0
  76. {threadkeeper-0.10.0 → threadkeeper-0.12.0}/tests/test_skill_passive_tier.py +0 -0
  77. {threadkeeper-0.10.0 → threadkeeper-0.12.0}/tests/test_skill_tier.py +0 -0
  78. {threadkeeper-0.10.0 → threadkeeper-0.12.0}/tests/test_skill_use_parser.py +0 -0
  79. {threadkeeper-0.10.0 → threadkeeper-0.12.0}/tests/test_skill_watcher.py +0 -0
  80. {threadkeeper-0.10.0 → threadkeeper-0.12.0}/tests/test_spawn_budget.py +0 -0
  81. {threadkeeper-0.10.0 → threadkeeper-0.12.0}/tests/test_spawn_codex_stdin.py +0 -0
  82. {threadkeeper-0.10.0 → threadkeeper-0.12.0}/tests/test_spawn_hint.py +0 -0
  83. {threadkeeper-0.10.0 → threadkeeper-0.12.0}/tests/test_spawn_reap.py +0 -0
  84. {threadkeeper-0.10.0 → threadkeeper-0.12.0}/tests/test_spawn_slim.py +0 -0
  85. {threadkeeper-0.10.0 → threadkeeper-0.12.0}/tests/test_spawn_wrap.py +0 -0
  86. {threadkeeper-0.10.0 → threadkeeper-0.12.0}/tests/test_thread_janitor.py +0 -0
  87. {threadkeeper-0.10.0 → threadkeeper-0.12.0}/tests/test_threads.py +0 -0
  88. {threadkeeper-0.10.0 → threadkeeper-0.12.0}/tests/test_tools_smoke.py +0 -0
  89. {threadkeeper-0.10.0 → threadkeeper-0.12.0}/tests/test_validate_threads.py +0 -0
  90. {threadkeeper-0.10.0 → threadkeeper-0.12.0}/tests/test_vec_search.py +0 -0
  91. {threadkeeper-0.10.0 → threadkeeper-0.12.0}/threadkeeper/__init__.py +0 -0
  92. {threadkeeper-0.10.0 → threadkeeper-0.12.0}/threadkeeper/_mcp.py +0 -0
  93. {threadkeeper-0.10.0 → threadkeeper-0.12.0}/threadkeeper/_spawn_wrap.py +0 -0
  94. {threadkeeper-0.10.0 → threadkeeper-0.12.0}/threadkeeper/adapters/claude_code.py +0 -0
  95. {threadkeeper-0.10.0 → threadkeeper-0.12.0}/threadkeeper/adapters/claude_desktop.py +0 -0
  96. {threadkeeper-0.10.0 → threadkeeper-0.12.0}/threadkeeper/adapters/copilot.py +0 -0
  97. {threadkeeper-0.10.0 → threadkeeper-0.12.0}/threadkeeper/adapters/gemini.py +0 -0
  98. {threadkeeper-0.10.0 → threadkeeper-0.12.0}/threadkeeper/assets/macos-agent-status/Info.plist +0 -0
  99. {threadkeeper-0.10.0 → threadkeeper-0.12.0}/threadkeeper/assets/macos-agent-status/build.sh +0 -0
  100. {threadkeeper-0.10.0 → threadkeeper-0.12.0}/threadkeeper/assets/macos-agent-status/install.sh +0 -0
  101. {threadkeeper-0.10.0 → threadkeeper-0.12.0}/threadkeeper/auto_update.py +0 -0
  102. {threadkeeper-0.10.0 → threadkeeper-0.12.0}/threadkeeper/candidate_reviewer.py +0 -0
  103. {threadkeeper-0.10.0 → threadkeeper-0.12.0}/threadkeeper/db.py +0 -0
  104. {threadkeeper-0.10.0 → threadkeeper-0.12.0}/threadkeeper/dialectic_miner.py +0 -0
  105. {threadkeeper-0.10.0 → threadkeeper-0.12.0}/threadkeeper/dialectic_validator.py +0 -0
  106. {threadkeeper-0.10.0 → threadkeeper-0.12.0}/threadkeeper/embeddings.py +0 -0
  107. {threadkeeper-0.10.0 → threadkeeper-0.12.0}/threadkeeper/extract_daemon.py +0 -0
  108. {threadkeeper-0.10.0 → threadkeeper-0.12.0}/threadkeeper/helpers.py +0 -0
  109. {threadkeeper-0.10.0 → threadkeeper-0.12.0}/threadkeeper/i18n.py +0 -0
  110. {threadkeeper-0.10.0 → threadkeeper-0.12.0}/threadkeeper/ingest.py +0 -0
  111. {threadkeeper-0.10.0 → threadkeeper-0.12.0}/threadkeeper/lessons.py +0 -0
  112. {threadkeeper-0.10.0 → threadkeeper-0.12.0}/threadkeeper/memory_guard.py +0 -0
  113. {threadkeeper-0.10.0 → threadkeeper-0.12.0}/threadkeeper/menubar_app.py +0 -0
  114. {threadkeeper-0.10.0 → threadkeeper-0.12.0}/threadkeeper/migrate_embeddings.py +0 -0
  115. {threadkeeper-0.10.0 → threadkeeper-0.12.0}/threadkeeper/probe_daemon.py +0 -0
  116. {threadkeeper-0.10.0 → threadkeeper-0.12.0}/threadkeeper/process_health.py +0 -0
  117. {threadkeeper-0.10.0 → threadkeeper-0.12.0}/threadkeeper/search_proxy.py +0 -0
  118. {threadkeeper-0.10.0 → threadkeeper-0.12.0}/threadkeeper/server.py +0 -0
  119. {threadkeeper-0.10.0 → threadkeeper-0.12.0}/threadkeeper/shadow_review.py +0 -0
  120. {threadkeeper-0.10.0 → threadkeeper-0.12.0}/threadkeeper/skill_watcher.py +0 -0
  121. {threadkeeper-0.10.0 → threadkeeper-0.12.0}/threadkeeper/spawn_budget.py +0 -0
  122. {threadkeeper-0.10.0 → threadkeeper-0.12.0}/threadkeeper/thread_janitor.py +0 -0
  123. {threadkeeper-0.10.0 → threadkeeper-0.12.0}/threadkeeper/tools/__init__.py +0 -0
  124. {threadkeeper-0.10.0 → threadkeeper-0.12.0}/threadkeeper/tools/agent_status.py +0 -0
  125. {threadkeeper-0.10.0 → threadkeeper-0.12.0}/threadkeeper/tools/candidate_reviewer.py +0 -0
  126. {threadkeeper-0.10.0 → threadkeeper-0.12.0}/threadkeeper/tools/concepts.py +0 -0
  127. {threadkeeper-0.10.0 → threadkeeper-0.12.0}/threadkeeper/tools/consolidate.py +0 -0
  128. {threadkeeper-0.10.0 → threadkeeper-0.12.0}/threadkeeper/tools/core_memory.py +0 -0
  129. {threadkeeper-0.10.0 → threadkeeper-0.12.0}/threadkeeper/tools/correlation.py +0 -0
  130. {threadkeeper-0.10.0 → threadkeeper-0.12.0}/threadkeeper/tools/curator.py +0 -0
  131. {threadkeeper-0.10.0 → threadkeeper-0.12.0}/threadkeeper/tools/dashboard.py +0 -0
  132. {threadkeeper-0.10.0 → threadkeeper-0.12.0}/threadkeeper/tools/dialectic.py +0 -0
  133. {threadkeeper-0.10.0 → threadkeeper-0.12.0}/threadkeeper/tools/dialectic_feed.py +0 -0
  134. {threadkeeper-0.10.0 → threadkeeper-0.12.0}/threadkeeper/tools/dialog.py +0 -0
  135. {threadkeeper-0.10.0 → threadkeeper-0.12.0}/threadkeeper/tools/distill.py +0 -0
  136. {threadkeeper-0.10.0 → threadkeeper-0.12.0}/threadkeeper/tools/extract.py +0 -0
  137. {threadkeeper-0.10.0 → threadkeeper-0.12.0}/threadkeeper/tools/graph.py +0 -0
  138. {threadkeeper-0.10.0 → threadkeeper-0.12.0}/threadkeeper/tools/invariants.py +0 -0
  139. {threadkeeper-0.10.0 → threadkeeper-0.12.0}/threadkeeper/tools/lessons.py +0 -0
  140. {threadkeeper-0.10.0 → threadkeeper-0.12.0}/threadkeeper/tools/memory_guard.py +0 -0
  141. {threadkeeper-0.10.0 → threadkeeper-0.12.0}/threadkeeper/tools/missed_spawns.py +0 -0
  142. {threadkeeper-0.10.0 → threadkeeper-0.12.0}/threadkeeper/tools/panel.py +0 -0
  143. {threadkeeper-0.10.0 → threadkeeper-0.12.0}/threadkeeper/tools/peers.py +0 -0
  144. {threadkeeper-0.10.0 → threadkeeper-0.12.0}/threadkeeper/tools/pickup.py +0 -0
  145. {threadkeeper-0.10.0 → threadkeeper-0.12.0}/threadkeeper/tools/probes.py +0 -0
  146. {threadkeeper-0.10.0 → threadkeeper-0.12.0}/threadkeeper/tools/process_health.py +0 -0
  147. {threadkeeper-0.10.0 → threadkeeper-0.12.0}/threadkeeper/tools/session.py +0 -0
  148. {threadkeeper-0.10.0 → threadkeeper-0.12.0}/threadkeeper/tools/shadow_review.py +0 -0
  149. {threadkeeper-0.10.0 → threadkeeper-0.12.0}/threadkeeper/tools/style.py +0 -0
  150. {threadkeeper-0.10.0 → threadkeeper-0.12.0}/threadkeeper/tools/validate.py +0 -0
  151. {threadkeeper-0.10.0 → threadkeeper-0.12.0}/threadkeeper.egg-info/dependency_links.txt +0 -0
  152. {threadkeeper-0.10.0 → threadkeeper-0.12.0}/threadkeeper.egg-info/entry_points.txt +0 -0
  153. {threadkeeper-0.10.0 → threadkeeper-0.12.0}/threadkeeper.egg-info/requires.txt +0 -0
  154. {threadkeeper-0.10.0 → threadkeeper-0.12.0}/threadkeeper.egg-info/top_level.txt +0 -0
@@ -1,7 +1,7 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: threadkeeper
3
- Version: 0.10.0
4
- Summary: Multi-agent shared brain across Claude Code/Desktop, Codex, Gemini, Copilot, VS Code. Cross-session memory, self-improving skill loops, inter-agent signaling — one local MCP server.
3
+ Version: 0.12.0
4
+ Summary: Multi-agent shared brain across Claude Code/Desktop, Codex, Antigravity CLI, Gemini, Copilot, VS Code. Cross-session memory, self-improving skill loops, inter-agent signaling — one local MCP server.
5
5
  Author: thread-keeper contributors
6
6
  License: MIT
7
7
  Project-URL: Homepage, https://github.com/po4erk91/thread-keeper
@@ -45,17 +45,17 @@ Dynamic: license-file
45
45
  [![Python](https://img.shields.io/badge/python-3.11%2B-blue)](https://www.python.org/downloads/)
46
46
  [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](LICENSE)
47
47
  [![PyPI](https://img.shields.io/pypi/v/threadkeeper.svg)](https://pypi.org/project/threadkeeper/)
48
- [![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)
48
+ [![CLIs](https://img.shields.io/badge/CLIs-Claude%20%7C%20Codex%20%7C%20Antigravity%20%7C%20Gemini%20legacy%20%7C%20Copilot%20%7C%20VS%20Code-green)](#multi-cli-integration)
49
49
 
50
- **Multi-agent shared brain across Claude Code/Desktop, Codex, Gemini,
51
- Copilot, and VS Code.** Cross-session memory, self-improving skill
52
- loops, and inter-agent signaling — one local MCP server turns parallel
53
- agent instances into a coordinated multi-agent system instead of N
54
- isolated chats.
50
+ **Multi-agent shared brain across Claude Code/Desktop, Codex,
51
+ Antigravity CLI (`agy`), Gemini legacy, Copilot, and VS Code.**
52
+ Cross-session memory, self-improving skill loops, and inter-agent signaling —
53
+ one local MCP server turns parallel agent instances into a coordinated
54
+ multi-agent system instead of N isolated chats.
55
55
 
56
- Every connected client (Claude Code, Claude Desktop, Codex CLI +
57
- desktop, Gemini, Copilot, every MCP-aware VS Code extension) shares
58
- one SQLite store, one set of threads, one user model, and one learning
56
+ Every connected client (Claude Code, Claude Desktop, Codex CLI + desktop,
57
+ Antigravity CLI, Gemini legacy, Copilot, every MCP-aware VS Code extension)
58
+ shares one SQLite store, one set of threads, one user model, and one learning
59
59
  loop that improves the skill library autonomously over time.
60
60
 
61
61
  The brief format is dense — structural tags, opaque IDs, ~6 KB per
@@ -67,7 +67,7 @@ session-start injection. Optimized for agent consumption, not human reading.
67
67
 
68
68
  Every agent CLI starts cold. Context dies at session boundaries.
69
69
  Skills you taught Claude don't transfer to Codex. Threads you closed
70
- in yesterday's Gemini chat are invisible to today's Copilot. Parallel
70
+ in yesterday's Antigravity chat are invisible to today's Copilot. Parallel
71
71
  agent instances running the same task don't know about each other and
72
72
  duplicate work or step on each other's writes.
73
73
 
@@ -92,9 +92,10 @@ make it more than a memory store:
92
92
  materialize class-level skills as the agents work. Adapted to multi-CLI:
93
93
  SKILL.md is the primary write target and gets mirrored to every
94
94
  known/configured skills root simultaneously (`~/.claude/skills/`,
95
- `~/.codex/skills/`, existing `~/.agents/skills/`, extra roots from
96
- `THREADKEEPER_EXTRA_SKILLS_DIRS`, and `~/.threadkeeper/skills/`),
97
- with lessons.md as a fallback for CLIs without a native skills loader.
95
+ `~/.codex/skills/`, `~/.gemini/config/skills/` for Antigravity,
96
+ existing `~/.agents/skills/`, extra roots from
97
+ `THREADKEEPER_EXTRA_SKILLS_DIRS`, and `~/.threadkeeper/skills/`), with
98
+ lessons.md as a fallback for CLIs without a native skills loader.
98
99
 
99
100
  Foreground MCP servers also run a daily self-update check by default. Source
100
101
  checkouts fast-forward their tracked git branch and reinstall the editable
@@ -113,15 +114,17 @@ pipx install 'threadkeeper[semantic]' && thread-keeper-setup
113
114
  ```
114
115
 
115
116
  `thread-keeper-setup` detects every CLI you have installed (Claude
116
- Code / Claude Desktop / Codex CLI + desktop / Gemini / Copilot / VS
117
- Code), registers the MCP server in each one's config, copies hooks to
117
+ Code / Claude Desktop / Codex CLI + desktop / Antigravity CLI `agy` /
118
+ Gemini legacy / Copilot / VS Code), registers the MCP server in each one's
119
+ config, copies hooks to
118
120
  `~/.threadkeeper/hooks/`, and writes a managed instructions block into
119
121
  each CLI's per-user instructions file (`CLAUDE.md` / `AGENTS.md` /
120
122
  `GEMINI.md` / `copilot-instructions.md` — Claude Desktop and VS Code
121
123
  have no global instructions file, so that step is skipped for them).
122
124
 
123
- Restart your CLI of choice. The SessionStart hook injects a brief on
124
- first message; no manual `brief()` call required.
125
+ Restart your CLI of choice. Hook-capable clients inject a brief on the first
126
+ message; hookless clients such as Codex and Antigravity CLI follow the managed
127
+ instructions block and call `brief()` / `context()` manually before answering.
125
128
 
126
129
  ### Alternative installs
127
130
 
@@ -168,16 +171,18 @@ thread-keeper-setup --dry-run
168
171
  | Claude Code | `~/.claude.json` `mcpServers` | `~/.claude/CLAUDE.md` | `~/.claude/settings.json` `hooks` | `~/.claude/projects/**/*.jsonl` |
169
172
  | 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 |
170
173
  | Codex (CLI + desktop) | `~/.codex/config.toml` `[mcp_servers]` (shared between CLI and `Codex.app`) | `~/.codex/AGENTS.md` | not supported | `~/.codex/sessions/**/rollout-*.jsonl` |
171
- | Gemini | `~/.gemini/settings.json` `mcpServers` | `~/.gemini/GEMINI.md` | `~/.gemini/settings.json` `hooks` | `~/.gemini/tmp/<user>/chats/session-*.jsonl` |
174
+ | Antigravity CLI (`agy`) | `~/.gemini/config/mcp_config.json` `mcpServers` | `~/.gemini/config/AGENTS.md` | not wired yet | not yet parsed — sqlite/protobuf under `~/.gemini/antigravity-cli/conversations/*.db` |
175
+ | Gemini legacy | `~/.gemini/settings.json` `mcpServers` | `~/.gemini/GEMINI.md` | `~/.gemini/settings.json` `hooks` | `~/.gemini/tmp/<user>/chats/session-*.jsonl` |
172
176
  | Copilot | `~/.copilot/mcp-config.json` `mcpServers` | `~/.copilot/copilot-instructions.md` | `~/.copilot/hooks.json` | `~/.copilot/session-store.db` (sqlite) |
173
177
  | 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 |
174
178
 
175
179
  Every CLI that produces parseable transcripts feeds the same
176
180
  `dialog_messages` table with a `source` tag, so `dialog_search()` finds
177
- matches regardless of where the conversation happened. Claude Desktop
178
- and the VS Code adapter are the exceptions — MCP registration only;
179
- their chats don't reach the table for now (Electron IndexedDB on the
180
- Claude Desktop side; per-extension stores on the VS Code side).
181
+ matches regardless of where the conversation happened. Claude Desktop,
182
+ Antigravity CLI, and the VS Code adapter are the exceptions — MCP registration
183
+ only; their chats don't reach the table for now (Electron IndexedDB on the
184
+ Claude Desktop side; sqlite/protobuf on the Antigravity side; per-extension
185
+ stores on the VS Code side).
181
186
 
182
187
  VS Code's user-level `mcp.json` is the central host that **every
183
188
  MCP-aware VS Code extension** consumes — GitHub Copilot Chat, the
@@ -234,7 +239,12 @@ memory button, self-restarts when its own RSS crosses
234
239
  notification permission, and sends a notification when a newly completed
235
240
  autonomous child task produces a useful result in `recent_results`; the first
236
241
  poll only marks existing results as seen, so old completions do not spam
237
- notifications. Probe backlog is due objective
242
+ notifications. The header gear opens a separate Settings window for
243
+ `~/.threadkeeper/.env`: common knobs are grouped into guided controls, the raw
244
+ `.env` remains editable for advanced values, three local presets can be saved
245
+ and loaded, and Save & Restart writes the file then asks existing
246
+ `threadkeeper.server` processes to exit so MCP hosts reconnect with the new
247
+ configuration. Probe backlog is due objective
238
248
  probes only, not every registered probe, so a healthy cooldown shows `0 due
239
249
  probes` instead of looking stuck. On macOS, `python -m threadkeeper.server`
240
250
  automatically installs and launches it on MCP startup, and restarts the app when
@@ -323,16 +333,19 @@ shows agents focused on their primary task rarely do).
323
333
  | 2 | shadow_review daemon | every 15 min (env knob) | recent `dialog_messages` window | SKILL.md, lessons.md |
324
334
  | 3 | extract daemon | every 10 min (env knob) | recent `dialog_messages` window | `extract_candidates` pending queue |
325
335
  | 4 | candidate-reviewer daemon | every 1 h (env knob) | pending candidates queue | SKILL.md (create/patch) / notes / verbatim / reject |
326
- | 5 | Curator daemon | every 7 days (env knob) | every existing lesson + recently-touched skill | REPORT-`<date>`.md; Evolve applier applies the latest complete report |
327
- | 6 | dialectic_miner daemon | configurable (env knob; 0=off) | recent `dialog_messages` user replies + preceding-assistant context | `dialectic_observations` buffer |
328
- | 7 | dialectic_validator daemon | configurable (env knob; 0=off) | buffered `dialectic_observations` | dialectic claims + evidence (support / contradict / supersede) via spawned opus child |
336
+ | 5 | Curator daemon | every 7 days (env knob) | every existing lesson + recently-touched skill | `REPORT-<date>.md`; Evolve applier applies it after roadmap issues |
337
+ | 6 | evolve_reviewer daemon | configurable (env knob; 0=off) | code/docs/issues + web research when useful | roadmap updates + GitHub issues |
338
+ | 7 | evolve_applier daemon | configurable (env knob; 0=off) | open GitHub issues, Curator reports, legacy promoted evolve suggestions | PRs + applied markers |
339
+ | 8 | dialectic_miner daemon | configurable (env knob; 0=off) | recent `dialog_messages` — user replies + preceding-assistant context | `dialectic_observations` buffer |
340
+ | 9 | dialectic_validator daemon | configurable (env knob; 0=off) | buffered `dialectic_observations` | dialectic claims + evidence (support / contradict / supersede) via spawned opus child |
329
341
 
330
- All five write into the universal Skill format (`SKILL.md` under each
342
+ Learning loops write into the universal Skill format (`SKILL.md` under each
331
343
  known/configured skills root — `~/.claude/skills/`, `~/.codex/skills/`,
332
- existing `~/.agents/skills/`, optional `THREADKEEPER_EXTRA_SKILLS_DIRS`,
333
- plus the canonical `~/.threadkeeper/skills/` mirror), with
334
- `~/.threadkeeper/lessons.md` as a CLI-agnostic fallback for clients
335
- without a native skills loader (Gemini, Copilot, bare MCP).
344
+ `~/.gemini/config/skills/` for Antigravity, existing `~/.agents/skills/`,
345
+ optional `THREADKEEPER_EXTRA_SKILLS_DIRS`, plus the canonical
346
+ `~/.threadkeeper/skills/` mirror), with `~/.threadkeeper/lessons.md` as a
347
+ CLI-agnostic fallback for clients without a native skills loader (Gemini
348
+ legacy, Copilot, bare MCP).
336
349
 
337
350
  #### 1. Auto-review on close_thread
338
351
 
@@ -420,56 +433,63 @@ entries are marked `[PROTECTED]` in the inventory so the curator
420
433
  never proposes destructive changes against them.
421
434
 
422
435
  Curator itself stays advisory-only by default. The existing Evolve applier is
423
- the apply worker: on its next pass it first looks for the latest complete
424
- Curator report (`CURATOR_PASS_COMPLETE`) that has not been marked applied, then
425
- spawns an `evolve_applier` child to apply only safe, still-current memory
426
- maintenance through `lesson_append` / `lesson_remove` / `skill_manage`. It never
427
- touches `[PROTECTED]`, foreground/user, pinned, or validated entries. Only after
428
- the child finishes does it call `evolve_mark_curator_report_applied(...)`, which
429
- prevents replaying the same report.
430
-
431
- #### 6. Evolve applier — code evolution + curator report apply
432
-
433
- The brief format is not fixed: any session can file a change to it with
434
- `evolve_format(suggestion, rationale)`. The `evolve_reviewer` daemon triages
435
- the queue and **promotes** the good ones promoted suggestions surface in the
436
- brief with a ★. Until now that's where it stopped: a human had to hand-edit
437
- `render_brief` in `brief.py`.
438
-
439
- `evolve_apply(evolve_id)` closes the loop. It spawns an `evolve_applier` child
440
- (resolved through the normal spawn role/model config — recommend opus, it
441
- writes code) that:
442
-
443
- 1. edits `render_brief()` to implement the suggestion;
444
- 2. adds/extends a **golden brief test** asserting both that the new
445
- behavior/field appears *and* that the existing brief sections still render —
446
- a format change can't silently break the brief;
447
- 3. runs the full suite (`.venv/bin/python -m pytest -q`) until green;
448
- 4. opens a **pull request** on a feature branch via `gh`, body quoting the
449
- suggestion + rationale. The generated commit and PR title use the repo's
450
- allowed Conventional Commit types (`feat:`/`fix:` etc.), never the internal
451
- `evolve:` label.
452
-
453
- **Autonomy is the PR gate, nothing more.** The child never pushes or commits to
454
- `main` (which has branch protection); a human reviews and merges. On a
455
- successful PR the child calls `evolve_mark_applied(evolve_id, pr_url)`, which
456
- sets `applied=1` so the suggestion stops resurfacing. Validation inside the
457
- child (golden render_brief test + full suite green) is the objective gate the
458
- loop otherwise lacks.
459
-
460
- The same applier role also drains Curator reports. `evolve_apply_curator_report`
461
- manually applies the latest complete report, or a specific report path. This
462
- path does **not** edit code or open a PR; it uses memory MCP tools only and
463
- marks the report applied with `evolve_mark_curator_report_applied(...)`.
464
-
465
- Manual: `evolve_apply(#id)` (get ids from `evolve_review()`). Optional daemon:
466
- set `THREADKEEPER_EVOLVE_APPLY_INTERVAL_S>0` (default 0 = off) to periodically
467
- apply the latest complete Curator report first, then implement the oldest
468
- promoted+unapplied suggestion. Pin the agent/model with
469
- `THREADKEEPER_SPAWN__LOOP__EVOLVE_APPLIER` /
436
+ also the Curator apply worker: after the roadmap issue queue is empty, it looks
437
+ for the latest complete Curator report (`CURATOR_PASS_COMPLETE`) that has not
438
+ been marked applied, then spawns an `evolve_applier` child to apply only safe,
439
+ still-current memory maintenance through `lesson_append` / `lesson_remove` /
440
+ `skill_manage`. It never touches `[PROTECTED]`, foreground/user, pinned, or
441
+ validated entries. Only after the child finishes does it call
442
+ `evolve_mark_curator_report_applied(...)`, which prevents replaying the same
443
+ report.
444
+
445
+ Curator can also feed the roadmap loop upstream: when a skill or lesson exposes
446
+ an important way to improve thread-keeper itself, the curator child may call
447
+ `evolve_format(...)` and add an `EVOLVE_CANDIDATE:` line to its report. Evolve
448
+ reviewer then audits that candidate and turns it into a GitHub issue when it is
449
+ worth doing.
450
+
451
+ #### 6. Evolve reviewer/applier — roadmap evolution loop
452
+
453
+ The Evolve reviewer is thread-keeper's upstream product/engineering auditor. On
454
+ its interval it audits thread-keeper itself for security/privacy risks, memory
455
+ leaks, runaway daemons, cost waste, reliability gaps, optimizations, and new
456
+ ideas from current agent/MCP/memory tooling research. It does **not** implement
457
+ code. Its durable outputs are updates to `docs/ROADMAP.md` and GitHub issues
458
+ with problem statement, proposed direction, acceptance criteria, test/docs
459
+ impact, and research sources when applicable. Legacy `evolve_format(...)`
460
+ suggestions are still included as audit input, but durable implementation work
461
+ should become GitHub issues.
462
+
463
+ The Evolve applier is the downstream implementer. `evolve_apply_roadmap_issue()`
464
+ picks one open GitHub issue at a time (`roadmap` label first, then FIFO), skips
465
+ issues with an active Evolve claim comment, posts its own claim comment before
466
+ spawning, and advances to the next issue when an issue-local dispatch failure
467
+ prevents startup. The child implements exactly that issue, runs the full suite,
468
+ opens a PR whose body includes `Closes #N`, and only then calls
469
+ `evolve_mark_roadmap_issue_applied(issue_number, pr_url)`. It never commits or
470
+ pushes to `main`, and it never marks an issue applied without a real PR URL. A
471
+ manual `evolve_apply_roadmap_issue(issue_number=N)` remains exact: it reports
472
+ why that issue cannot start instead of silently switching to another issue.
473
+
474
+ Fallback/manual paths remain:
475
+
476
+ - `evolve_apply_curator_report(report_path="")` applies safe Curator memory
477
+ maintenance when no roadmap issue is being drained.
478
+ - `evolve_apply(evolve_id)` still implements legacy promoted
479
+ `evolve_format(...)` suggestions behind a PR and calls
480
+ `evolve_mark_applied(evolve_id, pr_url)`.
481
+
482
+ Set `THREADKEEPER_EVOLVE_REVIEW_INTERVAL_S>0` to run periodic audit/research
483
+ passes and `THREADKEEPER_EVOLVE_APPLY_INTERVAL_S>0` to drain one issue per pass.
484
+ Pin the agent/model with `THREADKEEPER_SPAWN__LOOP__EVOLVE_APPLIER` /
470
485
  `THREADKEEPER_SPAWN__MODEL__EVOLVE_APPLIER`. Single-flight (one applier child at
471
486
  a time, enforced by a short dispatch file lock plus running-task detection)
472
487
  keeps code edits and memory maintenance from colliding.
488
+ Automatic apply passes respect the configured interval so multiple foreground
489
+ MCP server startups do not repeatedly spawn workers for the same open issue.
490
+ Manual tools such as `evolve_apply_roadmap_issue()` dispatch immediately. If no
491
+ roadmap issue is startable, the pass falls back to Curator reports and then
492
+ legacy promoted `evolve_format(...)` suggestions.
473
493
 
474
494
  #### Honest take
475
495
 
@@ -586,12 +606,14 @@ The most-used env knobs (full list in `threadkeeper/config.py`):
586
606
  | `THREADKEEPER_DIALECTIC_VALIDATE_INTERVAL_S` | 0 (off) | dialectic_validator daemon tick (s); 0 disables LLM-driven claim synthesis |
587
607
  | `THREADKEEPER_DIALECTIC_VALIDATE_MIN` | 5 | min buffered observations before validator engages |
588
608
  | `THREADKEEPER_DIALECTIC_VALIDATE_BATCH_SIZE` | 50 | max observations sent to one validator child; prevents oversized prompts and drains large queues incrementally |
589
- | `THREADKEEPER_EVOLVE_REVIEW_INTERVAL_S` | 0 (off) | evolve-reviewer daemon tick (s); triages the format-evolution queue (promote/dismiss) |
590
- | `THREADKEEPER_EVOLVE_APPLY_INTERVAL_S` | 0 (off) | evolve-applier daemon tick (s); applies latest complete Curator report first, then oldest promoted+unapplied suggestion behind a PR. Manual `evolve_apply` / `evolve_apply_curator_report` work regardless |
609
+ | `THREADKEEPER_EVOLVE_REVIEW_INTERVAL_S` | 0 (off) | evolve-reviewer daemon tick (s); audits thread-keeper for safety/leaks/optimization/new ideas, researches current approaches, updates roadmap/issues, and includes legacy evolve suggestions as input |
610
+ | `THREADKEEPER_EVOLVE_APPLY_INTERVAL_S` | 0 (off) | evolve-applier daemon tick (s); implements one open GitHub issue at a time, then falls back to Curator reports and promoted legacy evolve suggestions. Empty checks are throttled between intervals; actionable work and manual apply tools still dispatch |
591
611
  | `THREADKEEPER_DIALECTIC_MAX_NEW_CLAIMS` | 3 | max new dialectic claims the validator may create per pass |
592
612
 
593
613
  Persist them in `~/.threadkeeper/.env` (copy from `.env.example`) — one file,
594
- read via pydantic-settings; real environment variables still override it.
614
+ read via pydantic-settings; real environment variables still override it. On
615
+ macOS, the menu-bar app's gear button can edit the same file visually, save up
616
+ to three local presets, and request a ThreadKeeper restart after saving.
595
617
  Hot-config reload is
596
618
  [tracked](https://github.com/po4erk91/thread-keeper/issues/2).
597
619
 
@@ -622,7 +644,8 @@ THREADKEEPER_SPAWN__MODEL__DIALECTIC_VALIDATOR=opus
622
644
  Resolution per role: `SPAWN__LOOP__<role>` → `SPAWN__DEFAULT` → active CLI →
623
645
  `claude`; `"auto"` (or unset) defers to the active CLI. Real environment
624
646
  variables override the `.env`. Force host detection with
625
- `THREADKEEPER_ACTIVE_CLI=claude`. See `.env.example` for the full knob list.
647
+ `THREADKEEPER_ACTIVE_CLI=claude` (or `codex`, `antigravity`/`agy`,
648
+ `gemini`, `copilot`). See `.env.example` for the full knob list.
626
649
 
627
650
  Adapters without headless support (Claude Desktop, VS Code) can't be
628
651
  spawn targets — `spawn_status()` reports them as "no adapter" and any
@@ -760,6 +783,7 @@ threadkeeper/
760
783
  │ ├── claude_code.py
761
784
  │ ├── claude_desktop.py
762
785
  │ ├── codex.py
786
+ │ ├── antigravity.py
763
787
  │ ├── gemini.py
764
788
  │ ├── copilot.py
765
789
  │ └── vscode.py
@@ -4,17 +4,17 @@
4
4
  [![Python](https://img.shields.io/badge/python-3.11%2B-blue)](https://www.python.org/downloads/)
5
5
  [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](LICENSE)
6
6
  [![PyPI](https://img.shields.io/pypi/v/threadkeeper.svg)](https://pypi.org/project/threadkeeper/)
7
- [![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)
7
+ [![CLIs](https://img.shields.io/badge/CLIs-Claude%20%7C%20Codex%20%7C%20Antigravity%20%7C%20Gemini%20legacy%20%7C%20Copilot%20%7C%20VS%20Code-green)](#multi-cli-integration)
8
8
 
9
- **Multi-agent shared brain across Claude Code/Desktop, Codex, Gemini,
10
- Copilot, and VS Code.** Cross-session memory, self-improving skill
11
- loops, and inter-agent signaling — one local MCP server turns parallel
12
- agent instances into a coordinated multi-agent system instead of N
13
- isolated chats.
9
+ **Multi-agent shared brain across Claude Code/Desktop, Codex,
10
+ Antigravity CLI (`agy`), Gemini legacy, Copilot, and VS Code.**
11
+ Cross-session memory, self-improving skill loops, and inter-agent signaling —
12
+ one local MCP server turns parallel agent instances into a coordinated
13
+ multi-agent system instead of N isolated chats.
14
14
 
15
- Every connected client (Claude Code, Claude Desktop, Codex CLI +
16
- desktop, Gemini, Copilot, every MCP-aware VS Code extension) shares
17
- one SQLite store, one set of threads, one user model, and one learning
15
+ Every connected client (Claude Code, Claude Desktop, Codex CLI + desktop,
16
+ Antigravity CLI, Gemini legacy, Copilot, every MCP-aware VS Code extension)
17
+ shares one SQLite store, one set of threads, one user model, and one learning
18
18
  loop that improves the skill library autonomously over time.
19
19
 
20
20
  The brief format is dense — structural tags, opaque IDs, ~6 KB per
@@ -26,7 +26,7 @@ session-start injection. Optimized for agent consumption, not human reading.
26
26
 
27
27
  Every agent CLI starts cold. Context dies at session boundaries.
28
28
  Skills you taught Claude don't transfer to Codex. Threads you closed
29
- in yesterday's Gemini chat are invisible to today's Copilot. Parallel
29
+ in yesterday's Antigravity chat are invisible to today's Copilot. Parallel
30
30
  agent instances running the same task don't know about each other and
31
31
  duplicate work or step on each other's writes.
32
32
 
@@ -51,9 +51,10 @@ make it more than a memory store:
51
51
  materialize class-level skills as the agents work. Adapted to multi-CLI:
52
52
  SKILL.md is the primary write target and gets mirrored to every
53
53
  known/configured skills root simultaneously (`~/.claude/skills/`,
54
- `~/.codex/skills/`, existing `~/.agents/skills/`, extra roots from
55
- `THREADKEEPER_EXTRA_SKILLS_DIRS`, and `~/.threadkeeper/skills/`),
56
- with lessons.md as a fallback for CLIs without a native skills loader.
54
+ `~/.codex/skills/`, `~/.gemini/config/skills/` for Antigravity,
55
+ existing `~/.agents/skills/`, extra roots from
56
+ `THREADKEEPER_EXTRA_SKILLS_DIRS`, and `~/.threadkeeper/skills/`), with
57
+ lessons.md as a fallback for CLIs without a native skills loader.
57
58
 
58
59
  Foreground MCP servers also run a daily self-update check by default. Source
59
60
  checkouts fast-forward their tracked git branch and reinstall the editable
@@ -72,15 +73,17 @@ pipx install 'threadkeeper[semantic]' && thread-keeper-setup
72
73
  ```
73
74
 
74
75
  `thread-keeper-setup` detects every CLI you have installed (Claude
75
- Code / Claude Desktop / Codex CLI + desktop / Gemini / Copilot / VS
76
- Code), registers the MCP server in each one's config, copies hooks to
76
+ Code / Claude Desktop / Codex CLI + desktop / Antigravity CLI `agy` /
77
+ Gemini legacy / Copilot / VS Code), registers the MCP server in each one's
78
+ config, copies hooks to
77
79
  `~/.threadkeeper/hooks/`, and writes a managed instructions block into
78
80
  each CLI's per-user instructions file (`CLAUDE.md` / `AGENTS.md` /
79
81
  `GEMINI.md` / `copilot-instructions.md` — Claude Desktop and VS Code
80
82
  have no global instructions file, so that step is skipped for them).
81
83
 
82
- Restart your CLI of choice. The SessionStart hook injects a brief on
83
- first message; no manual `brief()` call required.
84
+ Restart your CLI of choice. Hook-capable clients inject a brief on the first
85
+ message; hookless clients such as Codex and Antigravity CLI follow the managed
86
+ instructions block and call `brief()` / `context()` manually before answering.
84
87
 
85
88
  ### Alternative installs
86
89
 
@@ -127,16 +130,18 @@ thread-keeper-setup --dry-run
127
130
  | Claude Code | `~/.claude.json` `mcpServers` | `~/.claude/CLAUDE.md` | `~/.claude/settings.json` `hooks` | `~/.claude/projects/**/*.jsonl` |
128
131
  | 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 |
129
132
  | Codex (CLI + desktop) | `~/.codex/config.toml` `[mcp_servers]` (shared between CLI and `Codex.app`) | `~/.codex/AGENTS.md` | not supported | `~/.codex/sessions/**/rollout-*.jsonl` |
130
- | Gemini | `~/.gemini/settings.json` `mcpServers` | `~/.gemini/GEMINI.md` | `~/.gemini/settings.json` `hooks` | `~/.gemini/tmp/<user>/chats/session-*.jsonl` |
133
+ | Antigravity CLI (`agy`) | `~/.gemini/config/mcp_config.json` `mcpServers` | `~/.gemini/config/AGENTS.md` | not wired yet | not yet parsed — sqlite/protobuf under `~/.gemini/antigravity-cli/conversations/*.db` |
134
+ | Gemini legacy | `~/.gemini/settings.json` `mcpServers` | `~/.gemini/GEMINI.md` | `~/.gemini/settings.json` `hooks` | `~/.gemini/tmp/<user>/chats/session-*.jsonl` |
131
135
  | Copilot | `~/.copilot/mcp-config.json` `mcpServers` | `~/.copilot/copilot-instructions.md` | `~/.copilot/hooks.json` | `~/.copilot/session-store.db` (sqlite) |
132
136
  | 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 |
133
137
 
134
138
  Every CLI that produces parseable transcripts feeds the same
135
139
  `dialog_messages` table with a `source` tag, so `dialog_search()` finds
136
- matches regardless of where the conversation happened. Claude Desktop
137
- and the VS Code adapter are the exceptions — MCP registration only;
138
- their chats don't reach the table for now (Electron IndexedDB on the
139
- Claude Desktop side; per-extension stores on the VS Code side).
140
+ matches regardless of where the conversation happened. Claude Desktop,
141
+ Antigravity CLI, and the VS Code adapter are the exceptions — MCP registration
142
+ only; their chats don't reach the table for now (Electron IndexedDB on the
143
+ Claude Desktop side; sqlite/protobuf on the Antigravity side; per-extension
144
+ stores on the VS Code side).
140
145
 
141
146
  VS Code's user-level `mcp.json` is the central host that **every
142
147
  MCP-aware VS Code extension** consumes — GitHub Copilot Chat, the
@@ -193,7 +198,12 @@ memory button, self-restarts when its own RSS crosses
193
198
  notification permission, and sends a notification when a newly completed
194
199
  autonomous child task produces a useful result in `recent_results`; the first
195
200
  poll only marks existing results as seen, so old completions do not spam
196
- notifications. Probe backlog is due objective
201
+ notifications. The header gear opens a separate Settings window for
202
+ `~/.threadkeeper/.env`: common knobs are grouped into guided controls, the raw
203
+ `.env` remains editable for advanced values, three local presets can be saved
204
+ and loaded, and Save & Restart writes the file then asks existing
205
+ `threadkeeper.server` processes to exit so MCP hosts reconnect with the new
206
+ configuration. Probe backlog is due objective
197
207
  probes only, not every registered probe, so a healthy cooldown shows `0 due
198
208
  probes` instead of looking stuck. On macOS, `python -m threadkeeper.server`
199
209
  automatically installs and launches it on MCP startup, and restarts the app when
@@ -282,16 +292,19 @@ shows agents focused on their primary task rarely do).
282
292
  | 2 | shadow_review daemon | every 15 min (env knob) | recent `dialog_messages` window | SKILL.md, lessons.md |
283
293
  | 3 | extract daemon | every 10 min (env knob) | recent `dialog_messages` window | `extract_candidates` pending queue |
284
294
  | 4 | candidate-reviewer daemon | every 1 h (env knob) | pending candidates queue | SKILL.md (create/patch) / notes / verbatim / reject |
285
- | 5 | Curator daemon | every 7 days (env knob) | every existing lesson + recently-touched skill | REPORT-`<date>`.md; Evolve applier applies the latest complete report |
286
- | 6 | dialectic_miner daemon | configurable (env knob; 0=off) | recent `dialog_messages` user replies + preceding-assistant context | `dialectic_observations` buffer |
287
- | 7 | dialectic_validator daemon | configurable (env knob; 0=off) | buffered `dialectic_observations` | dialectic claims + evidence (support / contradict / supersede) via spawned opus child |
295
+ | 5 | Curator daemon | every 7 days (env knob) | every existing lesson + recently-touched skill | `REPORT-<date>.md`; Evolve applier applies it after roadmap issues |
296
+ | 6 | evolve_reviewer daemon | configurable (env knob; 0=off) | code/docs/issues + web research when useful | roadmap updates + GitHub issues |
297
+ | 7 | evolve_applier daemon | configurable (env knob; 0=off) | open GitHub issues, Curator reports, legacy promoted evolve suggestions | PRs + applied markers |
298
+ | 8 | dialectic_miner daemon | configurable (env knob; 0=off) | recent `dialog_messages` — user replies + preceding-assistant context | `dialectic_observations` buffer |
299
+ | 9 | dialectic_validator daemon | configurable (env knob; 0=off) | buffered `dialectic_observations` | dialectic claims + evidence (support / contradict / supersede) via spawned opus child |
288
300
 
289
- All five write into the universal Skill format (`SKILL.md` under each
301
+ Learning loops write into the universal Skill format (`SKILL.md` under each
290
302
  known/configured skills root — `~/.claude/skills/`, `~/.codex/skills/`,
291
- existing `~/.agents/skills/`, optional `THREADKEEPER_EXTRA_SKILLS_DIRS`,
292
- plus the canonical `~/.threadkeeper/skills/` mirror), with
293
- `~/.threadkeeper/lessons.md` as a CLI-agnostic fallback for clients
294
- without a native skills loader (Gemini, Copilot, bare MCP).
303
+ `~/.gemini/config/skills/` for Antigravity, existing `~/.agents/skills/`,
304
+ optional `THREADKEEPER_EXTRA_SKILLS_DIRS`, plus the canonical
305
+ `~/.threadkeeper/skills/` mirror), with `~/.threadkeeper/lessons.md` as a
306
+ CLI-agnostic fallback for clients without a native skills loader (Gemini
307
+ legacy, Copilot, bare MCP).
295
308
 
296
309
  #### 1. Auto-review on close_thread
297
310
 
@@ -379,56 +392,63 @@ entries are marked `[PROTECTED]` in the inventory so the curator
379
392
  never proposes destructive changes against them.
380
393
 
381
394
  Curator itself stays advisory-only by default. The existing Evolve applier is
382
- the apply worker: on its next pass it first looks for the latest complete
383
- Curator report (`CURATOR_PASS_COMPLETE`) that has not been marked applied, then
384
- spawns an `evolve_applier` child to apply only safe, still-current memory
385
- maintenance through `lesson_append` / `lesson_remove` / `skill_manage`. It never
386
- touches `[PROTECTED]`, foreground/user, pinned, or validated entries. Only after
387
- the child finishes does it call `evolve_mark_curator_report_applied(...)`, which
388
- prevents replaying the same report.
389
-
390
- #### 6. Evolve applier — code evolution + curator report apply
391
-
392
- The brief format is not fixed: any session can file a change to it with
393
- `evolve_format(suggestion, rationale)`. The `evolve_reviewer` daemon triages
394
- the queue and **promotes** the good ones promoted suggestions surface in the
395
- brief with a ★. Until now that's where it stopped: a human had to hand-edit
396
- `render_brief` in `brief.py`.
397
-
398
- `evolve_apply(evolve_id)` closes the loop. It spawns an `evolve_applier` child
399
- (resolved through the normal spawn role/model config — recommend opus, it
400
- writes code) that:
401
-
402
- 1. edits `render_brief()` to implement the suggestion;
403
- 2. adds/extends a **golden brief test** asserting both that the new
404
- behavior/field appears *and* that the existing brief sections still render —
405
- a format change can't silently break the brief;
406
- 3. runs the full suite (`.venv/bin/python -m pytest -q`) until green;
407
- 4. opens a **pull request** on a feature branch via `gh`, body quoting the
408
- suggestion + rationale. The generated commit and PR title use the repo's
409
- allowed Conventional Commit types (`feat:`/`fix:` etc.), never the internal
410
- `evolve:` label.
411
-
412
- **Autonomy is the PR gate, nothing more.** The child never pushes or commits to
413
- `main` (which has branch protection); a human reviews and merges. On a
414
- successful PR the child calls `evolve_mark_applied(evolve_id, pr_url)`, which
415
- sets `applied=1` so the suggestion stops resurfacing. Validation inside the
416
- child (golden render_brief test + full suite green) is the objective gate the
417
- loop otherwise lacks.
418
-
419
- The same applier role also drains Curator reports. `evolve_apply_curator_report`
420
- manually applies the latest complete report, or a specific report path. This
421
- path does **not** edit code or open a PR; it uses memory MCP tools only and
422
- marks the report applied with `evolve_mark_curator_report_applied(...)`.
423
-
424
- Manual: `evolve_apply(#id)` (get ids from `evolve_review()`). Optional daemon:
425
- set `THREADKEEPER_EVOLVE_APPLY_INTERVAL_S>0` (default 0 = off) to periodically
426
- apply the latest complete Curator report first, then implement the oldest
427
- promoted+unapplied suggestion. Pin the agent/model with
428
- `THREADKEEPER_SPAWN__LOOP__EVOLVE_APPLIER` /
395
+ also the Curator apply worker: after the roadmap issue queue is empty, it looks
396
+ for the latest complete Curator report (`CURATOR_PASS_COMPLETE`) that has not
397
+ been marked applied, then spawns an `evolve_applier` child to apply only safe,
398
+ still-current memory maintenance through `lesson_append` / `lesson_remove` /
399
+ `skill_manage`. It never touches `[PROTECTED]`, foreground/user, pinned, or
400
+ validated entries. Only after the child finishes does it call
401
+ `evolve_mark_curator_report_applied(...)`, which prevents replaying the same
402
+ report.
403
+
404
+ Curator can also feed the roadmap loop upstream: when a skill or lesson exposes
405
+ an important way to improve thread-keeper itself, the curator child may call
406
+ `evolve_format(...)` and add an `EVOLVE_CANDIDATE:` line to its report. Evolve
407
+ reviewer then audits that candidate and turns it into a GitHub issue when it is
408
+ worth doing.
409
+
410
+ #### 6. Evolve reviewer/applier — roadmap evolution loop
411
+
412
+ The Evolve reviewer is thread-keeper's upstream product/engineering auditor. On
413
+ its interval it audits thread-keeper itself for security/privacy risks, memory
414
+ leaks, runaway daemons, cost waste, reliability gaps, optimizations, and new
415
+ ideas from current agent/MCP/memory tooling research. It does **not** implement
416
+ code. Its durable outputs are updates to `docs/ROADMAP.md` and GitHub issues
417
+ with problem statement, proposed direction, acceptance criteria, test/docs
418
+ impact, and research sources when applicable. Legacy `evolve_format(...)`
419
+ suggestions are still included as audit input, but durable implementation work
420
+ should become GitHub issues.
421
+
422
+ The Evolve applier is the downstream implementer. `evolve_apply_roadmap_issue()`
423
+ picks one open GitHub issue at a time (`roadmap` label first, then FIFO), skips
424
+ issues with an active Evolve claim comment, posts its own claim comment before
425
+ spawning, and advances to the next issue when an issue-local dispatch failure
426
+ prevents startup. The child implements exactly that issue, runs the full suite,
427
+ opens a PR whose body includes `Closes #N`, and only then calls
428
+ `evolve_mark_roadmap_issue_applied(issue_number, pr_url)`. It never commits or
429
+ pushes to `main`, and it never marks an issue applied without a real PR URL. A
430
+ manual `evolve_apply_roadmap_issue(issue_number=N)` remains exact: it reports
431
+ why that issue cannot start instead of silently switching to another issue.
432
+
433
+ Fallback/manual paths remain:
434
+
435
+ - `evolve_apply_curator_report(report_path="")` applies safe Curator memory
436
+ maintenance when no roadmap issue is being drained.
437
+ - `evolve_apply(evolve_id)` still implements legacy promoted
438
+ `evolve_format(...)` suggestions behind a PR and calls
439
+ `evolve_mark_applied(evolve_id, pr_url)`.
440
+
441
+ Set `THREADKEEPER_EVOLVE_REVIEW_INTERVAL_S>0` to run periodic audit/research
442
+ passes and `THREADKEEPER_EVOLVE_APPLY_INTERVAL_S>0` to drain one issue per pass.
443
+ Pin the agent/model with `THREADKEEPER_SPAWN__LOOP__EVOLVE_APPLIER` /
429
444
  `THREADKEEPER_SPAWN__MODEL__EVOLVE_APPLIER`. Single-flight (one applier child at
430
445
  a time, enforced by a short dispatch file lock plus running-task detection)
431
446
  keeps code edits and memory maintenance from colliding.
447
+ Automatic apply passes respect the configured interval so multiple foreground
448
+ MCP server startups do not repeatedly spawn workers for the same open issue.
449
+ Manual tools such as `evolve_apply_roadmap_issue()` dispatch immediately. If no
450
+ roadmap issue is startable, the pass falls back to Curator reports and then
451
+ legacy promoted `evolve_format(...)` suggestions.
432
452
 
433
453
  #### Honest take
434
454
 
@@ -545,12 +565,14 @@ The most-used env knobs (full list in `threadkeeper/config.py`):
545
565
  | `THREADKEEPER_DIALECTIC_VALIDATE_INTERVAL_S` | 0 (off) | dialectic_validator daemon tick (s); 0 disables LLM-driven claim synthesis |
546
566
  | `THREADKEEPER_DIALECTIC_VALIDATE_MIN` | 5 | min buffered observations before validator engages |
547
567
  | `THREADKEEPER_DIALECTIC_VALIDATE_BATCH_SIZE` | 50 | max observations sent to one validator child; prevents oversized prompts and drains large queues incrementally |
548
- | `THREADKEEPER_EVOLVE_REVIEW_INTERVAL_S` | 0 (off) | evolve-reviewer daemon tick (s); triages the format-evolution queue (promote/dismiss) |
549
- | `THREADKEEPER_EVOLVE_APPLY_INTERVAL_S` | 0 (off) | evolve-applier daemon tick (s); applies latest complete Curator report first, then oldest promoted+unapplied suggestion behind a PR. Manual `evolve_apply` / `evolve_apply_curator_report` work regardless |
568
+ | `THREADKEEPER_EVOLVE_REVIEW_INTERVAL_S` | 0 (off) | evolve-reviewer daemon tick (s); audits thread-keeper for safety/leaks/optimization/new ideas, researches current approaches, updates roadmap/issues, and includes legacy evolve suggestions as input |
569
+ | `THREADKEEPER_EVOLVE_APPLY_INTERVAL_S` | 0 (off) | evolve-applier daemon tick (s); implements one open GitHub issue at a time, then falls back to Curator reports and promoted legacy evolve suggestions. Empty checks are throttled between intervals; actionable work and manual apply tools still dispatch |
550
570
  | `THREADKEEPER_DIALECTIC_MAX_NEW_CLAIMS` | 3 | max new dialectic claims the validator may create per pass |
551
571
 
552
572
  Persist them in `~/.threadkeeper/.env` (copy from `.env.example`) — one file,
553
- read via pydantic-settings; real environment variables still override it.
573
+ read via pydantic-settings; real environment variables still override it. On
574
+ macOS, the menu-bar app's gear button can edit the same file visually, save up
575
+ to three local presets, and request a ThreadKeeper restart after saving.
554
576
  Hot-config reload is
555
577
  [tracked](https://github.com/po4erk91/thread-keeper/issues/2).
556
578
 
@@ -581,7 +603,8 @@ THREADKEEPER_SPAWN__MODEL__DIALECTIC_VALIDATOR=opus
581
603
  Resolution per role: `SPAWN__LOOP__<role>` → `SPAWN__DEFAULT` → active CLI →
582
604
  `claude`; `"auto"` (or unset) defers to the active CLI. Real environment
583
605
  variables override the `.env`. Force host detection with
584
- `THREADKEEPER_ACTIVE_CLI=claude`. See `.env.example` for the full knob list.
606
+ `THREADKEEPER_ACTIVE_CLI=claude` (or `codex`, `antigravity`/`agy`,
607
+ `gemini`, `copilot`). See `.env.example` for the full knob list.
585
608
 
586
609
  Adapters without headless support (Claude Desktop, VS Code) can't be
587
610
  spawn targets — `spawn_status()` reports them as "no adapter" and any
@@ -719,6 +742,7 @@ threadkeeper/
719
742
  │ ├── claude_code.py
720
743
  │ ├── claude_desktop.py
721
744
  │ ├── codex.py
745
+ │ ├── antigravity.py
722
746
  │ ├── gemini.py
723
747
  │ ├── copilot.py
724
748
  │ └── vscode.py
@@ -4,8 +4,8 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "threadkeeper"
7
- version = "0.10.0"
8
- description = "Multi-agent shared brain across Claude Code/Desktop, Codex, Gemini, Copilot, VS Code. Cross-session memory, self-improving skill loops, inter-agent signaling — one local MCP server."
7
+ version = "0.12.0"
8
+ description = "Multi-agent shared brain across Claude Code/Desktop, Codex, Antigravity CLI, Gemini, Copilot, VS Code. Cross-session memory, self-improving skill loops, inter-agent signaling — one local MCP server."
9
9
  requires-python = ">=3.11"
10
10
  authors = [{ name = "thread-keeper contributors" }]
11
11
  license = { text = "MIT" }