@codihaus/claude-skills 1.6.20 → 1.6.21

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/bin/cli.js CHANGED
@@ -23,6 +23,7 @@ program
23
23
  .option('--all', 'Install all skills (default)', true)
24
24
  .option('--no-deps', 'Skip dependency checking')
25
25
  .option('--no-hooks', 'Skip hooks setup')
26
+ .option('-k, --knowledge <path>', 'Path to custom knowledge base to install')
26
27
  .option('-y, --yes', 'Skip confirmation prompts')
27
28
  .action(init);
28
29
 
@@ -28,7 +28,7 @@ Each stack follows this structure:
28
28
 
29
29
  ```
30
30
  stacks/{stack-name}/
31
- ├── _index.md # Main knowledge file
31
+ ├── _index.md # Main knowledge file (always read first)
32
32
  │ ├── Overview # What it is, when to use
33
33
  │ ├── Best Practices # Patterns to follow
34
34
  │ ├── Anti-Patterns # What to avoid
@@ -37,17 +37,43 @@ stacks/{stack-name}/
37
37
  │ ├── For /dev-review # Review checklists
38
38
  │ └── Integration # How it works with other stacks
39
39
 
40
- ├── references/ # Detailed documentation
40
+ ├── references/ # Detailed documentation (load as needed)
41
41
  │ ├── api.md # API reference
42
42
  │ ├── patterns.md # Common patterns
43
43
  │ └── performance.md # Performance optimization
44
44
 
45
- └── assets/ # Code templates
45
+ └── assets/ # Code templates (load as needed)
46
46
  ├── composable.ts # Example composable
47
47
  ├── component.vue # Example component
48
48
  └── config.ts # Example config
49
49
  ```
50
50
 
51
+ ## Loading Knowledge
52
+
53
+ Skills can load knowledge in two ways:
54
+
55
+ ### 1. Quick Reference (Default)
56
+ Load only `_index.md` for overview and skill-specific guidance:
57
+ ```
58
+ Read knowledge/stacks/{stack}/_index.md
59
+ ```
60
+
61
+ ### 2. Deep Dive (When Needed)
62
+ Use `_knowledge.json` to discover and load additional files:
63
+ ```
64
+ 1. Read knowledge/_knowledge.json → Get file list for {stack}
65
+ 2. Read knowledge/stacks/{stack}/_index.md → Main guidance
66
+ 3. Read knowledge/stacks/{stack}/references/patterns.md → Detailed patterns
67
+ 4. Read knowledge/stacks/{stack}/references/performance.md → Performance tips
68
+ ```
69
+
70
+ ### When to Load More Than _index.md
71
+
72
+ - **Specs**: Usually `_index.md` is enough (high-level patterns)
73
+ - **Coding**: Load `references/` when implementing complex features
74
+ - **Review**: Load `references/performance.md` for performance reviews
75
+ - **Architecture**: Load `references/` for deep architectural decisions
76
+
51
77
  ## How Skills Use Stack Knowledge
52
78
 
53
79
  ### /dev-scout
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@codihaus/claude-skills",
3
- "version": "1.6.20",
3
+ "version": "1.6.21",
4
4
  "description": "Claude Code skills for software development workflow",
5
5
  "main": "src/index.js",
6
6
  "bin": {
@@ -227,6 +227,29 @@ Domain knowledge captures:
227
227
 
228
228
  See `knowledge/stacks/_index.md` and `knowledge/domains/_index.md` for details.
229
229
 
230
+ ### Knowledge Loading Patterns
231
+
232
+ Skills can load knowledge at two depths:
233
+
234
+ **Quick Reference (Default):**
235
+ - Load `knowledge/stacks/{stack}/_index.md` for overview and skill-specific sections
236
+ - Use for most tasks where general guidance is enough
237
+ - Examples: Specs, basic reviews, standard implementations
238
+
239
+ **Deep Dive (When Needed):**
240
+ 1. Read `knowledge/_knowledge.json` to discover available files
241
+ 2. Load `_index.md` for overview
242
+ 3. Load additional reference files based on needs:
243
+ - `references/patterns.md` - Detailed implementation patterns
244
+ - `references/performance.md` - Performance optimization
245
+ - `references/api.md` - API reference
246
+
247
+ **When to go deep:**
248
+ - Complex or performance-critical implementations
249
+ - Architecture decisions requiring deep framework knowledge
250
+ - Comprehensive code reviews
251
+ - Learning new patterns for unfamiliar stacks
252
+
230
253
  ## Skill Awareness Protocol
231
254
 
232
255
  Every skill should:
@@ -28,6 +28,7 @@ Create and maintain the unified BRD for a project. Handles initial requirements
28
28
  /debrief requirements.pdf # From document
29
29
  /debrief # Interactive
30
30
  /debrief --answers questionnaire.xlsx # Process customer answers
31
+ /debrief --questionnaire-only # Generate questionnaire only (no BRD)
31
32
  ```
32
33
 
33
34
  ## Output Structure
@@ -89,6 +90,11 @@ Depending on mode:
89
90
  - Open questions resolved
90
91
  - Status updated to "Confirmed" if complete
91
92
 
93
+ **Questionnaire Only:**
94
+ - Excel questionnaire file generated
95
+ - No BRD or feature folders created
96
+ - Ready to send to customer for answers
97
+
92
98
  ## Success Criteria
93
99
 
94
100
  - Use cases are testable (clear acceptance criteria)
@@ -108,6 +114,7 @@ Detect automatically on start:
108
114
  | `plans/brd/` exists, adding features | **Add Feature** | Add to existing BRD, check for duplicates |
109
115
  | Modifying confirmed use cases | **Change Request** | Create CR first, then update |
110
116
  | `--answers` flag provided | **Process Answers** | Update use cases with customer responses |
117
+ | `--questionnaire-only` flag provided | **Questionnaire Only** | Generate questionnaire Excel file only, no BRD |
111
118
 
112
119
  ## Context Gathering
113
120
 
@@ -345,6 +352,43 @@ Provide summary with:
345
352
 
346
353
  ---
347
354
 
355
+ ## Questionnaire-Only Mode
356
+
357
+ When `--questionnaire-only` flag is provided, skip BRD generation and only create questionnaire file.
358
+
359
+ ### Use Cases
360
+ - Quick requirements gathering without full debrief
361
+ - Ad-hoc customer clarifications
362
+ - Focused question sets for specific topics
363
+
364
+ ### Workflow
365
+
366
+ 1. **Ask Context Questions**
367
+ - Project name (or use current folder name)
368
+ - Topic/Feature being questioned
369
+ - Custom questions (user provides as text/list)
370
+
371
+ 2. **Generate Questionnaire**
372
+ - Create Excel file at `questionnaire-{YYYY-MM-DD}.xlsx` in current directory
373
+ - Include only the questions provided by user
374
+ - Use standard questionnaire format (Summary + Questions sheets)
375
+
376
+ 3. **Output Summary**
377
+ - File location
378
+ - Question count
379
+ - Next steps (send to customer, process with --answers)
380
+
381
+ ### Example
382
+
383
+ ```
384
+ /debrief --questionnaire-only "I need to ask customer about payment methods, billing cycle, and refund policy"
385
+
386
+ # Creates: questionnaire-2024-01-20.xlsx with 3 questions
387
+ # Ready to send to customer
388
+ ```
389
+
390
+ ---
391
+
348
392
  ## Process Answers Workflow
349
393
 
350
394
  When customer returns filled questionnaire, run:
@@ -73,6 +73,12 @@ You have three layers of knowledge to apply:
73
73
  - "Nuxt" → `knowledge/stacks/nuxt/_index.md`
74
74
  - "Directus" → `knowledge/stacks/directus/_index.md`
75
75
 
76
+ **Deep knowledge loading (for complex features):**
77
+ - First read `knowledge/_knowledge.json` to discover available reference files
78
+ - Load additional references when needed: `knowledge/stacks/{stack}/references/*.md`
79
+ - Example: For performance-critical features, load `references/performance.md`
80
+ - Example: For complex patterns, load `references/patterns.md`
81
+
76
82
  **If you skip this step**, you'll implement using generic patterns instead of framework-specific best practices (e.g., using fetch instead of Server Actions in Next.js).
77
83
 
78
84
  ## Expected Outcome
@@ -186,17 +186,22 @@ export async function init(options) {
186
186
  const knowledgeSpinner = ora('Installing knowledge base...').start();
187
187
 
188
188
  try {
189
- const { copied: knowledgeCopied, errors: knowledgeErrors } = await copyKnowledgeToProject(projectPath);
189
+ const { copied: knowledgeCopied, errors: knowledgeErrors } = await copyKnowledgeToProject(
190
+ projectPath,
191
+ options.knowledge // Custom knowledge path if provided
192
+ );
190
193
 
191
194
  if (knowledgeErrors.length > 0) {
192
195
  knowledgeSpinner.warn(`Installed ${knowledgeCopied.length} knowledge folders with ${knowledgeErrors.length} errors`);
193
196
  } else if (knowledgeCopied.length > 0) {
194
- knowledgeSpinner.succeed(`Installed knowledge: ${knowledgeCopied.join(', ')}`);
197
+ const source = options.knowledge ? ` from ${options.knowledge}` : '';
198
+ knowledgeSpinner.succeed(`Installed knowledge${source}: ${knowledgeCopied.join(', ')}`);
195
199
  } else {
196
200
  knowledgeSpinner.info('No knowledge to install');
197
201
  }
198
202
  } catch (e) {
199
203
  knowledgeSpinner.warn('Failed to install knowledge');
204
+ console.error(chalk.gray(` ${e.message}`));
200
205
  }
201
206
 
202
207
  // Step 6: Copy scripts (graph.py, etc.)
@@ -272,13 +272,24 @@ export async function checkForUpdates(projectPath) {
272
272
 
273
273
  /**
274
274
  * Copy knowledge (stacks, domains) to project
275
+ * @param {string} projectPath - Target project path
276
+ * @param {string} customSource - Optional custom knowledge source path
275
277
  */
276
- export async function copyKnowledgeToProject(projectPath) {
278
+ export async function copyKnowledgeToProject(projectPath, customSource = null) {
277
279
  const targetPath = path.join(projectPath, '.claude', 'knowledge');
280
+ const sourcePath = customSource
281
+ ? path.resolve(customSource)
282
+ : KNOWLEDGE_SOURCE;
278
283
 
279
284
  // Check if source exists
280
- if (!await fs.pathExists(KNOWLEDGE_SOURCE)) {
281
- return { copied: [], errors: [{ name: 'knowledge', error: 'Source not found' }] };
285
+ if (!await fs.pathExists(sourcePath)) {
286
+ return {
287
+ copied: [],
288
+ errors: [{
289
+ name: 'knowledge',
290
+ error: `Source not found: ${sourcePath}`
291
+ }]
292
+ };
282
293
  }
283
294
 
284
295
  // Remove existing and copy fresh
@@ -289,22 +300,27 @@ export async function copyKnowledgeToProject(projectPath) {
289
300
  const errors = [];
290
301
 
291
302
  try {
292
- const items = await fs.readdir(KNOWLEDGE_SOURCE);
303
+ const items = await fs.readdir(sourcePath);
293
304
 
294
305
  for (const item of items) {
295
306
  // Skip hidden files
296
307
  if (item.startsWith('.')) continue;
297
308
 
298
- const sourcePath = path.join(KNOWLEDGE_SOURCE, item);
309
+ const itemSourcePath = path.join(sourcePath, item);
299
310
  const targetItemPath = path.join(targetPath, item);
300
311
 
301
312
  try {
302
- await fs.copy(sourcePath, targetItemPath);
313
+ await fs.copy(itemSourcePath, targetItemPath);
303
314
  copied.push(item);
304
315
  } catch (e) {
305
316
  errors.push({ name: item, error: e.message });
306
317
  }
307
318
  }
319
+
320
+ // Generate knowledge declaration file
321
+ if (copied.length > 0) {
322
+ await generateKnowledgeDeclare(targetPath);
323
+ }
308
324
  } catch (e) {
309
325
  errors.push({ name: 'knowledge', error: e.message });
310
326
  }
@@ -312,6 +328,137 @@ export async function copyKnowledgeToProject(projectPath) {
312
328
  return { copied, errors };
313
329
  }
314
330
 
331
+ /**
332
+ * Generate knowledge declaration file
333
+ * Creates _knowledge.json that maps stacks/domains to their available files
334
+ */
335
+ async function generateKnowledgeDeclare(knowledgePath) {
336
+ const declaration = {
337
+ stacks: {},
338
+ domains: {},
339
+ generated: new Date().toISOString()
340
+ };
341
+
342
+ // Scan stacks
343
+ const stacksPath = path.join(knowledgePath, 'stacks');
344
+ if (await fs.pathExists(stacksPath)) {
345
+ const stacks = await fs.readdir(stacksPath);
346
+
347
+ for (const stack of stacks) {
348
+ if (stack.startsWith('.') || stack === '_index.md') continue;
349
+
350
+ const stackPath = path.join(stacksPath, stack);
351
+ const stat = await fs.stat(stackPath);
352
+
353
+ if (stat.isDirectory()) {
354
+ // Scan files in stack folder
355
+ const files = await scanKnowledgeFiles(stackPath);
356
+ if (files.length > 0) {
357
+ declaration.stacks[stack] = files;
358
+ }
359
+ }
360
+ }
361
+ }
362
+
363
+ // Scan domains
364
+ const domainsPath = path.join(knowledgePath, 'domains');
365
+ if (await fs.pathExists(domainsPath)) {
366
+ const domains = await fs.readdir(domainsPath);
367
+
368
+ for (const domain of domains) {
369
+ if (domain.startsWith('.') || domain === '_index.md') continue;
370
+
371
+ const domainPath = path.join(domainsPath, domain);
372
+ const stat = await fs.stat(domainPath);
373
+
374
+ if (stat.isDirectory()) {
375
+ // Scan files in domain folder
376
+ const files = await scanKnowledgeFiles(domainPath);
377
+ if (files.length > 0) {
378
+ declaration.domains[domain] = files;
379
+ }
380
+ }
381
+ }
382
+ }
383
+
384
+ // Write declaration file
385
+ const declarePath = path.join(knowledgePath, '_knowledge.json');
386
+ await fs.writeJson(declarePath, declaration, { spaces: 2 });
387
+
388
+ // Also create a markdown version for easy reading
389
+ await generateKnowledgeDeclareMd(knowledgePath, declaration);
390
+
391
+ return declaration;
392
+ }
393
+
394
+ /**
395
+ * Scan knowledge folder and return list of files with metadata
396
+ */
397
+ async function scanKnowledgeFiles(folderPath) {
398
+ const files = [];
399
+
400
+ async function scan(dir, relativePath = '') {
401
+ const items = await fs.readdir(dir);
402
+
403
+ for (const item of items) {
404
+ if (item.startsWith('.')) continue;
405
+
406
+ const itemPath = path.join(dir, item);
407
+ const stat = await fs.stat(itemPath);
408
+ const relPath = relativePath ? `${relativePath}/${item}` : item;
409
+
410
+ if (stat.isFile() && item.endsWith('.md')) {
411
+ files.push({
412
+ path: relPath,
413
+ name: item,
414
+ size: stat.size
415
+ });
416
+ } else if (stat.isDirectory()) {
417
+ await scan(itemPath, relPath);
418
+ }
419
+ }
420
+ }
421
+
422
+ await scan(folderPath);
423
+ return files;
424
+ }
425
+
426
+ /**
427
+ * Generate markdown version of knowledge declaration
428
+ */
429
+ async function generateKnowledgeDeclareMd(knowledgePath, declaration) {
430
+ let content = '# Knowledge Base Index\n\n';
431
+ content += `Generated: ${new Date().toLocaleString()}\n\n`;
432
+ content += 'This file is auto-generated. It lists all available knowledge files in this project.\n\n';
433
+
434
+ // Stacks
435
+ if (Object.keys(declaration.stacks).length > 0) {
436
+ content += '## Stacks\n\n';
437
+ for (const [stack, files] of Object.entries(declaration.stacks)) {
438
+ content += `### ${stack}\n\n`;
439
+ for (const file of files) {
440
+ content += `- \`${file.path}\`\n`;
441
+ }
442
+ content += '\n';
443
+ }
444
+ }
445
+
446
+ // Domains
447
+ if (Object.keys(declaration.domains).length > 0) {
448
+ content += '## Domains\n\n';
449
+ for (const [domain, files] of Object.entries(declaration.domains)) {
450
+ content += `### ${domain}\n\n`;
451
+ for (const file of files) {
452
+ content += `- \`${file.path}\`\n`;
453
+ }
454
+ content += '\n';
455
+ }
456
+ }
457
+
458
+ const declarePath = path.join(knowledgePath, '_knowledge.md');
459
+ await fs.writeFile(declarePath, content);
460
+ }
461
+
315
462
  /**
316
463
  * Copy scripts (graph.py, etc.) to project
317
464
  */