create-claude-cabinet 0.10.0 → 0.11.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.
Files changed (32) hide show
  1. package/lib/cli.js +218 -2
  2. package/package.json +1 -1
  3. package/templates/skills/cabinet/SKILL.md +53 -0
  4. package/templates/skills/cabinet-architecture/SKILL.md +8 -0
  5. package/templates/skills/cabinet-boundary-man/SKILL.md +5 -0
  6. package/templates/skills/cabinet-data-integrity/SKILL.md +1 -0
  7. package/templates/skills/cabinet-debugger/SKILL.md +6 -0
  8. package/templates/skills/cabinet-framework-quality/SKILL.md +1 -0
  9. package/templates/skills/cabinet-historian/SKILL.md +15 -0
  10. package/templates/skills/cabinet-organized-mind/SKILL.md +6 -0
  11. package/templates/skills/cabinet-process-therapist/SKILL.md +6 -1
  12. package/templates/skills/cabinet-qa/SKILL.md +8 -0
  13. package/templates/skills/cabinet-record-keeper/SKILL.md +6 -1
  14. package/templates/skills/cabinet-roster-check/SKILL.md +5 -1
  15. package/templates/skills/cabinet-security/SKILL.md +8 -0
  16. package/templates/skills/cabinet-speed-freak/SKILL.md +1 -0
  17. package/templates/skills/cabinet-system-advocate/SKILL.md +8 -0
  18. package/templates/skills/cabinet-technical-debt/SKILL.md +1 -0
  19. package/templates/skills/cabinet-usability/SKILL.md +1 -0
  20. package/templates/skills/cabinet-user-advocate/SKILL.md +5 -0
  21. package/templates/skills/cabinet-workflow-cop/SKILL.md +1 -0
  22. package/templates/skills/cc-upgrade/SKILL.md +13 -7
  23. package/templates/skills/debrief/SKILL.md +35 -23
  24. package/templates/skills/execute/SKILL.md +8 -4
  25. package/templates/skills/investigate/SKILL.md +15 -4
  26. package/templates/skills/menu/SKILL.md +19 -24
  27. package/templates/skills/orient/SKILL.md +48 -5
  28. package/templates/skills/plan/SKILL.md +7 -4
  29. package/templates/skills/seed/SKILL.md +17 -3
  30. package/templates/skills/work-tracker/SKILL.md +56 -0
  31. package/templates/hooks/memory-post-compact.sh +0 -43
  32. package/templates/hooks/memory-session-start.sh +0 -59
package/lib/cli.js CHANGED
@@ -12,6 +12,214 @@ const { reset } = require('./reset');
12
12
 
13
13
  const VERSION = require('../package.json').version;
14
14
 
15
+ /**
16
+ * Parse YAML frontmatter from a SKILL.md file (between first two --- lines).
17
+ * Returns an object with extracted fields, or null if no frontmatter found.
18
+ * Supports one level of nesting (e.g., directives: { orient: "...", debrief: "..." }).
19
+ */
20
+ function parseFrontmatter(content) {
21
+ const match = content.match(/^---\n([\s\S]*?)\n---/);
22
+ if (!match) return null;
23
+ const fm = {};
24
+ let currentKey = null;
25
+ let currentValue = '';
26
+ let nestedKey = null; // Parent key when parsing a nested map
27
+ let nestedMap = null; // The nested map being built
28
+ let nestedSubKey = null; // Current sub-key within the nested map
29
+ let nestedSubValue = '';
30
+ let blockScalarKey = null; // Key when parsing a block scalar (description: >)
31
+ let blockScalarValue = '';
32
+ let blockScalarStyle = null; // '>' for folded, '|' for literal
33
+
34
+ function flushNested() {
35
+ if (nestedSubKey && nestedMap) {
36
+ nestedMap[nestedSubKey] = nestedSubValue.trim();
37
+ nestedSubKey = null;
38
+ nestedSubValue = '';
39
+ }
40
+ if (nestedKey && nestedMap) {
41
+ fm[nestedKey] = nestedMap;
42
+ nestedKey = null;
43
+ nestedMap = null;
44
+ }
45
+ }
46
+
47
+ function flushCurrent() {
48
+ if (currentKey) {
49
+ fm[currentKey] = currentValue.trim();
50
+ currentKey = null;
51
+ currentValue = '';
52
+ }
53
+ }
54
+
55
+ for (const line of match[1].split('\n')) {
56
+ // Inside a block scalar (description: > or description: |)?
57
+ if (blockScalarKey) {
58
+ if (/^[\s]/.test(line) && line.trim() !== '') {
59
+ const sep = blockScalarStyle === '|' ? '\n' : ' ';
60
+ blockScalarValue += (blockScalarValue ? sep : '') + line.trim();
61
+ continue;
62
+ }
63
+ // Blank line inside block scalar — for '|' style, preserve as newline
64
+ if (line.trim() === '' && blockScalarStyle === '|') {
65
+ blockScalarValue += '\n';
66
+ continue;
67
+ }
68
+ // Not indented or blank line in '>' mode — end of block scalar
69
+ fm[blockScalarKey] = blockScalarValue.trim();
70
+ blockScalarKey = null;
71
+ blockScalarValue = '';
72
+ blockScalarStyle = null;
73
+ // Fall through to parse this line
74
+ }
75
+
76
+ // Inside a nested map?
77
+ if (nestedKey) {
78
+ // Nested sub-key (indented key: value)
79
+ const subKv = line.match(/^ ([a-z][a-z0-9_-]*)\s*:\s*(.*)/);
80
+ if (subKv) {
81
+ // Save previous sub-key
82
+ if (nestedSubKey) {
83
+ nestedMap[nestedSubKey] = nestedSubValue.trim();
84
+ }
85
+ nestedSubKey = subKv[1];
86
+ nestedSubValue = subKv[2].replace(/^[>|]\s*$/, '');
87
+ continue;
88
+ }
89
+ // First indented line doesn't look like a sub-key — this is a block scalar, not a map
90
+ if (!nestedSubKey && /^[\s]/.test(line) && line.trim() !== '') {
91
+ // Convert from nested map mode to block scalar mode
92
+ blockScalarKey = nestedKey;
93
+ blockScalarStyle = '>'; // Default to folded
94
+ blockScalarValue = line.trim();
95
+ nestedKey = null;
96
+ nestedMap = null;
97
+ continue;
98
+ }
99
+ // Continuation of nested sub-value (deeply indented)
100
+ if (nestedSubKey && /^ /.test(line)) {
101
+ nestedSubValue += ' ' + line.trim();
102
+ continue;
103
+ }
104
+ // Not indented — end of nested map
105
+ if (nestedSubKey) {
106
+ nestedMap[nestedSubKey] = nestedSubValue.trim();
107
+ nestedSubKey = null;
108
+ nestedSubValue = '';
109
+ }
110
+ fm[nestedKey] = nestedMap;
111
+ nestedKey = null;
112
+ nestedMap = null;
113
+ // Fall through to parse this line as a top-level key
114
+ }
115
+
116
+ // Continuation line (indented, for scalar values)
117
+ if (currentKey && /^[\s]/.test(line)) {
118
+ currentValue += ' ' + line.trim();
119
+ continue;
120
+ }
121
+
122
+ flushCurrent();
123
+
124
+ // New key-value pair
125
+ const kvMatch = line.match(/^([a-z][a-z0-9_-]*)\s*:\s*(.*)/);
126
+ if (kvMatch) {
127
+ const val = kvMatch[2].trim();
128
+ // Empty value after colon = start of nested map or block scalar
129
+ if (val === '' || val === '>' || val === '|') {
130
+ // Could be a nested map (directives:) or a block scalar (description: >).
131
+ // Start as nested map; if first indented line has no sub-key, fall back
132
+ // to block scalar mode.
133
+ nestedKey = kvMatch[1];
134
+ nestedMap = {};
135
+ blockScalarStyle = (val === '|') ? '|' : '>'; // Remember style hint
136
+ currentKey = null;
137
+ } else {
138
+ currentKey = kvMatch[1];
139
+ currentValue = val;
140
+ }
141
+ }
142
+ }
143
+ // Flush remaining
144
+ if (blockScalarKey) {
145
+ fm[blockScalarKey] = blockScalarValue.trim();
146
+ }
147
+ if (nestedSubKey && nestedMap) {
148
+ nestedMap[nestedSubKey] = nestedSubValue.trim();
149
+ }
150
+ if (nestedKey && nestedMap) {
151
+ fm[nestedKey] = Object.keys(nestedMap).length > 0 ? nestedMap : '';
152
+ }
153
+ flushCurrent();
154
+ return fm;
155
+ }
156
+
157
+ /**
158
+ * Generate .claude/skills/_index.json from all installed SKILL.md files.
159
+ * Consumers (menu, cabinet, audit, plan, execute) read this instead of
160
+ * scanning and parsing dozens of individual files.
161
+ */
162
+ function generateSkillIndex(projectDir) {
163
+ const skillsDir = path.join(projectDir, '.claude', 'skills');
164
+ if (!fs.existsSync(skillsDir)) return 0;
165
+
166
+ const entries = [];
167
+ const dirs = fs.readdirSync(skillsDir, { withFileTypes: true });
168
+ for (const dir of dirs) {
169
+ if (!dir.isDirectory()) continue;
170
+ const skillFile = path.join(skillsDir, dir.name, 'SKILL.md');
171
+ if (!fs.existsSync(skillFile)) continue;
172
+
173
+ const content = fs.readFileSync(skillFile, 'utf8');
174
+ const fm = parseFrontmatter(content);
175
+ if (!fm || !fm.name) continue;
176
+
177
+ // Extract first sentence of description (before "Use when:")
178
+ let shortDesc = (fm.description || '').replace(/\s*Use when:.*$/is, '').trim();
179
+ // Collapse to first sentence
180
+ const sentenceEnd = shortDesc.match(/\.\s/);
181
+ if (sentenceEnd) shortDesc = shortDesc.slice(0, sentenceEnd.index + 1);
182
+
183
+ const isCabinet = dir.name.startsWith('cabinet-');
184
+ const entry = {
185
+ name: fm.name,
186
+ path: `.claude/skills/${dir.name}/SKILL.md`,
187
+ description: shortDesc,
188
+ type: isCabinet ? 'cabinet' : 'workflow',
189
+ };
190
+
191
+ // Invocability flags
192
+ if (fm['disable-model-invocation'] === 'true') entry.manual = true;
193
+ if (fm['user-invocable'] === 'false') entry.userInvocable = false;
194
+
195
+ // Standing mandate (for audit/plan/execute/orient/debrief member selection)
196
+ if (fm['standing-mandate']) {
197
+ entry.standingMandate = fm['standing-mandate'].split(/,\s*/).map(s => s.trim());
198
+ }
199
+
200
+ // Directives (scoped tasks for orient/debrief/etc.)
201
+ if (fm.directives && typeof fm.directives === 'object') {
202
+ entry.directives = fm.directives;
203
+ }
204
+
205
+ entries.push(entry);
206
+ }
207
+
208
+ entries.sort((a, b) => a.name.localeCompare(b.name));
209
+
210
+ const index = {
211
+ skills: entries,
212
+ generatedAt: new Date().toISOString(),
213
+ version: VERSION,
214
+ };
215
+
216
+ fs.writeFileSync(
217
+ path.join(skillsDir, '_index.json'),
218
+ JSON.stringify(index, null, 2) + '\n'
219
+ );
220
+ return entries.length;
221
+ }
222
+
15
223
  const MODULES = {
16
224
  'session-loop': {
17
225
  name: 'Session Loop (orient + debrief)',
@@ -33,7 +241,7 @@ const MODULES = {
33
241
  mandatory: false,
34
242
  default: true,
35
243
  lean: false,
36
- templates: ['scripts/pib-db.js', 'scripts/pib-db-schema.sql', 'scripts/work-tracker-server.mjs', 'scripts/work-tracker-ui.html'],
244
+ templates: ['scripts/pib-db.js', 'scripts/pib-db-schema.sql', 'scripts/work-tracker-server.mjs', 'scripts/work-tracker-ui.html', 'skills/work-tracker'],
37
245
  needsDb: true,
38
246
  },
39
247
  'planning': {
@@ -59,7 +267,7 @@ const MODULES = {
59
267
  default: true,
60
268
  lean: true,
61
269
  templates: [
62
- 'skills/audit', 'skills/pulse', 'skills/triage-audit',
270
+ 'skills/audit', 'skills/pulse', 'skills/triage-audit', 'skills/cabinet',
63
271
  'cabinet', 'briefing',
64
272
  'skills/cabinet-accessibility', 'skills/cabinet-anti-confirmation',
65
273
  'skills/cabinet-architecture', 'skills/cabinet-boundary-man',
@@ -736,6 +944,14 @@ async function run() {
736
944
  }
737
945
  }
738
946
 
947
+ // --- Generate skill index ---
948
+ if (!flags.dryRun) {
949
+ const indexCount = generateSkillIndex(projectDir);
950
+ if (indexCount > 0) {
951
+ console.log(` 📇 Indexed ${indexCount} skills in .claude/skills/_index.json`);
952
+ }
953
+ }
954
+
739
955
  // --- Write metadata ---
740
956
  if (!flags.dryRun) {
741
957
  createMetadata(projectDir, {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "create-claude-cabinet",
3
- "version": "0.10.0",
3
+ "version": "0.11.1",
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"
@@ -0,0 +1,53 @@
1
+ ---
2
+ name: cabinet
3
+ description: |
4
+ List your cabinet members and invoke one by name. Shows who's available,
5
+ what they specialize in, and lets you call on a specific expert.
6
+ Use when: "cabinet", "who's on the cabinet", "ask the architect",
7
+ "what experts do I have", "/cabinet", "get me the [member]".
8
+ ---
9
+
10
+ # /cabinet — Your Expert Cabinet
11
+
12
+ ## Purpose
13
+
14
+ Show who's in your cabinet and let you consult a specific member. The
15
+ cabinet is your team of domain experts — each one evaluates from a
16
+ different lens. This skill is the front door.
17
+
18
+ ## Workflow
19
+
20
+ 1. **Read the skill index:** Read `.claude/skills/_index.json` and filter
21
+ to entries where `type === "cabinet"`. This gives you every cabinet
22
+ member's name and description in one read.
23
+
24
+ If the index file doesn't exist (older install), fall back to
25
+ Glob for `.claude/skills/cabinet-*/SKILL.md` and read frontmatter.
26
+
27
+ 2. **Strip the `cabinet-` prefix** for friendly display — the architect
28
+ is "architect", not "cabinet-architecture".
29
+
30
+ 3. **Present the roster:**
31
+
32
+ ### Your Cabinet
33
+ | Member | Expertise |
34
+ |--------|-----------|
35
+ | architect | System fit and infrastructure leverage |
36
+ | debugger | Dependency chains, error modes, environment prereqs |
37
+ | ... | ... |
38
+
39
+ Sort alphabetically.
40
+
41
+ 4. **If the user named a specific member** (e.g., "ask the architect",
42
+ "/cabinet architect", "get me the historian"), skip the roster and
43
+ invoke that member's skill directly.
44
+
45
+ 5. **If showing the roster**, ask: "Who do you want to consult?"
46
+ When they pick one, invoke that member's skill.
47
+
48
+ ## Important
49
+
50
+ - Roster is always discovered dynamically — never hardcoded.
51
+ - Member names are friendly (no `cabinet-` prefix in display).
52
+ - If the user asks for a member that doesn't exist, show the roster
53
+ and say which name didn't match.
@@ -11,6 +11,14 @@ briefing:
11
11
  - _briefing-identity.md
12
12
  - _briefing-architecture.md
13
13
  - _briefing-jurisdictions.md
14
+ standing-mandate: audit, plan, investigate
15
+ directives:
16
+ plan: >
17
+ Evaluate structural fit. Does this plan compose well with existing
18
+ architecture, or introduce unnecessary coupling or layering violations?
19
+ investigate: >
20
+ Guide where to look. Which layers, components, and boundaries are
21
+ most relevant to this investigation?
14
22
  ---
15
23
 
16
24
  # Architecture Cabinet Member
@@ -11,6 +11,11 @@ briefing:
11
11
  - _briefing-identity.md
12
12
  - _briefing-architecture.md
13
13
  - _briefing-jurisdictions.md
14
+ standing-mandate: execute
15
+ directives:
16
+ execute: >
17
+ Watch for implicit boundary conditions, unguarded state transitions,
18
+ and silent exclusions in the code being written.
14
19
  ---
15
20
 
16
21
  # Boundary Man
@@ -12,6 +12,7 @@ briefing:
12
12
  - _briefing-architecture.md
13
13
  - _briefing-jurisdictions.md
14
14
  - _briefing-api.md
15
+ standing-mandate: audit
15
16
  ---
16
17
 
17
18
  # Data Integrity Cabinet Member
@@ -9,6 +9,12 @@ user-invocable: false
9
9
  briefing:
10
10
  - _briefing-identity.md
11
11
  - _briefing-architecture.md
12
+ standing-mandate: execute
13
+ directives:
14
+ execute: >
15
+ Before code runs, verify prerequisites. Dependencies installed?
16
+ Environment configured? Migrations needed? Flag anything that will
17
+ surface as a runtime surprise.
12
18
  ---
13
19
 
14
20
  # Debugger Cabinet Member
@@ -12,6 +12,7 @@ user-invocable: false
12
12
  briefing:
13
13
  - _briefing-architecture.md
14
14
  - _briefing-jurisdictions.md
15
+ standing-mandate: audit
15
16
  ---
16
17
 
17
18
  # Framework Quality
@@ -10,6 +10,21 @@ user-invocable: false
10
10
  briefing:
11
11
  - _briefing-identity.md
12
12
  - _briefing-architecture.md
13
+ standing-mandate: plan, execute, orient, debrief
14
+ directives:
15
+ plan: >
16
+ Check prior art. Have we attempted something similar before? What
17
+ worked or failed? Surface relevant decisions and patterns.
18
+ execute: >
19
+ Flag if this code repeats a known mistake or contradicts an
20
+ established pattern.
21
+ orient: >
22
+ Review the loaded context. Surface 1-3 prior decisions or lessons
23
+ most relevant to today's likely work. Keep it brief — facts only,
24
+ no analysis.
25
+ debrief: >
26
+ Review this session's decisions and lessons. Verify they were
27
+ captured to memory. Flag any significant decision that wasn't recorded.
13
28
  ---
14
29
 
15
30
  # Historian Cabinet Member
@@ -13,6 +13,12 @@ user-invocable: false
13
13
  briefing:
14
14
  - _briefing-identity.md
15
15
  - _briefing-architecture.md
16
+ standing-mandate: audit, plan
17
+ directives:
18
+ plan: >
19
+ Evaluate cognitive load. Will this plan's result be understandable
20
+ and maintainable? Does it externalize complexity or pile it on the
21
+ operator?
16
22
  ---
17
23
 
18
24
  # The Organized Mind
@@ -11,7 +11,12 @@ briefing:
11
11
  - _briefing-identity.md
12
12
  - _briefing-cabinet.md
13
13
  - _briefing-jurisdictions.md
14
- standing-mandate: audit
14
+ standing-mandate: audit, seed
15
+ directives:
16
+ seed: >
17
+ Before adding new members, evaluate whether existing members are
18
+ healthy and being used effectively. Are current members overlapping
19
+ or underperforming?
15
20
  files:
16
21
  - skills/**/*.md
17
22
  - skills/cabinet-*/_prompt-guide.md
@@ -11,6 +11,14 @@ briefing:
11
11
  - _briefing-identity.md
12
12
  - _briefing-architecture.md
13
13
  - _briefing-jurisdictions.md
14
+ standing-mandate: plan, execute
15
+ directives:
16
+ plan: >
17
+ Evaluate testability. Are acceptance criteria verifiable? What edge
18
+ cases and failure modes are missing from the plan?
19
+ execute: >
20
+ Verify each checkpoint against acceptance criteria. Flag untested
21
+ paths and regressions.
14
22
  ---
15
23
 
16
24
  # QA Cabinet Member
@@ -10,7 +10,12 @@ user-invocable: false
10
10
  briefing:
11
11
  - _briefing-identity.md
12
12
  - _briefing-jurisdictions.md
13
- standing-mandate: audit
13
+ standing-mandate: audit, debrief
14
+ directives:
15
+ debrief: >
16
+ Review this session's changed files. Check if any CLAUDE.md,
17
+ system-status, briefing, or memory files now contain stale claims.
18
+ Fix what you find — don't create findings.
14
19
  files:
15
20
  - CLAUDE.md
16
21
  - "**/CLAUDE.md"
@@ -10,7 +10,11 @@ user-invocable: false
10
10
  briefing:
11
11
  - _briefing-identity.md
12
12
  - _briefing-cabinet.md
13
- standing-mandate: audit
13
+ standing-mandate: audit, seed
14
+ directives:
15
+ seed: >
16
+ Identify coverage gaps. What expertise is the cabinet missing for
17
+ this project's current technology stack and workflow?
14
18
  files:
15
19
  - .claude/skills/**/*.md
16
20
  - CLAUDE.md
@@ -11,6 +11,14 @@ briefing:
11
11
  - _briefing-architecture.md
12
12
  - _briefing-jurisdictions.md
13
13
  - _briefing-api.md
14
+ standing-mandate: audit, plan, execute
15
+ directives:
16
+ plan: >
17
+ Check for security exposure. Does this plan handle auth, data access,
18
+ and input validation? Any secrets or credentials at risk?
19
+ execute: >
20
+ Watch for hardcoded secrets, missing auth checks, unvalidated input,
21
+ and accidental data exposure in the code being written.
14
22
  ---
15
23
 
16
24
  # Security Cabinet Member
@@ -12,6 +12,7 @@ briefing:
12
12
  - _briefing-architecture.md
13
13
  - _briefing-jurisdictions.md
14
14
  interactive-only: true
15
+ standing-mandate: audit
15
16
  ---
16
17
 
17
18
  # Speed Freak
@@ -11,6 +11,14 @@ briefing:
11
11
  - _briefing-identity.md
12
12
  - _briefing-cabinet.md
13
13
  standing-mandate: orient, debrief
14
+ directives:
15
+ orient: >
16
+ Review installed skills and recent session activity. Spotlight one
17
+ underused capability relevant to today's context. One sentence.
18
+ debrief: >
19
+ Review what was built this session. Update the feature adoption
20
+ ledger if new capabilities were added. Note any that need
21
+ discoverability work.
14
22
  topics:
15
23
  - feature
16
24
  - adoption
@@ -10,6 +10,7 @@ user-invocable: false
10
10
  briefing:
11
11
  - _briefing-identity.md
12
12
  - _briefing-architecture.md
13
+ standing-mandate: audit
13
14
  ---
14
15
 
15
16
  # Technical Debt Cabinet Member
@@ -10,6 +10,7 @@ briefing:
10
10
  - _briefing-identity.md
11
11
  - _briefing-jurisdictions.md
12
12
  interactive-only: true
13
+ standing-mandate: audit
13
14
  ---
14
15
 
15
16
  # Usability Cabinet Member
@@ -16,6 +16,11 @@ briefing:
16
16
  - _briefing-architecture.md
17
17
  - _briefing-jurisdictions.md
18
18
  standing-mandate: orient
19
+ directives:
20
+ orient: >
21
+ Review what happened recently. If the system has grown in complexity
22
+ since the user last got an explanation, flag one thing worth
23
+ explaining. Otherwise, stay silent.
19
24
  topics:
20
25
  - why does
21
26
  - how does
@@ -9,6 +9,7 @@ user-invocable: false
9
9
  briefing:
10
10
  - _briefing-identity.md
11
11
  - _briefing-jurisdictions.md
12
+ standing-mandate: audit
12
13
  ---
13
14
 
14
15
  # Workflow Cop Cabinet Member
@@ -131,9 +131,15 @@ authorized update path for manifest-tracked files.
131
131
 
132
132
  ### 2.4. Memory Hook Migration (v0.9.x → v0.10+)
133
133
 
134
- **This step runs when upgrading from v0.9.x or earlier** (detected by
135
- the presence of `memory-session-start.sh` or `memory-post-compact.sh`
136
- in `.claude/settings.json`).
134
+ **This step runs when upgrading from v0.9.x or earlier.** Detect by
135
+ checking BOTH:
136
+ - `.claude/settings.json` for `memory-session-start.sh` or
137
+ `memory-post-compact.sh` references
138
+ - `.claude/hooks/` directory for the actual files on disk
139
+
140
+ Either condition triggers this step. The installer cleans settings.json
141
+ references but does NOT delete the orphaned files (it treats them as
142
+ project-owned since they're no longer in the upstream manifest).
137
143
 
138
144
  Starting in v0.10, omega's native hooks handle memory capture/recall
139
145
  directly (configured in global `~/.claude/settings.json`). The old
@@ -145,13 +151,13 @@ context injection if left in place.
145
151
  in `SessionStart` hooks and `memory-post-compact.sh` in `PostCompact`
146
152
  2. If found, remove those entries. Keep other hooks (git-guardrails,
147
153
  cc-upstream-guard, telemetry) untouched.
148
- 3. Verify omega native hooks are configured: run `omega hooks doctor`.
154
+ 3. Check for orphaned files: `ls .claude/hooks/memory-session-start.sh
155
+ .claude/hooks/memory-post-compact.sh 2>/dev/null`. Delete any that
156
+ exist — they are dead weight, not project-owned content.
157
+ 4. Verify omega native hooks are configured: run `omega hooks doctor`.
149
158
  If not configured, the installer's omega-setup already ran
150
159
  `omega hooks setup` — verify by checking `~/.claude/settings.json`
151
160
  for `fast_hook.py` entries.
152
- 4. The old shell scripts (`hooks/memory-session-start.sh`,
153
- `hooks/memory-post-compact.sh`) can be deleted from the project's
154
- `.claude/hooks/` directory — they're no longer called.
155
161
 
156
162
  **Tell the user:** "Memory hooks have been upgraded to omega native.
157
163
  You now get 3 additional capabilities: real-time decision capture,
@@ -180,27 +180,14 @@ Read `phases/update-state.md` for what state files and documentation
180
180
  to update. This keeps the system's persistent state aligned with
181
181
  reality so the next orient reads accurate information.
182
182
 
183
- **Default (absent/empty):** At minimum check whether `system-status.md`
183
+ **Default (absent/empty):** Check whether `system-status.md`
184
184
  (or equivalent) needs updating to reflect what was built, fixed, or
185
- changed.
186
-
187
- Also check **briefing freshness** — did this session's work invalidate
188
- any claims in the briefing files? Common drift signals:
189
- - Session installed a new module or capability, but the briefing still
190
- says it's not available
191
- - Session changed architecture (new data store, new framework, new
192
- deployment), but the briefing describes the old state
193
- - Version numbers in `.ccrc.json` or briefing don't match `package.json`
194
- - Work tracking was set up or changed, but `_briefing-work-tracking.md`
195
- doesn't reflect it
196
-
197
- If the briefing is stale, update the relevant split file (or the
198
- monolithic `_briefing.md` if the project hasn't split yet). Don't wait
199
- for `/audit` to catch this — stale briefings degrade every cabinet
200
- member's judgment until they're fixed.
201
-
202
- Also check the **user-level state** (silently — don't make this a
203
- conversation unless something needs updating):
185
+ changed. Also check the user-level state below.
186
+
187
+ #### User-Level State
188
+
189
+ Check silently don't make this a conversation unless something
190
+ needs updating:
204
191
 
205
192
  - **`~/.claude/CLAUDE.md`** — did the user reveal something about
206
193
  themselves this session that isn't in their profile? A new role,
@@ -390,14 +377,38 @@ these aren't captured somewhere, they rely on human memory.
390
377
 
391
378
  **Skip (absent/empty).**
392
379
 
393
- ### 12. Discover Custom Phases
380
+ ### 12. Cabinet Consultations (core)
381
+
382
+ Spawn cabinet members whose `standing-mandate` includes `debrief`.
383
+
384
+ **Discovery:** Read `.claude/skills/_index.json` and filter to entries
385
+ where `standingMandate` includes `"debrief"`. Each matching entry has
386
+ a `directives.debrief` field — this is the scoped task for that member.
387
+ If the index is missing, fall back to reading `cabinet-*/SKILL.md`
388
+ frontmatter for `standing-mandate` and `directives`.
389
+
390
+ **For each matching member**, spawn an agent with:
391
+ - The member's full SKILL.md (read from the `path` in the index)
392
+ - The session inventory from step 1 (what changed)
393
+ - The member's `directives.debrief` as the task
394
+
395
+ Spawn in parallel where possible. If a member has no directive for
396
+ `debrief`, skip it — a standing mandate without a directive is a data
397
+ error, not a reason to give the member an open-ended task.
398
+
399
+ **Cost control:** These are lightweight passes, not full audits. Each
400
+ agent should complete in under 2 minutes. If a member's directive
401
+ produces no findings or changes, it returns silently. Include their
402
+ results in the report only when they surfaced or changed something.
403
+
404
+ ### 13. Discover Custom Phases
394
405
 
395
406
  After running the core phases above, check for any additional phase
396
407
  files in `phases/` that the skeleton doesn't define. These are project-
397
408
  specific extensions. Each custom phase file declares its position in
398
409
  the workflow. Execute them at their declared position.
399
410
 
400
- ### 13. Present Report (presentation)
411
+ ### 14. Present Report (presentation)
401
412
 
402
413
  Read `phases/report.md` for how to present the debrief summary.
403
414
 
@@ -429,7 +440,8 @@ skip presentation phases. Core phases always run.
429
440
 
430
441
  - **Core phases** (always run): inventory, close-work, auto-maintenance,
431
442
  update-state, health-checks, record-lessons, upstream-feedback,
432
- skill-discovery, cabinet-check, loose-ends, persist work
443
+ skill-discovery, cabinet-check, loose-ends, cabinet-consultations,
444
+ persist work
433
445
  - **Presentation phases** (skippable): report
434
446
 
435
447
  A project that wants a quick debrief variant skips the report and
@@ -104,17 +104,21 @@ loop (Steps 4-5) and instead:
104
104
  Read `phases/cabinet.md` for which cabinet members to activate during
105
105
  execution, any always-on cabinet members, and any project-specific rules.
106
106
 
107
- **Default (absent/empty):** Read `.claude/skills/cabinet-*/SKILL.md`
108
- and select cabinet members whose convening criteria match:
109
- - **standing-mandate: execute** — always included
107
+ **Default (absent/empty):** Use `.claude/skills/_index.json` to select
108
+ cabinet members whose convening criteria match:
109
+ - **`standingMandate` includes `"execute"`** — always included
110
110
  - **File patterns** — any file in the plan's surface area matches
111
111
  - **Topic keywords** — any keyword in the plan description matches
112
112
 
113
+ Fall back to reading `cabinet-*/SKILL.md` if the index is missing.
114
+
113
115
  Err toward inclusion. A cabinet member that activates unnecessarily costs
114
116
  a few seconds; one that doesn't activate when needed costs rework.
115
117
 
116
118
  Prepare reusable briefing for agent prompts: read `_briefing.md` once and
117
- keep the essential facts ready to paste into each agent's prompt.
119
+ keep the essential facts ready to paste into each agent's prompt. When a
120
+ member has a `directives.execute`, include it in the agent prompt to
121
+ sharpen their focus during execution checkpoints.
118
122
 
119
123
  If no cabinet members exist in the project, skip all checkpoint steps
120
124
  (3, 4b, 5) and execute the plan directly. Checkpoints add depth, not
@@ -44,7 +44,18 @@ Bad questions (too vague — narrow first):
44
44
  - "How does the system work?" → Pick a specific subsystem
45
45
  - "Is the code good?" → That's /audit, not /investigate
46
46
 
47
- ### 2. Observe (Gather Facts)
47
+ ### 2. Cabinet Consultations
48
+
49
+ Before exploring, check if any cabinet members have relevant context.
50
+ Read `.claude/skills/_index.json` and filter to entries where
51
+ `standingMandate` includes `"investigate"` and `directives.investigate`
52
+ exists. Spawn matching members as agents in parallel, passing the
53
+ investigation question from step 1.
54
+
55
+ If no members match or the index is missing, proceed directly to
56
+ observation.
57
+
58
+ ### 3. Observe (Gather Facts)
48
59
 
49
60
  Collect raw data without interpreting it. Use the Explore agent or
50
61
  direct Grep/Glob/Read calls:
@@ -62,7 +73,7 @@ direct Grep/Glob/Read calls:
62
73
  **Output:** A bulleted list of concrete observations. Each observation
63
74
  should cite a specific file:line or data point.
64
75
 
65
- ### 3. Hypothesize (Form Explanations)
76
+ ### 4. Hypothesize (Form Explanations)
66
77
 
67
78
  Based on observations, form 1-3 hypotheses that explain what you're seeing.
68
79
 
@@ -75,7 +86,7 @@ For each hypothesis:
75
86
  first explanation. If you only have one hypothesis, you're not investigating
76
87
  — you're confirming.
77
88
 
78
- ### 4. Test (Verify)
89
+ ### 5. Test (Verify)
79
90
 
80
91
  For each hypothesis, actively seek the confirming AND refuting evidence
81
92
  you identified. This may involve:
@@ -87,7 +98,7 @@ you identified. This may involve:
87
98
  **Record results per hypothesis:** confirmed, refuted, or inconclusive
88
99
  (with what additional data would resolve it).
89
100
 
90
- ### 5. Conclude
101
+ ### 6. Conclude
91
102
 
92
103
  Summarize findings in a structured report:
93
104
 
@@ -14,33 +14,30 @@ whether they are auto-invocable or manual-only.
14
14
 
15
15
  ## Workflow
16
16
 
17
- 1. **Discover skills:** Use the Glob tool to find all `.claude/skills/*/SKILL.md` files.
17
+ 1. **Read the skill index:** Read `.claude/skills/_index.json`. This file
18
+ is generated by the installer and contains name, description, type,
19
+ and invocability for every installed skill.
18
20
 
19
- 2. **Read frontmatter from each:** For every discovered SKILL.md, use the Read tool
20
- to extract the YAML frontmatter (between the `---` delimiters). Parse these fields:
21
- - `name` — the skill name (used as `/name` in the table)
22
- - `description` — first line or sentence of the description (strip the
23
- "Use when:" portion for display)
24
- - `disable-model-invocation` — if `true`, the skill is manual-only.
25
- If absent or false, Claude can invoke it automatically.
21
+ If the index file doesn't exist (older install), fall back to
22
+ discovering skills via Glob + reading individual SKILL.md frontmatter.
26
23
 
27
- 3. **Group skills into two categories:**
24
+ 2. **Filter and group:**
25
+ - Exclude entries where `type === "cabinet"` — cabinet members are
26
+ accessed through `/cabinet`, not listed here.
27
+ - Group remaining skills into:
28
28
 
29
- **Auto (Claude uses these when relevant)** — skills where
30
- `disable-model-invocation` is absent or false. These trigger automatically
31
- when the context matches.
29
+ **Auto (Claude uses these when relevant)** — skills where `manual`
30
+ is absent or false.
32
31
 
33
- **Manual (user invokes these — they have side effects)** — skills where
34
- `disable-model-invocation: true`. The user must explicitly invoke these.
32
+ **Manual (user invokes these — they have side effects)** — skills
33
+ where `manual` is true.
35
34
 
36
- Note: `/menu` itself goes in whichever category its own frontmatter indicates.
37
-
38
- 4. **Format as two tables:**
35
+ 3. **Format as two tables:**
39
36
 
40
37
  ### Auto (Claude uses these when relevant)
41
- | Skill | When it triggers |
38
+ | Skill | What it does |
42
39
  |---|---|
43
- | `/name` | description (from the "Use when:" part of the description field) |
40
+ | `/name` | description |
44
41
 
45
42
  ### Manual (you invoke these — they have side effects)
46
43
  | Skill | What it does |
@@ -48,14 +45,12 @@ whether they are auto-invocable or manual-only.
48
45
 
49
46
  Sort alphabetically within each group.
50
47
 
51
- 5. **Suggest relevant skills:** Based on current context (open work items,
48
+ 4. **Suggest relevant skills:** Based on current context (open work items,
52
49
  queued tasks, recent activity), suggest which skills are most relevant
53
50
  right now.
54
51
 
55
52
  ## Important
56
53
 
57
- - Do NOT hardcode any skill names or descriptions. Every entry must come
58
- from reading the actual SKILL.md files at discovery time.
59
- - If a new skill is added to `.claude/skills/`, it automatically appears
60
- in the menu on the next invocation. No updates to this file needed.
54
+ - The index is the primary data source. Only fall back to scanning
55
+ individual SKILL.md files if `_index.json` is missing.
61
56
  - If a SKILL.md has no description, show the skill name with "(no description)".
@@ -29,6 +29,9 @@ related:
29
29
  - type: file
30
30
  path: .claude/skills/orient/phases/cabinet.md
31
31
  role: "Project-specific: which cabinet members to activate"
32
+ - type: file
33
+ path: .claude/skills/orient/phases/skills-menu.md
34
+ role: "Project-specific: what skills to show after briefing"
32
35
  - type: file
33
36
  path: cabinet/_briefing.md
34
37
  role: "Project identity and configuration"
@@ -227,7 +230,30 @@ without being explicitly invoked for each decision.
227
230
 
228
231
  **Skip (absent/empty).**
229
232
 
230
- ### 7. Present Briefing (presentation)
233
+ ### 7. Cabinet Consultations (core)
234
+
235
+ Spawn cabinet members whose `standing-mandate` includes `orient`.
236
+
237
+ **Discovery:** Read `.claude/skills/_index.json` and filter to entries
238
+ where `standingMandate` includes `"orient"`. Each matching entry has
239
+ a `directives.orient` field — this is the scoped task for that member.
240
+ If the index is missing, fall back to reading `cabinet-*/SKILL.md`
241
+ frontmatter for `standing-mandate` and `directives`.
242
+
243
+ **For each matching member**, spawn an agent with:
244
+ - The member's full SKILL.md (read from the `path` in the index)
245
+ - The context loaded in step 1 (project state, recent work)
246
+ - The member's `directives.orient` as the task
247
+
248
+ Spawn in parallel where possible. If a member has no directive for
249
+ `orient`, skip it — a standing mandate without a directive is a data
250
+ error, not a reason to give the member an open-ended task.
251
+
252
+ **Cost control:** These are lightweight passes, not full audits. Each
253
+ agent should complete in under 1 minute. Include their output in the
254
+ briefing only when they have something to contribute. Silent is fine.
255
+
256
+ ### 8. Present Briefing (presentation)
231
257
 
232
258
  Read `phases/briefing.md` for how to present the orientation results.
233
259
  This phase controls format, sections, tone, and any time-aware or
@@ -237,7 +263,23 @@ context-aware presentation modes.
237
263
  in steps 1-6: project state, work items needing attention, any health
238
264
  issues found, maintenance results.
239
265
 
240
- ### 8. Discover Custom Phases
266
+ ### 9. Show Available Skills (core)
267
+
268
+ After the briefing, show the user what skills are available. This
269
+ serves the same purpose as a menu at a restaurant — you can't order
270
+ what you don't know exists.
271
+
272
+ **Default (absent/empty):** Invoke the `/menu` skill. This dynamically
273
+ discovers all skills in `.claude/skills/` (both CC upstream and project-
274
+ specific), reads their frontmatter, and presents them grouped by
275
+ auto-invocable vs manual. It also suggests which skills are most
276
+ relevant given current context.
277
+
278
+ Read `phases/skills-menu.md` for project-specific overrides (e.g.,
279
+ highlighting certain skills, suppressing others, or changing the
280
+ presentation format).
281
+
282
+ ### 10. Discover Custom Phases
241
283
 
242
284
  After running the core phases above, check for any additional phase
243
285
  files in `phases/` that the skeleton doesn't define. These are project-
@@ -245,7 +287,7 @@ specific extensions. Each custom phase file declares its position in the
245
287
  workflow (e.g., "runs after work scan, before briefing"). Execute them
246
288
  at their declared position.
247
289
 
248
- ### 9. Name the Session
290
+ ### 11. Name the Session
249
291
 
250
292
  Rename the session so the sidebar is scannable. Every session that starts
251
293
  with `/orient` looks identical in the history — naming fixes this.
@@ -265,6 +307,7 @@ stated a focus, ask.
265
307
  | `auto-maintenance.md` | Default: omega memory hygiene | Recurring session-start tasks |
266
308
  | `cabinet.md` | Skip | Which cabinet members to activate |
267
309
  | `briefing.md` | Default: simple summary | How to present orientation |
310
+ | `skills-menu.md` | Default: invoke /menu | What skills to show and how |
268
311
 
269
312
  ## Quick Mode
270
313
 
@@ -274,7 +317,8 @@ user already knows what they're doing, skip presentation phases. Core
274
317
  phases always run because they keep the system healthy.
275
318
 
276
319
  - **Core phases** (always run): context, data-sync, work-scan,
277
- health-checks, auto-maintenance, cabinet
320
+ health-checks, auto-maintenance, cabinet, cabinet-consultations,
321
+ skills-menu
278
322
  - **Presentation phases** (skippable): briefing
279
323
 
280
324
  A project that wants a quick orient variant skips the briefing phase
@@ -292,7 +336,6 @@ Examples of phases mature projects add:
292
336
  - Command queue processing (check for instructions from external UIs)
293
337
  - Deferred item evaluation (re-check trigger conditions on paused work)
294
338
  - Time-aware briefing modes (first session of day vs. returning session)
295
- - Proactive skill suggestions (surface tools relevant to current state)
296
339
  - Calendar integration (upcoming events that need preparation)
297
340
 
298
341
  ## Calibration
@@ -177,13 +177,16 @@ activate during planning, any special rules (e.g., "always include a
177
177
  design committee for UI plans"), and any project-specific critique
178
178
  workflow.
179
179
 
180
- **Default (absent/empty):** Read `.claude/skills/cabinet-*/SKILL.md`
181
- and identify cabinet members whose convening criteria match the plan's
182
- surface area or topic. Spawn each matching cabinet member as a parallel
183
- agent. Each receives:
180
+ **Default (absent/empty):** Use `.claude/skills/_index.json` to
181
+ identify cabinet members whose convening criteria match the plan's
182
+ surface area or topic (check `standingMandate` for `"plan"`, file
183
+ patterns, and topic keywords). Fall back to reading `cabinet-*/SKILL.md`
184
+ if the index is missing. Spawn each matching member as a parallel agent.
185
+ Each receives:
184
186
  - The cabinet member's full SKILL.md content
185
187
  - Essential project briefing from `_briefing.md`
186
188
  - The draft plan (problem, implementation, surface area, AC)
189
+ - The member's `directives.plan` if it exists (scoped focus for planning)
187
190
  - Instructions to evaluate through their lens and return concerns + verdict
188
191
 
189
192
  **Collect all verdicts.** Apply escalation:
@@ -102,7 +102,21 @@ phase file). Projects override this phase to add domain-specific signals
102
102
  compliance cabinet member; a financial project might map payment libraries
103
103
  to a financial-integrity cabinet member.
104
104
 
105
- ### 2. Evaluate Existing Cabinet Members
105
+ ### 2. Cabinet Consultations
106
+
107
+ Before evaluating gaps, check if any cabinet members have relevant
108
+ context. Read `.claude/skills/_index.json` and filter to entries where
109
+ `standingMandate` includes `"seed"` and `directives.seed` exists.
110
+ Spawn matching members as agents in parallel, passing the scan results
111
+ from step 1.
112
+
113
+ Include their findings in the evaluation step — a roster-check member
114
+ might identify coverage gaps, a process-therapist might flag unhealthy
115
+ existing members before you add new ones.
116
+
117
+ If no members match or the index is missing, proceed directly.
118
+
119
+ ### 3. Evaluate Existing Cabinet Members
106
120
 
107
121
  Read `phases/evaluate-existing.md` for how to compare detected signals
108
122
  against the current cabinet members.
@@ -124,7 +138,7 @@ gaps to fill and which staleness to address. Not every technology needs
124
138
  a cabinet member — some are too minor, some are well-understood, some are
125
139
  covered by existing cabinet members with broader scope.
126
140
 
127
- ### 3. Build New Cabinet Members
141
+ ### 4. Build New Cabinet Members
128
142
 
129
143
  Read `phases/build-member.md` for how to collaboratively build a
130
144
  new cabinet member with the user.
@@ -149,7 +163,7 @@ built with the user's input — "we use Mantine, we care about keyboard
149
163
  navigation, our users are on slow connections" — catches what actually
150
164
  matters.
151
165
 
152
- ### 4. Maintain Existing Cabinet Members
166
+ ### 5. Maintain Existing Cabinet Members
153
167
 
154
168
  Read `phases/maintain.md` for how to review the health of existing
155
169
  cabinet members and recommend changes.
@@ -0,0 +1,56 @@
1
+ ---
2
+ name: work-tracker
3
+ description: |
4
+ Open the work tracking UI. Starts the local server and tells you to
5
+ open it in the browser. Use to review projects, actions, and plan
6
+ progress visually. Use when: "work tracker", "show work", "open tracker",
7
+ "show projects", "show actions", "/work-tracker".
8
+ related:
9
+ - type: file
10
+ path: scripts/work-tracker-server.mjs
11
+ role: "Local HTTP server for work tracker UI"
12
+ - type: file
13
+ path: scripts/work-tracker-ui.html
14
+ role: "Browser-based work tracking interface"
15
+ - type: file
16
+ path: scripts/pib-db.js
17
+ role: "Data layer — projects and actions in pib.db"
18
+ ---
19
+
20
+ # /work-tracker — Work Tracking UI
21
+
22
+ ## Purpose
23
+
24
+ Open the visual work tracker so the user can review projects, actions,
25
+ and progress in a browser rather than through conversation.
26
+
27
+ ## Steps
28
+
29
+ 1. **Check database exists:**
30
+ ```bash
31
+ ls pib.db
32
+ ```
33
+ If missing, initialize it:
34
+ ```bash
35
+ node scripts/pib-db.js init
36
+ ```
37
+
38
+ 2. **Start the server:**
39
+ ```bash
40
+ node scripts/work-tracker-server.mjs --port 3458
41
+ ```
42
+ Run this in the background. If port 3458 is taken, try 3459.
43
+
44
+ 3. **Tell the user** to open `http://localhost:3458` in their browser.
45
+
46
+ 4. **Stay available.** The user may come back with questions about what
47
+ they see, or ask you to create/update projects and actions based on
48
+ their review. Use `scripts/pib-db.js` for any mutations they request.
49
+
50
+ ## Notes
51
+
52
+ - The server must keep running for the UI to work. If the user ends
53
+ the conversation, the server stops.
54
+ - The UI shows projects filterable by status (active, paused, done,
55
+ dropped, someday) and their actions.
56
+ - Actions can be created, completed, and edited directly in the browser.
@@ -1,43 +0,0 @@
1
- #!/bin/bash
2
- # PostCompact hook — capture session context before it's lost
3
- #
4
- # Fires on: manual (/compact) and auto (context limit) compaction
5
- # Output: read-only (observability only, 10K char cap)
6
- # Design: D1 (absolute venv path), D2 (never block), D3 (graceful degradation)
7
-
8
- VENV_PYTHON="$HOME/.claude-cabinet/omega-venv/bin/python3"
9
- ADAPTER="scripts/cabinet-memory-adapter.py"
10
-
11
- # D3: graceful degradation — if venv or adapter missing, exit silently
12
- if [ ! -x "$VENV_PYTHON" ] || [ ! -f "$ADAPTER" ]; then
13
- exit 0
14
- fi
15
-
16
- # Read hook input from stdin (includes compact_summary)
17
- INPUT=$(cat)
18
-
19
- # Call adapter — pipe hook input as stdin for capture
20
- RESULT=$(echo "$INPUT" | "$VENV_PYTHON" "$ADAPTER" capture 2>/dev/null)
21
-
22
- # Log result for observability (PostCompact output is read-only)
23
- STORED=$(echo "$RESULT" | "$VENV_PYTHON" -c "
24
- import sys, json
25
- try:
26
- data = json.load(sys.stdin)
27
- if data.get('ok'):
28
- count = data.get('stored', 0)
29
- if count:
30
- print(f'cabinet-memory: captured {count} memories from compaction')
31
- else:
32
- print('cabinet-memory: no memories captured (nothing noteworthy)')
33
- else:
34
- print(f'cabinet-memory: {data.get(\"error\", \"unknown error\")}')
35
- except:
36
- pass
37
- " 2>/dev/null)
38
-
39
- if [ -n "$STORED" ]; then
40
- echo "$STORED"
41
- fi
42
-
43
- exit 0
@@ -1,59 +0,0 @@
1
- #!/bin/bash
2
- # SessionStart hook — surface relevant memories via omega
3
- #
4
- # Fires on: startup, resume, compact (not clear — fresh context)
5
- # Output: relevant memories injected into session context
6
- # Design: D1 (absolute venv path), D2 (never block), D3 (graceful degradation)
7
-
8
- VENV_PYTHON="$HOME/.claude-cabinet/omega-venv/bin/python3"
9
- ADAPTER="scripts/cabinet-memory-adapter.py"
10
-
11
- # D3: graceful degradation — if venv or adapter missing, warn but don't block
12
- if [ ! -x "$VENV_PYTHON" ] || [ ! -f "$ADAPTER" ]; then
13
- echo ""
14
- echo "**Note:** Memory module is installed but omega is not available."
15
- echo "Semantic memory (decisions, lessons, preferences) is not being captured or recalled."
16
- echo "Run \`npx create-claude-cabinet\` to set up the omega venv."
17
- exit 0
18
- fi
19
-
20
- # Read hook input from stdin
21
- INPUT=$(cat)
22
-
23
- # Extract source field to skip /clear (fresh context, no memories needed)
24
- SOURCE=$(echo "$INPUT" | "$VENV_PYTHON" -c "
25
- import sys, json
26
- try:
27
- data = json.load(sys.stdin)
28
- print(data.get('source', 'startup'))
29
- except:
30
- print('startup')
31
- " 2>/dev/null)
32
-
33
- if [ "$SOURCE" = "clear" ]; then
34
- exit 0
35
- fi
36
-
37
- # Call adapter — pipe hook input as stdin
38
- RESULT=$(echo "$INPUT" | "$VENV_PYTHON" "$ADAPTER" welcome 2>/dev/null)
39
-
40
- # Extract context from result
41
- CONTEXT=$(echo "$RESULT" | "$VENV_PYTHON" -c "
42
- import sys, json
43
- try:
44
- data = json.load(sys.stdin)
45
- if data.get('ok') and data.get('context'):
46
- print(data['context'])
47
- except:
48
- pass
49
- " 2>/dev/null)
50
-
51
- # Output context to stdout — SessionStart hook stdout becomes session context
52
- if [ -n "$CONTEXT" ]; then
53
- echo ""
54
- echo "## Recalled Memories (omega)"
55
- echo ""
56
- echo "$CONTEXT"
57
- fi
58
-
59
- exit 0