create-claude-cabinet 0.11.1 → 0.12.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.
Files changed (34) hide show
  1. package/README.md +6 -4
  2. package/lib/cli.js +86 -6
  3. package/lib/db-setup.js +4 -10
  4. package/lib/settings-merge.js +29 -3
  5. package/package.json +1 -1
  6. package/templates/EXTENSIONS.md +2 -2
  7. package/templates/README.md +188 -448
  8. package/templates/briefing/_briefing-template.md +14 -7
  9. package/templates/cabinet/directives-project.yaml +32 -0
  10. package/templates/cabinet/prompt-guide.md +14 -3
  11. package/templates/hooks/omega-memory-guard.sh +83 -0
  12. package/templates/scripts/merge-findings.js +1 -1
  13. package/templates/scripts/pib-db-schema.sql +2 -2
  14. package/templates/scripts/{pib-db.js → pib-db.mjs} +12 -12
  15. package/templates/scripts/work-tracker-server.mjs +1 -1
  16. package/templates/skills/audit/SKILL.md +1 -1
  17. package/templates/skills/cabinet-cc-health/SKILL.md +1 -1
  18. package/templates/skills/cabinet-record-keeper/SKILL.md +46 -13
  19. package/templates/skills/debrief/SKILL.md +60 -43
  20. package/templates/skills/debrief/phases/close-work.md +4 -4
  21. package/templates/skills/debrief/phases/record-lessons.md +6 -7
  22. package/templates/skills/execute-plans/SKILL.md +2 -2
  23. package/templates/skills/onboard/phases/post-onboard-audit.md +1 -1
  24. package/templates/skills/onboard/phases/work-tracking.md +2 -2
  25. package/templates/skills/orient/SKILL.md +20 -8
  26. package/templates/skills/orient/phases/work-scan.md +4 -4
  27. package/templates/skills/plan/SKILL.md +2 -2
  28. package/templates/skills/plan/phases/overlap-check.md +1 -1
  29. package/templates/skills/plan/phases/work-tracker.md +3 -3
  30. package/templates/skills/triage-audit/SKILL.md +1 -1
  31. package/templates/skills/triage-audit/phases/apply-verdicts.md +1 -1
  32. package/templates/skills/triage-audit/phases/load-findings.md +1 -1
  33. package/templates/skills/work-tracker/SKILL.md +3 -3
  34. package/templates/hooks/stop-hook.md +0 -56
package/README.md CHANGED
@@ -1,7 +1,7 @@
1
1
  # Claude Cabinet
2
2
 
3
3
  A cabinet of expert advisors for your Claude Code project. One command
4
- gives Claude a memory, 20 domain experts, a planning process, and the
4
+ gives Claude a memory, 27 domain experts, a planning process, and the
5
5
  habit of starting sessions informed and ending them properly.
6
6
 
7
7
  Built by a guy who'd rather talk to Claude than write code. Most of it
@@ -12,7 +12,7 @@ was built by Claude. I just complained until it worked.
12
12
  Your project gets a cabinet — specialist advisors who each own a domain
13
13
  and weigh in when their expertise matters:
14
14
 
15
- - **Cabinet members** — 20 domain experts (security, accessibility,
15
+ - **Cabinet members** — 27 domain experts (security, accessibility,
16
16
  architecture, QA, etc.) who review your project and surface what
17
17
  you'd miss alone
18
18
  - **Briefings** — project context members read before weighing in
@@ -37,7 +37,9 @@ say `/onboard`. It'll interview you about your project and set everything
37
37
  up based on your answers.
38
38
 
39
39
  **New to this?** See [GETTING-STARTED.md](GETTING-STARTED.md) for a
40
- step-by-step walkthrough.
40
+ step-by-step walkthrough. Then [WORKFLOW-GUIDE.md](WORKFLOW-GUIDE.md)
41
+ for how to use everything — when to plan, when to audit, what the
42
+ cabinet does for you, and how the system grows with your project.
41
43
 
42
44
  ### For developers
43
45
 
@@ -183,7 +185,7 @@ source code.
183
185
  └── settings.json # hook configuration
184
186
 
185
187
  scripts/
186
- ├── pib-db.js # work tracking CLI (if installed)
188
+ ├── pib-db.mjs # work tracking CLI (if installed)
187
189
  └── ... # triage tools (if audit installed)
188
190
 
189
191
  .ccrc.json # installation metadata
package/lib/cli.js CHANGED
@@ -163,6 +163,70 @@ function generateSkillIndex(projectDir) {
163
163
  const skillsDir = path.join(projectDir, '.claude', 'skills');
164
164
  if (!fs.existsSync(skillsDir)) return 0;
165
165
 
166
+ // Read project directive overlay if it exists
167
+ const projectDirectives = {};
168
+ const directivesFile = path.join(projectDir, '.claude', 'cabinet', 'directives-project.yaml');
169
+ if (fs.existsSync(directivesFile)) {
170
+ const dContent = fs.readFileSync(directivesFile, 'utf8');
171
+ // Parse simple YAML: top-level keys are member names, nested keys are
172
+ // standing-mandate (list) and directives (map)
173
+ let currentMember = null;
174
+ let inDirectives = false;
175
+ let currentDirectiveKey = null;
176
+ let currentDirectiveValue = '';
177
+ for (const line of dContent.split('\n')) {
178
+ if (/^\s*#/.test(line) || line.trim() === '') continue;
179
+ const indent = line.length - line.trimStart().length;
180
+ const content = line.trim();
181
+
182
+ // Flush previous directive value
183
+ if (currentDirectiveKey && indent <= 4 && !/^\s/.test(line.charAt(0)) || (indent <= 4 && currentDirectiveKey)) {
184
+ if (currentMember && currentDirectiveKey) {
185
+ if (!projectDirectives[currentMember]) projectDirectives[currentMember] = {};
186
+ if (!projectDirectives[currentMember].directives) projectDirectives[currentMember].directives = {};
187
+ projectDirectives[currentMember].directives[currentDirectiveKey] = currentDirectiveValue.trim();
188
+ }
189
+ currentDirectiveKey = null;
190
+ currentDirectiveValue = '';
191
+ }
192
+
193
+ if (indent === 0) {
194
+ // Top-level: member name
195
+ const m = content.match(/^(cabinet-[\w-]+):\s*$/);
196
+ if (m) {
197
+ currentMember = m[1];
198
+ projectDirectives[currentMember] = projectDirectives[currentMember] || {};
199
+ inDirectives = false;
200
+ }
201
+ } else if (indent === 2 && currentMember) {
202
+ const kv = content.match(/^([\w-]+):\s*(.*)$/);
203
+ if (kv) {
204
+ if (kv[1] === 'standing-mandate') {
205
+ // Parse [item1, item2] or item1, item2
206
+ const val = kv[2].replace(/^\[|\]$/g, '');
207
+ projectDirectives[currentMember].standingMandate = val.split(/,\s*/).map(s => s.trim()).filter(Boolean);
208
+ inDirectives = false;
209
+ } else if (kv[1] === 'directives') {
210
+ inDirectives = true;
211
+ }
212
+ }
213
+ } else if (indent === 4 && inDirectives && currentMember) {
214
+ const kv = content.match(/^([\w-]+):\s*(.*)$/);
215
+ if (kv) {
216
+ currentDirectiveKey = kv[1];
217
+ currentDirectiveValue = kv[2].replace(/^[>|]\s*$/, '');
218
+ }
219
+ } else if (indent >= 6 && currentDirectiveKey) {
220
+ currentDirectiveValue += ' ' + content;
221
+ }
222
+ }
223
+ // Flush last directive
224
+ if (currentMember && currentDirectiveKey) {
225
+ if (!projectDirectives[currentMember].directives) projectDirectives[currentMember].directives = {};
226
+ projectDirectives[currentMember].directives[currentDirectiveKey] = currentDirectiveValue.trim();
227
+ }
228
+ }
229
+
166
230
  const entries = [];
167
231
  const dirs = fs.readdirSync(skillsDir, { withFileTypes: true });
168
232
  for (const dir of dirs) {
@@ -202,6 +266,21 @@ function generateSkillIndex(projectDir) {
202
266
  entry.directives = fm.directives;
203
267
  }
204
268
 
269
+ // Merge project directive overlay (if any)
270
+ const overlay = projectDirectives[dir.name];
271
+ if (overlay) {
272
+ // Append project standing mandates (union, no duplicates)
273
+ if (overlay.standingMandate) {
274
+ const existing = entry.standingMandate || [];
275
+ const merged = [...new Set([...existing, ...overlay.standingMandate])];
276
+ entry.standingMandate = merged;
277
+ }
278
+ // Merge project directives (project wins on conflict)
279
+ if (overlay.directives) {
280
+ entry.directives = { ...(entry.directives || {}), ...overlay.directives };
281
+ }
282
+ }
283
+
205
284
  entries.push(entry);
206
285
  }
207
286
 
@@ -225,7 +304,7 @@ const MODULES = {
225
304
  name: 'Session Loop (orient + debrief)',
226
305
  description: 'The briefing cycle. Claude starts each session informed, ends by preparing the next briefing.',
227
306
  mandatory: true,
228
- templates: ['skills/orient', 'skills/orient-quick', 'skills/debrief', 'skills/debrief-quick', 'skills/debrief/phases/upstream-feedback.md', 'skills/menu', 'hooks/stop-hook.md'],
307
+ templates: ['skills/orient', 'skills/orient-quick', 'skills/debrief', 'skills/debrief-quick', 'skills/debrief/phases/upstream-feedback.md', 'skills/menu'],
229
308
  },
230
309
  'hooks': {
231
310
  name: 'Git Guardrails + Telemetry',
@@ -241,7 +320,7 @@ const MODULES = {
241
320
  mandatory: false,
242
321
  default: true,
243
322
  lean: false,
244
- templates: ['scripts/pib-db.js', 'scripts/pib-db-schema.sql', 'scripts/work-tracker-server.mjs', 'scripts/work-tracker-ui.html', 'skills/work-tracker'],
323
+ templates: ['scripts/pib-db.mjs', 'scripts/pib-db-schema.sql', 'scripts/work-tracker-server.mjs', 'scripts/work-tracker-ui.html', 'skills/work-tracker'],
245
324
  needsDb: true,
246
325
  },
247
326
  'planning': {
@@ -311,7 +390,7 @@ const MODULES = {
311
390
  default: true,
312
391
  lean: false,
313
392
  needsOmega: true,
314
- templates: ['skills/memory', 'scripts/cabinet-memory-adapter.py', 'rules/memory-capture.md'],
393
+ templates: ['skills/memory', 'scripts/cabinet-memory-adapter.py', 'rules/memory-capture.md', 'hooks/omega-memory-guard.sh'],
315
394
  },
316
395
  };
317
396
 
@@ -542,7 +621,7 @@ async function run() {
542
621
  selectedModules = Object.keys(MODULES);
543
622
  if (flags.noDb) {
544
623
  includeDb = false;
545
- // work-tracking templates are still copied (pib-db.js, schema) but
624
+ // work-tracking templates are still copied (pib-db.mjs, schema) but
546
625
  // the DB isn't initialized. Mark it as skipped so /onboard knows
547
626
  // to ask about the alternative work tracking system.
548
627
  selectedModules = selectedModules.filter(m => m !== 'work-tracking');
@@ -766,7 +845,8 @@ async function run() {
766
845
 
767
846
  // --- Merge hooks into settings.json ---
768
847
  if (selectedModules.includes('hooks') && !flags.dryRun) {
769
- const settingsPath = mergeSettings(projectDir, { includeDb });
848
+ const includeMemory = selectedModules.includes('memory');
849
+ const settingsPath = mergeSettings(projectDir, { includeDb, includeMemory });
770
850
  console.log(` ⚙️ Merged hooks into ${path.relative(projectDir, settingsPath)}`);
771
851
  }
772
852
 
@@ -777,7 +857,7 @@ async function run() {
777
857
  for (const r of dbResults) console.log(` 🗄️ ${r}`);
778
858
  } catch (err) {
779
859
  console.log(` ⚠ Database setup failed: ${err.message}`);
780
- console.log(' You can set it up later: node scripts/pib-db.js init');
860
+ console.log(' You can set it up later: node scripts/pib-db.mjs init');
781
861
  }
782
862
  }
783
863
 
package/lib/db-setup.js CHANGED
@@ -4,7 +4,7 @@ const path = require('path');
4
4
 
5
5
  /**
6
6
  * Set up the PIB database in the target project.
7
- * - Copies pib-db.js and schema to scripts/
7
+ * - Copies pib-db.mjs and schema to scripts/
8
8
  * - Runs npm init if no package.json
9
9
  * - Installs better-sqlite3
10
10
  * - Runs pib-db init
@@ -21,14 +21,8 @@ function setupDb(projectDir) {
21
21
  results.push('Created package.json');
22
22
  }
23
23
 
24
- // pib-db.js uses ESM imports — ensure package.json has "type": "module"
25
- // Skip this for the CC source repo itself (its CLI uses CommonJS)
26
- const pkg = JSON.parse(fs.readFileSync(pkgPath, 'utf8'));
27
- if (pkg.type !== 'module' && pkg.name !== 'create-claude-cabinet') {
28
- pkg.type = 'module';
29
- fs.writeFileSync(pkgPath, JSON.stringify(pkg, null, 2) + '\n');
30
- results.push('Set package.json type to "module"');
31
- }
24
+ // pib-db.mjs uses ESM imports — .mjs extension lets Node treat it as ESM
25
+ // regardless of the project's package.json type field
32
26
 
33
27
  // Install better-sqlite3 if not already installed
34
28
  const nodeModules = path.join(projectDir, 'node_modules', 'better-sqlite3');
@@ -39,7 +33,7 @@ function setupDb(projectDir) {
39
33
  }
40
34
 
41
35
  // Initialize the database
42
- const dbScript = path.join(scriptsDir, 'pib-db.js');
36
+ const dbScript = path.join(scriptsDir, 'pib-db.mjs');
43
37
  if (fs.existsSync(dbScript)) {
44
38
  console.log(' Initializing database...');
45
39
  execSync(`node ${dbScript} init`, { cwd: projectDir, stdio: 'pipe' });
@@ -1,6 +1,20 @@
1
1
  const fs = require('fs');
2
2
  const path = require('path');
3
3
 
4
+ const MEMORY_HOOKS = {
5
+ PreToolUse: [
6
+ {
7
+ matcher: 'Edit|Write',
8
+ hooks: [
9
+ {
10
+ type: 'command',
11
+ command: '.claude/hooks/omega-memory-guard.sh',
12
+ },
13
+ ],
14
+ },
15
+ ],
16
+ };
17
+
4
18
  const DEFAULT_HOOKS = {
5
19
  PreToolUse: [
6
20
  {
@@ -50,7 +64,7 @@ const DEFAULT_HOOKS = {
50
64
  * Merge PIB hooks into the project's .claude/settings.json.
51
65
  * Creates the file if it doesn't exist. Preserves existing hooks.
52
66
  */
53
- function mergeSettings(projectDir, { includeDb = true } = {}) {
67
+ function mergeSettings(projectDir, { includeDb = true, includeMemory = false } = {}) {
54
68
  const settingsDir = path.join(projectDir, '.claude');
55
69
  const settingsPath = path.join(settingsDir, 'settings.json');
56
70
 
@@ -81,8 +95,20 @@ function mergeSettings(projectDir, { includeDb = true } = {}) {
81
95
  });
82
96
  }
83
97
 
98
+ // Build the full hook set — include memory hooks if memory module is selected
99
+ const allHooks = { ...DEFAULT_HOOKS };
100
+ if (includeMemory) {
101
+ for (const [event, hooks] of Object.entries(MEMORY_HOOKS)) {
102
+ if (!allHooks[event]) {
103
+ allHooks[event] = hooks;
104
+ } else {
105
+ allHooks[event] = [...allHooks[event], ...hooks];
106
+ }
107
+ }
108
+ }
109
+
84
110
  // Merge each hook event type
85
- for (const [event, newHooks] of Object.entries(DEFAULT_HOOKS)) {
111
+ for (const [event, newHooks] of Object.entries(allHooks)) {
86
112
  if (!settings.hooks[event]) {
87
113
  settings.hooks[event] = newHooks;
88
114
  } else {
@@ -106,4 +132,4 @@ function mergeSettings(projectDir, { includeDb = true } = {}) {
106
132
  return settingsPath;
107
133
  }
108
134
 
109
- module.exports = { mergeSettings, DEFAULT_HOOKS };
135
+ module.exports = { mergeSettings, DEFAULT_HOOKS, MEMORY_HOOKS };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "create-claude-cabinet",
3
- "version": "0.11.1",
3
+ "version": "0.12.0",
4
4
  "description": "Claude Cabinet — opinionated process scaffolding for Claude Code projects",
5
5
  "bin": {
6
6
  "create-claude-cabinet": "bin/create-claude-cabinet.js"
@@ -226,8 +226,8 @@ command queue processing (needed by any project with an async work queue).
226
226
 
227
227
  ## Writing Domain-Specific Cabinet Members
228
228
 
229
- CC ships 14 generic cabinet members. Flow has 19 additional domain-specific
230
- cabinet members. Here are three examples showing how to write your own.
229
+ CC ships 27 generic cabinet members. Your project can add domain-specific
230
+ cabinet members on top of these. Here are three examples showing how to write your own.
231
231
 
232
232
  ### Example 1: GTD (encoding domain expertise)
233
233