@jaggerxtrm/specialists 2.1.21 → 3.0.1

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
@@ -6,22 +6,78 @@
6
6
  [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
7
7
  [![TypeScript](https://img.shields.io/badge/TypeScript-5.0-blue.svg)](https://www.typescriptlang.org/)
8
8
 
9
- **Specialists** is a **Model Context Protocol (MCP) server** that lets Claude (and other AI agents) discover and run specialist agents — each a full autonomous coding agent powered by [pi](https://github.com/mariozechner/pi), scoped to a specific task.
9
+ **Specialists** is a **Model Context Protocol (MCP) server** that lets Claude discover and delegate to specialist agents — each a full autonomous coding agent powered by [pi](https://github.com/mariozechner/pi), scoped to a specific task.
10
10
 
11
- **Designed for agents, not just users.** Claude can autonomously route heavy tasks (code review, bug hunting, deep reasoning, session init) to the right specialist without user intervention. Specialists run in the background while Claude continues working.
11
+ **Designed for agents, not users.** Claude autonomously routes heavy tasks (code review, bug hunting, deep reasoning, session init) to the right specialist. In v3, specialists run as **background CLI processes** zero polling overhead, notifications on completion.
12
12
 
13
13
  ---
14
14
 
15
15
  ## How it works
16
16
 
17
- Specialists are `.specialist.yaml` files that define an autonomous agent: its model, system prompt, task template, and permission tier. The server discovers them across two scopes:
17
+ ```
18
+ ┌──────────────────────────────────────────────┐
19
+ │ Claude Code │
20
+ │ │
21
+ │ MCP (control plane) CLI (execution plane) │
22
+ │ ───────────────────── ──────────────────── │
23
+ │ specialist_init specialists run \ │
24
+ │ list_specialists <name> --background│
25
+ │ use_specialist specialists result \ │
26
+ │ specialist_status <id> │
27
+ └──────────────────────────────────────────────┘
28
+ ↓ file-based job state
29
+ .specialists/jobs/<id>/
30
+ status.json result.txt events.jsonl
31
+ ```
32
+
33
+ Specialists are `.specialist.yaml` files discovered across two scopes:
18
34
 
19
35
  | Scope | Location | Purpose |
20
36
  |-------|----------|---------|
21
37
  | **project** | `./specialists/` | Per-project specialists |
22
38
  | **user** | `~/.agents/specialists/` | Built-in defaults (copied on install) + your own |
23
39
 
24
- When a specialist runs, the server spawns a `pi` subprocess with the right model, tools, and system prompt injected. Output streams back in real time via cursor-based polling.
40
+ When a specialist runs, the server spawns a `pi` subprocess with the right model, tools, and system prompt injected. For background jobs, a **Supervisor** writes job state to disk — status, events, and final output — so Claude gets a one-shot notification on completion instead of polling.
41
+
42
+ ---
43
+
44
+ ## Background Jobs (v3)
45
+
46
+ The primary workflow for long-running specialists:
47
+
48
+ ```bash
49
+ # Start in background — returns immediately
50
+ specialists run overthinker --prompt "Refactor strategy?" --background
51
+ # → Job started: a1b2c3
52
+
53
+ # Check progress
54
+ specialists status
55
+ # → Active Jobs
56
+ # a1b2c3 overthinker running 1m12s tool: bash
57
+
58
+ # Stream events live
59
+ specialists feed --job a1b2c3 --follow
60
+
61
+ # Get result when done
62
+ specialists result a1b2c3
63
+
64
+ # Cancel
65
+ specialists stop a1b2c3
66
+ ```
67
+
68
+ When a background job completes, Claude's next prompt automatically receives a banner:
69
+
70
+ ```
71
+ [Specialist 'overthinker' completed (job a1b2c3, 87s). Run: specialists result a1b2c3]
72
+ ```
73
+
74
+ Job files live in `.specialists/jobs/<id>/` (gitignored by `specialists init`):
75
+
76
+ | File | Contents |
77
+ |------|---------|
78
+ | `status.json` | id, specialist, status, model, backend, pid, elapsed_s, bead_id, error |
79
+ | `events.jsonl` | thinking\_start, toolcall\_start, tool\_execution\_end, agent\_end |
80
+ | `result.txt` | Final assistant output |
25
81
 
26
82
  ---
27
83
 
@@ -32,11 +88,13 @@ When a specialist runs, the server spawns a `pi` subprocess with the right model
32
88
  | `specialist_init` | Session bootstrap: init beads if needed, return available specialists |
33
89
  | `list_specialists` | Discover all available specialists across scopes |
34
90
  | `use_specialist` | Run a specialist synchronously and return the result |
35
- | `start_specialist` | Fire-and-forget: start a specialist job, returns `job_id` |
36
- | `poll_specialist` | Poll a running job; returns delta since last cursor + `beadId` |
37
- | `stop_specialist` | Cancel a running job |
38
- | `run_parallel` | Run multiple specialists concurrently or as a pipeline |
39
- | `specialist_status` | Circuit breaker health + job status |
91
+ | `specialist_status` | Circuit breaker health + background job summary |
92
+ | `start_specialist` | *(deprecated v3)* Async job via in-memory registry use CLI instead |
93
+ | `poll_specialist` | *(deprecated v3)* Poll in-memory job — use CLI instead |
94
+ | `stop_specialist` | *(deprecated v3)* Kill in-memory job use `specialists stop <id>` |
95
+ | `run_parallel` | *(deprecated v3)* Concurrent in-memory jobs use CLI `--background` |
96
+
97
+ For production use: `use_specialist` for short synchronous tasks, CLI `--background` for anything that takes more than a few seconds.
40
98
 
41
99
  ---
42
100
 
@@ -44,42 +102,42 @@ When a specialist runs, the server spawns a `pi` subprocess with the right model
44
102
 
45
103
  | Specialist | Model | Purpose |
46
104
  |-----------|-------|---------|
47
- | `init-session` | Haiku | Analyze git state, recent commits, surface relevant context |
105
+ | `init-session` | Haiku | Analyse git state, recent commits, surface relevant context |
48
106
  | `codebase-explorer` | Gemini Flash | Architecture analysis, directory structure, patterns |
49
107
  | `overthinker` | Sonnet | 4-phase deep reasoning: analysis → critique → synthesis → output |
50
108
  | `parallel-review` | Sonnet | Concurrent code review across multiple focus areas |
51
109
  | `bug-hunt` | Sonnet | Autonomous bug investigation from symptoms to root cause |
52
110
  | `feature-design` | Sonnet | Turn feature requests into structured implementation plans |
53
111
  | `auto-remediation` | Gemini Flash | Apply fixes to identified issues automatically |
54
- | `report-generator` | Haiku | Synthesize data/analysis results into structured markdown |
112
+ | `report-generator` | Haiku | Synthesise data/analysis results into structured markdown |
55
113
  | `test-runner` | Haiku | Run tests, parse results, surface failures |
56
114
 
57
115
  ---
58
116
 
59
117
  ## Permission Tiers
60
118
 
61
- Specialists declare their required permission level, enforced at spawn time via `pi --tools`:
119
+ | Tier | pi tools | Use case |
120
+ |------|---------|----------|
121
+ | `READ_ONLY` | read, bash, grep, find, ls | Analysis, exploration |
122
+ | `LOW` | read, bash, edit, write, grep, find, ls | Code modifications |
123
+ | `MEDIUM` | read, bash, edit, write, grep, find, ls | Code modifications + git |
124
+ | `HIGH` | read, bash, edit, write, grep, find, ls | Full autonomy |
62
125
 
63
- | Tier | Allowed tools | Use case |
64
- |------|--------------|----------|
65
- | `READ_ONLY` | read, bash (read-only), grep, find, ls | Analysis, exploration |
66
- | `LOW` | + edit, write | Code modifications |
67
- | `MEDIUM` | + git operations | Commits, branching |
68
- | `HIGH` | Full autonomy | External API calls, push |
126
+ Permission is enforced at spawn time via `pi --tools`, not just in the system prompt.
69
127
 
70
128
  ---
71
129
 
72
130
  ## Beads Integration
73
131
 
74
- Specialists with write permissions (`LOW`/`MEDIUM`/`HIGH`) automatically create a [beads](https://github.com/beads/bd) issue when they run and close it on completion. Control this per-specialist with `beads_integration`:
132
+ Specialists with write permissions automatically create a [beads](https://github.com/beads/bd) issue and close it on completion. Control this per-specialist:
75
133
 
76
134
  ```yaml
77
- beads_integration: auto # default — create for LOW/MEDIUM/HIGH, skip for READ_ONLY
78
- beads_integration: always # always create, regardless of permission tier
135
+ beads_integration: auto # default — create for LOW/MEDIUM/HIGH
136
+ beads_integration: always # always create
79
137
  beads_integration: never # never create
80
138
  ```
81
139
 
82
- The orchestrating agent can retrieve the `beadId` from `poll_specialist` output to link the issue for follow-up (`bd remember`, `bd update --notes`, etc.).
140
+ The `bead_id` is written to `status.json` so you can link issues for follow-up.
83
141
 
84
142
  ---
85
143
 
@@ -92,16 +150,17 @@ npm install -g @jaggerxtrm/specialists
92
150
  specialists install
93
151
  ```
94
152
 
95
- Installs: **pi** (`@mariozechner/pi-coding-agent`), **beads** (`@beads/bd`), **dolt** (interactive sudo on Linux / brew on macOS), registers the `specialists` MCP at user scope, scaffolds `~/.agents/specialists/`, copies built-in specialists, and installs four Claude Code hooks into `~/.claude/hooks/`:
153
+ Installs: **pi** (`@mariozechner/pi-coding-agent`), **beads** (`@beads/bd`), **dolt**, registers the `specialists` MCP at user scope, scaffolds `~/.agents/specialists/`, copies built-in specialists, and installs five Claude Code hooks:
96
154
 
97
155
  | Hook | Event | Enforces |
98
156
  |------|-------|---------|
99
- | `specialists-main-guard.mjs` | `PreToolUse` | No direct edits/commits on `main`/`master` — use a feature branch |
100
- | `beads-edit-gate.mjs` | `PreToolUse` | No file edits without an `in_progress` beads issue (beads projects only) |
101
- | `beads-commit-gate.mjs` | `PreToolUse` | No `git commit` while issues are still `in_progress` — close them first |
102
- | `beads-stop-gate.mjs` | `Stop` | Agent cannot declare done while `in_progress` issues remain |
157
+ | `specialists-main-guard.mjs` | `PreToolUse` | No direct edits/commits on `main`/`master` |
158
+ | `beads-edit-gate.mjs` | `PreToolUse` | No file edits without an `in_progress` beads issue |
159
+ | `beads-commit-gate.mjs` | `PreToolUse` | No `git commit` while issues are `in_progress` |
160
+ | `beads-stop-gate.mjs` | `Stop` | Agent cannot stop with unresolved issues |
161
+ | `specialists-complete.mjs` | `UserPromptSubmit` | Injects background job completion banners |
103
162
 
104
- After running, **restart Claude Code** to load the MCP. Re-run `specialists install` at any time to update or repair the installation.
163
+ After running, **restart Claude Code** to load the MCP. Re-run `specialists install` at any time to update or repair.
105
164
 
106
165
  ### One-time (no global install)
107
166
 
@@ -111,37 +170,6 @@ npx --package=@jaggerxtrm/specialists install
111
170
 
112
171
  ---
113
172
 
114
- ### Manual installation
115
-
116
- **1. pi** — coding agent runtime:
117
- ```bash
118
- npm install -g @mariozechner/pi-coding-agent
119
- ```
120
- Run `pi` once, then `pi config` to enable your model providers (Anthropic, Google, etc.).
121
-
122
- **2. beads** — issue tracker:
123
- ```bash
124
- npm install -g @beads/bd
125
- ```
126
-
127
- **3. dolt** — beads sync backend:
128
- ```bash
129
- # Linux
130
- sudo bash -c 'curl -L https://github.com/dolthub/dolt/releases/latest/download/install.sh | bash'
131
- # macOS
132
- brew install dolt
133
- ```
134
-
135
- **4. specialists + MCP:**
136
- ```bash
137
- npm install -g @jaggerxtrm/specialists
138
- claude mcp add --scope user specialists -- specialists
139
- ```
140
-
141
- Then **restart Claude Code**.
142
-
143
- ---
144
-
145
173
  ## Writing a Specialist
146
174
 
147
175
  Create a `.yaml` file in `./specialists/` (project scope) or `~/.agents/specialists/` (user scope):
@@ -154,7 +182,7 @@ specialist:
154
182
  description: "What this specialist does."
155
183
  category: analysis
156
184
  tags: [analysis, example]
157
- updated: "2026-03-09"
185
+ updated: "2026-03-11"
158
186
 
159
187
  execution:
160
188
  mode: tool
@@ -172,22 +200,26 @@ specialist:
172
200
  task_template: |
173
201
  $prompt
174
202
 
175
- Working directory: $cwd
203
+ # Inject a single skill file into the system prompt
204
+ skill_inherit: ~/.agents/skills/my-domain-knowledge.md
176
205
 
177
206
  communication:
178
- publishes: [result]
207
+ output_to: .specialists/my-specialist-result.md # optional file sink
179
208
 
180
- # Optional: run scripts before/after the specialist
181
209
  skills:
210
+ # Run scripts before/after the specialist
182
211
  scripts:
183
212
  - path: ./scripts/health-check.sh
184
213
  phase: pre # runs before the task prompt
185
- inject_output: true # output injected as $pre_script_output
214
+ inject_output: true # output available as $pre_script_output
186
215
  - path: ./scripts/cleanup.sh
187
- phase: post # runs after the specialist completes
188
- ```
216
+ phase: post
189
217
 
190
- Pre-script output is formatted as `<pre_flight_context>` XML and available in `task_template` via `$pre_script_output`. Scripts run locally via the host shell — not inside the pi agent. Failed scripts include their exit code so the specialist can reason about failures.
218
+ # Inject multiple skill/context files into the system prompt (v3)
219
+ paths:
220
+ - ~/skills/domain-context.md
221
+ - ./specialists/shared/conventions.md
222
+ ```
191
223
 
192
224
  **Model IDs** use the full provider/model format: `anthropic/claude-sonnet-4-6`, `google-gemini-cli/gemini-3-flash-preview`, `anthropic/claude-haiku-4-5`.
193
225
 
@@ -195,67 +227,39 @@ Pre-script output is formatted as `<pre_flight_context>` XML and available in `t
195
227
 
196
228
  ## CLI
197
229
 
198
- Once installed globally, `specialists <command>` provides:
199
-
200
230
  | Command | Description |
201
231
  |---------|-------------|
202
- | `specialists install` | Full-stack installer: pi, beads, dolt, MCP registration, hooks |
203
- | `specialists init` | Scaffold `./specialists/` and inject usage block into `AGENTS.md` |
204
- | `specialists list` | List discovered specialists with model, description, and scope |
232
+ | `specialists install` | Full-stack installer: pi, beads, dolt, MCP, hooks |
233
+ | `specialists init` | Scaffold `./specialists/`, `.specialists/`, update `.gitignore`, inject `AGENTS.md` block |
234
+ | `specialists list` | List discovered specialists with model, description, scope |
235
+ | `specialists models` | List models available on pi with capability flags |
205
236
  | `specialists edit <name> --<field> <value>` | Edit a specialist field in-place |
206
- | `specialists run <name>` | Run a specialist and stream output to stdout |
207
- | `specialists status` | Show system health: specialists, pi, beads, MCP |
208
- | `specialists version` | Print installed package version |
237
+ | `specialists run <name>` | Run a specialist (foreground by default) |
238
+ | `specialists run <name> --background` | Start as background job, print job ID |
239
+ | `specialists result <id>` | Print result of a completed background job |
240
+ | `specialists feed --job <id> [--follow]` | Tail events.jsonl; `--follow` streams live |
241
+ | `specialists stop <id>` | Send SIGTERM to a running background job |
242
+ | `specialists status` | System health + active background jobs |
243
+ | `specialists version` | Print installed version |
209
244
  | `specialists help` | Show command reference |
210
- | `specialists` | Start the MCP server (called by Claude Code — not for direct use) |
211
-
212
- ### specialists list
213
-
214
- ```
215
- Specialists (9)
216
-
217
- auto-remediation google-gemini-cli/gemini-3-flash-preview Autonomous self-healing workflow... [project]
218
- bug-hunt anthropic/claude-sonnet-4-6 Autonomously investigates bugs... [project]
219
- codebase-explorer google-gemini-cli/gemini-3-flash-preview Explores codebase structure... [project]
220
- init-session anthropic/claude-haiku-4-5 Gathers git/commit context... [project]
221
- overthinker anthropic/claude-sonnet-4-6 Multi-phase deep reasoning... [project]
222
- ```
223
-
224
- Scopes: `[project]` = `./specialists/` (or `.claude/specialists/`), `[user]` = `~/.agents/specialists/`
225
-
226
- Filter by scope or category: `specialists list --scope user --category analysis`
227
-
228
- ### specialists edit
229
-
230
- Edit individual fields without opening the file:
231
-
232
- ```bash
233
- specialists edit init-session --model anthropic/claude-sonnet-4-6
234
- specialists edit bug-hunt --permission MEDIUM
235
- specialists edit overthinker --timeout 300000
236
- specialists edit codebase-explorer --tags "analysis,architecture"
237
- specialists edit my-spec --description "New description" --dry-run
238
- ```
239
-
240
- Editable fields: `model`, `fallback-model`, `description`, `permission`, `timeout`, `tags`
241
245
 
242
246
  ### specialists run
243
247
 
244
- Run a specialist directly from the terminal — no MCP required:
245
-
246
248
  ```bash
247
- # Inline prompt
249
+ # Foreground — streams output to stdout
248
250
  specialists run init-session --prompt "What changed recently?"
249
251
 
252
+ # Background — returns job ID immediately
253
+ specialists run overthinker --prompt "Refactor?" --background
254
+
255
+ # Background with model override, no beads
256
+ specialists run bug-hunt --prompt "TypeError in auth" --background \
257
+ --model anthropic/claude-sonnet-4-6 --no-beads
258
+
250
259
  # Pipe from stdin
251
260
  echo "Analyse the architecture" | specialists run codebase-explorer
252
-
253
- # Override model, skip beads
254
- specialists run overthinker --prompt "Refactor strategy?" --model anthropic/claude-sonnet-4-6 --no-beads
255
261
  ```
256
262
 
257
- Output streams to stdout in real time. Model, duration, and bead ID appear on stderr.
258
-
259
263
  ### specialists status
260
264
 
261
265
  ```
@@ -273,7 +277,10 @@ specialists status
273
277
 
274
278
  ── MCP ───────────────────────────────────
275
279
  ✓ specialists binary installed /usr/local/bin/specialists
276
- verify registration: claude mcp get specialists
280
+
281
+ ── Active Jobs ───────────────────────────
282
+ a1b2c3 overthinker running 1m12s tool: bash
283
+ g7h8i9 init-session done 0m08s
277
284
  ```
278
285
 
279
286
  ---
@@ -284,15 +291,11 @@ specialists status
284
291
  git clone https://github.com/Jaggerxtrm/specialists.git
285
292
  cd specialists
286
293
  bun install
287
- bun run build
288
- bun test
294
+ bun run build # bun build src/index.ts --target=node --outfile=dist/index.js
295
+ bun test # bun --bun vitest run
289
296
  ```
290
297
 
291
- - **Build**: `bun build src/index.ts --target=node --outfile=dist/index.js`
292
- - **Test**: `bun --bun vitest run` (68 unit tests)
293
- - **Lint**: `tsc --noEmit`
294
-
295
- See [CLAUDE.md](CLAUDE.md) for the full architecture guide and [ROADMAP.md](ROADMAP.md) for planned features.
298
+ See [CLAUDE.md](CLAUDE.md) for the full architecture guide.
296
299
 
297
300
  ---
298
301
 
package/bin/install.js CHANGED
@@ -104,6 +104,15 @@ const BEADS_COMMIT_GATE_ENTRY = {
104
104
  const BEADS_STOP_GATE_ENTRY = {
105
105
  hooks: [{ type: 'command', command: BEADS_STOP_GATE_FILE, timeout: 10000 }],
106
106
  };
107
+ const BEADS_CLOSE_MEMORY_PROMPT_FILE = join(HOOKS_DIR, 'beads-close-memory-prompt.mjs');
108
+ const BEADS_CLOSE_MEMORY_PROMPT_ENTRY = {
109
+ matcher: 'Bash',
110
+ hooks: [{ type: 'command', command: BEADS_CLOSE_MEMORY_PROMPT_FILE, timeout: 10000 }],
111
+ };
112
+ const SPECIALISTS_COMPLETE_FILE = join(HOOKS_DIR, 'specialists-complete.mjs');
113
+ const SPECIALISTS_COMPLETE_ENTRY = {
114
+ hooks: [{ type: 'command', command: SPECIALISTS_COMPLETE_FILE, timeout: 5000 }],
115
+ };
107
116
 
108
117
  function promptYN(question) {
109
118
  if (!process.stdin.isTTY) return true; // non-interactive: default yes
@@ -118,10 +127,12 @@ function promptYN(question) {
118
127
 
119
128
  function getHookDrift() {
120
129
  const pairs = [
121
- ['specialists-main-guard.mjs', HOOK_FILE],
122
- ['beads-edit-gate.mjs', BEADS_EDIT_GATE_FILE],
123
- ['beads-commit-gate.mjs', BEADS_COMMIT_GATE_FILE],
124
- ['beads-stop-gate.mjs', BEADS_STOP_GATE_FILE],
130
+ ['specialists-main-guard.mjs', HOOK_FILE],
131
+ ['beads-edit-gate.mjs', BEADS_EDIT_GATE_FILE],
132
+ ['beads-commit-gate.mjs', BEADS_COMMIT_GATE_FILE],
133
+ ['beads-stop-gate.mjs', BEADS_STOP_GATE_FILE],
134
+ ['beads-close-memory-prompt.mjs', BEADS_CLOSE_MEMORY_PROMPT_FILE],
135
+ ['specialists-complete.mjs', SPECIALISTS_COMPLETE_FILE],
125
136
  ];
126
137
  return pairs
127
138
  .map(([bundled, dest]) => ({
@@ -147,6 +158,10 @@ function installHook() {
147
158
  chmodSync(BEADS_COMMIT_GATE_FILE, 0o755);
148
159
  copyFileSync(join(BUNDLED_HOOKS_DIR, 'beads-stop-gate.mjs'), BEADS_STOP_GATE_FILE);
149
160
  chmodSync(BEADS_STOP_GATE_FILE, 0o755);
161
+ copyFileSync(join(BUNDLED_HOOKS_DIR, 'beads-close-memory-prompt.mjs'), BEADS_CLOSE_MEMORY_PROMPT_FILE);
162
+ chmodSync(BEADS_CLOSE_MEMORY_PROMPT_FILE, 0o755);
163
+ copyFileSync(join(BUNDLED_HOOKS_DIR, 'specialists-complete.mjs'), SPECIALISTS_COMPLETE_FILE);
164
+ chmodSync(SPECIALISTS_COMPLETE_FILE, 0o755);
150
165
 
151
166
  let settings = {};
152
167
  if (existsSync(SETTINGS_FILE)) {
@@ -168,6 +183,13 @@ function installHook() {
168
183
  settings.hooks.PreToolUse.push(BEADS_EDIT_GATE_ENTRY);
169
184
  settings.hooks.PreToolUse.push(BEADS_COMMIT_GATE_ENTRY);
170
185
 
186
+ // PostToolUse — replace any existing beads-close-memory-prompt entry
187
+ if (!Array.isArray(settings.hooks.PostToolUse)) settings.hooks.PostToolUse = [];
188
+ settings.hooks.PostToolUse = settings.hooks.PostToolUse.filter(e =>
189
+ !e.hooks?.some(h => h.command?.includes('beads-close-memory-prompt'))
190
+ );
191
+ settings.hooks.PostToolUse.push(BEADS_CLOSE_MEMORY_PROMPT_ENTRY);
192
+
171
193
  // Stop — replace any existing beads-stop-gate entry
172
194
  if (!Array.isArray(settings.hooks.Stop)) settings.hooks.Stop = [];
173
195
  settings.hooks.Stop = settings.hooks.Stop.filter(e =>
@@ -175,6 +197,13 @@ function installHook() {
175
197
  );
176
198
  settings.hooks.Stop.push(BEADS_STOP_GATE_ENTRY);
177
199
 
200
+ // UserPromptSubmit — replace any existing specialists-complete entry
201
+ if (!Array.isArray(settings.hooks.UserPromptSubmit)) settings.hooks.UserPromptSubmit = [];
202
+ settings.hooks.UserPromptSubmit = settings.hooks.UserPromptSubmit.filter(e =>
203
+ !e.hooks?.some(h => h.command?.includes('specialists-complete'))
204
+ );
205
+ settings.hooks.UserPromptSubmit.push(SPECIALISTS_COMPLETE_ENTRY);
206
+
178
207
  mkdirSync(CLAUDE_DIR, { recursive: true });
179
208
  writeFileSync(SETTINGS_FILE, JSON.stringify(settings, null, 2) + '\n', 'utf8');
180
209
  }