supermind-claude 2.0.1 → 2.1.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/README.md +14 -13
- package/cli/commands/doctor.js +36 -12
- package/cli/commands/install.js +2 -1
- package/cli/commands/uninstall.js +2 -1
- package/cli/commands/update.js +2 -1
- package/cli/lib/plugins.js +4 -0
- package/cli/lib/settings.js +41 -17
- package/hooks/bash-permissions.js +32 -15
- package/package.json +1 -1
- package/skills/supermind-init/SKILL.md +36 -18
- package/skills/supermind-living-docs/SKILL.md +15 -5
- package/templates/CLAUDE.md +8 -6
package/README.md
CHANGED
|
@@ -5,10 +5,11 @@ Complete, opinionated Claude Code setup — hooks, skills, status line, MCP serv
|
|
|
5
5
|
## Quick Install
|
|
6
6
|
|
|
7
7
|
```bash
|
|
8
|
-
|
|
8
|
+
npm install -g supermind-claude
|
|
9
|
+
supermind-claude
|
|
9
10
|
```
|
|
10
11
|
|
|
11
|
-
Or
|
|
12
|
+
Or run without installing: `npx supermind-claude`
|
|
12
13
|
|
|
13
14
|
## What Gets Installed
|
|
14
15
|
|
|
@@ -46,21 +47,21 @@ Choose during setup:
|
|
|
46
47
|
|
|
47
48
|
| Command | Purpose |
|
|
48
49
|
|---------|---------|
|
|
49
|
-
| `
|
|
50
|
-
| `
|
|
51
|
-
| `
|
|
52
|
-
| `
|
|
53
|
-
| `
|
|
50
|
+
| `supermind-claude` | Full global setup |
|
|
51
|
+
| `supermind-claude update` | Refresh hooks, skills, templates |
|
|
52
|
+
| `supermind-claude doctor` | Verify installation health |
|
|
53
|
+
| `supermind-claude uninstall` | Remove all components |
|
|
54
|
+
| `supermind-claude approve "cmd"` | Permanently auto-approve a command |
|
|
54
55
|
|
|
55
56
|
## Approved Commands
|
|
56
57
|
|
|
57
58
|
Permanently auto-approve specific commands that the bash-permissions hook would normally flag:
|
|
58
59
|
|
|
59
60
|
```bash
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
61
|
+
supermind-claude approve "git push" # exact/prefix match
|
|
62
|
+
supermind-claude approve "/npm run .*/" # regex match
|
|
63
|
+
supermind-claude approve --list # see all approved
|
|
64
|
+
supermind-claude approve --remove "git push" # remove approval
|
|
64
65
|
```
|
|
65
66
|
|
|
66
67
|
Or tell Claude: "add that to my approved commands" — it knows how to edit the file directly.
|
|
@@ -71,7 +72,7 @@ Windows, macOS, and Linux. Requires Node.js >= 18.
|
|
|
71
72
|
|
|
72
73
|
## Troubleshooting
|
|
73
74
|
|
|
74
|
-
Run `
|
|
75
|
+
Run `supermind-claude doctor` to check installation health. Common issues:
|
|
75
76
|
- **Plugins not active**: Restart Claude Code after install
|
|
76
77
|
- **Status line not showing**: Ensure Node.js is in PATH
|
|
77
|
-
- **Hooks not firing**: Run `
|
|
78
|
+
- **Hooks not firing**: Run `supermind-claude update` to re-register
|
package/cli/commands/doctor.js
CHANGED
|
@@ -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 {
|
|
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,
|
|
49
|
+
} catch (err) {
|
|
50
|
+
run('settings.json is valid JSON', false, err.message);
|
|
51
51
|
}
|
|
52
52
|
}
|
|
53
53
|
|
|
54
54
|
// Hooks present
|
|
55
|
-
|
|
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
|
-
|
|
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
|
-
|
|
69
|
-
|
|
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
|
-
|
|
81
|
-
return
|
|
82
|
-
}
|
|
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 {
|
|
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`);
|
package/cli/commands/install.js
CHANGED
|
@@ -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
|
-
|
|
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...');
|
|
@@ -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);
|
package/cli/commands/update.js
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
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');
|
|
@@ -30,6 +30,7 @@ module.exports = function update(flags) {
|
|
|
30
30
|
|
|
31
31
|
// Step 2: Hook settings (re-merge to pick up any new hooks)
|
|
32
32
|
logger.step(2, TOTAL, 'Updating settings...');
|
|
33
|
+
backupSettings();
|
|
33
34
|
const existing = readSettings();
|
|
34
35
|
const hookSettings = getHookSettings();
|
|
35
36
|
const merged = mergeSettings(existing, hookSettings);
|
package/cli/lib/plugins.js
CHANGED
|
@@ -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
|
}
|
package/cli/lib/settings.js
CHANGED
|
@@ -10,23 +10,42 @@ const SUPERMIND_HOOKS = [
|
|
|
10
10
|
'cost-tracker.js', 'statusline-command.js',
|
|
11
11
|
];
|
|
12
12
|
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
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
|
-
|
|
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 (
|
|
122
|
-
|
|
123
|
-
|
|
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
|
|
@@ -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 =
|
|
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 {
|
|
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",
|
|
67
|
+
"grep", "rg", "awk", "sort", "uniq", "cut", "tr",
|
|
55
68
|
"diff", "comm", "paste", "column", "fmt", "fold", "rev",
|
|
56
|
-
"jq", "yq",
|
|
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
|
|
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 (
|
|
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 (
|
|
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
|
@@ -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. **
|
|
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
|
-
|
|
148
|
+
15. Ask the user: "Would you like me to check your Supermind setup and research additional tools for this project?"
|
|
143
149
|
|
|
144
|
-
|
|
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. **
|
|
151
|
-
-
|
|
152
|
-
- If
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
-
|
|
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
|
-
|
|
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`
|
|
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
|
-
-
|
|
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. **
|
|
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. **
|
|
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
|
-
|
|
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
|
|
package/templates/CLAUDE.md
CHANGED
|
@@ -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
|
-
- **
|
|
28
|
-
- **
|
|
29
|
-
- **
|
|
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. **
|
|
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,7 +74,7 @@ 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.
|