continuous-improvement 2.2.0 → 3.0.0

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/bin/install.mjs CHANGED
@@ -4,12 +4,15 @@
4
4
  * continuous-improvement installer
5
5
  *
6
6
  * Usage:
7
- * npx continuous-improvement install # auto-detect & install
8
- * npx continuous-improvement install --target claude # install to ~/.claude/skills/ + Mulahazah
9
- * npx continuous-improvement install --target openclaw # install to ~/.openclaw/skills/
10
- * npx continuous-improvement install --target cursor # install to ~/.cursor/skills/
11
- * npx continuous-improvement install --target all # install to all detected targets
12
- * npx continuous-improvement install --uninstall # remove from all targets
7
+ * npx continuous-improvement install # auto-detect & install (beginner)
8
+ * npx continuous-improvement install --target claude # install to ~/.claude/skills/ + Mulahazah
9
+ * npx continuous-improvement install --target openclaw # install to ~/.openclaw/skills/
10
+ * npx continuous-improvement install --target cursor # install to ~/.cursor/skills/
11
+ * npx continuous-improvement install --target all # install to all detected targets
12
+ * npx continuous-improvement install --mode beginner # hooks only (default)
13
+ * npx continuous-improvement install --mode expert # hooks + MCP server + session hooks
14
+ * npx continuous-improvement install --mode mcp # MCP server only (any editor)
15
+ * npx continuous-improvement install --uninstall # remove from all targets
13
16
  */
14
17
 
15
18
  import {
@@ -31,6 +34,11 @@ const SKILL_SOURCE = join(__dirname, "..", "SKILL.md");
31
34
  const SKILL_NAME = "continuous-improvement";
32
35
  const REPO_ROOT = join(__dirname, "..");
33
36
 
37
+ // Parse --mode flag
38
+ const _args = process.argv.slice(2);
39
+ const _modeIdx = _args.indexOf("--mode");
40
+ const INSTALL_MODE = _modeIdx !== -1 && _args[_modeIdx + 1] ? _args[_modeIdx + 1] : "beginner";
41
+
34
42
  const TARGETS = {
35
43
  claude: {
36
44
  label: "Claude Code",
@@ -70,6 +78,17 @@ function installTo(key) {
70
78
  }
71
79
 
72
80
  try {
81
+ // MCP-only mode: skip skill file copy, just register MCP server
82
+ if (INSTALL_MODE === "mcp") {
83
+ if (key === "claude") {
84
+ setupMulahazah();
85
+ console.log(` ✓ ${target.label} → MCP server only`);
86
+ } else {
87
+ console.log(` ⊘ ${target.label} — MCP mode only applies to Claude Code`);
88
+ }
89
+ return true;
90
+ }
91
+
73
92
  mkdirSync(target.dir, { recursive: true });
74
93
  copyFileSync(SKILL_SOURCE, join(target.dir, "SKILL.md"));
75
94
  console.log(` ✓ ${target.label} → ${target.dir}/SKILL.md`);
@@ -103,7 +122,18 @@ function setupMulahazah() {
103
122
  console.log(` ✓ observe.sh → ${observeDest}`);
104
123
  }
105
124
 
106
- // 3. Copy /continuous-improvement command
125
+ // 3. Copy session.sh for expert mode
126
+ if (INSTALL_MODE === "expert") {
127
+ const sessionSrc = join(REPO_ROOT, "hooks", "session.sh");
128
+ const sessionDest = join(instinctsDir, "session.sh");
129
+ if (existsSync(sessionSrc)) {
130
+ copyFileSync(sessionSrc, sessionDest);
131
+ chmodSync(sessionDest, 0o755);
132
+ console.log(` ✓ session.sh → ${sessionDest}`);
133
+ }
134
+ }
135
+
136
+ // 4. Copy /continuous-improvement command
107
137
  const commandsDir = join(home, ".claude", "commands");
108
138
  mkdirSync(commandsDir, { recursive: true });
109
139
  const cmdSrc = join(REPO_ROOT, "commands", "continuous-improvement.md");
@@ -113,8 +143,64 @@ function setupMulahazah() {
113
143
  console.log(` ✓ /continuous-improvement command → ${cmdDest}`);
114
144
  }
115
145
 
116
- // 4. Patch ~/.claude/settings.json with hooks
146
+ // 5. Patch ~/.claude/settings.json with hooks
117
147
  patchClaudeSettings(observeDest);
148
+
149
+ // 6. Setup MCP server for expert or mcp mode
150
+ if (INSTALL_MODE === "expert" || INSTALL_MODE === "mcp") {
151
+ setupMcpServer();
152
+ }
153
+ }
154
+
155
+ function setupMcpServer() {
156
+ const home = homedir();
157
+ const mcpServerPath = join(REPO_ROOT, "bin", "mcp-server.mjs");
158
+ const mcpMode = INSTALL_MODE === "mcp" ? "beginner" : "expert";
159
+
160
+ // Patch Claude Code settings.json with MCP server config
161
+ const settingsPath = join(home, ".claude", "settings.json");
162
+ let settings = {};
163
+ if (existsSync(settingsPath)) {
164
+ try {
165
+ settings = JSON.parse(readFileSync(settingsPath, "utf8"));
166
+ } catch {
167
+ console.warn(` ! Could not parse settings.json — skipping MCP setup`);
168
+ return;
169
+ }
170
+ }
171
+
172
+ if (!settings.mcpServers) settings.mcpServers = {};
173
+
174
+ const alreadySetup = settings.mcpServers["continuous-improvement"];
175
+ if (!alreadySetup) {
176
+ settings.mcpServers["continuous-improvement"] = {
177
+ command: "node",
178
+ args: [mcpServerPath, "--mode", mcpMode],
179
+ };
180
+ writeFileSync(settingsPath, JSON.stringify(settings, null, 2) + "\n");
181
+ console.log(` ✓ MCP server registered (mode: ${mcpMode})`);
182
+ } else {
183
+ console.log(` ✓ MCP server already registered — no change`);
184
+ }
185
+
186
+ // Also write claude_desktop_config.json if it exists
187
+ const desktopConfig = join(home, ".claude", "claude_desktop_config.json");
188
+ if (existsSync(desktopConfig)) {
189
+ try {
190
+ const config = JSON.parse(readFileSync(desktopConfig, "utf8"));
191
+ if (!config.mcpServers) config.mcpServers = {};
192
+ if (!config.mcpServers["continuous-improvement"]) {
193
+ config.mcpServers["continuous-improvement"] = {
194
+ command: "node",
195
+ args: [mcpServerPath, "--mode", mcpMode],
196
+ };
197
+ writeFileSync(desktopConfig, JSON.stringify(config, null, 2) + "\n");
198
+ console.log(` ✓ Claude Desktop MCP config updated`);
199
+ }
200
+ } catch {
201
+ // skip
202
+ }
203
+ }
118
204
  }
119
205
 
120
206
  function patchClaudeSettings(observePath) {
@@ -159,11 +245,40 @@ function patchClaudeSettings(observePath) {
159
245
  }
160
246
  }
161
247
 
248
+ // Expert mode: add session hooks
249
+ if (INSTALL_MODE === "expert") {
250
+ const sessionPath = join(homedir(), ".claude", "instincts", "session.sh");
251
+ const sessionHook = {
252
+ matcher: "",
253
+ hooks: [{ type: "command", command: `bash "${sessionPath}"` }],
254
+ };
255
+
256
+ // Note: SessionStart/SessionEnd hooks may not be supported in all versions.
257
+ // We register them — they'll be silently ignored if unsupported.
258
+ for (const hookType of ["SessionStart", "SessionEnd"]) {
259
+ if (!Array.isArray(settings.hooks[hookType])) {
260
+ settings.hooks[hookType] = [];
261
+ }
262
+ const alreadyPatched = settings.hooks[hookType].some(
263
+ (h) =>
264
+ Array.isArray(h.hooks) &&
265
+ h.hooks.some((hh) => hh.command && hh.command.includes("session.sh"))
266
+ );
267
+ if (!alreadyPatched) {
268
+ settings.hooks[hookType].push(sessionHook);
269
+ changed = true;
270
+ }
271
+ }
272
+ }
273
+
162
274
  if (changed) {
163
275
  writeFileSync(settingsPath, JSON.stringify(settings, null, 2) + "\n");
164
- console.log(` ✓ Patched ~/.claude/settings.json with PreToolUse/PostToolUse hooks`);
276
+ const hookTypes = INSTALL_MODE === "expert"
277
+ ? "PreToolUse/PostToolUse/SessionStart/SessionEnd"
278
+ : "PreToolUse/PostToolUse";
279
+ console.log(` ✓ Patched ~/.claude/settings.json with ${hookTypes} hooks`);
165
280
  } else {
166
- console.log(` ✓ settings.json already has observe.sh hooks — no change needed`);
281
+ console.log(` ✓ settings.json already has hooks — no change needed`);
167
282
  }
168
283
  }
169
284
 
@@ -197,24 +312,28 @@ function uninstallAll() {
197
312
  }
198
313
  }
199
314
 
200
- // 3. Remove observe.sh from instincts dir
201
- const observeFile = join(home, ".claude", "instincts", "observe.sh");
202
- if (existsSync(observeFile)) {
203
- try {
204
- rmSync(observeFile);
205
- console.log(` ✓ Removed observe.sh`);
206
- } catch (err) {
207
- console.error(` ✗ observe.sh: ${err.message}`);
315
+ // 3. Remove observe.sh and session.sh from instincts dir
316
+ for (const hookFile of ["observe.sh", "session.sh"]) {
317
+ const filePath = join(home, ".claude", "instincts", hookFile);
318
+ if (existsSync(filePath)) {
319
+ try {
320
+ rmSync(filePath);
321
+ console.log(` ✓ Removed ${hookFile}`);
322
+ } catch (err) {
323
+ console.error(` ✗ ${hookFile}: ${err.message}`);
324
+ }
208
325
  }
209
326
  }
210
327
 
211
- // 4. Remove hooks from settings.json
328
+ // 4. Remove hooks and MCP server from settings.json
212
329
  const settingsPath = join(home, ".claude", "settings.json");
213
330
  if (existsSync(settingsPath)) {
214
331
  try {
215
332
  const settings = JSON.parse(readFileSync(settingsPath, "utf8"));
216
333
  let changed = false;
217
- for (const hookType of ["PreToolUse", "PostToolUse"]) {
334
+
335
+ // Remove all hook types
336
+ for (const hookType of ["PreToolUse", "PostToolUse", "SessionStart", "SessionEnd"]) {
218
337
  if (Array.isArray(settings.hooks?.[hookType])) {
219
338
  const before = settings.hooks[hookType].length;
220
339
  settings.hooks[hookType] = settings.hooks[hookType].filter(
@@ -222,22 +341,44 @@ function uninstallAll() {
222
341
  !(
223
342
  Array.isArray(h.hooks) &&
224
343
  h.hooks.some(
225
- (hh) => hh.command && hh.command.includes("observe.sh")
344
+ (hh) => hh.command && (hh.command.includes("observe.sh") || hh.command.includes("session.sh"))
226
345
  )
227
346
  )
228
347
  );
229
348
  if (settings.hooks[hookType].length < before) changed = true;
230
349
  }
231
350
  }
351
+
352
+ // Remove MCP server
353
+ if (settings.mcpServers?.["continuous-improvement"]) {
354
+ delete settings.mcpServers["continuous-improvement"];
355
+ changed = true;
356
+ }
357
+
232
358
  if (changed) {
233
359
  writeFileSync(settingsPath, JSON.stringify(settings, null, 2) + "\n");
234
- console.log(` ✓ Removed hooks from settings.json`);
360
+ console.log(` ✓ Removed hooks and MCP server from settings.json`);
235
361
  }
236
362
  } catch {
237
363
  console.warn(` ! Could not clean settings.json — remove hooks manually`);
238
364
  }
239
365
  }
240
366
 
367
+ // 5. Clean claude_desktop_config.json MCP entry
368
+ const desktopConfig = join(home, ".claude", "claude_desktop_config.json");
369
+ if (existsSync(desktopConfig)) {
370
+ try {
371
+ const config = JSON.parse(readFileSync(desktopConfig, "utf8"));
372
+ if (config.mcpServers?.["continuous-improvement"]) {
373
+ delete config.mcpServers["continuous-improvement"];
374
+ writeFileSync(desktopConfig, JSON.stringify(config, null, 2) + "\n");
375
+ console.log(` ✓ Removed MCP server from Claude Desktop config`);
376
+ }
377
+ } catch {
378
+ // skip
379
+ }
380
+ }
381
+
241
382
  if (removed === 0) {
242
383
  console.log(" No skill installations found.");
243
384
  }
@@ -253,13 +394,30 @@ Usage: npx continuous-improvement install [options]
253
394
 
254
395
  Options:
255
396
  --target <name> Install to specific target (claude, openclaw, cursor, codex, all)
397
+ --mode <mode> Installation mode:
398
+ beginner — hooks only, no MCP server (default)
399
+ expert — hooks + MCP server + session hooks + all tools
400
+ mcp — MCP server only (works with any MCP client)
256
401
  --uninstall Remove from all targets
257
402
  --help Show this help
258
403
 
404
+ Modes explained:
405
+ BEGINNER (default) Just works. Hooks capture silently, instincts grow over time.
406
+ 3 tools via /continuous-improvement command.
407
+
408
+ EXPERT Everything in beginner + MCP server with 8 tools:
409
+ import/export, manual instinct creation, observation viewer,
410
+ confidence tuning. Plus session start/end hooks.
411
+
412
+ MCP MCP server only — for editors that support MCP but not
413
+ Claude Code hooks (Cursor, Zed, Windsurf, VS Code).
414
+
259
415
  Examples:
260
- npx continuous-improvement install # auto-detect & install
261
- npx continuous-improvement install --target all # install everywhere
262
- npx continuous-improvement install --uninstall # remove all
416
+ npx continuous-improvement install # beginner (default)
417
+ npx continuous-improvement install --mode expert # full power
418
+ npx continuous-improvement install --mode mcp # MCP server only
419
+ npx continuous-improvement install --target all # install everywhere
420
+ npx continuous-improvement install --uninstall # remove all
263
421
  `);
264
422
  }
265
423
 
@@ -284,7 +442,7 @@ if (args.includes("--uninstall")) {
284
442
  }
285
443
 
286
444
  console.log(`
287
- continuous-improvement v2.1
445
+ continuous-improvement v3.0 (mode: ${INSTALL_MODE})
288
446
  Research → Plan → Execute → Verify → Reflect → Learn → Iterate
289
447
  `);
290
448
 
@@ -321,11 +479,19 @@ for (const t of targets) {
321
479
 
322
480
  const hasClaude = targets.includes("claude");
323
481
 
482
+ const modeInfo = {
483
+ beginner: "Hooks are capturing silently. System auto-levels as you use it.",
484
+ expert: "Full plugin active: hooks + MCP server + session hooks. 8 tools available.",
485
+ mcp: "MCP server registered. Connect from any MCP-compatible editor.",
486
+ };
487
+
324
488
  console.log(`
325
489
  ${installed > 0 ? "Done." : "Failed."} Installed to ${installed}/${targets.length} target(s).
326
- ${hasClaude ? "\nHooks are capturing. System auto-levels as you use it." : ""}
490
+ ${hasClaude ? `\n${modeInfo[INSTALL_MODE] || modeInfo.beginner}` : ""}
327
491
  Next steps:
328
492
  1. Start a new Claude Code session
329
493
  2. Say: "Use the continuous-improvement framework to [your task]"
330
494
  3. After your first task, run: /continuous-improvement
495
+ ${INSTALL_MODE === "expert" ? "\nMCP tools available: ci_status, ci_instincts, ci_reflect, ci_reinforce,\n ci_create_instinct, ci_observations, ci_export, ci_import" : ""}
496
+ ${INSTALL_MODE === "mcp" ? "\nMCP tools available: ci_status, ci_instincts, ci_reflect" : ""}
331
497
  `);