@jeffober/thatch 0.1.9 → 0.1.10

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -2,18 +2,23 @@
2
2
 
3
3
  [![CI](https://github.com/sysread/thatch/actions/workflows/ci.yml/badge.svg)](https://github.com/sysread/thatch/actions/workflows/ci.yml)
4
4
 
5
- Persistent memory and operational methodology for AI coding agents — local
6
- embeddings, SQLite stores, zero config.
5
+ ## Synopsis
6
+
7
+ Persistent memory and useful dev skills for AI coding agents that requires zero
8
+ manual config.
7
9
 
8
10
  Works with **OpenCode** (as a plugin), **Claude Code** (as an MCP server), and
9
11
  **Cursor** (as an MCP server).
12
+
10
13
  Each session inherits the accumulated knowledge of every session before it —
11
14
  project architecture, conventions, gotchas, user preferences — so your agent
12
- starts with context instead of a blank slate. Stores are per-repo with a
13
- shared `global` store. On top of the memory layer, thatch ships a suite of
14
- skills that prime, maintain, and reflect on memory, plus a structured
15
- multi-agent code review framework. No API keys, no cloud services —
16
- everything runs on your machine.
15
+ starts with context instead of a blank slate. Stores are per-repo with a shared
16
+ `global` store.
17
+
18
+ On top of the memory layer, thatch ships a suite of skills for managing memories,
19
+ performing in-depth, structured code reviews, and researching your code base.
20
+
21
+ No API keys, no cloud services; everything runs on your machine.
17
22
 
18
23
  ## Quick start
19
24
 
@@ -118,6 +123,8 @@ agent follows to maintain its own memory and review code systematically.
118
123
  | `thatch-review-no-slop` | AI writing anti-pattern detection — change narration, fourth wall breaks, hedging |
119
124
  | `thatch-review-breadcrumbs` | Comment narrative — do comments form a coherent outline of the code's behavior? |
120
125
  | `thatch-review-synthesizer` | Verify specialist findings against actual code, deduplicate, produce severity-grouped report |
126
+ | `thatch-review-context` | Gather project/feature context (PRs, tickets, TODOs, deferred work) before a review |
127
+ | `thatch-workflow-research` | Research code workflows affected by a change or planned change, before reviewing or planning |
121
128
  | `thatch-code-review` | Multi-agent review coordinator — triage, partition, dispatch specialists in parallel (opencode only) |
122
129
 
123
130
  The five review specialists run independently and can be used standalone. The
@@ -142,7 +149,7 @@ thatch prime Prime project memory (runs via opencode or clau
142
149
  thatch mcp Start the stdio MCP server (for Claude Code)
143
150
  thatch reminder Print session-start reminder (for hooks)
144
151
  thatch hygiene Print the hygiene report (standalone)
145
- thatch setup --claude [--global] Install config + instructions + hooks + skills
152
+ thatch setup --claude [--cursor] [--global] Install config + instructions + hooks + skills
146
153
  ```
147
154
 
148
155
  Stores default to the repo detected from `git remote`. Use `global` for the
@@ -190,17 +197,18 @@ buffer and flush. On Claude Code, `PostToolBatch` and `UserPromptSubmit`
190
197
  hooks drive a file-backed queue. Both paths produce the same payload for the
191
198
  fact-extractor skill.
192
199
 
193
- ## OpenCode vs Claude Code parity
194
-
195
- | Feature | OpenCode (plugin) | Claude Code (MCP + hooks) |
196
- |---------|-------------------|--------------------------|
197
- | Tools | Plugin tool registration | MCP `tools/list` + `tools/call` |
198
- | System prompt | Injected at runtime with repo name | Static CLAUDE.md (repo auto-detected by MCP server) |
199
- | Session-start reminder | `session.created` event | `SessionStart` hook → `thatch reminder` |
200
- | Compaction context | `experimental.session.compacting` hook | **Gap**: no equivalent (CLAUDE.md persists through compaction) |
201
- | Extraction nudge | `tool.execute.after` + `chat.message` | `PostToolBatch` + `UserPromptSubmit` (file-backed queue) |
202
- | Skills | `$XDG_CONFIG_HOME/opencode/skills` | `~/.claude/skills/` |
203
- | Store detection | `worktree` param from plugin | `CLAUDE_PROJECT_DIR` env var |
200
+ ## OpenCode vs Claude Code vs Cursor parity
201
+
202
+ | Feature | OpenCode (plugin) | Claude Code (MCP + hooks) | Cursor (MCP + hooks) |
203
+ |---------|-------------------|--------------------------|---------------------|
204
+ | Tools | Plugin tool registration | MCP `tools/list` + `tools/call` | MCP `tools/list` + `tools/call` |
205
+ | System prompt | Injected at runtime with repo name | Static CLAUDE.md (repo auto-detected by MCP server) | Static AGENTS.md (repo auto-detected at startup) |
206
+ | Session-start reminder | `session.created` event | `SessionStart` hook → `thatch reminder` | `sessionStart` hook → `thatch reminder --json` |
207
+ | Compaction context | `experimental.session.compacting` hook | **Gap**: no equivalent (CLAUDE.md persists) | **Gap**: no equivalent |
208
+ | Extraction nudge | `tool.execute.after` + `chat.message` | `PostToolBatch` + `UserPromptSubmit` (file-backed queue) | `postToolUse` + `beforeSubmitPrompt` (file-backed queue) |
209
+ | Setup detection at startup | n/a (plugin auto-installs) | `checkSetup` in MCP server: detects missing/broken instructions | Same as Claude Code |
210
+ | Skills | 13 (shared + coordinator) | 12 (shared only) | 12 (shared only) |
211
+ | Store detection | `worktree` param from plugin | `CLAUDE_PROJECT_DIR` env var | `CURSOR_PROJECT_DIR` then `CLAUDE_PROJECT_DIR` |
204
212
 
205
213
  See [docs/dev/mcp-parity.md](docs/dev/mcp-parity.md) for the full analysis.
206
214
 
@@ -26,6 +26,7 @@ This document maps the feature parity and documents the remaining gaps.
26
26
  | **Prompt-aware recall nudge** | `chat.message` hook embeds the prompt with the in-process warm model, searches `db.search()`, pushes a nudge part if matches ≥ threshold | `UserPromptSubmit` hook → `thatch flush-tools` connects to the MCP server's sideband socket; the warm server embeds + searches; hook prints the nudge or falls back to the write nudge | `beforeSubmitPrompt` hook → `thatch flush-tools --json` (same sideband path) | **Full** — sideband socket gives cold hook processes access to the warm MCP server's model |
27
27
  | **Skills** | Installed to `$XDG_CONFIG_HOME/opencode/skills` at plugin init (shared **+** opencode-only) | Installed to `$CLAUDE_CONFIG_DIR/skills/` by `thatch setup` (shared only) | Installed to `~/.cursor/skills/` by `thatch setup` (shared only) | **Full** — same SKILL.md format; the code-review coordinator is opencode-only (needs sub-agents) |
28
28
  | **Store detection** (repo identity from git remote) | `worktree` parameter from the opencode plugin | `CLAUDE_PROJECT_DIR` env (set by Claude Code for stdio MCP servers) | `CURSOR_PROJECT_DIR` then `CLAUDE_PROJECT_DIR` then cwd | **Full** |
29
+ | **Setup detection at startup** | n/a — plugin auto-installs at init | `checkSetup` in MCP server: detects missing or broken instructions in CLAUDE.md | Same as Claude Code (checks AGENTS.md) | **Full** — warns the agent to tell the user to run `thatch setup` |
29
30
  | **Hook config format** | n/a — plugin registers hooks in code | Nested: `.claude/settings.json` `{hooks:{Event:{hooks:[{type,command}]}}}` | Flat: `.cursor/hooks.json` `{version:1,hooks:{event:[{command}]}}` | n/a |
30
31
 
31
32
  ## Tool name conventions
@@ -132,3 +132,39 @@ All setup operations are idempotent:
132
132
  `thatch setup` resolves `<bin>` from PATH, falling back to the absolute path of
133
133
  the running script. This is baked into every installed hook command, so the
134
134
  hooks keep working after the session that ran setup ends.
135
+
136
+ ## Setup detection at MCP startup
137
+
138
+ When the MCP server starts (`thatch mcp`, spawned by Claude Code or Cursor),
139
+ it calls `checkSetup` (`src/setup.ts`) to verify that `thatch setup` was run
140
+ for the current host. This catches two failure modes that would otherwise leave
141
+ the agent without usage instructions:
142
+
143
+ ### Host detection
144
+
145
+ The host is determined from env vars set by the host process:
146
+
147
+ - `CURSOR_PROJECT_DIR` set → Cursor
148
+ - `CLAUDE_PROJECT_DIR` set (and Cursor not) → Claude Code
149
+ - Neither set → returns `null` (no check — manual `thatch mcp` invocation)
150
+
151
+ Cursor takes priority because Cursor also sets `CLAUDE_PROJECT_DIR` as an alias.
152
+
153
+ ### What it checks
154
+
155
+ `checkSetup` looks for the instruction markers (start and end) in the host's
156
+ instructions file — `CLAUDE.md` for Claude Code, `AGENTS.md` for Cursor. It
157
+ checks local (in the project directory) first, then global (in the config
158
+ directory). Local takes priority.
159
+
160
+ ### Three outcomes
161
+
162
+ | Outcome | Condition | Action |
163
+ |---------|-----------|--------|
164
+ | **installed** | Markers found in local or global instructions file | No warning — setup is complete |
165
+ | **not-installed** | No instructions file with markers found anywhere | Warning to stderr + prepended to first `tools/call` response: "Tell the user to run `thatch setup --<host>`" |
166
+ | **markers-broken** | Start marker found but end marker missing (file edited externally) | Warning with the specific file path and fix instructions: run `thatch setup`, or manually remove the corrupted block and re-run |
167
+
168
+ The warning is cleared after the first `tools/call` response so it surfaces
169
+ once, not on every tool call. The message instructs the LLM to notify the user
170
+ with the specific `thatch setup` command to run.
@@ -21,9 +21,9 @@ description: Extract durable project facts ... Use when ...
21
21
  - `description` drives when the agent loads the skill (both opencode and
22
22
  Cursor auto-discover skills and use the description for relevance).
23
23
 
24
- ## The 12 skills
24
+ ## The 13 skills
25
25
 
26
- **Shared (11)** — installed everywhere; no sub-agents required:
26
+ **Shared (12)** — installed everywhere; no sub-agents required:
27
27
 
28
28
  | Skill | Role |
29
29
  |-------|------|
@@ -37,13 +37,14 @@ description: Extract durable project facts ... Use when ...
37
37
  | `thatch-review-breadcrumbs` | Comment narrative: do comments form a coherent outline of behavior? |
38
38
  | `thatch-review-synthesizer` | Verify specialist findings against code, dedupe, classify, calibrate severity. |
39
39
  | `thatch-review-context` | Gather project/feature context (PR descriptions, git archaeology, ticket references, memory) before fan-out. Prevents false positives about intentionally deferred work. |
40
+ | `thatch-workflow-research` | Research code workflows/features affected by a change or planned change. Reads code flows, comments, git history, memories, docs. Produces a guide to the code for reviewers or planners. |
40
41
  | `thatch-session-reflection` | End-of-session memory recording (project, user, tools, self). |
41
42
 
42
43
  **opencode-only (1)** — the coordinator needs sub-agent support:
43
44
 
44
45
  | Skill | Role |
45
46
  |-------|------|
46
- | `thatch-code-review` | Resolve review target, gather context, estimate complexity, partition, dispatch the 5 specialists in parallel, synthesize. |
47
+ | `thatch-code-review` | Resolve review target, gather project context, research affected workflows, estimate complexity, partition, dispatch the 5 specialists in parallel, synthesize. |
47
48
 
48
49
  ## REVIEW_COMMON
49
50
 
@@ -61,6 +62,10 @@ The five review specialists share a framework interpolated via `${REVIEW_COMMON}
61
62
  - **Project context awareness** — if a context brief is provided (from the
62
63
  coordinator or from loading `thatch-review-context`), use it to avoid false
63
64
  positives about intentionally deferred work.
65
+ - **Workflow context awareness** — if a workflow guide is provided (from the
66
+ coordinator or from loading `thatch-workflow-research`), use it to understand
67
+ the purpose and evolution of the code, distinguishing intentional behavior
68
+ and long-standing design decisions from new issues.
64
69
  - **TODO ($ticket) markers** — recognize `TODO ($TICKET-ID): ...` as legitimate
65
70
  breadcrumbs for deferred work, not stale artifacts. Flag only if the referenced
66
71
  ticket is closed or merged.
@@ -73,7 +78,7 @@ The synthesizer reuses the same verification rigor but has its own structure
73
78
  ## The two arrays
74
79
 
75
80
  ```ts
76
- const SHARED_SKILLS: SkillDef[] = [ /* 11 skills above */ ];
81
+ const SHARED_SKILLS: SkillDef[] = [ /* 12 skills above */ ];
77
82
  const OPENCODE_ONLY_SKILLS: SkillDef[] = [ /* code-review coordinator */ ];
78
83
  ```
79
84
 
@@ -107,8 +112,7 @@ and `--cursor` pass only the shared set.
107
112
  ## Memory review skills in practice
108
113
 
109
114
  - **Quick single lens**: load any specialist directly and point it at a branch.
110
- - **Full review on opencode**: load `thatch-code-review` — it gathers project context, dispatches all 5
111
- specialists in parallel (with context injected into each briefing), then synthesizes.
115
+ - **Full review on opencode**: load `thatch-code-review` — it gathers project context, researches affected workflows, dispatches all 5 specialists in parallel (with both the context brief and workflow guide injected into each briefing), then synthesizes.
112
116
  - **Full review on Claude Code/Cursor**: run each specialist in sequence, then
113
117
  run `thatch-review-synthesizer` to verify and aggregate.
114
118
 
@@ -26,6 +26,7 @@ file/IPC/CLI contracts ready to graduate into `bun:test` integration tests.
26
26
  | [UC-015](UC-015-env-override-matrix.md) | `THATCH_DB_PATH`, `XDG_CONFIG_HOME`, `CLAUDE_CONFIG_DIR`, `THATCH_QUEUE_DIR`, `THATCH_RECALL_THRESHOLD`, `THATCH_MODEL` |
27
27
  | [UC-016](UC-016-concurrent-session-isolation.md) | Per-session extraction isolation (in-memory + file queue); shared stateless sideband |
28
28
  | [UC-017](UC-017-buffer-tool-vs-buffer-batch.md) | `buffer-batch` (Claude, `tool_calls[]`+`session_id`) vs `buffer-tool` (Cursor, single+`conversation_id`) |
29
+ | [UC-018](UC-018-mcp-startup-setup-detection.md) | MCP startup detects missing/broken setup instructions and warns the agent |
29
30
 
30
31
  ## Template
31
32
 
@@ -17,12 +17,12 @@
17
17
  appends a thatch block to `CLAUDE.md` bracketed by start/end markers (replaced, not
18
18
  duplicated, on re-run), writes `.claude/settings.json` hooks (`SessionStart` -> `thatch reminder`,
19
19
  `PostToolBatch` -> `thatch buffer-batch`, `UserPromptSubmit` -> `thatch flush-tools`), and installs
20
- **10 shared skills** (no code-review coordinator) to `$CLAUDE_CONFIG_DIR/skills/` — user-scoped
20
+ **12 shared skills** (no code-review coordinator) to `$CLAUDE_CONFIG_DIR/skills/` — user-scoped
21
21
  even in project-local mode.
22
22
  - `--cursor` project-local writes `.cursor/mcp.json`, appends to `AGENTS.md`, writes
23
23
  `.cursor/hooks.json` in the **flat format** (`{version:1, hooks:{...}}`): `sessionStart` ->
24
24
  `thatch reminder --json`, `postToolUse` -> `thatch buffer-tool`, `beforeSubmitPrompt` ->
25
- `thatch flush-tools --json`; and installs 10 shared skills to `~/.cursor/skills/`.
25
+ `thatch flush-tools --json`; and installs 12 shared skills to `~/.cursor/skills/`.
26
26
  - Re-run is idempotent: instructions are not duplicated, thatch hooks are replaced (not appended),
27
27
  and non-thatch hooks are preserved. A legacy `thatch echo` hook is replaced with `flush-tools`.
28
28
  - `--global` (Claude) writes `~/.claude/CLAUDE.md` + `~/.claude/settings.json` but **no project
@@ -13,16 +13,16 @@
13
13
  5. Check whether the `thatch-code-review` coordinator skill is present.
14
14
 
15
15
  **Expected**
16
- - Claude Code and Cursor install exactly **10 shared skills** to the skills
16
+ - Claude Code and Cursor install exactly **12 shared skills** to the skills
17
17
  dir — the coordinator (`thatch-code-review`) is **absent** (it needs
18
18
  sub-agents, which those hosts lack).
19
- - opencode installs **11** — the 10 shared plus the coordinator.
19
+ - opencode installs **13** — the 12 shared plus the coordinator.
20
20
  - The locally edited `SKILL.md` is **overwritten** with the canonical content
21
21
  on the next `setup`/init (drift detection: a file is only rewritten when its
22
22
  content differs from the definition). Unrelated skill files are untouched.
23
23
  - Skills never land in the worktree — always under the user-scoped config dir
24
24
  (`~/.claude/skills`, `~/.cursor/skills`, `$XDG_CONFIG_HOME/opencode/skills`).
25
25
 
26
- _Automatable: yes — file presence, count (10 vs 11), content-diff-overwrite, and
26
+ _Automatable: yes — file presence, count (12 vs 13), content-diff-overwrite, and
27
27
  coordinator host-gating are all file assertions (`setup.test.ts` already covers
28
28
  the unit contract)._
@@ -0,0 +1,38 @@
1
+ # UC-018: MCP startup setup detection
2
+
3
+ **Preconditions**
4
+ - Thatch installed and `bun` on PATH
5
+ - MCP server launched by Claude Code (`thatch mcp` with `CLAUDE_PROJECT_DIR` set)
6
+ or Cursor (`thatch mcp` with `CURSOR_PROJECT_DIR` set)
7
+
8
+ **Steps**
9
+ 1. Start a Claude Code session in a project where `thatch setup --claude` was
10
+ never run (no `CLAUDE.md` with thatch markers, neither local nor global).
11
+ 2. Call any thatch tool (e.g. `mcp__thatch__store_list`).
12
+ 3. Repeat in a project where setup was run but `CLAUDE.md` was edited externally
13
+ and the thatch block's end marker was deleted.
14
+ 4. Repeat in a project where setup was run correctly.
15
+ 5. Repeat all steps for Cursor (substituting `--cursor`, `AGENTS.md`,
16
+ `CURSOR_PROJECT_DIR`).
17
+
18
+ **Expected**
19
+ - **Not-installed**: The first `tools/call` response is prepended with a
20
+ warning: "[thatch] Thatch is running as an MCP server but has not been set
21
+ up for Claude Code. ... Tell the user to run: thatch setup --claude". The
22
+ warning also appears on stderr. Subsequent tool responses are clean (warning
23
+ is one-shot).
24
+ - **Markers-broken**: The first `tools/call` response is prepended with a
25
+ warning naming the corrupted file and instructing the user to run
26
+ `thatch setup` (or manually remove the corrupted block and re-run).
27
+ - **Installed**: No warning. Tool responses are clean from the first call.
28
+ - **Cursor**: Same behavior, with "Cursor" substituted for "Claude Code" and
29
+ `thatch setup --cursor` in the message. When both `CURSOR_PROJECT_DIR` and
30
+ `CLAUDE_PROJECT_DIR` are set, Cursor detection takes priority.
31
+ - **No env var**: When neither `CURSOR_PROJECT_DIR` nor `CLAUDE_PROJECT_DIR` is
32
+ set (manual `thatch mcp` invocation), `checkSetup` returns `null` and no
33
+ warning is emitted.
34
+
35
+ _Automatable: yes — `setup.test.ts` already covers the unit contract (10 tests
36
+ in the `checkSetup` describe block: null, local, global, not-installed,
37
+ markers-broken, local priority, Cursor variants, Cursor priority). This is the
38
+ end-to-end runbook version._
@@ -114,6 +114,17 @@ Beyond the tools, thatch hooks into opencode itself:
114
114
  - **Compaction context.** When opencode compacts a long session, thatch injects
115
115
  a reminder so the summarized session still knows memory tools exist.
116
116
 
117
+ ### Setup detection (Claude Code and Cursor)
118
+
119
+ When the MCP server starts (Claude Code or Cursor), it checks whether
120
+ `thatch setup` was run for the current host by looking for the instruction
121
+ markers in `CLAUDE.md` (Claude Code) or `AGENTS.md` (Cursor). It checks local
122
+ first (in the project directory), then global (in the config directory). If
123
+ setup was never run, or if the instruction markers are broken (e.g. the file
124
+ was edited externally and the thatch block was partially modified), the server
125
+ emits a warning to stderr and prepends it to the first tool response so the
126
+ agent can tell the user to run `thatch setup`.
127
+
117
128
  ## Skills
118
129
 
119
130
  On startup thatch installs [skills] into your global opencode config
@@ -143,6 +154,8 @@ Five specialist review lenses, each a self-contained static-analysis pass:
143
154
  | `thatch-review-no-slop` | AI writing anti-patterns: change narration, fourth wall breaks, em dashes, hedging, filler. |
144
155
  | `thatch-review-breadcrumbs` | Comment narrative: do comments form a coherent outline of the code's behavior? |
145
156
  | `thatch-review-synthesizer` | Verifies and synthesizes findings from multiple specialists into a single deduplicated, severity-grouped report. |
157
+ | `thatch-review-context` | Gathers project context (PR descriptions, git archaeology, ticket references, memory) before a review. Prevents false positives about intentionally deferred work. |
158
+ | `thatch-workflow-research` | Researches code workflows and features affected by a change or planned change. Reads code flows, comments, git history, and produces a guide for reviewers or planners. |
146
159
 
147
160
  ### opencode-only skills
148
161
 
@@ -152,12 +165,13 @@ Five specialist review lenses, each a self-contained static-analysis pass:
152
165
 
153
166
  ### Host availability
154
167
 
155
- | Skill | opencode | Claude Code |
156
- |-------|----------|-------------|
157
- | Memory skills (4) | Yes | Yes |
158
- | Review specialists (5) | Yes | Yes |
159
- | Review synthesizer | Yes | Yes |
160
- | Code review coordinator | Yes | No (requires sub-agents) |
168
+ | Skill | opencode | Claude Code | Cursor |
169
+ |-------|----------|-------------|--------|
170
+ | Memory skills (4) | Yes | Yes | Yes |
171
+ | Review specialists (5) | Yes | Yes | Yes |
172
+ | Review synthesizer | Yes | Yes | Yes |
173
+ | Review context + workflow research | Yes | Yes | Yes |
174
+ | Code review coordinator | Yes | No (requires sub-agents) | No (requires sub-agents) |
161
175
 
162
176
  ### Using review skills
163
177
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@jeffober/thatch",
3
- "version": "0.1.9",
3
+ "version": "0.1.10",
4
4
  "description": "Persistent memory for AI coding agents — local embeddings, SQLite stores, zero config. Works with OpenCode (as a plugin), Claude Code (as an MCP server), and Cursor (as an MCP server).",
5
5
  "type": "module",
6
6
  "main": "src/index.ts",
package/src/mcp.ts CHANGED
@@ -2,6 +2,7 @@ import { z } from "zod";
2
2
  import { ThatchDB } from "./db";
3
3
  import { BgeEmbeddingModel } from "./embeddings";
4
4
  import { detectRepo } from "./git";
5
+ import { checkSetup } from "./setup";
5
6
  import { TOOL_DEFS, type CoreContext, type ToolDef } from "./tool-defs";
6
7
  import { SidebandServer, sidebandSocketPath } from "./sideband";
7
8
 
@@ -99,6 +100,17 @@ export async function runMcpServer(): Promise<void> {
99
100
  const ctx: CoreContext = { db, model, defaultStore: repo };
100
101
  const tools = compileTools();
101
102
 
103
+ // Check whether `thatch setup` was run for the current host. If not, or if
104
+ // markers are broken, surface a warning on the first tools/call response so
105
+ // the agent can tell the user to run setup. Also emit to stderr for
106
+ // visibility in host debug logs.
107
+ let setupWarning: string | null = null;
108
+ const setupStatus = checkSetup(projectDir);
109
+ if (setupStatus && setupStatus.status !== "installed") {
110
+ setupWarning = setupStatus.message;
111
+ console.error(`[thatch] ${setupWarning}`);
112
+ }
113
+
102
114
  // The sideband socket lets one-shot hook processes (flush-tools) ask the
103
115
  // warm MCP server to embed a prompt and search for matches — without
104
116
  // loading the ~34 MB model themselves. If the socket can't be opened
@@ -137,6 +149,17 @@ export async function runMcpServer(): Promise<void> {
137
149
  const isNotification = req.id === null || req.id === undefined;
138
150
  const res = await dispatch(req, tools, ctx);
139
151
  if (res === null || isNotification) continue;
152
+
153
+ // Surface the setup warning on the first tools/call response so the
154
+ // agent sees it and can notify the user. Cleared after one surfacing.
155
+ if (setupWarning && req.method === "tools/call" && !res.error) {
156
+ const content = res.result?.content;
157
+ if (Array.isArray(content) && content[0]?.text != null) {
158
+ content[0].text = `[thatch] ${setupWarning}\n\n${content[0].text}`;
159
+ }
160
+ setupWarning = null;
161
+ }
162
+
140
163
  send(res);
141
164
  }
142
165
  }
package/src/prompts.ts CHANGED
@@ -27,6 +27,19 @@ WIP, PR status). Unscoped memories are project-wide and always included in searc
27
27
  Before diving into code, thatch_memory_recall with a query relevant to the area
28
28
  you're working in. Prior sessions may have already investigated it.
29
29
 
30
+ ## Skills
31
+
32
+ Thatch ships skills for code review, project investigation, and memory
33
+ workflows. The host auto-discovers them, but reach for them proactively:
34
+
35
+ - \`thatch-code-review\` — full multi-agent code review (dispatches 5 specialists + synthesizer). Requires sub-agent support.
36
+ - \`thatch-workflow-research\` — research code workflows affected by a change or planned change, before reviewing or planning.
37
+ - \`thatch-review-context\` — gather project context (PRs, tickets, TODOs, deferred work) before a review.
38
+ - \`thatch-project-primer\` — investigate a new project and write foundational memories.
39
+ - \`thatch-session-reflection\` — record what you learned at end of session.
40
+ - \`thatch-fact-extractor\` — extract durable facts from recent tool interactions (auto-triggered by the extraction pipeline).
41
+ - \`thatch-dedup-classifier\` — resolve duplicate memory pairs from \`thatch_find_duplicates\`.
42
+
30
43
  ## When to Write
31
44
 
32
45
  **One signal is enough.** Do not wait for confirmation.
@@ -126,6 +139,19 @@ WIP, PR status). Unscoped memories are project-wide and always included in searc
126
139
  Before diving into code, \`memory_recall\` with a query relevant to the area
127
140
  you're working in. Prior sessions may have already investigated it.
128
141
 
142
+ ## Skills
143
+
144
+ Thatch ships skills for code review, project investigation, and memory
145
+ workflows. The host auto-discovers them, but reach for them proactively:
146
+
147
+ - \`thatch-workflow-research\` — research code workflows affected by a change or planned change, before reviewing or planning.
148
+ - \`thatch-review-context\` — gather project context (PRs, tickets, TODOs, deferred work) before a review.
149
+ - \`thatch-review-pedantic\` / \`-acceptance\` / \`-state-flow\` / \`-no-slop\` / \`-breadcrumbs\` — five specialist review lenses. Run individually, then \`thatch-review-synthesizer\` to verify and aggregate.
150
+ - \`thatch-project-primer\` — investigate a new project and write foundational memories.
151
+ - \`thatch-session-reflection\` — record what you learned at end of session.
152
+ - \`thatch-fact-extractor\` — extract durable facts from recent tool interactions (auto-triggered by the extraction pipeline).
153
+ - \`thatch-dedup-classifier\` — resolve duplicate memory pairs from \`find_duplicates\`.
154
+
129
155
  ## When to Write
130
156
 
131
157
  **One signal is enough.** Do not wait for confirmation.
@@ -241,6 +267,19 @@ WIP, PR status). Unscoped memories are project-wide and always included in searc
241
267
  Before diving into code, \`memory_recall\` with a query relevant to the area
242
268
  you're working in. Prior sessions may have already investigated it.
243
269
 
270
+ ## Skills
271
+
272
+ Thatch ships skills for code review, project investigation, and memory
273
+ workflows. The host auto-discovers them, but reach for them proactively:
274
+
275
+ - \`thatch-workflow-research\` — research code workflows affected by a change or planned change, before reviewing or planning.
276
+ - \`thatch-review-context\` — gather project context (PRs, tickets, TODOs, deferred work) before a review.
277
+ - \`thatch-review-pedantic\` / \`-acceptance\` / \`-state-flow\` / \`-no-slop\` / \`-breadcrumbs\` — five specialist review lenses. Run individually, then \`thatch-review-synthesizer\` to verify and aggregate.
278
+ - \`thatch-project-primer\` — investigate a new project and write foundational memories.
279
+ - \`thatch-session-reflection\` — record what you learned at end of session.
280
+ - \`thatch-fact-extractor\` — extract durable facts from recent tool interactions (auto-triggered by the extraction pipeline).
281
+ - \`thatch-dedup-classifier\` — resolve duplicate memory pairs from \`find_duplicates\`.
282
+
244
283
  ## When to Write
245
284
 
246
285
  **One signal is enough.** Do not wait for confirmation.
package/src/setup.ts CHANGED
@@ -415,8 +415,120 @@ export function setupCursor(
415
415
  return {
416
416
  mcpConfig: paths.mcpConfigPath,
417
417
  agentsMd: paths.agentsMdPath,
418
- hooks: paths.hooksPath,
419
- skills,
420
- global,
418
+ hooks: paths.hooksPath,
419
+ skills,
420
+ global,
421
+ };
422
+ }
423
+
424
+ // ---------------------------------------------------------------------------
425
+ // Setup detection — check whether setup was completed for the current host
426
+ // ---------------------------------------------------------------------------
427
+
428
+ export type HostKind = "claude" | "cursor";
429
+
430
+ export type SetupStatus =
431
+ | { status: "installed"; scope: "local" | "global"; host: HostKind }
432
+ | { status: "not-installed"; host: HostKind; message: string }
433
+ | { status: "markers-broken"; host: HostKind; file: string; message: string };
434
+
435
+ type FileCheck = "installed" | "absent" | "broken";
436
+
437
+ function checkInstructionsFile(path: string, startMarker: string, endMarker: string): FileCheck {
438
+ if (!existsSync(path)) return "absent";
439
+ const content = readFileSync(path, "utf8");
440
+ const startIdx = content.indexOf(startMarker);
441
+ if (startIdx === -1) return "absent";
442
+ const endIdx = content.indexOf(endMarker, startIdx);
443
+ if (endIdx === -1) return "broken";
444
+ return "installed";
445
+ }
446
+
447
+ /**
448
+ * Detects the host from env vars (CURSOR_PROJECT_DIR for Cursor,
449
+ * CLAUDE_PROJECT_DIR for Claude Code) and checks whether `thatch setup` was
450
+ * run for that host. Checks local instructions (in the project dir) first,
451
+ * then global (in the config dir). Returns null if the host cannot be
452
+ * determined (neither env var is set — e.g. manual `thatch mcp` invocation).
453
+ */
454
+ export function checkSetup(projectDir: string, homeDir?: string): SetupStatus | null {
455
+ const home = homeDir ?? process.env.HOME ?? "/tmp";
456
+ const isCursor = !!process.env.CURSOR_PROJECT_DIR;
457
+ const isClaude = !!process.env.CLAUDE_PROJECT_DIR && !isCursor;
458
+ if (!isCursor && !isClaude) return null;
459
+
460
+ const host: HostKind = isCursor ? "cursor" : "claude";
461
+
462
+ if (host === "claude") {
463
+ return checkClaudeSetup(projectDir, home);
464
+ }
465
+ return checkCursorSetup(projectDir, home);
466
+ }
467
+
468
+ function checkClaudeSetup(projectDir: string, home: string): SetupStatus {
469
+ const configDir = claudeConfigDir(home);
470
+
471
+ const localMd = join(projectDir, "CLAUDE.md");
472
+ const localCheck = checkInstructionsFile(localMd, THATCH_MARKER, THATCH_END_MARKER);
473
+ if (localCheck === "installed") return { status: "installed", scope: "local", host: "claude" };
474
+ if (localCheck === "broken") {
475
+ return {
476
+ status: "markers-broken",
477
+ host: "claude",
478
+ file: localMd,
479
+ message: `Thatch's instructions in ${localMd} have corrupted markers: the start marker was found but the end marker is missing. This usually happens when the file was edited externally and the thatch block was partially modified. Tell the user to fix this by running: thatch setup --claude. If that doesn't resolve it, they may need to manually remove the corrupted thatch block from ${localMd} and re-run setup.`,
480
+ };
481
+ }
482
+
483
+ const globalMd = join(configDir, "CLAUDE.md");
484
+ const globalCheck = checkInstructionsFile(globalMd, THATCH_MARKER, THATCH_END_MARKER);
485
+ if (globalCheck === "installed") return { status: "installed", scope: "global", host: "claude" };
486
+ if (globalCheck === "broken") {
487
+ return {
488
+ status: "markers-broken",
489
+ host: "claude",
490
+ file: globalMd,
491
+ message: `Thatch's instructions in ${globalMd} have corrupted markers: the start marker was found but the end marker is missing. This usually happens when the file was edited externally and the thatch block was partially modified. Tell the user to fix this by running: thatch setup --claude --global. If that doesn't resolve it, they may need to manually remove the corrupted thatch block from ${globalMd} and re-run setup.`,
492
+ };
493
+ }
494
+
495
+ return {
496
+ status: "not-installed",
497
+ host: "claude",
498
+ message: "Thatch is running as an MCP server but has not been set up for Claude Code. The instructions that tell you how to use thatch's memory tools are missing from CLAUDE.md. Tell the user to run: thatch setup --claude",
499
+ };
500
+ }
501
+
502
+ function checkCursorSetup(projectDir: string, home: string): SetupStatus {
503
+ const configDir = cursorConfigDir(home);
504
+
505
+ const localMd = join(projectDir, "AGENTS.md");
506
+ const localCheck = checkInstructionsFile(localMd, CURSOR_MARKER, CURSOR_END_MARKER);
507
+ if (localCheck === "installed") return { status: "installed", scope: "local", host: "cursor" };
508
+ if (localCheck === "broken") {
509
+ return {
510
+ status: "markers-broken",
511
+ host: "cursor",
512
+ file: localMd,
513
+ message: `Thatch's instructions in ${localMd} have corrupted markers: the start marker was found but the end marker is missing. This usually happens when the file was edited externally and the thatch block was partially modified. Tell the user to fix this by running: thatch setup --cursor. If that doesn't resolve it, they may need to manually remove the corrupted thatch block from ${localMd} and re-run setup.`,
514
+ };
515
+ }
516
+
517
+ const globalMd = join(configDir, "AGENTS.md");
518
+ const globalCheck = checkInstructionsFile(globalMd, CURSOR_MARKER, CURSOR_END_MARKER);
519
+ if (globalCheck === "installed") return { status: "installed", scope: "global", host: "cursor" };
520
+ if (globalCheck === "broken") {
521
+ return {
522
+ status: "markers-broken",
523
+ host: "cursor",
524
+ file: globalMd,
525
+ message: `Thatch's instructions in ${globalMd} have corrupted markers: the start marker was found but the end marker is missing. This usually happens when the file was edited externally and the thatch block was partially modified. Tell the user to fix this by running: thatch setup --cursor --global. If that doesn't resolve it, they may need to manually remove the corrupted thatch block from ${globalMd} and re-run setup.`,
526
+ };
527
+ }
528
+
529
+ return {
530
+ status: "not-installed",
531
+ host: "cursor",
532
+ message: "Thatch is running as an MCP server but has not been set up for Cursor. The instructions that tell you how to use thatch's memory tools are missing from AGENTS.md. Tell the user to run: thatch setup --cursor",
421
533
  };
422
534
  }
package/src/skills.ts CHANGED
@@ -88,6 +88,13 @@ If your briefing includes a project context brief (from the coordinator or from
88
88
  - **Dependencies** in the brief tell you whether base-branch behavior is expected to be present or not. Do not assert that base-branch behavior exists without verifying it landed.
89
89
  - **Relevant constraints** may explain why code is structured a certain way. Consider them before flagging design choices.
90
90
 
91
+ ## Workflow context awareness
92
+ If your briefing includes a workflow guide (from the coordinator or from loading thatch-workflow-research), use it to understand the purpose and evolution of the code you are reviewing:
93
+ - **Purpose** sections explain why the workflow exists, which helps distinguish intentional behavior from bugs.
94
+ - **Major evolutions** sections explain how the code reached its current state, which helps distinguish recent changes from long-standing design decisions.
95
+ - **Constraints and design decisions** sections explain tradeoffs and intentional choices, which prevents flagging known design decisions as issues.
96
+ - **Current state** sections list known limitations and incomplete work, which prevents flagging known gaps as new bugs.
97
+
91
98
  ## TODO ($ticket) markers
92
99
  Code may contain \`TODO ($TICKET-ID): description\` comments that mark intentionally deferred work: temporary code, placeholders for future tickets, or planned cleanups. These are legitimate breadcrumbs, not stale artifacts.
93
100
  - Do NOT flag a TODO ($ticket) marker as a stale artifact if the ticket it references is still open or future work.
@@ -861,6 +868,103 @@ These markers serve as breadcrumbs for reviewers (human and LLM) who lack projec
861
868
  - They SHOULD be flagged if the referenced ticket is closed or merged (the TODO is now stale)
862
869
  `;
863
870
 
871
+ // ---------------------------------------------------------------------------
872
+ // Workflow research — code archaeology for review or planning
873
+ // ---------------------------------------------------------------------------
874
+
875
+ const WORKFLOW_RESEARCH = `---
876
+ name: thatch-workflow-research
877
+ description: Research the code workflows and features affected by a change or planned change. Identifies affected workflows, reads code flows and comments, traces git history, recalls memories, and produces a guide to the code. Use before reviewing a change or planning new work in an unfamiliar area.
878
+ ---
879
+
880
+ You are a code workflow researcher. Your job is to identify the features and logical workflows affected by a change (or a planned change), do deep code archaeology on them, and produce a guide that gives other agents the context they need to review or plan effectively.
881
+
882
+ ## Why this matters
883
+
884
+ A specialist reviewer without code-level context will misidentify intentional behavior as bugs, miss known design constraints, and duplicate the same code-tracing work across every specialist lens. A planner without code-level context will propose changes that conflict with existing flows. This skill produces the code guide that prevents both.
885
+
886
+ ## Relationship to thatch-review-context
887
+
888
+ These two skills are complementary, not overlapping:
889
+ - **thatch-review-context** gathers project metadata: tickets, PRs, TODO markers, deferred work, issue-tracker context. It answers "what is this change trying to do and what is intentionally left out?"
890
+ - **thatch-workflow-research** (this skill) gathers code-level context: actual code flows, comments, git history, evolutions. It answers "how does the code being changed actually work, and how did it get that way?"
891
+
892
+ Use both before a review. The coordinator runs thatch-review-context in Step 2 and this skill in Step 3.
893
+
894
+ ## Two modes
895
+
896
+ ### Review mode (existing change)
897
+ Given a git range, branch, or PR:
898
+ 1. Run \`git diff --stat\` on the resolved range to identify changed files.
899
+ 2. For each changed file, read the diff to understand what is being modified.
900
+ 3. From the changes, identify which features and business-logic workflows are touched. A single file may participate in multiple workflows; a single workflow may span multiple files.
901
+
902
+ ### Planning mode (new change)
903
+ Given a description of work to be done:
904
+ 1. Identify which areas of the codebase the planned change would affect.
905
+ 2. Use grep/glob to find the files and modules that implement the relevant features.
906
+ 3. From those files, identify which existing workflows the change will interact with or modify.
907
+
908
+ ## Research process
909
+
910
+ For each identified workflow or feature, work through these steps. Not every step will yield information for every workflow. Skip steps that produce nothing rather than forcing a narrative.
911
+
912
+ ### 1. Retrieve memories
913
+ Call \`thatch_memory_recall\` with queries like:
914
+ - The workflow or feature name
915
+ - The primary files or modules involved
916
+ - "architecture" or "design" or "convention" for the area
917
+ - Any gotchas or known issues in the area
918
+
919
+ ### 2. Read documentation
920
+ - README, docs/, design docs, ADRs related to the workflow
921
+ - CLAUDE.md, AGENTS.md, CONTRIBUTING.md for conventions
922
+ - Any inline documentation at the module level
923
+
924
+ ### 3. Read the code flow
925
+ Trace each workflow through the codebase. Do not just read the changed lines; read the full flow:
926
+ - Identify the entry point(s) for the workflow
927
+ - Follow the data path through the functions and modules involved
928
+ - Read the comments in the flow. Comments encode intention, rationale, and design decisions that are invisible from the code alone.
929
+ - Note key contracts: what does each function or module assume about its inputs? What does it guarantee about its outputs?
930
+ - Note implicit state machines: what states can the workflow be in? What transitions are guarded?
931
+
932
+ ### 4. Read git history
933
+ Trace the evolution of the workflow through git:
934
+ - \`git log --oneline -- <key files>\` for the commit history of the files involved
935
+ - \`git log -S "<function name>"\` to find when key functions were introduced or changed
936
+ - \`git blame\` on critical sections to find when and why they were written
937
+ - \`git log --all --oneline --grep="<feature name>"\` to find related work on other branches
938
+ - Look for commit messages that explain design decisions, refactors, or bug fixes that shaped the workflow
939
+
940
+ Focus on *why* the code evolved, not just *when*. Major evolutions are: creation, significant refactors, behavior changes, bug fixes that changed the flow, and additions of new paths or states.
941
+
942
+ ## Output: code guide
943
+
944
+ Produce a guide with one section per affected workflow or feature. Each section should be self-contained enough that a reviewer or planner can understand the workflow without reading the code themselves.
945
+
946
+ ### Workflow: <name>
947
+
948
+ - **Purpose**: What this workflow does and why it exists in the system
949
+ - **Key files**: The primary files and entry points, with file:line references
950
+ - **Data flow**: How data moves through the workflow (high-level, not line-by-line)
951
+ - **Major evolutions**: Key changes from git history. When was it created? What refactors or behavior changes shaped it? What drove those changes? Cite commit hashes or dates.
952
+ - **Constraints and design decisions**: From comments, memories, and docs. Known constraints, tradeoffs, intentional design choices, and gotchas.
953
+ - **Current state**: Any open issues, TODOs, known limitations, or incomplete migrations
954
+
955
+ ## Scope discipline
956
+
957
+ Only research workflows that the change actually touches. Do not research every workflow in the codebase. If a changed file participates in three workflows but the change only affects one, research only that one.
958
+
959
+ If the change is small and touches a single workflow, the guide may be one section. If the change is cross-cutting, the guide may have several sections. Let the change determine the scope.
960
+
961
+ ## What this skill is NOT
962
+
963
+ - It is not a code review. Do not evaluate the quality of the code or flag issues. That is the job of the review specialists.
964
+ - It is not a project context builder. That is the job of thatch-review-context, which gathers project metadata (tickets, PRs, TODOs, deferred work). This skill gathers code-level context (flows, comments, git history, evolutions).
965
+ - It is not a memory writer. Do not call thatch_memory_remember. If you discover durable facts, note them in the guide; the session-reflection or fact-extractor skills will persist them later.
966
+ `;
967
+
864
968
  // ---------------------------------------------------------------------------
865
969
  // Session reflection — end-of-session memory recording guidance
866
970
  // ---------------------------------------------------------------------------
@@ -976,7 +1080,20 @@ Produce the context brief in the format the skill prescribes (project context, t
976
1080
 
977
1081
  If context is sparse (no PR description, no ticket references, no relevant memories), note that the change appears standalone. Even a sparse brief is valuable: it tells specialists you looked and found nothing, so they do not need to repeat the search.
978
1082
 
979
- ## Step 3: Estimate complexity
1083
+ ## Step 3: Research affected workflows
1084
+
1085
+ Dispatch a sub-agent using the Task tool to research the code workflows affected by this change. Pass the sub-agent:
1086
+ - The git range and changed files (from Step 1)
1087
+ - The project context brief (from Step 2)
1088
+ - Instructions to load the thatch-workflow-research skill and follow its methodology
1089
+
1090
+ The sub-agent produces a code guide with one section per affected workflow or feature. Wait for it to complete and collect the guide.
1091
+
1092
+ This guide gives specialists the code-level context (purpose, data flow, evolutions, constraints) they need to avoid false positives about intentional behavior and long-standing design decisions, and reduces duplicate code-tracing across the five specialist lenses.
1093
+
1094
+ For small changes (a single file or trivial diff), you may do this research inline instead of dispatching a sub-agent. Use your judgment: if the workflow research would require reading more than 3-4 files, dispatch a sub-agent to preserve your context for orchestration.
1095
+
1096
+ ## Step 4: Estimate complexity
980
1097
 
981
1098
  Estimate the review effort in scrum points (1-13 scale):
982
1099
  - **1**: Trivial — typo fix, config tweak, single-line change.
@@ -990,7 +1107,7 @@ Points reflect *review complexity*, not implementation effort.
990
1107
 
991
1108
  Identify files to exclude from review: vendored dependencies, generated files, lockfiles, compiled assets.
992
1109
 
993
- ## Step 4: Partition (if > 3 points)
1110
+ ## Step 5: Partition (if > 3 points)
994
1111
 
995
1112
  For changes estimated at more than 3 points, partition into review units of approximately 3 points each:
996
1113
  - Group files by logical component or feature, not by directory.
@@ -1000,7 +1117,7 @@ For changes estimated at more than 3 points, partition into review units of appr
1000
1117
 
1001
1118
  For changes estimated at 3 points or fewer, skip partitioning — dispatch one set of specialists covering the full scope. A single 3-point unit is not large enough to warrant decomposition.
1002
1119
 
1003
- ## Step 5: Dispatch specialist sub-agents
1120
+ ## Step 6: Dispatch specialist sub-agents
1004
1121
 
1005
1122
  For each review unit, dispatch sub-agents using the Task tool. Each sub-agent runs one specialist lens on one review unit. The five specialists are:
1006
1123
 
@@ -1019,7 +1136,7 @@ For the integration review unit (5+ points), dispatch a sub-agent focused on:
1019
1136
  - Boundary correctness — race conditions, ordering dependencies, shared state issues at boundaries.
1020
1137
  - Top-level coherence — does the overall change make sense as a unit?
1021
1138
 
1022
- ## Step 6: Synthesize
1139
+ ## Step 7: Synthesize
1023
1140
 
1024
1141
  After all sub-agents complete, load the thatch-review-synthesizer skill to verify findings, deduplicate across specialists, classify (CONFIRMED/REJECTED/UNVERIFIABLE), and produce the final severity-grouped report.
1025
1142
 
@@ -1041,6 +1158,7 @@ When dispatching each sub-agent, include in the prompt:
1041
1158
  - The specialist focus (from the five specialists above)
1042
1159
  - The diff stat for this unit's files
1043
1160
  - **The project context brief** from Step 2, filtered to what is relevant to this unit's scope. Explicitly list any deferred work that falls within this unit's files, and call out TODO ($ticket) markers the specialists should recognize as intentional.
1161
+ - **The workflow guide** from Step 3, filtered to the workflows relevant to this unit's scope. Use it to understand the purpose and evolution of the code before flagging issues. It provides the code-level context (flows, contracts, history, constraints) that prevents false positives about intentional behavior and long-standing design decisions.
1044
1162
  - Any design context or specific concerns
1045
1163
  - Explicit scope boundaries ("your scope is X; do NOT review Y")
1046
1164
  - Instruction to produce markdown findings with: severity, category, file:line, finding, evidence, trigger scenario, reachability, source of truth, producer chain, provenance
@@ -1064,6 +1182,7 @@ const SHARED_SKILLS: SkillDef[] = [
1064
1182
  { name: "thatch-review-breadcrumbs", content: REVIEW_BREADCRUMBS },
1065
1183
  { name: "thatch-review-synthesizer", content: REVIEW_SYNTHESIZER },
1066
1184
  { name: "thatch-review-context", content: REVIEW_CONTEXT },
1185
+ { name: "thatch-workflow-research", content: WORKFLOW_RESEARCH },
1067
1186
  { name: "thatch-session-reflection", content: SESSION_REFLECTION },
1068
1187
  ];
1069
1188