@h1dr0n/skill-pool 0.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.
- package/LICENSE +21 -0
- package/README.md +296 -0
- package/bin/cli.js +157 -0
- package/package.json +41 -0
- package/skills/api/agents/backend-specialist.md +69 -0
- package/skills/api/agents/database-optimizer.md +176 -0
- package/skills/api/manifest.yaml +20 -0
- package/skills/api/rules/auth-security.md +45 -0
- package/skills/api/skills/api-patterns/SKILL.md +81 -0
- package/skills/api/skills/api-patterns/api-style.md +42 -0
- package/skills/api/skills/api-patterns/auth.md +24 -0
- package/skills/api/skills/api-patterns/documentation.md +26 -0
- package/skills/api/skills/api-patterns/graphql.md +41 -0
- package/skills/api/skills/api-patterns/rate-limiting.md +31 -0
- package/skills/api/skills/api-patterns/response.md +37 -0
- package/skills/api/skills/api-patterns/rest.md +40 -0
- package/skills/api/skills/api-patterns/scripts/api_validator.py +211 -0
- package/skills/api/skills/api-patterns/security-testing.md +122 -0
- package/skills/api/skills/api-patterns/trpc.md +41 -0
- package/skills/api/skills/api-patterns/versioning.md +22 -0
- package/skills/api/skills/database-patterns.md +126 -0
- package/skills/api/skills/deployment-patterns.md +105 -0
- package/skills/api/skills/docker-patterns.md +135 -0
- package/skills/common/agents/code-reviewer.md +78 -0
- package/skills/common/agents/planner.md +80 -0
- package/skills/common/agents/security-reviewer.md +82 -0
- package/skills/common/agents/software-architect.md +81 -0
- package/skills/common/manifest.yaml +25 -0
- package/skills/common/rules/coding-style.md +39 -0
- package/skills/common/rules/git-workflow.md +33 -0
- package/skills/common/rules/security.md +25 -0
- package/skills/common/skills/architecture/SKILL.md +55 -0
- package/skills/common/skills/architecture/context-discovery.md +43 -0
- package/skills/common/skills/architecture/examples.md +94 -0
- package/skills/common/skills/architecture/pattern-selection.md +68 -0
- package/skills/common/skills/architecture/patterns-reference.md +50 -0
- package/skills/common/skills/architecture/trade-off-analysis.md +77 -0
- package/skills/common/skills/brainstorming/SKILL.md +163 -0
- package/skills/common/skills/brainstorming/dynamic-questioning.md +350 -0
- package/skills/common/skills/clean-code.md +99 -0
- package/skills/common/skills/code-review-checklist.md +86 -0
- package/skills/common/skills/plan-writing/SKILL.md +152 -0
- package/skills/common/skills/skill-feedback.md +94 -0
- package/skills/common/skills/tdd-workflow.md +130 -0
- package/skills/common/skills/verification-loop.md +112 -0
- package/skills/cpp/agents/cpp-build-resolver.md +90 -0
- package/skills/cpp/agents/cpp-reviewer.md +72 -0
- package/skills/cpp/manifest.yaml +15 -0
- package/skills/cpp/skills/cpp-coding-standards.md +722 -0
- package/skills/cpp/skills/cpp-testing.md +323 -0
- package/skills/devops/agents/devops-automator.md +376 -0
- package/skills/devops/agents/sre.md +90 -0
- package/skills/devops/manifest.yaml +20 -0
- package/skills/devops/skills/deployment-patterns.md +427 -0
- package/skills/devops/skills/deployment-procedures/SKILL.md +241 -0
- package/skills/devops/skills/docker-patterns.md +364 -0
- package/skills/devops/skills/e2e-testing.md +326 -0
- package/skills/devops/skills/github-ops.md +144 -0
- package/skills/django/manifest.yaml +16 -0
- package/skills/django/skills/django-patterns.md +734 -0
- package/skills/django/skills/django-security.md +593 -0
- package/skills/django/skills/django-tdd.md +729 -0
- package/skills/django/skills/django-verification.md +469 -0
- package/skills/dotnet/agents/csharp-reviewer.md +101 -0
- package/skills/dotnet/manifest.yaml +14 -0
- package/skills/dotnet/skills/csharp-testing.md +321 -0
- package/skills/dotnet/skills/dotnet-patterns.md +321 -0
- package/skills/go/agents/code-reviewer.md +76 -0
- package/skills/go/agents/go-build-resolver.md +94 -0
- package/skills/go/agents/go-reviewer.md +76 -0
- package/skills/go/manifest.yaml +17 -0
- package/skills/go/rules/go-style.md +55 -0
- package/skills/go/skills/golang-patterns.md +674 -0
- package/skills/go/skills/golang-testing.md +720 -0
- package/skills/java/agents/java-build-resolver.md +153 -0
- package/skills/java/agents/java-reviewer.md +92 -0
- package/skills/java/manifest.yaml +18 -0
- package/skills/java/skills/java-coding-standards.md +147 -0
- package/skills/java/skills/jpa-patterns.md +151 -0
- package/skills/java/skills/springboot-patterns.md +314 -0
- package/skills/java/skills/springboot-security.md +272 -0
- package/skills/kotlin/agents/kotlin-build-resolver.md +118 -0
- package/skills/kotlin/agents/kotlin-reviewer.md +159 -0
- package/skills/kotlin/manifest.yaml +17 -0
- package/skills/kotlin/skills/kotlin-coroutines-flows.md +284 -0
- package/skills/kotlin/skills/kotlin-patterns.md +711 -0
- package/skills/kotlin/skills/kotlin-testing.md +824 -0
- package/skills/laravel/manifest.yaml +15 -0
- package/skills/laravel/skills/laravel-patterns.md +409 -0
- package/skills/laravel/skills/laravel-security.md +279 -0
- package/skills/laravel/skills/laravel-tdd.md +277 -0
- package/skills/laravel/skills/laravel-verification.md +173 -0
- package/skills/mobile/agents/dart-build-resolver.md +201 -0
- package/skills/mobile/agents/flutter-reviewer.md +243 -0
- package/skills/mobile/manifest.yaml +19 -0
- package/skills/mobile/skills/android-clean-architecture.md +339 -0
- package/skills/mobile/skills/dart-flutter-patterns.md +563 -0
- package/skills/mobile/skills/swiftui-patterns.md +259 -0
- package/skills/nestjs/manifest.yaml +13 -0
- package/skills/nestjs/skills/nestjs-patterns.md +230 -0
- package/skills/perl/manifest.yaml +13 -0
- package/skills/perl/skills/perl-patterns.md +504 -0
- package/skills/perl/skills/perl-security.md +503 -0
- package/skills/perl/skills/perl-testing.md +475 -0
- package/skills/python/agents/python-reviewer.md +98 -0
- package/skills/python/manifest.yaml +18 -0
- package/skills/python/rules/python-style.md +69 -0
- package/skills/python/skills/python-patterns/SKILL.md +441 -0
- package/skills/python/skills/python-patterns.md +90 -0
- package/skills/python/skills/python-testing.md +81 -0
- package/skills/rust/agents/rust-build-resolver.md +148 -0
- package/skills/rust/agents/rust-reviewer.md +94 -0
- package/skills/rust/manifest.yaml +16 -0
- package/skills/rust/rules/rust-style.md +107 -0
- package/skills/rust/skills/rust-patterns.md +499 -0
- package/skills/rust/skills/rust-testing.md +500 -0
- package/skills/security/agents/accessibility-auditor.md +316 -0
- package/skills/security/agents/security-reviewer.md +108 -0
- package/skills/security/manifest.yaml +19 -0
- package/skills/security/skills/red-team-tactics/SKILL.md +199 -0
- package/skills/security/skills/security-bounty-hunter.md +99 -0
- package/skills/security/skills/security-review.md +495 -0
- package/skills/security/skills/security-scan.md +165 -0
- package/skills/security/skills/vulnerability-scanner/SKILL.md +276 -0
- package/skills/security/skills/vulnerability-scanner/checklists.md +121 -0
- package/skills/security/skills/vulnerability-scanner/scripts/security_scan.py +458 -0
- package/skills/swift/manifest.yaml +16 -0
- package/skills/swift/skills/swift-actor-persistence.md +142 -0
- package/skills/swift/skills/swift-concurrency.md +216 -0
- package/skills/swift/skills/swift-protocol-di-testing.md +190 -0
- package/skills/swift/skills/swiftui-patterns.md +259 -0
- package/skills/unity/agents/game-designer.md +167 -0
- package/skills/unity/agents/unity-architect.md +52 -0
- package/skills/unity/agents/unity-editor-tool-developer.md +310 -0
- package/skills/unity/agents/unity-multiplayer-engineer.md +321 -0
- package/skills/unity/agents/unity-shader-graph-artist.md +269 -0
- package/skills/unity/manifest.yaml +21 -0
- package/skills/unity/rules/csharp-patterns.md +48 -0
- package/skills/unity/rules/unity-specific.md +53 -0
- package/skills/unity/skills/systematic-debugging.md +92 -0
- package/skills/unity/skills/unity-architecture.md +173 -0
- package/skills/unreal/agents/level-designer.md +208 -0
- package/skills/unreal/agents/technical-artist.md +229 -0
- package/skills/unreal/agents/unreal-multiplayer-architect.md +313 -0
- package/skills/unreal/agents/unreal-systems-engineer.md +310 -0
- package/skills/unreal/agents/unreal-technical-artist.md +256 -0
- package/skills/unreal/agents/unreal-world-builder.md +273 -0
- package/skills/unreal/manifest.yaml +21 -0
- package/skills/unreal/skills/unreal-patterns.md +183 -0
- package/skills/web/agents/frontend-specialist.md +71 -0
- package/skills/web/agents/ui-designer.md +383 -0
- package/skills/web/agents/ux-architect.md +469 -0
- package/skills/web/manifest.yaml +22 -0
- package/skills/web/rules/accessibility.md +54 -0
- package/skills/web/rules/css-performance.md +52 -0
- package/skills/web/skills/e2e-testing.md +132 -0
- package/skills/web/skills/frontend-design/SKILL.md +452 -0
- package/skills/web/skills/frontend-design/animation-guide.md +331 -0
- package/skills/web/skills/frontend-design/color-system.md +311 -0
- package/skills/web/skills/frontend-design/decision-trees.md +418 -0
- package/skills/web/skills/frontend-design/motion-graphics.md +306 -0
- package/skills/web/skills/frontend-design/scripts/accessibility_checker.py +183 -0
- package/skills/web/skills/frontend-design/scripts/ux_audit.py +722 -0
- package/skills/web/skills/frontend-design/typography-system.md +345 -0
- package/skills/web/skills/frontend-design/ux-psychology.md +1116 -0
- package/skills/web/skills/frontend-design/visual-effects.md +383 -0
- package/skills/web/skills/react-nextjs.md +135 -0
- package/skills/web/skills/tailwind-patterns/SKILL.md +269 -0
- package/src/adapters/antigravity.js +164 -0
- package/src/adapters/claude.js +188 -0
- package/src/adapters/cursor.js +161 -0
- package/src/adapters/index.js +67 -0
- package/src/adapters/windsurf.js +158 -0
- package/src/commands/add.js +266 -0
- package/src/commands/create.js +127 -0
- package/src/commands/diff.js +78 -0
- package/src/commands/info.js +88 -0
- package/src/commands/init.js +224 -0
- package/src/commands/install.js +90 -0
- package/src/commands/list.js +54 -0
- package/src/commands/remove.js +101 -0
- package/src/commands/targets.js +32 -0
- package/src/commands/update.js +57 -0
- package/src/core/manifest.js +57 -0
- package/src/core/plugins.js +86 -0
- package/src/core/resolver.js +84 -0
- package/src/core/tracker.js +49 -0
- package/src/utils/fs.js +80 -0
- package/src/utils/git.js +52 -0
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
import path from 'node:path';
|
|
2
|
+
import chalk from 'chalk';
|
|
3
|
+
import { ensureDir, writeFileAtomic, fileExists } from '../utils/fs.js';
|
|
4
|
+
|
|
5
|
+
const MANIFEST_TEMPLATE = (name) => `name: ${name}
|
|
6
|
+
version: 0.1.0
|
|
7
|
+
description: "${name} skill pack"
|
|
8
|
+
depends:
|
|
9
|
+
- common
|
|
10
|
+
tags:
|
|
11
|
+
- ${name}
|
|
12
|
+
rules: []
|
|
13
|
+
skills:
|
|
14
|
+
- skills/example.md
|
|
15
|
+
agents:
|
|
16
|
+
- agents/example.md
|
|
17
|
+
`;
|
|
18
|
+
|
|
19
|
+
const SKILL_TEMPLATE = `---
|
|
20
|
+
name: example
|
|
21
|
+
description: Example skill - replace with your skill description. Use when...
|
|
22
|
+
---
|
|
23
|
+
|
|
24
|
+
# Example Skill
|
|
25
|
+
|
|
26
|
+
## When to Activate
|
|
27
|
+
- Describe when this skill should be used
|
|
28
|
+
|
|
29
|
+
## Content
|
|
30
|
+
- Add your skill content here
|
|
31
|
+
`;
|
|
32
|
+
|
|
33
|
+
const AGENT_TEMPLATE = `---
|
|
34
|
+
name: example-agent
|
|
35
|
+
description: Example agent - replace with your agent description
|
|
36
|
+
tools: ["Read", "Write", "Edit", "Glob", "Grep"]
|
|
37
|
+
model: sonnet
|
|
38
|
+
---
|
|
39
|
+
|
|
40
|
+
You are an expert in...
|
|
41
|
+
|
|
42
|
+
## Core Mission
|
|
43
|
+
- Describe what this agent does
|
|
44
|
+
|
|
45
|
+
## Rules
|
|
46
|
+
- Add agent-specific rules
|
|
47
|
+
`;
|
|
48
|
+
|
|
49
|
+
const README_TEMPLATE = (name) => `# ${name}
|
|
50
|
+
|
|
51
|
+
A skill pack for agent-skill-pool.
|
|
52
|
+
|
|
53
|
+
## Structure
|
|
54
|
+
|
|
55
|
+
\`\`\`
|
|
56
|
+
${name}/
|
|
57
|
+
├── manifest.yaml # Pack metadata, dependencies, and file listings
|
|
58
|
+
├── rules/ # Rule files (.md) installed to AI tool config
|
|
59
|
+
├── skills/ # Skill files (.md) with frontmatter metadata
|
|
60
|
+
├── agents/ # Agent files (.md) with frontmatter metadata
|
|
61
|
+
└── README.md # This file
|
|
62
|
+
\`\`\`
|
|
63
|
+
|
|
64
|
+
## manifest.yaml
|
|
65
|
+
|
|
66
|
+
The manifest defines the pack name, version, description, dependencies,
|
|
67
|
+
tags, and lists all rules, skills, and agents included in the pack.
|
|
68
|
+
|
|
69
|
+
## File Format
|
|
70
|
+
|
|
71
|
+
### Skills
|
|
72
|
+
|
|
73
|
+
Skills use YAML frontmatter with \`name\` and \`description\` fields,
|
|
74
|
+
followed by markdown content describing when and how to use the skill.
|
|
75
|
+
|
|
76
|
+
### Agents
|
|
77
|
+
|
|
78
|
+
Agents use YAML frontmatter with \`name\`, \`description\`, \`tools\`,
|
|
79
|
+
and \`model\` fields, followed by a system prompt in markdown.
|
|
80
|
+
|
|
81
|
+
### Rules
|
|
82
|
+
|
|
83
|
+
Rules are plain markdown files installed into the AI tool's
|
|
84
|
+
configuration directory.
|
|
85
|
+
|
|
86
|
+
## Getting Started
|
|
87
|
+
|
|
88
|
+
1. Edit \`manifest.yaml\` with your pack details
|
|
89
|
+
2. Add rules to \`rules/\`
|
|
90
|
+
3. Edit or add skills in \`skills/\`
|
|
91
|
+
4. Edit or add agents in \`agents/\`
|
|
92
|
+
5. Install with: \`skill-pool install ${name}\`
|
|
93
|
+
`;
|
|
94
|
+
|
|
95
|
+
export async function createCommand(name, options) {
|
|
96
|
+
const baseDir = path.resolve(options.path);
|
|
97
|
+
const packDir = path.join(baseDir, name);
|
|
98
|
+
|
|
99
|
+
if (await fileExists(packDir)) {
|
|
100
|
+
throw new Error(`Directory already exists: ${packDir}`);
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
await ensureDir(path.join(packDir, 'rules'));
|
|
104
|
+
await writeFileAtomic(path.join(packDir, 'manifest.yaml'), MANIFEST_TEMPLATE(name));
|
|
105
|
+
await writeFileAtomic(path.join(packDir, 'skills', 'example.md'), SKILL_TEMPLATE);
|
|
106
|
+
await writeFileAtomic(path.join(packDir, 'agents', 'example.md'), AGENT_TEMPLATE);
|
|
107
|
+
await writeFileAtomic(path.join(packDir, 'README.md'), README_TEMPLATE(name));
|
|
108
|
+
|
|
109
|
+
console.log(chalk.green(`\nCreated skill pack "${name}" at ${packDir}\n`));
|
|
110
|
+
console.log(chalk.bold('Structure:\n'));
|
|
111
|
+
console.log(` ${chalk.cyan(name)}/`);
|
|
112
|
+
console.log(` ├── manifest.yaml`);
|
|
113
|
+
console.log(` ├── rules/`);
|
|
114
|
+
console.log(` ├── skills/`);
|
|
115
|
+
console.log(` │ └── example.md`);
|
|
116
|
+
console.log(` ├── agents/`);
|
|
117
|
+
console.log(` │ └── example.md`);
|
|
118
|
+
console.log(` └── README.md`);
|
|
119
|
+
console.log('');
|
|
120
|
+
console.log(chalk.bold('Next steps:\n'));
|
|
121
|
+
console.log(` 1. Edit ${chalk.cyan('manifest.yaml')} with your pack details`);
|
|
122
|
+
console.log(` 2. Add rules to ${chalk.cyan('rules/')}`);
|
|
123
|
+
console.log(` 3. Edit or add skills in ${chalk.cyan('skills/')}`);
|
|
124
|
+
console.log(` 4. Edit or add agents in ${chalk.cyan('agents/')}`);
|
|
125
|
+
console.log(` 5. Install with: ${chalk.cyan(`skill-pool install ${name}`)}`);
|
|
126
|
+
console.log('');
|
|
127
|
+
}
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
import chalk from 'chalk';
|
|
2
|
+
import { loadManifest } from '../core/manifest.js';
|
|
3
|
+
import { loadTracker, isInstalled } from '../core/tracker.js';
|
|
4
|
+
|
|
5
|
+
export async function diffCommand(packName) {
|
|
6
|
+
const projectDir = process.cwd();
|
|
7
|
+
const tracker = await loadTracker(projectDir);
|
|
8
|
+
|
|
9
|
+
if (!isInstalled(tracker, packName)) {
|
|
10
|
+
console.log(
|
|
11
|
+
chalk.yellow(`Pack "${packName}" is not installed. Use \`skill-pool install ${packName}\` first.`)
|
|
12
|
+
);
|
|
13
|
+
return;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
let manifest;
|
|
17
|
+
try {
|
|
18
|
+
manifest = await loadManifest(packName);
|
|
19
|
+
} catch {
|
|
20
|
+
console.log(chalk.red(`Could not load manifest for "${packName}". Pack may no longer exist.`));
|
|
21
|
+
return;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
const installed = tracker.installed[packName];
|
|
25
|
+
const installedVersion = installed.version;
|
|
26
|
+
const availableVersion = manifest.version;
|
|
27
|
+
const installedDate = new Date(installed.installedAt).toLocaleDateString();
|
|
28
|
+
|
|
29
|
+
console.log(chalk.bold(`\nDiff for ${packName}:\n`));
|
|
30
|
+
|
|
31
|
+
console.log(` Installed: ${chalk.cyan(installedVersion)} (${installedDate})`);
|
|
32
|
+
console.log(` Available: ${chalk.cyan(availableVersion)}`);
|
|
33
|
+
|
|
34
|
+
if (installedVersion === availableVersion) {
|
|
35
|
+
console.log(chalk.green('\n Same version - no update available.\n'));
|
|
36
|
+
} else {
|
|
37
|
+
console.log(chalk.yellow(`\n Version change: ${installedVersion} -> ${availableVersion}\n`));
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
const installedTargets = installed.targets || [];
|
|
41
|
+
const manifestItems = collectItems(manifest);
|
|
42
|
+
|
|
43
|
+
console.log(chalk.bold(' Contents in latest manifest:\n'));
|
|
44
|
+
|
|
45
|
+
if (manifestItems.length === 0) {
|
|
46
|
+
console.log(chalk.gray(' (no items)'));
|
|
47
|
+
} else {
|
|
48
|
+
for (const item of manifestItems) {
|
|
49
|
+
const symbol = installedVersion === availableVersion
|
|
50
|
+
? chalk.gray(' ')
|
|
51
|
+
: chalk.yellow('~ ');
|
|
52
|
+
console.log(` ${symbol}${chalk.white(item.path)} ${chalk.gray(`(${item.type})`)}`);
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
if (installedTargets.length > 0) {
|
|
57
|
+
console.log(chalk.bold('\n Installed targets:'));
|
|
58
|
+
console.log(` ${chalk.gray(installedTargets.join(', '))}`);
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
console.log('');
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
function collectItems(manifest) {
|
|
65
|
+
const items = [];
|
|
66
|
+
|
|
67
|
+
for (const rule of manifest.rules) {
|
|
68
|
+
items.push({ path: rule, type: 'rule' });
|
|
69
|
+
}
|
|
70
|
+
for (const skill of manifest.skills) {
|
|
71
|
+
items.push({ path: skill, type: 'skill' });
|
|
72
|
+
}
|
|
73
|
+
for (const agent of manifest.agents) {
|
|
74
|
+
items.push({ path: agent, type: 'agent' });
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
return items;
|
|
78
|
+
}
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
import chalk from 'chalk';
|
|
2
|
+
import { loadManifest } from '../core/manifest.js';
|
|
3
|
+
import { loadTracker } from '../core/tracker.js';
|
|
4
|
+
import { resolveDependencies } from '../core/resolver.js';
|
|
5
|
+
|
|
6
|
+
export async function infoCommand(packName) {
|
|
7
|
+
const manifest = await loadManifest(packName);
|
|
8
|
+
|
|
9
|
+
const projectDir = process.cwd();
|
|
10
|
+
const tracker = await loadTracker(projectDir);
|
|
11
|
+
const installInfo = tracker.installed[packName] || null;
|
|
12
|
+
|
|
13
|
+
// Header
|
|
14
|
+
console.log(chalk.bold(`\n${manifest.name}`) + chalk.gray(`@${manifest.version}`));
|
|
15
|
+
if (manifest.description) {
|
|
16
|
+
console.log(chalk.gray(manifest.description));
|
|
17
|
+
}
|
|
18
|
+
console.log('');
|
|
19
|
+
|
|
20
|
+
// Tags
|
|
21
|
+
if (manifest.tags.length > 0) {
|
|
22
|
+
console.log(chalk.bold('Tags:'));
|
|
23
|
+
console.log(` ${manifest.tags.map((t) => chalk.cyan(t)).join(', ')}`);
|
|
24
|
+
console.log('');
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
// Dependencies
|
|
28
|
+
console.log(chalk.bold('Dependencies:'));
|
|
29
|
+
if (manifest.depends.length === 0) {
|
|
30
|
+
console.log(chalk.gray(' None'));
|
|
31
|
+
} else {
|
|
32
|
+
const resolved = await resolveDependencies(packName);
|
|
33
|
+
// Remove the pack itself from the resolved chain
|
|
34
|
+
const chain = resolved.filter((d) => d !== packName);
|
|
35
|
+
console.log(` Direct: ${manifest.depends.map((d) => chalk.cyan(d)).join(', ')}`);
|
|
36
|
+
if (chain.length > manifest.depends.length) {
|
|
37
|
+
console.log(` Resolved chain: ${chain.map((d) => chalk.cyan(d)).join(' → ')}`);
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
console.log('');
|
|
41
|
+
|
|
42
|
+
// Rules
|
|
43
|
+
console.log(chalk.bold(`Rules (${manifest.rules.length}):`));
|
|
44
|
+
if (manifest.rules.length === 0) {
|
|
45
|
+
console.log(chalk.gray(' None'));
|
|
46
|
+
} else {
|
|
47
|
+
for (const rule of manifest.rules) {
|
|
48
|
+
console.log(` ${chalk.white(rule)}`);
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
console.log('');
|
|
52
|
+
|
|
53
|
+
// Skills
|
|
54
|
+
console.log(chalk.bold(`Skills (${manifest.skills.length}):`));
|
|
55
|
+
if (manifest.skills.length === 0) {
|
|
56
|
+
console.log(chalk.gray(' None'));
|
|
57
|
+
} else {
|
|
58
|
+
for (const skill of manifest.skills) {
|
|
59
|
+
const isDir = !skill.endsWith('.md');
|
|
60
|
+
const label = isDir ? chalk.white(skill) + chalk.gray(' (directory)') : chalk.white(skill);
|
|
61
|
+
console.log(` ${label}`);
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
console.log('');
|
|
65
|
+
|
|
66
|
+
// Agents
|
|
67
|
+
console.log(chalk.bold(`Agents (${manifest.agents.length}):`));
|
|
68
|
+
if (manifest.agents.length === 0) {
|
|
69
|
+
console.log(chalk.gray(' None'));
|
|
70
|
+
} else {
|
|
71
|
+
for (const agent of manifest.agents) {
|
|
72
|
+
console.log(` ${chalk.white(agent)}`);
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
console.log('');
|
|
76
|
+
|
|
77
|
+
// Install status
|
|
78
|
+
console.log(chalk.bold('Install status:'));
|
|
79
|
+
if (installInfo) {
|
|
80
|
+
const date = new Date(installInfo.installedAt).toLocaleDateString();
|
|
81
|
+
const targets = installInfo.targets ? installInfo.targets.join(', ') : 'N/A';
|
|
82
|
+
console.log(` ${chalk.green('Installed')} v${installInfo.version} on ${date}`);
|
|
83
|
+
console.log(` Targets: ${targets}`);
|
|
84
|
+
} else {
|
|
85
|
+
console.log(chalk.gray(' Not installed'));
|
|
86
|
+
}
|
|
87
|
+
console.log('');
|
|
88
|
+
}
|
|
@@ -0,0 +1,224 @@
|
|
|
1
|
+
import path from 'node:path';
|
|
2
|
+
import chalk from 'chalk';
|
|
3
|
+
import { fileExists, listDir, ensureDir, readFileContent } from '../utils/fs.js';
|
|
4
|
+
import { detectTargets } from '../adapters/index.js';
|
|
5
|
+
import { listAvailablePacks } from '../core/manifest.js';
|
|
6
|
+
import { installCommand } from './install.js';
|
|
7
|
+
|
|
8
|
+
const PROJECT_DETECTORS = [
|
|
9
|
+
{
|
|
10
|
+
pack: 'unity',
|
|
11
|
+
files: ['*.unity'],
|
|
12
|
+
extensions: ['.cs'],
|
|
13
|
+
description: 'Unity project detected',
|
|
14
|
+
},
|
|
15
|
+
{
|
|
16
|
+
pack: 'unreal',
|
|
17
|
+
files: ['*.uproject'],
|
|
18
|
+
extensions: [],
|
|
19
|
+
description: 'Unreal Engine project detected',
|
|
20
|
+
},
|
|
21
|
+
{
|
|
22
|
+
pack: 'web',
|
|
23
|
+
files: ['package.json'],
|
|
24
|
+
extensions: [],
|
|
25
|
+
packageJsonMatch: /["'](?:react|next|vue|nuxt|svelte|astro)["']/,
|
|
26
|
+
description: 'Web/frontend project detected',
|
|
27
|
+
},
|
|
28
|
+
{
|
|
29
|
+
pack: 'python',
|
|
30
|
+
files: ['requirements.txt', 'pyproject.toml', 'setup.py'],
|
|
31
|
+
extensions: ['.py'],
|
|
32
|
+
description: 'Python project detected',
|
|
33
|
+
},
|
|
34
|
+
{
|
|
35
|
+
pack: 'django',
|
|
36
|
+
files: ['manage.py'],
|
|
37
|
+
extensions: [],
|
|
38
|
+
requirementsMatch: /django/i,
|
|
39
|
+
description: 'Django project detected',
|
|
40
|
+
},
|
|
41
|
+
{
|
|
42
|
+
pack: 'go',
|
|
43
|
+
files: ['go.mod'],
|
|
44
|
+
extensions: [],
|
|
45
|
+
description: 'Go project detected',
|
|
46
|
+
},
|
|
47
|
+
{
|
|
48
|
+
pack: 'rust',
|
|
49
|
+
files: ['Cargo.toml'],
|
|
50
|
+
extensions: [],
|
|
51
|
+
description: 'Rust project detected',
|
|
52
|
+
},
|
|
53
|
+
{
|
|
54
|
+
pack: 'swift',
|
|
55
|
+
files: ['Package.swift'],
|
|
56
|
+
extensions: ['.swift'],
|
|
57
|
+
description: 'Swift project detected',
|
|
58
|
+
},
|
|
59
|
+
{
|
|
60
|
+
pack: 'kotlin',
|
|
61
|
+
files: ['build.gradle', 'build.gradle.kts'],
|
|
62
|
+
extensions: ['.kt'],
|
|
63
|
+
description: 'Kotlin project detected',
|
|
64
|
+
},
|
|
65
|
+
{
|
|
66
|
+
pack: 'java',
|
|
67
|
+
files: ['pom.xml'],
|
|
68
|
+
extensions: ['.java'],
|
|
69
|
+
description: 'Java project detected',
|
|
70
|
+
},
|
|
71
|
+
{
|
|
72
|
+
pack: 'laravel',
|
|
73
|
+
files: ['composer.json'],
|
|
74
|
+
extensions: [],
|
|
75
|
+
description: 'Laravel/PHP project detected',
|
|
76
|
+
},
|
|
77
|
+
{
|
|
78
|
+
pack: 'devops',
|
|
79
|
+
files: ['Dockerfile', 'docker-compose.yml', 'docker-compose.yaml'],
|
|
80
|
+
extensions: [],
|
|
81
|
+
description: 'Docker/DevOps project detected',
|
|
82
|
+
},
|
|
83
|
+
{
|
|
84
|
+
pack: 'dotnet',
|
|
85
|
+
files: ['*.sln'],
|
|
86
|
+
extensions: ['.csproj'],
|
|
87
|
+
description: '.NET project detected',
|
|
88
|
+
},
|
|
89
|
+
{
|
|
90
|
+
pack: 'cpp',
|
|
91
|
+
files: ['CMakeLists.txt'],
|
|
92
|
+
extensions: ['.cpp', '.cc', '.cxx'],
|
|
93
|
+
description: 'C++ project detected',
|
|
94
|
+
},
|
|
95
|
+
];
|
|
96
|
+
|
|
97
|
+
async function hasFileWithExtension(projectDir, extensions) {
|
|
98
|
+
const entries = await listDir(projectDir);
|
|
99
|
+
return entries.some((entry) =>
|
|
100
|
+
extensions.some((ext) => entry.endsWith(ext))
|
|
101
|
+
);
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
async function hasMatchingFile(projectDir, patterns) {
|
|
105
|
+
const entries = await listDir(projectDir);
|
|
106
|
+
for (const pattern of patterns) {
|
|
107
|
+
if (pattern.startsWith('*')) {
|
|
108
|
+
const ext = pattern.slice(1);
|
|
109
|
+
if (entries.some((entry) => entry.endsWith(ext))) {
|
|
110
|
+
return true;
|
|
111
|
+
}
|
|
112
|
+
} else {
|
|
113
|
+
if (entries.includes(pattern)) {
|
|
114
|
+
return true;
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
return false;
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
async function detectProjectPacks(projectDir) {
|
|
122
|
+
const detected = [];
|
|
123
|
+
|
|
124
|
+
for (const detector of PROJECT_DETECTORS) {
|
|
125
|
+
let matched = false;
|
|
126
|
+
|
|
127
|
+
if (detector.files.length > 0) {
|
|
128
|
+
matched = await hasMatchingFile(projectDir, detector.files);
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
if (!matched && detector.extensions && detector.extensions.length > 0) {
|
|
132
|
+
matched = await hasFileWithExtension(projectDir, detector.extensions);
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
if (matched && detector.packageJsonMatch) {
|
|
136
|
+
const pkgPath = path.join(projectDir, 'package.json');
|
|
137
|
+
if (await fileExists(pkgPath)) {
|
|
138
|
+
const content = await readFileContent(pkgPath);
|
|
139
|
+
matched = detector.packageJsonMatch.test(content);
|
|
140
|
+
} else {
|
|
141
|
+
matched = false;
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
if (matched && detector.requirementsMatch) {
|
|
146
|
+
const reqPath = path.join(projectDir, 'requirements.txt');
|
|
147
|
+
if (await fileExists(reqPath)) {
|
|
148
|
+
const content = await readFileContent(reqPath);
|
|
149
|
+
matched = detector.requirementsMatch.test(content);
|
|
150
|
+
} else {
|
|
151
|
+
matched = false;
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
if (matched) {
|
|
156
|
+
detected.push({ pack: detector.pack, description: detector.description });
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
return detected;
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
export async function initCommand(packs = [], options = {}) {
|
|
164
|
+
const projectDir = process.cwd();
|
|
165
|
+
|
|
166
|
+
console.log(chalk.bold('\nSkill Pool - Project Init\n'));
|
|
167
|
+
|
|
168
|
+
// Detect AI tool targets
|
|
169
|
+
let targets = await detectTargets(projectDir);
|
|
170
|
+
if (targets.length === 0) {
|
|
171
|
+
console.log(chalk.yellow('No AI tool directories detected. Creating .claude/ as default target.'));
|
|
172
|
+
await ensureDir(path.join(projectDir, '.claude'));
|
|
173
|
+
targets = ['claude'];
|
|
174
|
+
} else {
|
|
175
|
+
console.log(chalk.green(`Detected targets: ${targets.join(', ')}`));
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
// Get available packs
|
|
179
|
+
const availablePacks = await listAvailablePacks();
|
|
180
|
+
const availableNames = availablePacks.map((p) => p.name);
|
|
181
|
+
|
|
182
|
+
// Determine which packs to install
|
|
183
|
+
let packsToInstall = [];
|
|
184
|
+
|
|
185
|
+
if (packs.length > 0) {
|
|
186
|
+
// Validate user-provided pack names
|
|
187
|
+
const invalid = packs.filter((p) => !availableNames.includes(p));
|
|
188
|
+
if (invalid.length > 0) {
|
|
189
|
+
console.error(chalk.red(`\nUnknown pack(s): ${invalid.join(', ')}`));
|
|
190
|
+
console.log(chalk.gray(`Available: ${availableNames.join(', ')}`));
|
|
191
|
+
process.exit(1);
|
|
192
|
+
}
|
|
193
|
+
packsToInstall = packs;
|
|
194
|
+
} else {
|
|
195
|
+
// Auto-detect project type
|
|
196
|
+
const detected = await detectProjectPacks(projectDir);
|
|
197
|
+
|
|
198
|
+
if (detected.length > 0) {
|
|
199
|
+
console.log(chalk.cyan('\nDetected project types:'));
|
|
200
|
+
for (const d of detected) {
|
|
201
|
+
console.log(chalk.cyan(` - ${d.description} → ${chalk.bold(d.pack)}`));
|
|
202
|
+
}
|
|
203
|
+
packsToInstall = detected.map((d) => d.pack);
|
|
204
|
+
} else {
|
|
205
|
+
console.log(chalk.yellow('\nNo project type detected automatically.'));
|
|
206
|
+
console.log(chalk.gray(`Available packs: ${availableNames.join(', ')}`));
|
|
207
|
+
console.log(chalk.gray('Run: skill-pool init <pack1> <pack2> ...'));
|
|
208
|
+
return;
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
// Always include common pack if available and not already listed
|
|
213
|
+
if (availableNames.includes('common') && !packsToInstall.includes('common')) {
|
|
214
|
+
packsToInstall.unshift('common');
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
console.log(chalk.bold(`\nInstalling packs: ${packsToInstall.join(', ')}\n`));
|
|
218
|
+
|
|
219
|
+
await installCommand(packsToInstall, {
|
|
220
|
+
target: options.target || targets.join(','),
|
|
221
|
+
});
|
|
222
|
+
|
|
223
|
+
console.log(chalk.green('\nProject initialized successfully.'));
|
|
224
|
+
}
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
import chalk from 'chalk';
|
|
2
|
+
import { resolveDependencies, checkConflicts } from '../core/resolver.js';
|
|
3
|
+
import { loadManifest } from '../core/manifest.js';
|
|
4
|
+
import {
|
|
5
|
+
loadTracker,
|
|
6
|
+
saveTracker,
|
|
7
|
+
getInstalledVersion,
|
|
8
|
+
recordInstall,
|
|
9
|
+
} from '../core/tracker.js';
|
|
10
|
+
import { getAdapter, detectTargets, getAllTargetNames } from '../adapters/index.js';
|
|
11
|
+
|
|
12
|
+
async function resolveTargets(projectDir, targetOption) {
|
|
13
|
+
if (targetOption) {
|
|
14
|
+
const names = targetOption.split(',').map((t) => t.trim());
|
|
15
|
+
names.forEach((n) => getAdapter(n)); // validate
|
|
16
|
+
return names;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
const detected = await detectTargets(projectDir);
|
|
20
|
+
if (detected.length > 0) return detected;
|
|
21
|
+
|
|
22
|
+
// Default to claude if nothing detected
|
|
23
|
+
return ['claude'];
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
export async function installCommand(packNames, options = {}) {
|
|
27
|
+
const projectDir = process.cwd();
|
|
28
|
+
const targets = await resolveTargets(projectDir, options.target);
|
|
29
|
+
let tracker = await loadTracker(projectDir);
|
|
30
|
+
|
|
31
|
+
console.log(chalk.gray(`Targets: ${targets.join(', ')}\n`));
|
|
32
|
+
|
|
33
|
+
if (packNames.length > 1) {
|
|
34
|
+
const conflicts = await checkConflicts(packNames);
|
|
35
|
+
if (conflicts.length > 0) {
|
|
36
|
+
console.log(chalk.yellow('⚠ Dependency version conflicts detected:\n'));
|
|
37
|
+
for (const conflict of conflicts) {
|
|
38
|
+
console.log(
|
|
39
|
+
chalk.yellow(
|
|
40
|
+
` "${conflict.dep}" has versions [${conflict.versions.join(', ')}] ` +
|
|
41
|
+
`(requested by: ${conflict.requestedBy.join(', ')})`
|
|
42
|
+
)
|
|
43
|
+
);
|
|
44
|
+
}
|
|
45
|
+
console.log(chalk.yellow('\n Using latest version for each conflicting dependency.\n'));
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
const allPacks = new Set();
|
|
50
|
+
for (const name of packNames) {
|
|
51
|
+
const deps = await resolveDependencies(name);
|
|
52
|
+
deps.forEach((d) => allPacks.add(d));
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
const toInstall = [...allPacks];
|
|
56
|
+
let installedCount = 0;
|
|
57
|
+
|
|
58
|
+
for (const packName of toInstall) {
|
|
59
|
+
const manifest = await loadManifest(packName);
|
|
60
|
+
const currentVersion = getInstalledVersion(tracker, packName);
|
|
61
|
+
|
|
62
|
+
if (currentVersion === manifest.version) {
|
|
63
|
+
console.log(chalk.gray(` ${packName}@${manifest.version} already installed, skipping`));
|
|
64
|
+
continue;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
let totalFiles = 0;
|
|
68
|
+
for (const targetName of targets) {
|
|
69
|
+
const adapter = getAdapter(targetName);
|
|
70
|
+
const files = await adapter.install(manifest, projectDir);
|
|
71
|
+
totalFiles += files.length;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
tracker = recordInstall(tracker, packName, manifest.version, targets);
|
|
75
|
+
installedCount++;
|
|
76
|
+
|
|
77
|
+
console.log(
|
|
78
|
+
chalk.green(` + ${packName}@${manifest.version}`) +
|
|
79
|
+
chalk.gray(` (${totalFiles} rules)`)
|
|
80
|
+
);
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
await saveTracker(projectDir, tracker);
|
|
84
|
+
|
|
85
|
+
if (installedCount === 0) {
|
|
86
|
+
console.log(chalk.yellow('\nAll packs already up to date.'));
|
|
87
|
+
} else {
|
|
88
|
+
console.log(chalk.green(`\nInstalled ${installedCount} pack(s) for ${targets.join(', ')}.`));
|
|
89
|
+
}
|
|
90
|
+
}
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import chalk from 'chalk';
|
|
2
|
+
import { listAvailablePacks } from '../core/manifest.js';
|
|
3
|
+
import { loadTracker } from '../core/tracker.js';
|
|
4
|
+
|
|
5
|
+
export async function listCommand(options) {
|
|
6
|
+
if (options.installed) {
|
|
7
|
+
await listInstalled();
|
|
8
|
+
} else {
|
|
9
|
+
await listAvailable();
|
|
10
|
+
}
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
async function listAvailable() {
|
|
14
|
+
const packs = await listAvailablePacks();
|
|
15
|
+
|
|
16
|
+
if (packs.length === 0) {
|
|
17
|
+
console.log(chalk.yellow('No packs available.'));
|
|
18
|
+
return;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
console.log(chalk.bold('\nAvailable packs:\n'));
|
|
22
|
+
|
|
23
|
+
for (const pack of packs) {
|
|
24
|
+
const deps = pack.depends.length > 0 ? chalk.gray(` (requires: ${pack.depends.join(', ')})`) : '';
|
|
25
|
+
console.log(` ${chalk.cyan(pack.name)}@${pack.version}${deps}`);
|
|
26
|
+
if (pack.description) {
|
|
27
|
+
console.log(` ${chalk.gray(pack.description)}`);
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
console.log('');
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
async function listInstalled() {
|
|
35
|
+
const projectDir = process.cwd();
|
|
36
|
+
const tracker = await loadTracker(projectDir);
|
|
37
|
+
const installed = Object.entries(tracker.installed);
|
|
38
|
+
|
|
39
|
+
if (installed.length === 0) {
|
|
40
|
+
console.log(chalk.yellow('No packs installed in this project.'));
|
|
41
|
+
return;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
console.log(chalk.bold('\nInstalled packs:\n'));
|
|
45
|
+
|
|
46
|
+
for (const [name, info] of installed) {
|
|
47
|
+
const date = new Date(info.installedAt).toLocaleDateString();
|
|
48
|
+
const targets = info.targets.join(', ');
|
|
49
|
+
console.log(` ${chalk.cyan(name)}@${info.version}`);
|
|
50
|
+
console.log(` ${chalk.gray(`installed: ${date} | targets: ${targets}`)}`);
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
console.log('');
|
|
54
|
+
}
|