@hivehub/rulebook 1.2.0 ā 2.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +116 -1
- package/dist/cli/commands.d.ts +24 -0
- package/dist/cli/commands.d.ts.map +1 -1
- package/dist/cli/commands.js +363 -2
- package/dist/cli/commands.js.map +1 -1
- package/dist/cli/prompts.d.ts +8 -0
- package/dist/cli/prompts.d.ts.map +1 -1
- package/dist/cli/prompts.js +97 -0
- package/dist/cli/prompts.js.map +1 -1
- package/dist/core/generator.d.ts.map +1 -1
- package/dist/core/generator.js +43 -0
- package/dist/core/generator.js.map +1 -1
- package/dist/core/skills-manager.d.ts +126 -0
- package/dist/core/skills-manager.d.ts.map +1 -0
- package/dist/core/skills-manager.js +654 -0
- package/dist/core/skills-manager.js.map +1 -0
- package/dist/core/task-manager.d.ts.map +1 -1
- package/dist/core/task-manager.js +56 -15
- package/dist/core/task-manager.js.map +1 -1
- package/dist/core/workflow-generator.d.ts +5 -0
- package/dist/core/workflow-generator.d.ts.map +1 -1
- package/dist/core/workflow-generator.js +166 -0
- package/dist/core/workflow-generator.js.map +1 -1
- package/dist/index.js +28 -1
- package/dist/index.js.map +1 -1
- package/dist/mcp/rulebook-server.d.ts.map +1 -1
- package/dist/mcp/rulebook-server.js +327 -1
- package/dist/mcp/rulebook-server.js.map +1 -1
- package/dist/types.d.ts +50 -0
- package/dist/types.d.ts.map +1 -1
- package/package.json +3 -3
- package/templates/cli/gemini-extension.json +77 -0
- package/templates/skills/core/rulebook/SKILL.md +176 -0
- package/templates/skills/languages/typescript/SKILL.md +302 -0
package/README.md
CHANGED
|
@@ -48,7 +48,25 @@ npx @hivehub/rulebook@latest update
|
|
|
48
48
|
|
|
49
49
|
## What's New
|
|
50
50
|
|
|
51
|
-
###
|
|
51
|
+
### v2.0.0 (Latest)
|
|
52
|
+
|
|
53
|
+
- š§© **Skills System**: New modular skills architecture for AI-assisted development
|
|
54
|
+
- Skills are YAML-frontmatter Markdown files with enable/disable functionality
|
|
55
|
+
- 10 skill categories: languages, frameworks, modules, services, workflows, ides, core, cli, git, hooks
|
|
56
|
+
- Auto-detection of skills based on project configuration
|
|
57
|
+
- CLI commands: `rulebook skill list|add|remove|show|search`
|
|
58
|
+
- MCP functions: `rulebook_skill_list|show|enable|disable|search|validate`
|
|
59
|
+
- š¤ **AI CLI Configuration Files**: Auto-generated files for AI CLI tools
|
|
60
|
+
- `CLAUDE.md` - Claude Code CLI configuration
|
|
61
|
+
- `CODEX.md` - OpenAI Codex CLI configuration
|
|
62
|
+
- `GEMINI.md` - Google Gemini CLI configuration
|
|
63
|
+
- `gemini-extension.json` - Gemini CLI extension manifest
|
|
64
|
+
- š **Claude Code Plugin**: `marketplace.json` + `.claude-plugin/` structure for marketplace distribution
|
|
65
|
+
- `marketplace.json` - Marketplace manifest for plugin discovery
|
|
66
|
+
- Plugin manifest, MCP configuration, slash commands, and skills
|
|
67
|
+
- šŖ **Windows Test Suite Fix**: Tests no longer hang on Windows (705 tests passing, 11x faster)
|
|
68
|
+
|
|
69
|
+
### v1.1.5
|
|
52
70
|
|
|
53
71
|
- šļø **Service Integration Templates**: Added comprehensive service integration templates
|
|
54
72
|
- 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 +255,15 @@ npx @hivehub/rulebook@latest task archive <task-id> # Archive completed task
|
|
|
237
255
|
npx @hivehub/rulebook@latest task archive --skip-validation <task-id> # Archive without validation
|
|
238
256
|
npx @hivehub/rulebook@latest tasks [options] # Legacy command (DEPRECATED - use 'task' commands)
|
|
239
257
|
|
|
258
|
+
# Skills Management (v2.0)
|
|
259
|
+
npx @hivehub/rulebook@latest skill list # List all available skills
|
|
260
|
+
npx @hivehub/rulebook@latest skill list --category languages # Filter by category
|
|
261
|
+
npx @hivehub/rulebook@latest skill list --enabled # Show only enabled skills
|
|
262
|
+
npx @hivehub/rulebook@latest skill add <skill-id> # Enable a skill
|
|
263
|
+
npx @hivehub/rulebook@latest skill remove <skill-id> # Disable a skill
|
|
264
|
+
npx @hivehub/rulebook@latest skill show <skill-id> # Show skill details
|
|
265
|
+
npx @hivehub/rulebook@latest skill search <query> # Search for skills
|
|
266
|
+
|
|
240
267
|
# Configuration
|
|
241
268
|
npx @hivehub/rulebook@latest config --show # Show current config
|
|
242
269
|
npx @hivehub/rulebook@latest config --set key=value # Set config value
|
|
@@ -328,6 +355,94 @@ This command:
|
|
|
328
355
|
|
|
329
356
|
**Total: 7 MCP functions** for complete task lifecycle management.
|
|
330
357
|
|
|
358
|
+
**Skills MCP Functions (v2.0):**
|
|
359
|
+
|
|
360
|
+
- `rulebook_skill_list` - List available skills with optional category filter
|
|
361
|
+
- `rulebook_skill_show` - Show detailed skill information
|
|
362
|
+
- `rulebook_skill_enable` - Enable a skill for the project
|
|
363
|
+
- `rulebook_skill_disable` - Disable a skill
|
|
364
|
+
- `rulebook_skill_search` - Search skills by name, description, or tags
|
|
365
|
+
- `rulebook_skill_validate` - Validate skills configuration
|
|
366
|
+
|
|
367
|
+
**Total: 13 MCP functions** (7 task + 6 skills).
|
|
368
|
+
|
|
369
|
+
## Skills System (v2.0)
|
|
370
|
+
|
|
371
|
+
Rulebook v2.0 introduces a modular skills system for AI-assisted development. Skills are pluggable capabilities that can be enabled or disabled per project.
|
|
372
|
+
|
|
373
|
+
### What are Skills?
|
|
374
|
+
|
|
375
|
+
Skills are YAML-frontmatter Markdown files that define specific capabilities or rules for AI assistants. Each skill has:
|
|
376
|
+
|
|
377
|
+
- **Metadata**: Name, description, version, category, tags, dependencies
|
|
378
|
+
- **Content**: Markdown content with rules, patterns, and examples
|
|
379
|
+
|
|
380
|
+
### Skill Categories
|
|
381
|
+
|
|
382
|
+
Skills are organized into 10 categories:
|
|
383
|
+
|
|
384
|
+
| Category | Description | Examples |
|
|
385
|
+
|----------|-------------|----------|
|
|
386
|
+
| `languages` | Language-specific rules | TypeScript, Rust, Python |
|
|
387
|
+
| `frameworks` | Framework conventions | NestJS, React, Django |
|
|
388
|
+
| `modules` | MCP module integration | Vectorizer, Context7 |
|
|
389
|
+
| `services` | Service integration | PostgreSQL, Redis |
|
|
390
|
+
| `workflows` | CI/CD patterns | GitHub Actions |
|
|
391
|
+
| `ides` | IDE configuration | Cursor, VS Code |
|
|
392
|
+
| `core` | Core rulebook standards | Quality gates |
|
|
393
|
+
| `cli` | AI CLI configuration | Claude Code, Codex |
|
|
394
|
+
| `git` | Git workflow rules | Branching, commits |
|
|
395
|
+
| `hooks` | Git hooks configuration | Pre-commit, pre-push |
|
|
396
|
+
|
|
397
|
+
### Using Skills
|
|
398
|
+
|
|
399
|
+
```bash
|
|
400
|
+
# List all available skills
|
|
401
|
+
rulebook skill list
|
|
402
|
+
|
|
403
|
+
# Filter by category
|
|
404
|
+
rulebook skill list --category languages
|
|
405
|
+
|
|
406
|
+
# Enable a skill
|
|
407
|
+
rulebook skill add languages/typescript
|
|
408
|
+
|
|
409
|
+
# Disable a skill
|
|
410
|
+
rulebook skill remove languages/typescript
|
|
411
|
+
|
|
412
|
+
# Show skill details
|
|
413
|
+
rulebook skill show languages/typescript
|
|
414
|
+
|
|
415
|
+
# Search for skills
|
|
416
|
+
rulebook skill search "testing"
|
|
417
|
+
```
|
|
418
|
+
|
|
419
|
+
### Auto-Detection
|
|
420
|
+
|
|
421
|
+
During `rulebook init` and `rulebook update`, skills are automatically detected and enabled based on your project's:
|
|
422
|
+
|
|
423
|
+
- Detected languages (e.g., TypeScript ā `languages/typescript`)
|
|
424
|
+
- Detected frameworks (e.g., NestJS ā `frameworks/nestjs`)
|
|
425
|
+
- Detected modules (e.g., Vectorizer ā `modules/vectorizer`)
|
|
426
|
+
- Detected services (e.g., PostgreSQL ā `services/postgresql`)
|
|
427
|
+
|
|
428
|
+
### Creating Custom Skills
|
|
429
|
+
|
|
430
|
+
Create a `SKILL.md` file in `templates/skills/<category>/<skill-name>/`:
|
|
431
|
+
|
|
432
|
+
```markdown
|
|
433
|
+
---
|
|
434
|
+
name: My Custom Skill
|
|
435
|
+
description: Description of what this skill does
|
|
436
|
+
version: 1.0.0
|
|
437
|
+
category: core
|
|
438
|
+
tags: ["custom", "example"]
|
|
439
|
+
---
|
|
440
|
+
|
|
441
|
+
# My Custom Skill
|
|
442
|
+
|
|
443
|
+
Add your rules and patterns here.
|
|
444
|
+
```
|
|
445
|
+
|
|
331
446
|
## Service Integration Templates (20)
|
|
332
447
|
|
|
333
448
|
Rulebook provides comprehensive integration templates for popular backend services, including databases, caches, message queues, and object storage.
|
package/dist/cli/commands.d.ts
CHANGED
|
@@ -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":"
|
|
1
|
+
{"version":3,"file":"commands.d.ts","sourceRoot":"","sources":["../../src/cli/commands.ts"],"names":[],"mappings":"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"}
|
package/dist/cli/commands.js
CHANGED
|
@@ -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
|