supermind-claude 2.0.2 → 2.1.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.
@@ -4,7 +4,7 @@ const fs = require('fs');
4
4
  const path = require('path');
5
5
  const { PATHS } = require('../lib/platform');
6
6
  const logger = require('../lib/logger');
7
- const { readSettings, SUPERMIND_PLUGINS } = require('../lib/settings');
7
+ const { SUPERMIND_PLUGINS } = require('../lib/settings');
8
8
  const { getHookFiles } = require('../lib/hooks');
9
9
  const { getSkillDirs } = require('../lib/skills');
10
10
  const { version } = require('../../package.json');
@@ -46,27 +46,43 @@ module.exports = function doctor(flags) {
46
46
  try {
47
47
  settings = JSON.parse(fs.readFileSync(PATHS.settings, 'utf-8'));
48
48
  run('settings.json is valid JSON', true);
49
- } catch {
50
- run('settings.json is valid JSON', false, 'parse error');
49
+ } catch (err) {
50
+ run('settings.json is valid JSON', false, err.message);
51
51
  }
52
52
  }
53
53
 
54
54
  // Hooks present
55
- const expectedHooks = getHookFiles();
55
+ let expectedHooks;
56
+ try {
57
+ expectedHooks = getHookFiles();
58
+ } catch (err) {
59
+ run('Hook enumeration', false, err.message);
60
+ expectedHooks = [];
61
+ }
56
62
  for (const file of expectedHooks) {
57
63
  run(`Hook: ${file}`, fs.existsSync(path.join(PATHS.hooksDir, file)));
58
64
  }
59
65
 
60
66
  // Skills present
61
- const expectedSkills = getSkillDirs();
67
+ let expectedSkills;
68
+ try {
69
+ expectedSkills = getSkillDirs();
70
+ } catch (err) {
71
+ run('Skill enumeration', false, err.message);
72
+ expectedSkills = [];
73
+ }
62
74
  for (const dir of expectedSkills) {
63
75
  const skillPath = path.join(PATHS.skillsDir, dir);
64
76
  run(`Skill: ${dir}`, fs.existsSync(skillPath) && fs.existsSync(path.join(skillPath, 'SKILL.md')));
65
77
  }
66
78
 
67
79
  // Plugins
68
- for (const id of SUPERMIND_PLUGINS) {
69
- run(`Plugin: ${id.split('@')[0]}`, settings.enabledPlugins?.[id] === true);
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
+ }
70
86
  }
71
87
 
72
88
  // Template
@@ -74,12 +90,14 @@ module.exports = function doctor(flags) {
74
90
 
75
91
  // Sessions directory
76
92
  run('Sessions directory writable', (() => {
93
+ const testFile = path.join(PATHS.sessionsDir, '.doctor-test');
77
94
  try {
78
- const testFile = path.join(PATHS.sessionsDir, '.doctor-test');
79
95
  fs.writeFileSync(testFile, 'test');
80
- fs.unlinkSync(testFile);
81
- return true;
82
- } catch { return false; }
96
+ } catch {
97
+ return false;
98
+ }
99
+ try { fs.unlinkSync(testFile); } catch { /* cleanup non-critical */ }
100
+ return true;
83
101
  })());
84
102
 
85
103
  // Docker (warn only, not required)
@@ -93,7 +111,13 @@ module.exports = function doctor(flags) {
93
111
 
94
112
  // Version
95
113
  let installedVersion = 'not found';
96
- try { installedVersion = fs.readFileSync(PATHS.versionFile, 'utf-8').trim(); } catch {}
114
+ try {
115
+ installedVersion = fs.readFileSync(PATHS.versionFile, 'utf-8').trim();
116
+ } catch (err) {
117
+ if (err.code !== 'ENOENT') {
118
+ installedVersion = `error: ${err.message}`;
119
+ }
120
+ }
97
121
  run('Version marker', installedVersion === version, installedVersion !== version ? `installed: ${installedVersion}, package: ${version}` : undefined);
98
122
 
99
123
  console.log(`\n ${passed} passed, ${failed} failed\n`);
@@ -58,7 +58,8 @@ module.exports = async function install(flags) {
58
58
 
59
59
  // Step 5: Plugins (data already merged in Step 2 via getPluginDefaults — this step is log-only)
60
60
  logger.step(5, TOTAL, 'Enabling plugins...');
61
- logger.success('superpowers, frontend-design, claude-md-management, ui-ux-pro-max');
61
+ const pluginNames = Object.keys(pluginDefaults.enabledPlugins).map(k => k.split('@')[0]);
62
+ logger.success(pluginNames.join(', '));
62
63
 
63
64
  // Step 6: MCP servers
64
65
  logger.step(6, TOTAL, 'MCP server setup...');
@@ -71,7 +72,7 @@ module.exports = async function install(flags) {
71
72
 
72
73
  // Step 7: Templates
73
74
  logger.step(7, TOTAL, 'Installing templates...');
74
- installTemplates();
75
+ installTemplates(mcpConfig.mode);
75
76
 
76
77
  // Write version marker
77
78
  fs.writeFileSync(PATHS.versionFile, version);
@@ -4,7 +4,7 @@ const fs = require('fs');
4
4
  const readline = require('readline');
5
5
  const { PATHS } = require('../lib/platform');
6
6
  const logger = require('../lib/logger');
7
- const { readSettings, writeSettings, removeSupermindEntries } = require('../lib/settings');
7
+ const { readSettings, writeSettings, removeSupermindEntries, backupSettings } = require('../lib/settings');
8
8
  const { removeHooks } = require('../lib/hooks');
9
9
  const { removeSkills } = require('../lib/skills');
10
10
  const { removeTemplates } = require('../lib/templates');
@@ -41,6 +41,7 @@ module.exports = async function uninstall(flags) {
41
41
 
42
42
  // Clean settings
43
43
  console.log(' Cleaning settings...');
44
+ backupSettings();
44
45
  const settings = readSettings();
45
46
  const cleaned = removeSupermindEntries(settings);
46
47
  writeSettings(cleaned);
@@ -3,10 +3,11 @@
3
3
  const fs = require('fs');
4
4
  const { PATHS } = require('../lib/platform');
5
5
  const logger = require('../lib/logger');
6
- const { readSettings, writeSettings, mergeSettings } = require('../lib/settings');
6
+ const { readSettings, writeSettings, mergeSettings, backupSettings } = require('../lib/settings');
7
7
  const { installHooks, getHookSettings } = require('../lib/hooks');
8
8
  const { installSkills, removeLegacySkills } = require('../lib/skills');
9
9
  const { installTemplates } = require('../lib/templates');
10
+ const { detectMcpMode } = require('../lib/mcp');
10
11
  const { version } = require('../../package.json');
11
12
 
12
13
  module.exports = function update(flags) {
@@ -30,6 +31,7 @@ module.exports = function update(flags) {
30
31
 
31
32
  // Step 2: Hook settings (re-merge to pick up any new hooks)
32
33
  logger.step(2, TOTAL, 'Updating settings...');
34
+ backupSettings();
33
35
  const existing = readSettings();
34
36
  const hookSettings = getHookSettings();
35
37
  const merged = mergeSettings(existing, hookSettings);
@@ -43,7 +45,7 @@ module.exports = function update(flags) {
43
45
 
44
46
  // Step 4: Templates
45
47
  logger.step(4, TOTAL, 'Updating templates...');
46
- installTemplates();
48
+ installTemplates(detectMcpMode());
47
49
 
48
50
  // Write version marker
49
51
  fs.writeFileSync(PATHS.versionFile, version);
package/cli/lib/mcp.js CHANGED
@@ -91,22 +91,42 @@ async function setupMcp(flags) {
91
91
  }
92
92
  if (!mode || mode === 'skip') {
93
93
  logger.info('Skipping MCP setup');
94
- return {};
94
+ return { mode: 'skip' };
95
95
  }
96
96
 
97
97
  if (mode === 'docker') {
98
98
  await setupDocker();
99
- return {}; // Docker mode uses AIRIS, not settings.json mcpServers
99
+ return { mode: 'docker' }; // Docker uses AIRIS gateway; mode drives template MCP section
100
100
  }
101
101
 
102
102
  if (mode === 'direct') {
103
103
  const apiKeys = await promptApiKeys(flags);
104
104
  const servers = setupDirect(apiKeys);
105
105
  logger.success(`Configured ${Object.keys(servers).length} MCP servers`);
106
- return { mcpServers: servers };
106
+ return { mode: 'direct', mcpServers: servers };
107
107
  }
108
108
 
109
- return {};
109
+ return { mode: 'skip' };
110
110
  }
111
111
 
112
- module.exports = { setupMcp };
112
+ // Infer MCP mode from installed artifacts. Used by update to re-render the template MCP section.
113
+ function detectMcpMode() {
114
+ if (fs.existsSync(path.join(PATHS.airisDir, 'docker-compose.yml'))) {
115
+ return 'docker';
116
+ }
117
+ // Any known direct-mode server in settings.json means direct install was used
118
+ try {
119
+ const settings = JSON.parse(fs.readFileSync(PATHS.settings, 'utf-8'));
120
+ const servers = settings.mcpServers || {};
121
+ if (servers.context7 || servers.playwright || servers.serena || servers.tavily) {
122
+ return 'direct';
123
+ }
124
+ } catch (err) {
125
+ if (err.code !== 'ENOENT') {
126
+ logger.warn(`Could not read settings.json to detect MCP mode: ${err.message}`);
127
+ }
128
+ }
129
+ return 'skip';
130
+ }
131
+
132
+ module.exports = { setupMcp, detectMcpMode };
@@ -7,11 +7,15 @@ function getPluginDefaults() {
7
7
  'claude-md-management@claude-plugins-official': true,
8
8
  'frontend-design@claude-plugins-official': true,
9
9
  'ui-ux-pro-max@ui-ux-pro-max-skill': true,
10
+ 'pr-review-toolkit@claude-plugins-official': true,
11
+ 'security-guidance@claude-plugins-official': true,
12
+ 'elements-of-style@superpowers-marketplace': true,
10
13
  },
11
14
  extraKnownMarketplaces: {
12
15
  'ui-ux-pro-max-skill': {
13
16
  source: { source: 'github', repo: 'nextlevelbuilder/ui-ux-pro-max-skill' },
14
17
  },
18
+ // superpowers-marketplace is a built-in Claude Code marketplace — no source config needed
15
19
  },
16
20
  };
17
21
  }
@@ -10,23 +10,42 @@ const SUPERMIND_HOOKS = [
10
10
  'cost-tracker.js', 'statusline-command.js',
11
11
  ];
12
12
 
13
- const SUPERMIND_PLUGINS = [
14
- 'superpowers@claude-plugins-official',
15
- 'claude-md-management@claude-plugins-official',
16
- 'frontend-design@claude-plugins-official',
17
- 'ui-ux-pro-max@ui-ux-pro-max-skill',
18
- ];
13
+ // Derived from plugins.js — single source of truth for plugin and marketplace IDs.
14
+ // Wrapped in try-catch so a plugins.js error doesn't crash doctor/uninstall.
15
+ function loadPluginIds() {
16
+ try {
17
+ const { getPluginDefaults } = require('./plugins');
18
+ const defaults = getPluginDefaults();
19
+ return {
20
+ plugins: Object.keys(defaults.enabledPlugins),
21
+ marketplaces: Object.keys(defaults.extraKnownMarketplaces),
22
+ };
23
+ } catch (err) {
24
+ logger.warn(`Could not load plugins.js — plugin checks/cleanup will be skipped (${err.message})`);
25
+ return { plugins: [], marketplaces: [] };
26
+ }
27
+ }
28
+
29
+ const { plugins: SUPERMIND_PLUGINS, marketplaces: SUPERMIND_MARKETPLACES } = loadPluginIds();
30
+ // SUPERMIND_MARKETPLACES is used only within this module (for uninstall cleanup) — intentionally not exported
19
31
 
20
32
  function readSettings() {
21
33
  try {
22
34
  return JSON.parse(fs.readFileSync(PATHS.settings, 'utf-8'));
23
- } catch {
35
+ } catch (err) {
36
+ if (err.code === 'ENOENT') return {};
37
+ logger.warn(`Failed to read settings.json: ${err.message}`);
24
38
  return {};
25
39
  }
26
40
  }
27
41
 
28
42
  function writeSettings(settings) {
29
- fs.writeFileSync(PATHS.settings, JSON.stringify(settings, null, 2) + '\n');
43
+ try {
44
+ fs.writeFileSync(PATHS.settings, JSON.stringify(settings, null, 2) + '\n');
45
+ } catch (err) {
46
+ logger.error(`Could not write settings.json: ${err.message}`);
47
+ throw err;
48
+ }
30
49
  }
31
50
 
32
51
  function backupSettings() {
@@ -117,16 +136,21 @@ function removeSupermindEntries(settings) {
117
136
  // Remove statusLine
118
137
  delete result.statusLine;
119
138
 
120
- // Remove Supermind plugins
121
- if (result.enabledPlugins) {
122
- for (const id of SUPERMIND_PLUGINS) {
123
- delete result.enabledPlugins[id];
139
+ // Remove Supermind plugins and marketplace entries
140
+ if (SUPERMIND_PLUGINS.length === 0) {
141
+ logger.warn('Plugin/marketplace list unavailable these entries were NOT removed from settings. ' +
142
+ 'You may need to manually edit ~/.claude/settings.json');
143
+ } else {
144
+ if (result.enabledPlugins) {
145
+ for (const id of SUPERMIND_PLUGINS) {
146
+ delete result.enabledPlugins[id];
147
+ }
148
+ }
149
+ if (result.extraKnownMarketplaces) {
150
+ for (const id of SUPERMIND_MARKETPLACES) {
151
+ delete result.extraKnownMarketplaces[id];
152
+ }
124
153
  }
125
- }
126
-
127
- // Remove Supermind marketplace entries
128
- if (result.extraKnownMarketplaces) {
129
- delete result.extraKnownMarketplaces['ui-ux-pro-max-skill'];
130
154
  }
131
155
 
132
156
  // Remove Supermind hooks from each event
@@ -5,11 +5,58 @@ const path = require('path');
5
5
  const { PATHS, ensureDir, getPackageRoot } = require('./platform');
6
6
  const logger = require('./logger');
7
7
 
8
- function installTemplates() {
8
+ const MCP_SECTIONS = {
9
+ docker: `## MCP Servers
10
+ Use these naturally when relevant — don't wait to be asked.
11
+
12
+ - **Magic MCP** — \`component_builder\`, \`component_inspiration\`, \`component_refiner\`, \`logo_search\` — use when building/refining UI components
13
+ - **Airis Gateway** (Docker, localhost:9400) — cold-start sub-servers:
14
+ - **context7** — Library docs lookup
15
+ - **playwright** — Browser automation/testing
16
+ - **serena** — Symbolic code navigation (run \`activate_project\` on first use)
17
+ - **tavily** — Web search/research
18
+ - **chrome-devtools** — Chrome debugging
19
+ - **shadcn** — shadcn/ui component search
20
+ `,
21
+
22
+ direct: `## MCP Servers
23
+ Use these naturally when relevant — don't wait to be asked.
24
+
25
+ - **Magic MCP** — \`component_builder\`, \`component_inspiration\`, \`component_refiner\`, \`logo_search\` — use when building/refining UI components
26
+ - **context7** — Library docs lookup (npx)
27
+ - **playwright** — Browser automation/testing (npx)
28
+ - **serena** — Symbolic code navigation; run \`activate_project\` on first use (uvx)
29
+ - **tavily** — Web search/research (npx, requires TAVILY_API_KEY)
30
+ - **chrome-devtools** — Chrome debugging (npx)
31
+ - **shadcn** — shadcn/ui component search (npx)
32
+ `,
33
+
34
+ skip: `## MCP Servers
35
+ Use these naturally when relevant — don't wait to be asked.
36
+
37
+ - **Magic MCP** — \`component_builder\`, \`component_inspiration\`, \`component_refiner\`, \`logo_search\` — use when building/refining UI components
38
+ <!-- Add your MCP servers here. Run \`npx supermind-claude\` to set up context7, playwright, serena, tavily, and more. -->
39
+ `,
40
+ };
41
+
42
+ // Matches MCP section up to next heading or end of file (with or without trailing newline)
43
+ const MCP_SECTION_PATTERN = /## MCP Servers\nUse these naturally when relevant.*?(?=\n## |\n?$)/s;
44
+
45
+ function installTemplates(mcpMode) {
9
46
  ensureDir(PATHS.templatesDir);
10
47
  const src = path.join(getPackageRoot(), 'templates', 'CLAUDE.md');
11
48
  const dest = path.join(PATHS.templatesDir, 'CLAUDE.md');
12
49
  fs.copyFileSync(src, dest);
50
+
51
+ if (mcpMode && MCP_SECTIONS[mcpMode]) {
52
+ const content = fs.readFileSync(dest, 'utf-8');
53
+ const updated = content.replace(MCP_SECTION_PATTERN, MCP_SECTIONS[mcpMode]);
54
+ if (updated === content && mcpMode !== 'docker') { // docker is the template default, so no-op is expected
55
+ logger.warn('MCP section pattern did not match template — using default MCP content');
56
+ }
57
+ fs.writeFileSync(dest, updated);
58
+ }
59
+
13
60
  logger.success('CLAUDE.md template');
14
61
  }
15
62
 
@@ -17,13 +17,24 @@ function loadApprovedCommands() {
17
17
  try {
18
18
  const data = JSON.parse(fs.readFileSync(APPROVED_FILE, 'utf-8'));
19
19
  return Array.isArray(data) ? data : [];
20
- } catch {
20
+ } catch (err) {
21
+ if (err.code !== 'ENOENT') {
22
+ process.stderr.write(`[bash-permissions] Could not load approved commands: ${err.message}\n`);
23
+ }
21
24
  return [];
22
25
  }
23
26
  }
24
27
 
28
+ let _approvedCache;
29
+ function getApprovedCommands() {
30
+ if (_approvedCache === undefined) {
31
+ _approvedCache = loadApprovedCommands();
32
+ }
33
+ return _approvedCache;
34
+ }
35
+
25
36
  function isUserApproved(cmd) {
26
- const approved = loadApprovedCommands();
37
+ const approved = getApprovedCommands();
27
38
  const trimmed = cmd.trim();
28
39
  for (const pattern of approved) {
29
40
  // Exact match
@@ -34,7 +45,9 @@ function isUserApproved(cmd) {
34
45
  if (pattern.startsWith('/') && pattern.endsWith('/')) {
35
46
  try {
36
47
  if (new RegExp(pattern.slice(1, -1)).test(trimmed)) return true;
37
- } catch { /* invalid regex, skip */ }
48
+ } catch (e) {
49
+ process.stderr.write(`[bash-permissions] Invalid regex in approved commands: ${pattern} (${e.message})\n`);
50
+ }
38
51
  }
39
52
  }
40
53
  return false;
@@ -51,29 +64,32 @@ const SAFE_READ_COMMANDS = [
51
64
  "echo", "printf", "pwd", "true", "false", "set", "export",
52
65
  "cd", "pushd", "popd", "source", ".",
53
66
  // Text processing (read-only)
54
- "grep", "rg", "awk", "sort", "uniq", "cut", "tr", "tee",
67
+ "grep", "rg", "awk", "sort", "uniq", "cut", "tr",
55
68
  "diff", "comm", "paste", "column", "fmt", "fold", "rev",
56
- "jq", "yq", "xargs",
69
+ "jq", "yq",
57
70
  // System info
58
71
  "uname", "whoami", "hostname", "date", "env", "printenv",
59
72
  "nproc", "free", "uptime", "id",
73
+ // Encoding utilities
74
+ "base64",
75
+ // Claude CLI management (config, MCP, plugin operations)
76
+ "claude config", "claude mcp", "claude plugin",
77
+ "claude --version", "claude -v",
60
78
  // Node/npm/npx (two-word matches)
61
79
  "node -e", "node -p", "npm ls", "npm list", "npm view", "npm info",
62
80
  "npx which", "npx tsc", "npx eslint", "npx prettier", "npx vitest",
63
81
  "npx jest", "npx tsx", "npx ts-node",
64
82
  ];
65
83
 
66
- // Prefix-matched safe commands (not just first word)
84
+ // Prefix-matched safe syntax (bash conditionals)
67
85
  const SAFE_PREFIXES = [
68
- "sed -n", // read-only sed
69
- "sed -e", // expression sed (read-only when no -i)
70
86
  "[[ ", // bash conditional
71
87
  "[ ", // test
72
88
  ];
73
89
 
74
90
  // Safe write commands (mkdir, touch, etc.) — still checked against DANGEROUS_PATTERNS
75
91
  const SAFE_WRITE_COMMANDS = [
76
- "mkdir", "touch", "cp", "mv",
92
+ "mkdir", "touch", "cp", "mv", "tee", "xargs",
77
93
  ];
78
94
 
79
95
  // ─── Git classification lists ────────────────────────────────────────────────
@@ -136,6 +152,7 @@ const GH_DANGEROUS_PATTERNS = [
136
152
  /^gh\s+release\s+(create|delete|edit)/,
137
153
  /^gh\s+api\s+-X\s+(DELETE|PUT|PATCH|POST)/,
138
154
  /^gh\s+api\s+--method\s+(DELETE|PUT|PATCH|POST)/,
155
+ /^gh\s+api\s+(\S+\s+)*(-f[\s=]|-f\S|--field[\s=]|--raw-field[\s=]|-F[\s=]|-F\S|--typed-field[\s=]|--input[\s=])/,
139
156
  ];
140
157
 
141
158
  // ─── Git global flag stripping ───────────────────────────────────────────────
@@ -179,7 +196,7 @@ function classifyGitCommand(cmd, { inWorktree = false } = {}) {
179
196
  }
180
197
 
181
198
  // Bare "git stash" (no subcommand) is safe — equivalent to stash push
182
- if (gitCmd === "stash" || /^stash\s*$/.test(gitCmd)) return "allow";
199
+ if (/^stash\s*$/.test(gitCmd)) return "allow";
183
200
 
184
201
  // Dangerous patterns (--force, --hard, rm, etc.)
185
202
  for (const p of DANGEROUS_PATTERNS) {
@@ -210,6 +227,7 @@ function classifyGitCommand(cmd, { inWorktree = false } = {}) {
210
227
 
211
228
  function isSedSafe(cmd) {
212
229
  // sed is safe only when it does NOT have -i (in-place edit)
230
+ // Note: conservative match — may flag -i in filenames/patterns, which errs on the side of asking
213
231
  return /^sed\s/.test(cmd) && !/-i/.test(cmd);
214
232
  }
215
233
 
@@ -233,7 +251,7 @@ function classifySegment(raw, { inWorktree = false } = {}) {
233
251
  // sed special handling (safe only without -i)
234
252
  if (withoutEnv.startsWith("sed ")) return isSedSafe(withoutEnv) ? "allow" : "ask";
235
253
 
236
- // Safe prefixes (sed -n, [[ , etc.)
254
+ // Safe prefixes ([[ , [ conditionals)
237
255
  for (const p of SAFE_PREFIXES) {
238
256
  if (withoutEnv.startsWith(p)) return "allow";
239
257
  }
@@ -276,10 +294,6 @@ function detectWorktreeContext(segments) {
276
294
  if (/git\s+worktree\s+remove\s+.*\.worktrees?[/\\]/.test(trimmed)) {
277
295
  return true;
278
296
  }
279
- // git worktree remove with a relative .worktrees path
280
- if (/git\s+worktree\s+remove\s+\.worktrees?[/\\]/.test(trimmed)) {
281
- return true;
282
- }
283
297
  }
284
298
  return false;
285
299
  }
@@ -416,6 +430,9 @@ function main() {
416
430
  console.log(JSON.stringify(output));
417
431
  } catch (err) {
418
432
  // On parse error, don't block — let the normal permission system handle it
433
+ if (!(err instanceof SyntaxError)) {
434
+ process.stderr.write(`[bash-permissions] Unexpected error: ${err.stack || err.message}\n`);
435
+ }
419
436
  console.log(JSON.stringify({
420
437
  hookSpecificOutput: {
421
438
  hookEventName: "PreToolUse",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "supermind-claude",
3
- "version": "2.0.2",
3
+ "version": "2.1.1",
4
4
  "description": "Complete, opinionated Claude Code setup — hooks, skills, status line, MCP servers, and living documentation",
5
5
  "bin": {
6
6
  "supermind-claude": "cli/index.js",
@@ -31,9 +31,9 @@ Section-level merging preserves your project-specific customizations while keepi
31
31
 
32
32
  ### Steps
33
33
 
34
- 1. Read the template from `~/.claude/templates/CLAUDE.md`. If missing, tell the user to run `npx supermind-claude` first and stop.
34
+ 1. Read the template from `~/.claude/templates/CLAUDE.md`. If missing, tell the user to run `npx supermind-claude` first and stop. **Important:** The template is only a *source* to read from — all writes go to `./CLAUDE.md` in the project root. Never modify the template file at `~/.claude/templates/CLAUDE.md`.
35
35
 
36
- 2. Check if `CLAUDE.md` exists in the project root.
36
+ 2. Check if `CLAUDE.md` exists in the project root (`./CLAUDE.md`).
37
37
 
38
38
  3. **No existing CLAUDE.md** — copy the template as-is, then proceed to step 5.
39
39
 
@@ -127,7 +127,13 @@ ARCHITECTURE.md uses tables-over-prose because it saves tokens — the AI reads
127
127
 
128
128
  Leave unfilled sections with `<!-- No [X] detected -->`.
129
129
 
130
- 13. **Commit** generated or migrated docs:
130
+ 13. **Verify generated documentation**:
131
+ - Re-read the generated ARCHITECTURE.md (and DESIGN.md if created)
132
+ - Spot-check at least 5 claims (or 10% of all claims, whichever is larger) against actual source code: verify constant names, function signatures, dependency lists, and behavioral descriptions match the source
133
+ - If discrepancies are found, fix each one and tell the user what was wrong and what was corrected
134
+ - If more than 30% of checked claims are wrong, warn the user that generation quality was low and suggest reviewing the full document manually
135
+
136
+ 14. **Commit** generated or migrated docs:
131
137
  - New project: `git commit -m "Initialize project (CLAUDE.md, ARCHITECTURE.md[, DESIGN.md])"`
132
138
  - Migrated: `git commit -m "Migrate living documentation to AI-optimized format"`
133
139
 
@@ -139,29 +145,41 @@ Different projects benefit from different tools. A database-heavy project might
139
145
 
140
146
  ### Steps
141
147
 
142
- 14. Ask the user: "Would you like me to check your Supermind setup and research additional tools for this project?"
148
+ 15. Ask the user: "Would you like me to check your Supermind setup and research additional tools for this project?"
143
149
 
144
- 15. **If yes**:
150
+ 16. **If yes**:
145
151
 
146
152
  a. **Verify session hooks are firing**:
147
153
  - Check `~/.claude/sessions/` for recent session files
148
154
  - If no recent files found, warn that session persistence may not be configured
149
155
 
150
- b. **Check Serena configuration**:
151
- - Look for `.serena/` directory in the project root
152
- - If missing, suggest setting up Serena for semantic code navigation
153
-
154
- c. **Research relevant tools**:
155
- - Spawn a subagent to research skills and MCPs relevant to the detected tech stack
156
- - Consider the project's language, framework, database, deployment target, and testing approach
157
- - Look at available MCP servers and Superpowers skills that match
158
-
159
- d. **Present findings**:
160
- - Show suggestions as a list with brief explanations of why each tool is relevant
156
+ b. **Set up Serena** (semantic code navigation):
157
+ - Check if `.serena/` directory exists in the project root
158
+ - If already present, tell the user: "Serena directory already configured."
159
+ - If missing, create it: `mkdir -p .serena/memories`
160
+ - Verify `.serena/` is in `.gitignore` — if not, add it and commit
161
+ - Tell the user: "Created `.serena/` for semantic code navigation."
162
+
163
+ c. **Research relevant tools** dispatch **two parallel agents**:
164
+
165
+ **Agent 1: Skills research**
166
+ - Search for Superpowers skills and Claude plugins relevant to the detected tech stack
167
+ - Consider the project's language, framework, testing approach, and deployment target
168
+ - Check installed vs. available skills and identify gaps
169
+
170
+ **Agent 2: MCP servers research**
171
+ - Search for MCP servers relevant to the detected tech stack
172
+ - Consider database, API, deployment, and tooling needs
173
+ - Check installed vs. available MCPs and identify gaps
174
+ - **Exclusion:** Never recommend `sequential-thinking-mcp` — it is incompatible with Supermind's skill system
175
+
176
+ d. **Present findings** (after both agents complete):
177
+ - Combine results from both agents into a unified list
178
+ - Show suggestions grouped by category: code navigation, testing, deployment, UI, database, etc.
179
+ - Include a brief explanation of why each tool is relevant to this project
161
180
  - Do not auto-install anything — let the user decide
162
- - Group by category: code navigation, testing, deployment, UI, database, etc.
163
181
 
164
- 16. **If no**: skip this phase. Initialization is complete.
182
+ 17. **If no**: skip this phase. Initialization is complete.
165
183
 
166
184
  ---
167
185
 
@@ -16,9 +16,11 @@ Surgical edits preserve your existing formatting and avoid unnecessary diffs. Th
16
16
  - Read `DESIGN.md` from the project root (only if it exists — its presence means this is a UI project)
17
17
 
18
18
  2. **Assess recent changes**:
19
- - Run `git diff --name-only` to see which files changed
19
+ - Run `git diff --name-only` for unstaged changes
20
+ - Run `git diff --name-only --cached` for staged changes
21
+ - Run `git status --short` for untracked files
20
22
  - Run `git diff --stat` to understand the scope of changes
21
- - If working on uncommitted changes, also check `git diff --name-only HEAD` and `git status`
23
+ - Combine all lists into the set of changed files for subsequent steps
22
24
 
23
25
  3. **Reason about what needs updating**:
24
26
  - Files added, removed, or renamed — update **File Index**
@@ -31,16 +33,24 @@ Surgical edits preserve your existing formatting and avoid unnecessary diffs. Th
31
33
  - Components added or modified — update **Component Patterns**
32
34
  - Layout or animation changes — update **Layout Conventions** or **Animation Patterns**
33
35
 
34
- 4. **If nothing meaningful changed**, say so and stop. Do not make edits for the sake of making edits.
36
+ 4. **Validate existing claims against changed files**:
37
+ - Using the full list of changed files from step 2:
38
+ a. For each changed file, check if ARCHITECTURE.md (or DESIGN.md) makes specific claims about that file's behavior, constants, patterns, or dependencies
39
+ b. For deleted files: remove or update any documentation entries that reference them
40
+ c. For modified files: verify claims are still accurate by reading the actual source
41
+ d. Fix any stale or incorrect claims (e.g., renamed constants, changed function signatures, outdated behavioral descriptions)
42
+ - Report to the user what stale claims were found and corrected
35
43
 
36
- 5. **Make surgical edits**:
44
+ 5. **If nothing meaningful changed**, say so and stop. Do not make edits for the sake of making edits.
45
+
46
+ 6. **Make surgical edits**:
37
47
  - Use the Edit tool to update only the sections that need changing
38
48
  - Do NOT rewrite entire files — change only the rows, entries, or paragraphs that are affected
39
49
  - Match the existing format and section structure exactly
40
50
  - Keep content factual — document what IS, not what should be
41
51
  - Always include file paths when referencing source files
42
52
 
43
- 6. **Commit** with a descriptive message:
53
+ 7. **Commit** with a descriptive message:
44
54
  - Example: `git commit -m "Update ARCHITECTURE.md: add new API routes, update file index"`
45
55
  - If both files were updated: `git commit -m "Update living docs: [brief description of changes]"`
46
56
 
@@ -24,12 +24,13 @@ A PreToolUse hook (`bash-permissions.js`) handles all Bash permission classifica
24
24
  **Auto-approved** (standalone or in any compound):
25
25
  - **Read-only shell**: ls, cat, head, tail, find, sed (without -i), grep, echo, pwd, jq, etc.
26
26
  - **Safe writes**: mkdir, touch, cp, mv
27
- - **Read-only git**: status, diff, log, show, blame, rev-parse, check-ignore, branch listing, tag listing, config
28
- - **Non-destructive git writes**: add, commit, stash (push/save/list/show), worktree add, worktree list, branch create
29
- - **gh CLI**: read-only gh commands (pr list/view/diff, issue list/view, repo view, etc. not merge, close, delete)
27
+ - **Utilities**: base64, claude CLI (config/mcp/plugin subcommands)
28
+ - **Read-only git**: status, diff, log, show, blame, rev-parse, check-ignore, branch listing, tag listing, config (read-only: --get, --list)
29
+ - **Non-destructive git writes**: add, commit, stash (bare/push/save/list/show), worktree add, worktree list, branch create, branch rename
30
+ - **gh CLI**: read-only gh commands (pr list/view/diff, issue list/view, repo view, gh api GET — not merge, close, delete, or mutating API calls)
30
31
 
31
32
  **Worktree-only** (auto-approved only when `cd` targets a `.worktrees/` path or CWD is inside one):
32
- - git merge, git worktree remove, git branch -d
33
+ - git merge, git worktree remove, git worktree prune, git branch -d
33
34
 
34
35
  **Always requires approval**:
35
36
  - push, pull, fetch, reset, revert, rebase, clean, checkout (discarding), restore, branch -D
@@ -64,7 +65,8 @@ Use the superpowers `/using-git-worktrees` skill for worktree creation. It handl
64
65
  3. **Commit** all work in the worktree
65
66
  4. **Review** — run the superpowers `code-reviewer` agent against the changes
66
67
  5. **Fix everything** — address ALL issues found by the reviewer (critical, minor, style, naming — everything). Do not ask what to fix. Fix all of them. Then re-review until the reviewer passes clean.
67
- 6. **Finish** — invoke `/finishing-a-development-branch` to merge back and clean up. The skill handles:
68
+ 6. **Living docs check** — before merging, check if the changes affect anything documented in ARCHITECTURE.md (or DESIGN.md). For each changed file, verify that any claims the docs make about that file's behavior, constants, or patterns are still accurate. If updates are needed, make them and commit in the worktree branch.
69
+ 7. **Finish** — invoke `/finishing-a-development-branch` to merge back and clean up. The skill handles:
68
70
  - Merging the worktree branch into the originating branch
69
71
  - Removing the worktree directory
70
72
  - Deleting the temporary branch
@@ -72,10 +74,11 @@ Use the superpowers `/using-git-worktrees` skill for worktree creation. It handl
72
74
  ### Rules
73
75
 
74
76
  - The worktree branch must always be created from and merged back into the **same branch** — the one you are currently on locally. Never merge into a different branch.
75
- - `git merge`, `git worktree remove`, and `git branch -d` are auto-approved **only** within this worktree workflow. In all other contexts, these still require user approval.
77
+ - `git merge`, `git worktree remove`, `git worktree prune`, and `git branch -d` are auto-approved **only** within this worktree workflow. In all other contexts, these still require user approval.
76
78
  - The code reviewer must find zero remaining issues before merging. If it finds problems, fix them and run the reviewer again. Repeat until clean.
77
79
  - Never skip the review step. Never skip "minor" fixes. Every finding gets fixed.
78
80
  - This entire process — create, implement, review, fix, merge, clean up — executes without stopping to ask for permission.
81
+ - **Branch safety:** If the current branch is `main` or `master` when a code change is requested, create a feature branch first (`feature/…`, `fix/…`, or `chore/…`) before making any changes. Never commit directly to `main` or `master`.
79
82
 
80
83
  ## MCP Servers
81
84
  Use these naturally when relevant — don't wait to be asked.