supermind-claude 2.1.1 → 4.0.2

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 (42) hide show
  1. package/.claude-plugin/plugin.json +21 -0
  2. package/README.md +34 -46
  3. package/agents/code-reviewer.md +81 -0
  4. package/cli/commands/doctor.js +415 -79
  5. package/cli/commands/install.js +16 -17
  6. package/cli/commands/skill.js +164 -0
  7. package/cli/commands/uninstall.js +32 -3
  8. package/cli/commands/update.js +25 -4
  9. package/cli/index.js +16 -4
  10. package/cli/lib/agents.js +413 -0
  11. package/cli/lib/executor.js +365 -0
  12. package/cli/lib/hooks.js +8 -1
  13. package/cli/lib/logger.js +1 -1
  14. package/cli/lib/planning.js +502 -0
  15. package/cli/lib/platform.js +4 -0
  16. package/cli/lib/plugin.js +127 -0
  17. package/cli/lib/settings.js +2 -40
  18. package/cli/lib/skills.js +39 -2
  19. package/cli/lib/vendor-skills.js +594 -0
  20. package/hooks/bash-permissions.js +196 -176
  21. package/hooks/context-monitor.js +79 -0
  22. package/hooks/improvement-logger.js +94 -0
  23. package/hooks/pre-merge-checklist.js +102 -0
  24. package/hooks/session-start.js +109 -5
  25. package/hooks/statusline-command.js +115 -29
  26. package/package.json +4 -2
  27. package/skills/anti-rationalization/SKILL.md +38 -0
  28. package/skills/brainstorming/SKILL.md +165 -0
  29. package/skills/code-review/SKILL.md +144 -0
  30. package/skills/executing-plans/SKILL.md +138 -0
  31. package/skills/finishing-branches/SKILL.md +144 -0
  32. package/skills/project/SKILL.md +533 -0
  33. package/skills/quick/SKILL.md +178 -0
  34. package/skills/supermind/SKILL.md +58 -4
  35. package/skills/supermind-init/SKILL.md +48 -2
  36. package/skills/systematic-debugging/SKILL.md +129 -0
  37. package/skills/tdd/SKILL.md +179 -0
  38. package/skills/using-git-worktrees/SKILL.md +138 -0
  39. package/skills/verification-before-completion/SKILL.md +54 -0
  40. package/skills/writing-plans/SKILL.md +169 -0
  41. package/templates/CLAUDE.md +124 -62
  42. package/cli/lib/plugins.js +0 -23
@@ -2,124 +2,460 @@
2
2
 
3
3
  const fs = require('fs');
4
4
  const path = require('path');
5
- const { PATHS } = require('../lib/platform');
5
+ const { PATHS, getPackageRoot } = require('../lib/platform');
6
6
  const logger = require('../lib/logger');
7
- const { SUPERMIND_PLUGINS } = require('../lib/settings');
8
7
  const { getHookFiles } = require('../lib/hooks');
9
- const { getSkillDirs } = require('../lib/skills');
8
+ const { getSkillDirs, getAgentFiles } = require('../lib/skills');
9
+ const { PLUGIN_KEY } = require('../lib/plugin');
10
+ const { readSettings } = require('../lib/settings');
10
11
  const { version } = require('../../package.json');
11
12
 
12
- function check(label, pass, detail) {
13
- if (pass) {
14
- logger.success(label);
15
- } else {
16
- logger.error(`${label}${detail ? ' \u2014 ' + detail : ''}`);
13
+ const { GREEN, RED, BOLD, R } = require('../lib/logger');
14
+
15
+ // ---------------------------------------------------------------------------
16
+ // Helpers
17
+ // ---------------------------------------------------------------------------
18
+
19
+ function section(title) {
20
+ console.log(`\n ${BOLD}${title}${R}`);
21
+ }
22
+
23
+ function ok(label) {
24
+ logger.success(label);
25
+ return true;
26
+ }
27
+
28
+ function fail(label, detail) {
29
+ logger.error(`${label}${detail ? ' — ' + detail : ''}`);
30
+ return false;
31
+ }
32
+
33
+ // ---------------------------------------------------------------------------
34
+ // Individual checks
35
+ // ---------------------------------------------------------------------------
36
+
37
+ function checkNode() {
38
+ const major = parseInt(process.versions.node.split('.')[0], 10);
39
+ return major >= 18
40
+ ? ok(`Node.js v${process.versions.node} (>= 18 required)`)
41
+ : fail(`Node.js v${process.versions.node}`, '>= 18 required');
42
+ }
43
+
44
+ function checkClaudeHome() {
45
+ return fs.existsSync(PATHS.claudeHome)
46
+ ? ok('~/.claude/ directory structure OK')
47
+ : fail('~/.claude/ directory missing');
48
+ }
49
+
50
+ function checkSettings() {
51
+ if (!fs.existsSync(PATHS.settings)) return fail('settings.json missing');
52
+ try {
53
+ JSON.parse(fs.readFileSync(PATHS.settings, 'utf-8'));
54
+ return ok('settings.json valid');
55
+ } catch (err) {
56
+ return fail('settings.json invalid', err.message);
17
57
  }
18
- return pass;
19
58
  }
20
59
 
21
- module.exports = function doctor(flags) {
22
- logger.banner();
23
- console.log(' Running health checks...\n');
60
+ // Template
61
+ function checkTemplate() {
62
+ return fs.existsSync(path.join(PATHS.templatesDir, 'CLAUDE.md'))
63
+ ? ok('CLAUDE.md template')
64
+ : fail('CLAUDE.md template missing');
65
+ }
24
66
 
25
- let passed = 0;
26
- let failed = 0;
67
+ // Sessions directory writable
68
+ function checkSessions() {
69
+ if (!fs.existsSync(PATHS.sessionsDir)) {
70
+ return fail('Sessions directory missing');
71
+ }
72
+ try {
73
+ fs.accessSync(PATHS.sessionsDir, fs.constants.W_OK);
74
+ return ok('Sessions directory writable');
75
+ } catch (err) {
76
+ return fail('Sessions directory not writable', err.message);
77
+ }
78
+ }
27
79
 
28
- function run(label, pass, detail) {
29
- if (check(label, pass, detail)) passed++;
30
- else failed++;
80
+ // Improvement log writable
81
+ function checkImprovementLog() {
82
+ try {
83
+ fs.appendFileSync(PATHS.improvementLog, '', { flag: 'a' });
84
+ return ok('Improvement log writable');
85
+ } catch (err) {
86
+ return fail('Improvement log not writable', err.message);
31
87
  }
88
+ }
32
89
 
33
- // Node.js version
34
- const nodeVersion = parseInt(process.versions.node.split('.')[0], 10);
35
- run('Node.js >= 18', nodeVersion >= 18, `found v${process.versions.node}`);
90
+ // Skills: verify all methodology skills installed with SKILL.md
91
+ function checkSkills() {
92
+ section('Skills');
93
+ let expectedDirs;
94
+ try {
95
+ expectedDirs = getSkillDirs();
96
+ } catch (err) {
97
+ logger.warn(`Could not enumerate skills from package: ${err.message}`);
98
+ expectedDirs = [
99
+ 'supermind', 'quick', 'project', 'brainstorming', 'tdd',
100
+ 'systematic-debugging', 'anti-rationalization', 'verification-before-completion',
101
+ 'code-review', 'writing-plans', 'executing-plans', 'finishing-branches',
102
+ 'using-git-worktrees', 'supermind-init', 'supermind-living-docs',
103
+ ];
104
+ }
36
105
 
37
- // Claude home
38
- run('~/.claude/ exists', fs.existsSync(PATHS.claudeHome));
106
+ const missing = [];
107
+ for (const dir of expectedDirs) {
108
+ const skillPath = path.join(PATHS.skillsDir, dir);
109
+ const hasDir = fs.existsSync(skillPath);
110
+ const hasSkillMd = hasDir && fs.existsSync(path.join(skillPath, 'SKILL.md'));
111
+ if (!hasDir || !hasSkillMd) missing.push(dir);
112
+ }
39
113
 
40
- // Settings
41
- const settingsExists = fs.existsSync(PATHS.settings);
42
- run('settings.json exists', settingsExists);
114
+ const installed = expectedDirs.length - missing.length;
115
+ if (missing.length === 0) {
116
+ ok(`${installed}/${expectedDirs.length} skills installed`);
117
+ return true;
118
+ }
119
+ fail(`${installed}/${expectedDirs.length} skills installed — missing: ${missing.join(', ')}`);
120
+ return false;
121
+ }
43
122
 
44
- let settings = {};
45
- if (settingsExists) {
46
- try {
47
- settings = JSON.parse(fs.readFileSync(PATHS.settings, 'utf-8'));
48
- run('settings.json is valid JSON', true);
49
- } catch (err) {
50
- run('settings.json is valid JSON', false, err.message);
123
+ // Agents: verify agent definitions exist
124
+ function checkAgents() {
125
+ section('Agents');
126
+ let expectedFiles;
127
+ try {
128
+ expectedFiles = getAgentFiles();
129
+ } catch (err) {
130
+ logger.warn(`Could not enumerate agents from package: ${err.message}`);
131
+ expectedFiles = ['code-reviewer.md'];
132
+ }
133
+
134
+ const missing = [];
135
+ for (const file of expectedFiles) {
136
+ if (!fs.existsSync(path.join(PATHS.agentsDir, file))) missing.push(file);
137
+ }
138
+
139
+ const installed = expectedFiles.length - missing.length;
140
+ if (missing.length === 0) {
141
+ ok(`${installed}/${expectedFiles.length} agents installed`);
142
+ return true;
143
+ }
144
+ fail(`${installed}/${expectedFiles.length} agents installed — missing: ${missing.join(', ')}`);
145
+ return false;
146
+ }
147
+
148
+ // Hooks: verify all 8 hooks exist and are registered in settings.json
149
+ function checkHooks() {
150
+ section('Hooks');
151
+ let expectedFiles;
152
+ try {
153
+ expectedFiles = getHookFiles();
154
+ } catch (err) {
155
+ logger.warn(`Could not enumerate hooks from package: ${err.message}`);
156
+ expectedFiles = [
157
+ 'bash-permissions.js', 'session-start.js', 'session-end.js',
158
+ 'cost-tracker.js', 'statusline-command.js', 'context-monitor.js',
159
+ 'pre-merge-checklist.js', 'improvement-logger.js',
160
+ ];
161
+ }
162
+
163
+ // Check files on disk
164
+ const missingFiles = [];
165
+ for (const file of expectedFiles) {
166
+ if (!fs.existsSync(path.join(PATHS.hooksDir, file))) missingFiles.push(file);
167
+ }
168
+
169
+ // Check registration in settings.json
170
+ const settings = readSettings();
171
+ if (!settings || Object.keys(settings).length === 0) {
172
+ if (missingFiles.length > 0) {
173
+ fail(`Hooks — missing files: ${missingFiles.join(', ')}`);
174
+ } else {
175
+ ok(`${expectedFiles.length}/${expectedFiles.length} hooks installed`);
176
+ }
177
+ logger.warn('Hook registration check skipped — settings.json empty or unreadable');
178
+ return missingFiles.length === 0;
179
+ }
180
+ const settingsJson = JSON.stringify(settings);
181
+ const unregistered = [];
182
+ for (const file of expectedFiles) {
183
+ // statusline-command.js is registered under statusLine, not hooks
184
+ if (file === 'statusline-command.js') {
185
+ if (!settings.statusLine || !JSON.stringify(settings.statusLine).includes(file)) {
186
+ unregistered.push(file);
187
+ }
188
+ } else if (!settingsJson.includes(file)) {
189
+ unregistered.push(file);
51
190
  }
52
191
  }
53
192
 
54
- // Hooks present
55
- let expectedHooks;
193
+ const fileOk = missingFiles.length === 0;
194
+ const regOk = unregistered.length === 0;
195
+ const total = expectedFiles.length;
196
+
197
+ if (fileOk && regOk) {
198
+ ok(`${total}/${total} hooks installed and registered`);
199
+ return true;
200
+ }
201
+ const issues = [];
202
+ if (!fileOk) issues.push(`missing files: ${missingFiles.join(', ')}`);
203
+ if (!regOk) issues.push(`not registered: ${unregistered.join(', ')}`);
204
+ fail(`Hooks — ${issues.join('; ')}`);
205
+ return false;
206
+ }
207
+
208
+ // Context monitor: verify hook exists, optionally check metrics file
209
+ function checkContextMonitor() {
210
+ section('Context monitor');
211
+ const hookExists = fs.existsSync(path.join(PATHS.hooksDir, 'context-monitor.js'));
212
+ if (!hookExists) {
213
+ fail('context-monitor.js hook missing');
214
+ return false;
215
+ }
216
+
217
+ const metricsPath = path.join(PATHS.claudeHome, 'context-metrics.json');
218
+ if (fs.existsSync(metricsPath)) {
219
+ ok('active (metrics file present)');
220
+ } else {
221
+ ok('installed (metrics written during active sessions)');
222
+ }
223
+ return true;
224
+ }
225
+
226
+ // Plugin manifest: verify registration and cached manifest
227
+ function checkPlugin() {
228
+ section('Plugin manifest');
229
+
230
+ const pluginsPath = path.join(PATHS.claudeHome, 'plugins', 'installed_plugins.json');
231
+ if (!fs.existsSync(pluginsPath)) {
232
+ return fail('not registered — installed_plugins.json missing');
233
+ }
234
+
235
+ let registry;
56
236
  try {
57
- expectedHooks = getHookFiles();
237
+ registry = JSON.parse(fs.readFileSync(pluginsPath, 'utf-8'));
58
238
  } catch (err) {
59
- run('Hook enumeration', false, err.message);
60
- expectedHooks = [];
239
+ return fail('installed_plugins.json invalid', err.message);
61
240
  }
62
- for (const file of expectedHooks) {
63
- run(`Hook: ${file}`, fs.existsSync(path.join(PATHS.hooksDir, file)));
241
+
242
+ const entry = registry.plugins && registry.plugins[PLUGIN_KEY];
243
+ if (!entry || !Array.isArray(entry) || entry.length === 0) {
244
+ return fail('not registered in installed_plugins.json');
245
+ }
246
+
247
+ const installPath = entry[0].installPath;
248
+ if (!installPath) {
249
+ return fail('plugin registry entry missing installPath');
250
+ }
251
+
252
+ const manifestPath = path.join(installPath, '.claude-plugin', 'plugin.json');
253
+ if (!fs.existsSync(manifestPath)) {
254
+ return fail('manifest missing from cache');
64
255
  }
65
256
 
66
- // Skills present
67
- let expectedSkills;
68
257
  try {
69
- expectedSkills = getSkillDirs();
258
+ JSON.parse(fs.readFileSync(manifestPath, 'utf-8'));
259
+ return ok('valid');
70
260
  } catch (err) {
71
- run('Skill enumeration', false, err.message);
72
- expectedSkills = [];
261
+ return fail('plugin.json manifest invalid', err.message);
73
262
  }
74
- for (const dir of expectedSkills) {
75
- const skillPath = path.join(PATHS.skillsDir, dir);
76
- run(`Skill: ${dir}`, fs.existsSync(skillPath) && fs.existsSync(path.join(skillPath, 'SKILL.md')));
263
+ }
264
+
265
+ // Executor engine: verify core modules exist in package
266
+ function checkExecutorEngine() {
267
+ section('Executor engine');
268
+ const root = getPackageRoot();
269
+ const modules = ['cli/lib/executor.js', 'cli/lib/agents.js', 'cli/lib/planning.js'];
270
+ const missing = modules.filter(m => !fs.existsSync(path.join(root, m)));
271
+
272
+ if (missing.length === 0) {
273
+ return ok('modules present');
77
274
  }
275
+ return fail(`missing: ${missing.join(', ')}`);
276
+ }
78
277
 
79
- // Plugins
80
- if (SUPERMIND_PLUGINS.length === 0) {
81
- logger.warn('Plugin list unavailable — plugin checks skipped');
82
- } else {
83
- for (const id of SUPERMIND_PLUGINS) {
84
- run(`Plugin: ${id.split('@')[0]}`, settings.enabledPlugins?.[id] === true);
85
- }
278
+ // Safety layer: verify blocklist model
279
+ function checkSafety() {
280
+ section('Safety layer');
281
+ const hookPath = path.join(PATHS.hooksDir, 'bash-permissions.js');
282
+ if (!fs.existsSync(hookPath)) {
283
+ return fail('bash-permissions.js not found');
284
+ }
285
+
286
+ let content;
287
+ try {
288
+ content = fs.readFileSync(hookPath, 'utf-8');
289
+ } catch (err) {
290
+ return fail('bash-permissions.js unreadable', err.message);
291
+ }
292
+
293
+ const blocklist = content.includes('BLOCKED') || content.includes('blocklist');
294
+ if (!blocklist) {
295
+ return fail('bash-permissions.js does not use blocklist model');
296
+ }
297
+
298
+ return ok('blocklist model');
299
+ }
300
+
301
+ // .planning/ check: project-specific, not an error if absent
302
+ function checkPlanning() {
303
+ section('Planning');
304
+ const projectDir = process.env.PROJECT_DIR || process.cwd();
305
+ const planningDir = path.join(projectDir, '.planning');
306
+
307
+ if (!fs.existsSync(planningDir)) {
308
+ return ok('no active session');
86
309
  }
87
310
 
88
- // Template
89
- run('CLAUDE.md template', fs.existsSync(path.join(PATHS.templatesDir, 'CLAUDE.md')));
311
+ let allOk = true;
90
312
 
91
- // Sessions directory
92
- run('Sessions directory writable', (() => {
93
- const testFile = path.join(PATHS.sessionsDir, '.doctor-test');
313
+ // Verify roadmap.md — read once, reuse for active phase detection
314
+ const roadmapPath = path.join(planningDir, 'roadmap.md');
315
+ let roadmapContent = null;
316
+ if (fs.existsSync(roadmapPath)) {
94
317
  try {
95
- fs.writeFileSync(testFile, 'test');
96
- } catch {
97
- return false;
318
+ roadmapContent = fs.readFileSync(roadmapPath, 'utf-8');
319
+ ok('roadmap.md present');
320
+ } catch (err) {
321
+ fail('roadmap.md unreadable', err.message);
322
+ allOk = false;
98
323
  }
99
- try { fs.unlinkSync(testFile); } catch { /* cleanup non-critical */ }
100
- return true;
101
- })());
324
+ } else {
325
+ fail('roadmap.md missing from .planning/');
326
+ allOk = false;
327
+ }
102
328
 
103
- // Docker (warn only, not required)
104
- try {
105
- require('child_process').execSync('docker compose version', { stdio: 'pipe', timeout: 5000 });
106
- logger.success('Docker available');
107
- passed++;
108
- } catch {
109
- logger.warn('Docker not available (optional \u2014 needed for AIRIS mode)');
329
+ // Verify config.json
330
+ const configPath = path.join(planningDir, 'config.json');
331
+ if (fs.existsSync(configPath)) {
332
+ try {
333
+ JSON.parse(fs.readFileSync(configPath, 'utf-8'));
334
+ ok('config.json valid');
335
+ } catch (err) {
336
+ fail('config.json invalid', err.message);
337
+ allOk = false;
338
+ }
339
+ } else {
340
+ fail('config.json missing from .planning/');
341
+ allOk = false;
110
342
  }
111
343
 
112
- // Version
344
+ // Report active phase if detectable
345
+ if (roadmapContent) {
346
+ const activeMatch = roadmapContent.match(/\|\s*(\d+)\s*\|[^|]*\|\s*(?:in.progress|active|executing)/i);
347
+ if (activeMatch) {
348
+ logger.info(`Active phase: ${activeMatch[1]}`);
349
+ }
350
+ }
351
+
352
+ return allOk;
353
+ }
354
+
355
+ // Version marker
356
+ function checkVersion() {
357
+ section('Version');
113
358
  let installedVersion = 'not found';
114
359
  try {
115
360
  installedVersion = fs.readFileSync(PATHS.versionFile, 'utf-8').trim();
116
361
  } catch (err) {
117
- if (err.code !== 'ENOENT') {
118
- installedVersion = `error: ${err.message}`;
119
- }
362
+ if (err.code !== 'ENOENT') installedVersion = `error: ${err.message}`;
120
363
  }
121
- run('Version marker', installedVersion === version, installedVersion !== version ? `installed: ${installedVersion}, package: ${version}` : undefined);
122
364
 
123
- console.log(`\n ${passed} passed, ${failed} failed\n`);
124
- if (failed > 0) process.exit(1);
365
+ if (installedVersion === version) {
366
+ return ok(`v${version}`);
367
+ }
368
+ return fail(`Version mismatch — installed: ${installedVersion}, package: ${version}`);
369
+ }
370
+
371
+ // Vendor skills (optional, returns failure count)
372
+ function checkVendorSkills() {
373
+ let vendorSkills;
374
+ try {
375
+ vendorSkills = require('../lib/vendor-skills');
376
+ } catch {
377
+ return 0; // Module not available — no vendor skills to check
378
+ }
379
+
380
+ try {
381
+ const result = vendorSkills.verifySkills();
382
+ if (result.valid.length === 0 && result.missing.length === 0) return 0;
383
+ section('Vendor skills');
384
+ let failures = 0;
385
+ for (const name of result.valid) { ok(name); }
386
+ for (const name of result.missing) { fail(name, 'directory not found'); failures++; }
387
+ return failures;
388
+ } catch (err) {
389
+ section('Vendor skills');
390
+ fail('Vendor skill verification failed', err.message);
391
+ return 1;
392
+ }
393
+ }
394
+
395
+ // Docker (optional, warn only)
396
+ function checkDocker() {
397
+ try {
398
+ // Static command, no user input — safe to use execSync
399
+ require('child_process').execSync('docker compose version', { stdio: 'pipe', timeout: 5000 });
400
+ ok('Docker available');
401
+ } catch {
402
+ logger.warn('Docker not available (optional — needed for AIRIS mode)');
403
+ }
404
+ }
405
+
406
+ // ---------------------------------------------------------------------------
407
+ // Main
408
+ // ---------------------------------------------------------------------------
409
+
410
+ module.exports = function doctor(flags) {
411
+ logger.banner();
412
+ console.log(' Running health checks...');
413
+
414
+ let failed = 0;
415
+ const run = (fn) => {
416
+ try {
417
+ if (!fn()) failed++;
418
+ } catch (err) {
419
+ fail(`${fn.name || 'check'} crashed`, err.message);
420
+ failed++;
421
+ }
422
+ };
423
+
424
+ // Foundation
425
+ run(checkNode);
426
+ run(checkClaudeHome);
427
+ run(checkSettings);
428
+ run(checkTemplate);
429
+ run(checkSessions);
430
+ run(checkImprovementLog);
431
+
432
+ // Components
433
+ run(checkSkills);
434
+ run(checkAgents);
435
+ run(checkHooks);
436
+
437
+ // Subsystems
438
+ run(checkContextMonitor);
439
+ run(checkPlugin);
440
+ run(checkExecutorEngine);
441
+ run(checkSafety);
442
+
443
+ // Project-specific
444
+ run(checkPlanning);
445
+
446
+ // Version
447
+ run(checkVersion);
448
+
449
+ // Optional (don't count as failures for overall health)
450
+ failed += checkVendorSkills();
451
+ checkDocker();
452
+
453
+ // Overall
454
+ console.log('');
455
+ if (failed === 0) {
456
+ console.log(` ${GREEN}${BOLD}Overall: healthy ✓${R}\n`);
457
+ } else {
458
+ console.log(` ${RED}${BOLD}Overall: ${failed} issue${failed === 1 ? '' : 's'} found${R}\n`);
459
+ process.exit(1);
460
+ }
125
461
  };
@@ -5,10 +5,10 @@ const { PATHS, ensureDir } = require('../lib/platform');
5
5
  const logger = require('../lib/logger');
6
6
  const { readSettings, writeSettings, backupSettings, mergeSettings } = require('../lib/settings');
7
7
  const { installHooks, getHookSettings } = require('../lib/hooks');
8
- const { installSkills, removeLegacySkills } = require('../lib/skills');
9
- const { getPluginDefaults } = require('../lib/plugins');
8
+ const { installSkills, removeLegacySkills, installAgents } = require('../lib/skills');
10
9
  const { setupMcp } = require('../lib/mcp');
11
10
  const { installTemplates } = require('../lib/templates');
11
+ const { installPlugin } = require('../lib/plugin');
12
12
  const { version } = require('../../package.json');
13
13
 
14
14
  module.exports = async function install(flags) {
@@ -20,6 +20,7 @@ module.exports = async function install(flags) {
20
20
  ensureDir(PATHS.claudeHome);
21
21
  ensureDir(PATHS.hooksDir);
22
22
  ensureDir(PATHS.skillsDir);
23
+ ensureDir(PATHS.agentsDir);
23
24
  ensureDir(PATHS.sessionsDir);
24
25
  logger.success(`Claude home: ${PATHS.claudeHome}`);
25
26
 
@@ -34,10 +35,8 @@ module.exports = async function install(flags) {
34
35
  backupSettings();
35
36
  const existing = readSettings();
36
37
  const hookSettings = getHookSettings();
37
- const pluginDefaults = getPluginDefaults();
38
38
  const defaults = {
39
39
  ...hookSettings,
40
- ...pluginDefaults,
41
40
  alwaysThinkingEnabled: true,
42
41
  effortLevel: 'high',
43
42
  };
@@ -50,19 +49,15 @@ module.exports = async function install(flags) {
50
49
  const hookFiles = installHooks();
51
50
  logger.info(`${hookFiles.length} hooks installed`);
52
51
 
53
- // Step 4: Skills
54
- logger.step(4, TOTAL, 'Installing skills...');
52
+ // Step 4: Skills & agents
53
+ logger.step(4, TOTAL, 'Installing skills and agents...');
55
54
  removeLegacySkills();
56
55
  const skillDirs = installSkills();
57
- logger.info(`${skillDirs.length} skill directories installed`);
56
+ const agentFiles = installAgents();
57
+ logger.info(`${skillDirs.length} skill directories, ${agentFiles.length} agent definitions installed`);
58
58
 
59
- // Step 5: Plugins (data already merged in Step 2 via getPluginDefaults — this step is log-only)
60
- logger.step(5, TOTAL, 'Enabling plugins...');
61
- const pluginNames = Object.keys(pluginDefaults.enabledPlugins).map(k => k.split('@')[0]);
62
- logger.success(pluginNames.join(', '));
63
-
64
- // Step 6: MCP servers
65
- logger.step(6, TOTAL, 'MCP server setup...');
59
+ // Step 5: MCP servers
60
+ logger.step(5, TOTAL, 'MCP server setup...');
66
61
  const mcpConfig = await setupMcp(flags);
67
62
  if (mcpConfig.mcpServers) {
68
63
  merged = readSettings();
@@ -70,17 +65,21 @@ module.exports = async function install(flags) {
70
65
  writeSettings(merged);
71
66
  }
72
67
 
73
- // Step 7: Templates
74
- logger.step(7, TOTAL, 'Installing templates...');
68
+ // Step 6: Templates
69
+ logger.step(6, TOTAL, 'Installing templates...');
75
70
  installTemplates(mcpConfig.mode);
76
71
 
72
+ // Step 7: Plugin manifest
73
+ logger.step(7, TOTAL, 'Registering plugin...');
74
+ installPlugin();
75
+
77
76
  // Write version marker
78
77
  fs.writeFileSync(PATHS.versionFile, version);
79
78
 
80
79
  // Summary
81
80
  console.log(`\n${'\x1b[32m'}\u2713 Supermind v${version} installed successfully${'\x1b[0m'}\n`);
82
81
  console.log(' Next steps:');
83
- console.log(' 1. Restart Claude Code to activate plugins');
82
+ console.log(' 1. Restart Claude Code to activate hooks');
84
83
  console.log(' 2. In any project, run /supermind-init to set up project docs');
85
84
  console.log(' 3. Run: npx supermind-claude doctor to verify installation\n');
86
85
  };