@hivehub/rulebook 1.2.0 → 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.
Files changed (35) hide show
  1. package/README.md +123 -1
  2. package/dist/cli/commands.d.ts +24 -0
  3. package/dist/cli/commands.d.ts.map +1 -1
  4. package/dist/cli/commands.js +363 -2
  5. package/dist/cli/commands.js.map +1 -1
  6. package/dist/cli/prompts.d.ts +8 -0
  7. package/dist/cli/prompts.d.ts.map +1 -1
  8. package/dist/cli/prompts.js +97 -0
  9. package/dist/cli/prompts.js.map +1 -1
  10. package/dist/core/generator.d.ts.map +1 -1
  11. package/dist/core/generator.js +43 -0
  12. package/dist/core/generator.js.map +1 -1
  13. package/dist/core/skills-manager.d.ts +126 -0
  14. package/dist/core/skills-manager.d.ts.map +1 -0
  15. package/dist/core/skills-manager.js +654 -0
  16. package/dist/core/skills-manager.js.map +1 -0
  17. package/dist/core/task-manager.d.ts.map +1 -1
  18. package/dist/core/task-manager.js +56 -15
  19. package/dist/core/task-manager.js.map +1 -1
  20. package/dist/core/workflow-generator.d.ts +5 -0
  21. package/dist/core/workflow-generator.d.ts.map +1 -1
  22. package/dist/core/workflow-generator.js +251 -0
  23. package/dist/core/workflow-generator.js.map +1 -1
  24. package/dist/index.js +28 -1
  25. package/dist/index.js.map +1 -1
  26. package/dist/mcp/rulebook-server.d.ts.map +1 -1
  27. package/dist/mcp/rulebook-server.js +327 -1
  28. package/dist/mcp/rulebook-server.js.map +1 -1
  29. package/dist/types.d.ts +50 -0
  30. package/dist/types.d.ts.map +1 -1
  31. package/package.json +3 -3
  32. package/templates/cli/CLAUDE_CODE.md +114 -13
  33. package/templates/cli/gemini-extension.json +77 -0
  34. package/templates/skills/core/rulebook/SKILL.md +176 -0
  35. package/templates/skills/languages/typescript/SKILL.md +302 -0
package/README.md CHANGED
@@ -48,7 +48,32 @@ npx @hivehub/rulebook@latest update
48
48
 
49
49
  ## What's New
50
50
 
51
- ### v1.1.5 (Latest)
51
+ ### v2.1.0 (Latest)
52
+
53
+ - šŸ”’ **Claude Code Critical Directives**: New mandatory rules for Claude Code CLI
54
+ - **Sequential File Editing**: Files must be edited one at a time to prevent failures from parallel edits
55
+ - **Complete Test Implementation**: Strict rules against simplifying tests, placeholder assertions, or skipping test cases
56
+ - Updated `CLAUDE.md` generation with comprehensive guidelines and examples
57
+ - 🪟 **Windows Test Suite Fix**: Tests no longer hang on Windows (705 tests passing, 11x faster)
58
+
59
+ ### v2.0.0
60
+
61
+ - 🧩 **Skills System**: New modular skills architecture for AI-assisted development
62
+ - Skills are YAML-frontmatter Markdown files with enable/disable functionality
63
+ - 10 skill categories: languages, frameworks, modules, services, workflows, ides, core, cli, git, hooks
64
+ - Auto-detection of skills based on project configuration
65
+ - CLI commands: `rulebook skill list|add|remove|show|search`
66
+ - MCP functions: `rulebook_skill_list|show|enable|disable|search|validate`
67
+ - šŸ¤– **AI CLI Configuration Files**: Auto-generated files for AI CLI tools
68
+ - `CLAUDE.md` - Claude Code CLI configuration
69
+ - `CODEX.md` - OpenAI Codex CLI configuration
70
+ - `GEMINI.md` - Google Gemini CLI configuration
71
+ - `gemini-extension.json` - Gemini CLI extension manifest
72
+ - šŸ”Œ **Claude Code Plugin**: `marketplace.json` + `.claude-plugin/` structure for marketplace distribution
73
+ - `marketplace.json` - Marketplace manifest for plugin discovery
74
+ - Plugin manifest, MCP configuration, slash commands, and skills
75
+
76
+ ### v1.1.5
52
77
 
53
78
  - šŸ—„ļø **Service Integration Templates**: Added comprehensive service integration templates
54
79
  - 20 service templates: PostgreSQL, MySQL, MariaDB, SQL Server, Oracle, SQLite, MongoDB, Cassandra, DynamoDB, Redis, Memcached, Elasticsearch, Neo4j, InfluxDB, RabbitMQ, Kafka, S3, Azure Blob, GCS, MinIO
@@ -237,6 +262,15 @@ npx @hivehub/rulebook@latest task archive <task-id> # Archive completed task
237
262
  npx @hivehub/rulebook@latest task archive --skip-validation <task-id> # Archive without validation
238
263
  npx @hivehub/rulebook@latest tasks [options] # Legacy command (DEPRECATED - use 'task' commands)
239
264
 
265
+ # Skills Management (v2.0)
266
+ npx @hivehub/rulebook@latest skill list # List all available skills
267
+ npx @hivehub/rulebook@latest skill list --category languages # Filter by category
268
+ npx @hivehub/rulebook@latest skill list --enabled # Show only enabled skills
269
+ npx @hivehub/rulebook@latest skill add <skill-id> # Enable a skill
270
+ npx @hivehub/rulebook@latest skill remove <skill-id> # Disable a skill
271
+ npx @hivehub/rulebook@latest skill show <skill-id> # Show skill details
272
+ npx @hivehub/rulebook@latest skill search <query> # Search for skills
273
+
240
274
  # Configuration
241
275
  npx @hivehub/rulebook@latest config --show # Show current config
242
276
  npx @hivehub/rulebook@latest config --set key=value # Set config value
@@ -328,6 +362,94 @@ This command:
328
362
 
329
363
  **Total: 7 MCP functions** for complete task lifecycle management.
330
364
 
365
+ **Skills MCP Functions (v2.0):**
366
+
367
+ - `rulebook_skill_list` - List available skills with optional category filter
368
+ - `rulebook_skill_show` - Show detailed skill information
369
+ - `rulebook_skill_enable` - Enable a skill for the project
370
+ - `rulebook_skill_disable` - Disable a skill
371
+ - `rulebook_skill_search` - Search skills by name, description, or tags
372
+ - `rulebook_skill_validate` - Validate skills configuration
373
+
374
+ **Total: 13 MCP functions** (7 task + 6 skills).
375
+
376
+ ## Skills System (v2.0)
377
+
378
+ Rulebook v2.0 introduces a modular skills system for AI-assisted development. Skills are pluggable capabilities that can be enabled or disabled per project.
379
+
380
+ ### What are Skills?
381
+
382
+ Skills are YAML-frontmatter Markdown files that define specific capabilities or rules for AI assistants. Each skill has:
383
+
384
+ - **Metadata**: Name, description, version, category, tags, dependencies
385
+ - **Content**: Markdown content with rules, patterns, and examples
386
+
387
+ ### Skill Categories
388
+
389
+ Skills are organized into 10 categories:
390
+
391
+ | Category | Description | Examples |
392
+ |----------|-------------|----------|
393
+ | `languages` | Language-specific rules | TypeScript, Rust, Python |
394
+ | `frameworks` | Framework conventions | NestJS, React, Django |
395
+ | `modules` | MCP module integration | Vectorizer, Context7 |
396
+ | `services` | Service integration | PostgreSQL, Redis |
397
+ | `workflows` | CI/CD patterns | GitHub Actions |
398
+ | `ides` | IDE configuration | Cursor, VS Code |
399
+ | `core` | Core rulebook standards | Quality gates |
400
+ | `cli` | AI CLI configuration | Claude Code, Codex |
401
+ | `git` | Git workflow rules | Branching, commits |
402
+ | `hooks` | Git hooks configuration | Pre-commit, pre-push |
403
+
404
+ ### Using Skills
405
+
406
+ ```bash
407
+ # List all available skills
408
+ rulebook skill list
409
+
410
+ # Filter by category
411
+ rulebook skill list --category languages
412
+
413
+ # Enable a skill
414
+ rulebook skill add languages/typescript
415
+
416
+ # Disable a skill
417
+ rulebook skill remove languages/typescript
418
+
419
+ # Show skill details
420
+ rulebook skill show languages/typescript
421
+
422
+ # Search for skills
423
+ rulebook skill search "testing"
424
+ ```
425
+
426
+ ### Auto-Detection
427
+
428
+ During `rulebook init` and `rulebook update`, skills are automatically detected and enabled based on your project's:
429
+
430
+ - Detected languages (e.g., TypeScript → `languages/typescript`)
431
+ - Detected frameworks (e.g., NestJS → `frameworks/nestjs`)
432
+ - Detected modules (e.g., Vectorizer → `modules/vectorizer`)
433
+ - Detected services (e.g., PostgreSQL → `services/postgresql`)
434
+
435
+ ### Creating Custom Skills
436
+
437
+ Create a `SKILL.md` file in `templates/skills/<category>/<skill-name>/`:
438
+
439
+ ```markdown
440
+ ---
441
+ name: My Custom Skill
442
+ description: Description of what this skill does
443
+ version: 1.0.0
444
+ category: core
445
+ tags: ["custom", "example"]
446
+ ---
447
+
448
+ # My Custom Skill
449
+
450
+ Add your rules and patterns here.
451
+ ```
452
+
331
453
  ## Service Integration Templates (20)
332
454
 
333
455
  Rulebook provides comprehensive integration templates for popular backend services, including databases, caches, message queues, and object storage.
@@ -1,5 +1,6 @@
1
1
  export declare function initCommand(options: {
2
2
  yes?: boolean;
3
+ quick?: boolean;
3
4
  minimal?: boolean;
4
5
  light?: boolean;
5
6
  }): Promise<void>;
@@ -54,4 +55,27 @@ export declare function updateCommand(options: {
54
55
  minimal?: boolean;
55
56
  light?: boolean;
56
57
  }): Promise<void>;
58
+ /**
59
+ * List all available skills
60
+ */
61
+ export declare function skillListCommand(options: {
62
+ category?: string;
63
+ enabled?: boolean;
64
+ }): Promise<void>;
65
+ /**
66
+ * Add (enable) a skill
67
+ */
68
+ export declare function skillAddCommand(skillId: string): Promise<void>;
69
+ /**
70
+ * Remove (disable) a skill
71
+ */
72
+ export declare function skillRemoveCommand(skillId: string): Promise<void>;
73
+ /**
74
+ * Show skill details
75
+ */
76
+ export declare function skillShowCommand(skillId: string): Promise<void>;
77
+ /**
78
+ * Search for skills
79
+ */
80
+ export declare function skillSearchCommand(query: string): Promise<void>;
57
81
  //# sourceMappingURL=commands.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"commands.d.ts","sourceRoot":"","sources":["../../src/cli/commands.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"commands.d.ts","sourceRoot":"","sources":["../../src/cli/commands.ts"],"names":[],"mappings":"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"}
@@ -1,10 +1,10 @@
1
1
  import chalk from 'chalk';
2
2
  import ora from 'ora';
3
3
  import { detectProject } from '../core/detector.js';
4
- import { promptProjectConfig, promptMergeStrategy } from './prompts.js';
4
+ import { promptProjectConfig, promptSimplifiedConfig, promptMergeStrategy } from './prompts.js';
5
5
  import { generateFullAgents } from '../core/generator.js';
6
6
  import { mergeFullAgents } from '../core/merger.js';
7
- import { generateWorkflows, generateIDEFiles } from '../core/workflow-generator.js';
7
+ import { generateWorkflows, generateIDEFiles, generateAICLIFiles, } from '../core/workflow-generator.js';
8
8
  import { writeFile, createBackup, readFile, fileExists } from '../utils/file-system.js';
9
9
  import { existsSync } from 'fs';
10
10
  import { parseRulesIgnore } from '../utils/rulesignore.js';
@@ -13,6 +13,7 @@ import { scaffoldMinimalProject } from '../core/minimal-scaffolder.js';
13
13
  import path from 'path';
14
14
  import { readFileSync } from 'fs';
15
15
  import { fileURLToPath } from 'url';
16
+ import { SkillsManager, getDefaultTemplatesPath } from '../core/skills-manager.js';
16
17
  const FRAMEWORK_LABELS = {
17
18
  nestjs: 'NestJS',
18
19
  spring: 'Spring Boot',
@@ -86,7 +87,9 @@ export async function initCommand(options) {
86
87
  let config;
87
88
  const cliMinimal = Boolean(options.minimal);
88
89
  const cliLight = Boolean(options.light);
90
+ const cliQuick = Boolean(options.quick);
89
91
  if (options.yes) {
92
+ // Full auto mode - no prompts at all
90
93
  config = {
91
94
  languages: detection.languages.map((l) => l.language),
92
95
  modules: cliMinimal ? [] : detection.modules.filter((m) => m.detected).map((m) => m.module),
@@ -105,7 +108,14 @@ export async function initCommand(options) {
105
108
  };
106
109
  console.log(chalk.blue('\nUsing detected defaults...'));
107
110
  }
111
+ else if (cliQuick) {
112
+ // Quick mode - minimal prompts (language, MCP, hooks only)
113
+ config = await promptSimplifiedConfig(detection);
114
+ config.lightMode = cliLight;
115
+ config.minimal = cliMinimal;
116
+ }
108
117
  else {
118
+ // Full interactive mode
109
119
  console.log('');
110
120
  config = await promptProjectConfig(detection, {
111
121
  defaultMode: cliMinimal ? 'minimal' : 'full',
@@ -169,6 +179,29 @@ export async function initCommand(options) {
169
179
  // Save project configuration to .rulebook
170
180
  const { createConfigManager } = await import('../core/config-manager.js');
171
181
  const configManager = createConfigManager(cwd);
182
+ // Auto-detect and enable skills based on project detection (v2.0)
183
+ let enabledSkills = [];
184
+ try {
185
+ const { SkillsManager, getDefaultTemplatesPath } = await import('../core/skills-manager.js');
186
+ const skillsManager = new SkillsManager(getDefaultTemplatesPath(), cwd);
187
+ // Build a RulebookConfig-like object for skill detection
188
+ const rulebookConfigForSkills = {
189
+ languages: config.languages,
190
+ frameworks: config.frameworks,
191
+ modules: config.modules,
192
+ services: config.services,
193
+ };
194
+ enabledSkills = await skillsManager.autoDetectSkills(rulebookConfigForSkills);
195
+ if (enabledSkills.length > 0) {
196
+ console.log(chalk.green('\nāœ“ Auto-detected skills:'));
197
+ for (const skillId of enabledSkills) {
198
+ console.log(chalk.gray(` - ${skillId}`));
199
+ }
200
+ }
201
+ }
202
+ catch {
203
+ // Skills system not available or error - continue without skills
204
+ }
172
205
  await configManager.updateConfig({
173
206
  languages: config.languages,
174
207
  frameworks: config.frameworks,
@@ -176,6 +209,7 @@ export async function initCommand(options) {
176
209
  services: config.services,
177
210
  modular: config.modular ?? true,
178
211
  rulebookDir: config.rulebookDir || 'rulebook',
212
+ skills: enabledSkills.length > 0 ? { enabled: enabledSkills } : undefined,
179
213
  });
180
214
  // Generate or merge AGENTS.md
181
215
  const agentsPath = path.join(cwd, 'AGENTS.md');
@@ -244,6 +278,20 @@ export async function initCommand(options) {
244
278
  ideSpinner.info('IDE files already exist (skipped)');
245
279
  }
246
280
  }
281
+ // Generate AI CLI configuration files (CLAUDE.md, CODEX.md, GEMINI.md)
282
+ if (!minimalMode) {
283
+ const cliSpinner = ora('Generating AI CLI configuration files...').start();
284
+ const cliFiles = await generateAICLIFiles(config, cwd);
285
+ if (cliFiles.length > 0) {
286
+ cliSpinner.succeed(`Generated ${cliFiles.length} AI CLI configuration files`);
287
+ for (const file of cliFiles) {
288
+ console.log(chalk.gray(` - ${path.relative(cwd, file)}`));
289
+ }
290
+ }
291
+ else {
292
+ cliSpinner.info('AI CLI files already exist (skipped)');
293
+ }
294
+ }
247
295
  if (minimalMode && minimalArtifacts.length > 0) {
248
296
  console.log(chalk.green('\nāœ… Essentials created:'));
249
297
  for (const artifact of minimalArtifacts) {
@@ -1262,6 +1310,39 @@ export async function updateCommand(options) {
1262
1310
  // Save project configuration to .rulebook
1263
1311
  const { createConfigManager } = await import('../core/config-manager.js');
1264
1312
  const configManager = createConfigManager(cwd);
1313
+ // Load existing config to preserve skills
1314
+ const existingConfig = await configManager.loadConfig();
1315
+ const existingSkills = existingConfig.skills?.enabled || [];
1316
+ // Auto-detect skills based on project detection (v2.0)
1317
+ let detectedSkills = [];
1318
+ try {
1319
+ const { SkillsManager, getDefaultTemplatesPath } = await import('../core/skills-manager.js');
1320
+ const skillsManager = new SkillsManager(getDefaultTemplatesPath(), cwd);
1321
+ // Build a RulebookConfig-like object for skill detection
1322
+ const rulebookConfigForSkills = {
1323
+ languages: config.languages,
1324
+ frameworks: config.frameworks,
1325
+ modules: config.modules,
1326
+ services: config.services,
1327
+ };
1328
+ detectedSkills = await skillsManager.autoDetectSkills(rulebookConfigForSkills);
1329
+ // Merge with existing skills (keep existing, add new detected)
1330
+ const mergedSkills = [...new Set([...existingSkills, ...detectedSkills])];
1331
+ if (detectedSkills.length > existingSkills.length) {
1332
+ const newSkills = detectedSkills.filter((s) => !existingSkills.includes(s));
1333
+ if (newSkills.length > 0) {
1334
+ console.log(chalk.green('\nāœ“ New skills detected:'));
1335
+ for (const skillId of newSkills) {
1336
+ console.log(chalk.gray(` - ${skillId}`));
1337
+ }
1338
+ }
1339
+ }
1340
+ detectedSkills = mergedSkills;
1341
+ }
1342
+ catch {
1343
+ // Skills system not available or error - preserve existing skills
1344
+ detectedSkills = existingSkills;
1345
+ }
1265
1346
  await configManager.updateConfig({
1266
1347
  languages: config.languages,
1267
1348
  frameworks: config.frameworks,
@@ -1269,6 +1350,7 @@ export async function updateCommand(options) {
1269
1350
  services: config.services,
1270
1351
  modular: config.modular ?? true,
1271
1352
  rulebookDir: config.rulebookDir || 'rulebook',
1353
+ skills: detectedSkills.length > 0 ? { enabled: detectedSkills } : undefined,
1272
1354
  });
1273
1355
  // Merge with existing AGENTS.md (with migration support)
1274
1356
  const mergeSpinner = ora('Updating AGENTS.md with latest templates...').start();
@@ -1367,4 +1449,283 @@ export async function updateCommand(options) {
1367
1449
  process.exit(1);
1368
1450
  }
1369
1451
  }
1452
+ // ============================================
1453
+ // Skills Commands (v2.0)
1454
+ // ============================================
1455
+ /**
1456
+ * List all available skills
1457
+ */
1458
+ export async function skillListCommand(options) {
1459
+ try {
1460
+ const cwd = process.cwd();
1461
+ const spinner = ora('Discovering skills...').start();
1462
+ const skillsManager = new SkillsManager(getDefaultTemplatesPath(), cwd);
1463
+ const { createConfigManager } = await import('../core/config-manager.js');
1464
+ const configManager = createConfigManager(cwd);
1465
+ let skills;
1466
+ if (options.category) {
1467
+ skills = await skillsManager.getSkillsByCategory(options.category);
1468
+ }
1469
+ else {
1470
+ skills = await skillsManager.getSkills();
1471
+ }
1472
+ // Get enabled status from config
1473
+ let enabledIds = new Set();
1474
+ try {
1475
+ const config = await configManager.loadConfig();
1476
+ enabledIds = new Set(config.skills?.enabled || []);
1477
+ }
1478
+ catch {
1479
+ // No config file, all skills disabled
1480
+ }
1481
+ // Filter by enabled status if requested
1482
+ if (options.enabled) {
1483
+ skills = skills.filter((s) => enabledIds.has(s.id));
1484
+ }
1485
+ spinner.succeed(`Found ${skills.length} skill(s)`);
1486
+ if (skills.length === 0) {
1487
+ console.log(chalk.yellow('\nNo skills found matching criteria.'));
1488
+ return;
1489
+ }
1490
+ // Group by category
1491
+ const byCategory = new Map();
1492
+ for (const skill of skills) {
1493
+ const cat = skill.category;
1494
+ if (!byCategory.has(cat)) {
1495
+ byCategory.set(cat, []);
1496
+ }
1497
+ byCategory.get(cat).push(skill);
1498
+ }
1499
+ console.log(chalk.bold.blue('\nšŸ“¦ Available Skills\n'));
1500
+ for (const [category, categorySkills] of byCategory) {
1501
+ console.log(chalk.bold.white(`${category.toUpperCase()}`));
1502
+ for (const skill of categorySkills) {
1503
+ const enabled = enabledIds.has(skill.id);
1504
+ const status = enabled ? chalk.green('āœ“') : chalk.gray('ā—‹');
1505
+ const name = enabled ? chalk.green(skill.metadata.name) : chalk.white(skill.metadata.name);
1506
+ console.log(` ${status} ${name}`);
1507
+ console.log(chalk.gray(` ${skill.metadata.description}`));
1508
+ console.log(chalk.gray(` ID: ${skill.id}`));
1509
+ }
1510
+ console.log('');
1511
+ }
1512
+ console.log(chalk.gray('Use "rulebook skill add <skill-id>" to enable a skill'));
1513
+ console.log(chalk.gray('Use "rulebook skill remove <skill-id>" to disable a skill'));
1514
+ }
1515
+ catch (error) {
1516
+ console.error(chalk.red('\nāŒ Failed to list skills:'), error);
1517
+ process.exit(1);
1518
+ }
1519
+ }
1520
+ /**
1521
+ * Add (enable) a skill
1522
+ */
1523
+ export async function skillAddCommand(skillId) {
1524
+ try {
1525
+ const cwd = process.cwd();
1526
+ const spinner = ora(`Adding skill: ${skillId}...`).start();
1527
+ const skillsManager = new SkillsManager(getDefaultTemplatesPath(), cwd);
1528
+ const { createConfigManager } = await import('../core/config-manager.js');
1529
+ const configManager = createConfigManager(cwd);
1530
+ // Check if skill exists
1531
+ const skill = await skillsManager.getSkillById(skillId);
1532
+ if (!skill) {
1533
+ spinner.fail(`Skill not found: ${skillId}`);
1534
+ // Search for similar skills
1535
+ const allSkills = await skillsManager.getSkills();
1536
+ const similar = allSkills.filter((s) => s.id.includes(skillId.toLowerCase()) ||
1537
+ s.metadata.name.toLowerCase().includes(skillId.toLowerCase()));
1538
+ if (similar.length > 0) {
1539
+ console.log(chalk.yellow('\nDid you mean one of these?'));
1540
+ for (const s of similar.slice(0, 5)) {
1541
+ console.log(chalk.gray(` - ${s.id} (${s.metadata.name})`));
1542
+ }
1543
+ }
1544
+ console.log(chalk.gray('\nUse "rulebook skill list" to see all available skills'));
1545
+ process.exit(1);
1546
+ }
1547
+ // Load config and enable skill
1548
+ let config = await configManager.loadConfig();
1549
+ config = await skillsManager.enableSkill(skillId, config);
1550
+ // Validate for conflicts
1551
+ const validation = await skillsManager.validateSkills(config);
1552
+ if (validation.conflicts.length > 0) {
1553
+ spinner.warn(`Skill enabled with conflicts`);
1554
+ console.log(chalk.yellow('\nāš ļø Conflicts detected:'));
1555
+ for (const conflict of validation.conflicts) {
1556
+ console.log(chalk.yellow(` - ${conflict.skillA} conflicts with ${conflict.skillB}`));
1557
+ console.log(chalk.gray(` ${conflict.reason}`));
1558
+ }
1559
+ }
1560
+ else {
1561
+ spinner.succeed(`Skill added: ${skill.metadata.name}`);
1562
+ }
1563
+ // Save config
1564
+ await configManager.saveConfig(config);
1565
+ console.log(chalk.green(`\nāœ“ Skill "${skill.metadata.name}" is now enabled`));
1566
+ console.log(chalk.gray(` Category: ${skill.category}`));
1567
+ console.log(chalk.gray(` Description: ${skill.metadata.description}`));
1568
+ if (validation.warnings.length > 0) {
1569
+ console.log(chalk.yellow('\nāš ļø Warnings:'));
1570
+ for (const warning of validation.warnings) {
1571
+ console.log(chalk.yellow(` - ${warning}`));
1572
+ }
1573
+ }
1574
+ console.log(chalk.gray('\nRun "rulebook update" to regenerate AGENTS.md with the new skill'));
1575
+ }
1576
+ catch (error) {
1577
+ console.error(chalk.red('\nāŒ Failed to add skill:'), error);
1578
+ process.exit(1);
1579
+ }
1580
+ }
1581
+ /**
1582
+ * Remove (disable) a skill
1583
+ */
1584
+ export async function skillRemoveCommand(skillId) {
1585
+ try {
1586
+ const cwd = process.cwd();
1587
+ const spinner = ora(`Removing skill: ${skillId}...`).start();
1588
+ const skillsManager = new SkillsManager(getDefaultTemplatesPath(), cwd);
1589
+ const { createConfigManager } = await import('../core/config-manager.js');
1590
+ const configManager = createConfigManager(cwd);
1591
+ // Check if skill exists
1592
+ const skill = await skillsManager.getSkillById(skillId);
1593
+ if (!skill) {
1594
+ spinner.fail(`Skill not found: ${skillId}`);
1595
+ console.log(chalk.gray('Use "rulebook skill list" to see all available skills'));
1596
+ process.exit(1);
1597
+ }
1598
+ // Load config
1599
+ let config = await configManager.loadConfig();
1600
+ // Check if skill is enabled
1601
+ if (!config.skills?.enabled?.includes(skillId)) {
1602
+ spinner.fail(`Skill "${skillId}" is not currently enabled`);
1603
+ process.exit(1);
1604
+ }
1605
+ // Disable skill
1606
+ config = await skillsManager.disableSkill(skillId, config);
1607
+ await configManager.saveConfig(config);
1608
+ spinner.succeed(`Skill removed: ${skill.metadata.name}`);
1609
+ console.log(chalk.green(`\nāœ“ Skill "${skill.metadata.name}" is now disabled`));
1610
+ console.log(chalk.gray('\nRun "rulebook update" to regenerate AGENTS.md without this skill'));
1611
+ }
1612
+ catch (error) {
1613
+ console.error(chalk.red('\nāŒ Failed to remove skill:'), error);
1614
+ process.exit(1);
1615
+ }
1616
+ }
1617
+ /**
1618
+ * Show skill details
1619
+ */
1620
+ export async function skillShowCommand(skillId) {
1621
+ try {
1622
+ const cwd = process.cwd();
1623
+ const spinner = ora(`Loading skill: ${skillId}...`).start();
1624
+ const skillsManager = new SkillsManager(getDefaultTemplatesPath(), cwd);
1625
+ const { createConfigManager } = await import('../core/config-manager.js');
1626
+ const configManager = createConfigManager(cwd);
1627
+ const skill = await skillsManager.getSkillById(skillId);
1628
+ if (!skill) {
1629
+ spinner.fail(`Skill not found: ${skillId}`);
1630
+ // Search for similar skills
1631
+ const allSkills = await skillsManager.getSkills();
1632
+ const similar = allSkills.filter((s) => s.id.includes(skillId.toLowerCase()) ||
1633
+ s.metadata.name.toLowerCase().includes(skillId.toLowerCase()));
1634
+ if (similar.length > 0) {
1635
+ console.log(chalk.yellow('\nDid you mean one of these?'));
1636
+ for (const s of similar.slice(0, 5)) {
1637
+ console.log(chalk.gray(` - ${s.id} (${s.metadata.name})`));
1638
+ }
1639
+ }
1640
+ process.exit(1);
1641
+ }
1642
+ spinner.stop();
1643
+ // Check if enabled
1644
+ let enabled = false;
1645
+ try {
1646
+ const config = await configManager.loadConfig();
1647
+ enabled = config.skills?.enabled?.includes(skillId) || false;
1648
+ }
1649
+ catch {
1650
+ // No config
1651
+ }
1652
+ console.log(chalk.bold.blue(`\nšŸ“¦ ${skill.metadata.name}\n`));
1653
+ console.log(chalk.white(`ID: ${skill.id}`));
1654
+ console.log(chalk.white(`Category: ${skill.category}`));
1655
+ console.log(chalk.white(`Status: ${enabled ? chalk.green('Enabled') : chalk.gray('Disabled')}`));
1656
+ if (skill.metadata.version) {
1657
+ console.log(chalk.white(`Version: ${skill.metadata.version}`));
1658
+ }
1659
+ if (skill.metadata.author) {
1660
+ console.log(chalk.white(`Author: ${skill.metadata.author}`));
1661
+ }
1662
+ console.log(chalk.white(`\nDescription:`));
1663
+ console.log(chalk.gray(` ${skill.metadata.description}`));
1664
+ if (skill.metadata.tags && skill.metadata.tags.length > 0) {
1665
+ console.log(chalk.white(`\nTags: ${skill.metadata.tags.join(', ')}`));
1666
+ }
1667
+ if (skill.metadata.dependencies && skill.metadata.dependencies.length > 0) {
1668
+ console.log(chalk.white(`\nDependencies:`));
1669
+ for (const dep of skill.metadata.dependencies) {
1670
+ console.log(chalk.gray(` - ${dep}`));
1671
+ }
1672
+ }
1673
+ if (skill.metadata.conflicts && skill.metadata.conflicts.length > 0) {
1674
+ console.log(chalk.yellow(`\nConflicts with:`));
1675
+ for (const conflict of skill.metadata.conflicts) {
1676
+ console.log(chalk.yellow(` - ${conflict}`));
1677
+ }
1678
+ }
1679
+ // Show preview of content
1680
+ console.log(chalk.white(`\nContent Preview:`));
1681
+ const preview = skill.content.slice(0, 500);
1682
+ console.log(chalk.gray(preview + (skill.content.length > 500 ? '...' : '')));
1683
+ console.log(chalk.gray(`\nPath: ${skill.path}`));
1684
+ }
1685
+ catch (error) {
1686
+ console.error(chalk.red('\nāŒ Failed to show skill:'), error);
1687
+ process.exit(1);
1688
+ }
1689
+ }
1690
+ /**
1691
+ * Search for skills
1692
+ */
1693
+ export async function skillSearchCommand(query) {
1694
+ try {
1695
+ const cwd = process.cwd();
1696
+ const spinner = ora(`Searching for: ${query}...`).start();
1697
+ const skillsManager = new SkillsManager(getDefaultTemplatesPath(), cwd);
1698
+ const { createConfigManager } = await import('../core/config-manager.js');
1699
+ const configManager = createConfigManager(cwd);
1700
+ const skills = await skillsManager.searchSkills(query);
1701
+ spinner.succeed(`Found ${skills.length} result(s)`);
1702
+ if (skills.length === 0) {
1703
+ console.log(chalk.yellow(`\nNo skills found matching "${query}"`));
1704
+ console.log(chalk.gray('Try a different search term or use "rulebook skill list"'));
1705
+ return;
1706
+ }
1707
+ // Get enabled status
1708
+ let enabledIds = new Set();
1709
+ try {
1710
+ const config = await configManager.loadConfig();
1711
+ enabledIds = new Set(config.skills?.enabled || []);
1712
+ }
1713
+ catch {
1714
+ // No config
1715
+ }
1716
+ console.log(chalk.bold.blue(`\nšŸ” Search Results for "${query}"\n`));
1717
+ for (const skill of skills) {
1718
+ const enabled = enabledIds.has(skill.id);
1719
+ const status = enabled ? chalk.green('āœ“') : chalk.gray('ā—‹');
1720
+ const name = enabled ? chalk.green(skill.metadata.name) : chalk.white(skill.metadata.name);
1721
+ console.log(`${status} ${name} (${skill.category})`);
1722
+ console.log(chalk.gray(` ${skill.metadata.description}`));
1723
+ console.log(chalk.gray(` ID: ${skill.id}\n`));
1724
+ }
1725
+ }
1726
+ catch (error) {
1727
+ console.error(chalk.red('\nāŒ Search failed:'), error);
1728
+ process.exit(1);
1729
+ }
1730
+ }
1370
1731
  //# sourceMappingURL=commands.js.map