claude-cli-advanced-starter-pack 1.0.16 → 1.8.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/OVERVIEW.md +5 -1
- package/README.md +241 -132
- package/bin/gtask.js +53 -0
- package/package.json +1 -1
- package/src/cli/menu.js +27 -0
- package/src/commands/explore-mcp/mcp-registry.js +99 -0
- package/src/commands/init.js +309 -80
- package/src/commands/install-panel-hook.js +108 -0
- package/src/commands/install-scripts.js +232 -0
- package/src/commands/install-skill.js +220 -0
- package/src/commands/panel.js +297 -0
- package/src/commands/setup-wizard.js +4 -3
- package/src/commands/test-setup.js +4 -5
- package/src/data/releases.json +209 -0
- package/src/panel/queue.js +188 -0
- package/templates/commands/ask-claude.template.md +118 -0
- package/templates/commands/ccasp-panel.template.md +72 -0
- package/templates/commands/ccasp-setup.template.md +470 -79
- package/templates/commands/create-smoke-test.template.md +186 -0
- package/templates/commands/project-impl.template.md +9 -113
- package/templates/commands/refactor-check.template.md +112 -0
- package/templates/commands/refactor-cleanup.template.md +144 -0
- package/templates/commands/refactor-prep.template.md +192 -0
- package/templates/docs/AI_ARCHITECTURE_CONSTITUTION.template.md +198 -0
- package/templates/docs/DETAILED_GOTCHAS.template.md +347 -0
- package/templates/docs/PHASE-DEV-CHECKLIST.template.md +241 -0
- package/templates/docs/PROGRESS_JSON_TEMPLATE.json +117 -0
- package/templates/docs/background-agent.template.md +264 -0
- package/templates/hooks/autonomous-decision-logger.template.js +207 -0
- package/templates/hooks/branch-merge-checker.template.js +272 -0
- package/templates/hooks/context-injector.template.js +261 -0
- package/templates/hooks/git-commit-tracker.template.js +267 -0
- package/templates/hooks/happy-mode-detector.template.js +214 -0
- package/templates/hooks/happy-title-generator.template.js +260 -0
- package/templates/hooks/issue-completion-detector.template.js +205 -0
- package/templates/hooks/panel-queue-reader.template.js +83 -0
- package/templates/hooks/phase-validation-gates.template.js +307 -0
- package/templates/hooks/session-id-generator.template.js +236 -0
- package/templates/hooks/token-budget-loader.template.js +234 -0
- package/templates/hooks/token-usage-monitor.template.js +193 -0
- package/templates/hooks/tool-output-cacher.template.js +219 -0
- package/templates/patterns/README.md +129 -0
- package/templates/patterns/l1-l2-orchestration.md +189 -0
- package/templates/patterns/multi-phase-orchestration.md +258 -0
- package/templates/patterns/two-tier-query-pipeline.md +192 -0
- package/templates/scripts/README.md +109 -0
- package/templates/scripts/analyze-delegation-log.js +299 -0
- package/templates/scripts/autonomous-decision-logger.js +277 -0
- package/templates/scripts/git-history-analyzer.py +269 -0
- package/templates/scripts/phase-validation-gates.js +307 -0
- package/templates/scripts/poll-deployment-status.js +260 -0
- package/templates/scripts/roadmap-scanner.js +263 -0
- package/templates/scripts/validate-deployment.js +293 -0
- package/templates/skills/agent-creator/skill.json +18 -0
- package/templates/skills/agent-creator/skill.md +335 -0
- package/templates/skills/hook-creator/skill.json +18 -0
- package/templates/skills/hook-creator/skill.md +318 -0
- package/templates/skills/panel/skill.json +18 -0
- package/templates/skills/panel/skill.md +90 -0
- package/templates/skills/rag-agent-creator/skill.json +18 -0
- package/templates/skills/rag-agent-creator/skill.md +307 -0
|
@@ -0,0 +1,232 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Install Scripts Command
|
|
3
|
+
*
|
|
4
|
+
* Copies utility scripts from templates to project's .claude/scripts/ directory.
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import chalk from 'chalk';
|
|
8
|
+
import inquirer from 'inquirer';
|
|
9
|
+
import ora from 'ora';
|
|
10
|
+
import { existsSync, mkdirSync, readdirSync, copyFileSync, readFileSync } from 'fs';
|
|
11
|
+
import { join, dirname, basename } from 'path';
|
|
12
|
+
import { fileURLToPath } from 'url';
|
|
13
|
+
import { showHeader } from '../cli/menu.js';
|
|
14
|
+
|
|
15
|
+
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
16
|
+
const TEMPLATES_DIR = join(__dirname, '../../templates/scripts');
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* Available scripts with descriptions
|
|
20
|
+
*/
|
|
21
|
+
const SCRIPTS = [
|
|
22
|
+
{
|
|
23
|
+
id: 'validate-deployment',
|
|
24
|
+
file: 'validate-deployment.js',
|
|
25
|
+
name: 'Deployment Validator',
|
|
26
|
+
description: 'Pre-deployment environment validation for Railway, Cloudflare, Vercel',
|
|
27
|
+
category: 'deployment',
|
|
28
|
+
},
|
|
29
|
+
{
|
|
30
|
+
id: 'poll-deployment-status',
|
|
31
|
+
file: 'poll-deployment-status.js',
|
|
32
|
+
name: 'Deployment Poller',
|
|
33
|
+
description: 'Poll deployment status until complete or timeout',
|
|
34
|
+
category: 'deployment',
|
|
35
|
+
},
|
|
36
|
+
{
|
|
37
|
+
id: 'roadmap-scanner',
|
|
38
|
+
file: 'roadmap-scanner.js',
|
|
39
|
+
name: 'Roadmap Scanner',
|
|
40
|
+
description: 'Multi-roadmap progress dashboard',
|
|
41
|
+
category: 'project',
|
|
42
|
+
},
|
|
43
|
+
{
|
|
44
|
+
id: 'analyze-delegation-log',
|
|
45
|
+
file: 'analyze-delegation-log.js',
|
|
46
|
+
name: 'Delegation Log Analyzer',
|
|
47
|
+
description: 'Analyze Claude Code model usage and token consumption',
|
|
48
|
+
category: 'analysis',
|
|
49
|
+
},
|
|
50
|
+
{
|
|
51
|
+
id: 'autonomous-decision-logger',
|
|
52
|
+
file: 'autonomous-decision-logger.js',
|
|
53
|
+
name: 'Decision Logger',
|
|
54
|
+
description: 'JSONL audit trail for agent decisions',
|
|
55
|
+
category: 'logging',
|
|
56
|
+
},
|
|
57
|
+
{
|
|
58
|
+
id: 'phase-validation-gates',
|
|
59
|
+
file: 'phase-validation-gates.js',
|
|
60
|
+
name: 'Phase Validation Gates',
|
|
61
|
+
description: '5-gate validation (EXIST, INIT, REGISTER, INVOKE, PROPAGATE)',
|
|
62
|
+
category: 'phased-dev',
|
|
63
|
+
},
|
|
64
|
+
{
|
|
65
|
+
id: 'git-history-analyzer',
|
|
66
|
+
file: 'git-history-analyzer.py',
|
|
67
|
+
name: 'Git History Analyzer',
|
|
68
|
+
description: 'Security audit for sensitive data in git history (Python)',
|
|
69
|
+
category: 'security',
|
|
70
|
+
},
|
|
71
|
+
];
|
|
72
|
+
|
|
73
|
+
/**
|
|
74
|
+
* Run the install-scripts command
|
|
75
|
+
*/
|
|
76
|
+
export async function runInstallScripts(options = {}) {
|
|
77
|
+
showHeader('Install Utility Scripts');
|
|
78
|
+
|
|
79
|
+
console.log(chalk.dim('Copy utility scripts to .claude/scripts/ for project use.\n'));
|
|
80
|
+
|
|
81
|
+
const targetDir = join(process.cwd(), '.claude/scripts');
|
|
82
|
+
|
|
83
|
+
// Show available scripts
|
|
84
|
+
if (options.list) {
|
|
85
|
+
return showScriptList();
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
// Interactive selection
|
|
89
|
+
const { selections } = await inquirer.prompt([
|
|
90
|
+
{
|
|
91
|
+
type: 'checkbox',
|
|
92
|
+
name: 'selections',
|
|
93
|
+
message: 'Select scripts to install:',
|
|
94
|
+
choices: SCRIPTS.map((script) => {
|
|
95
|
+
const installed = existsSync(join(targetDir, script.file));
|
|
96
|
+
const status = installed ? chalk.green(' [installed]') : '';
|
|
97
|
+
|
|
98
|
+
return {
|
|
99
|
+
name: `${script.name}${status}\n ${chalk.dim(script.description)}`,
|
|
100
|
+
value: script.id,
|
|
101
|
+
short: script.name,
|
|
102
|
+
checked: !installed,
|
|
103
|
+
};
|
|
104
|
+
}),
|
|
105
|
+
pageSize: 10,
|
|
106
|
+
},
|
|
107
|
+
]);
|
|
108
|
+
|
|
109
|
+
if (selections.length === 0) {
|
|
110
|
+
console.log(chalk.yellow('\nNo scripts selected.'));
|
|
111
|
+
return;
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
// Create target directory
|
|
115
|
+
if (!existsSync(targetDir)) {
|
|
116
|
+
mkdirSync(targetDir, { recursive: true });
|
|
117
|
+
console.log(chalk.dim(`Created ${targetDir}`));
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
// Copy selected scripts
|
|
121
|
+
const spinner = ora('Installing scripts...').start();
|
|
122
|
+
const results = [];
|
|
123
|
+
|
|
124
|
+
for (const scriptId of selections) {
|
|
125
|
+
const script = SCRIPTS.find((s) => s.id === scriptId);
|
|
126
|
+
if (!script) continue;
|
|
127
|
+
|
|
128
|
+
try {
|
|
129
|
+
const sourcePath = join(TEMPLATES_DIR, script.file);
|
|
130
|
+
const targetPath = join(targetDir, script.file);
|
|
131
|
+
|
|
132
|
+
if (!existsSync(sourcePath)) {
|
|
133
|
+
results.push({ script, success: false, error: 'Template not found' });
|
|
134
|
+
continue;
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
copyFileSync(sourcePath, targetPath);
|
|
138
|
+
results.push({ script, success: true });
|
|
139
|
+
} catch (error) {
|
|
140
|
+
results.push({ script, success: false, error: error.message });
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
spinner.stop();
|
|
145
|
+
|
|
146
|
+
// Copy README if not exists
|
|
147
|
+
const readmePath = join(targetDir, 'README.md');
|
|
148
|
+
if (!existsSync(readmePath)) {
|
|
149
|
+
try {
|
|
150
|
+
const sourceReadme = join(TEMPLATES_DIR, 'README.md');
|
|
151
|
+
if (existsSync(sourceReadme)) {
|
|
152
|
+
copyFileSync(sourceReadme, readmePath);
|
|
153
|
+
}
|
|
154
|
+
} catch (e) {
|
|
155
|
+
// Ignore
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
// Display results
|
|
160
|
+
console.log(chalk.cyan.bold('\n📋 Installation Results\n'));
|
|
161
|
+
|
|
162
|
+
const successful = results.filter((r) => r.success);
|
|
163
|
+
const failed = results.filter((r) => !r.success);
|
|
164
|
+
|
|
165
|
+
if (successful.length > 0) {
|
|
166
|
+
console.log(chalk.green('✓ Installed:'));
|
|
167
|
+
for (const result of successful) {
|
|
168
|
+
console.log(` - ${result.script.name}`);
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
if (failed.length > 0) {
|
|
173
|
+
console.log(chalk.red('\n✗ Failed:'));
|
|
174
|
+
for (const result of failed) {
|
|
175
|
+
console.log(` - ${result.script.name}: ${result.error}`);
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
// Show usage tips
|
|
180
|
+
if (successful.length > 0) {
|
|
181
|
+
console.log(chalk.cyan('\n📚 Usage Tips\n'));
|
|
182
|
+
console.log(chalk.dim(`Scripts installed to: ${targetDir}\n`));
|
|
183
|
+
|
|
184
|
+
for (const result of successful) {
|
|
185
|
+
const script = result.script;
|
|
186
|
+
if (script.file.endsWith('.js')) {
|
|
187
|
+
console.log(chalk.white(`${script.name}:`));
|
|
188
|
+
console.log(chalk.dim(` node .claude/scripts/${script.file} --help`));
|
|
189
|
+
} else if (script.file.endsWith('.py')) {
|
|
190
|
+
console.log(chalk.white(`${script.name}:`));
|
|
191
|
+
console.log(chalk.dim(` python .claude/scripts/${script.file} --help`));
|
|
192
|
+
}
|
|
193
|
+
console.log('');
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
/**
|
|
199
|
+
* Show list of available scripts
|
|
200
|
+
*/
|
|
201
|
+
function showScriptList() {
|
|
202
|
+
const targetDir = join(process.cwd(), '.claude/scripts');
|
|
203
|
+
|
|
204
|
+
console.log(chalk.cyan.bold('Available Scripts\n'));
|
|
205
|
+
|
|
206
|
+
// Group by category
|
|
207
|
+
const categories = {};
|
|
208
|
+
for (const script of SCRIPTS) {
|
|
209
|
+
if (!categories[script.category]) {
|
|
210
|
+
categories[script.category] = [];
|
|
211
|
+
}
|
|
212
|
+
categories[script.category].push(script);
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
for (const [category, scripts] of Object.entries(categories)) {
|
|
216
|
+
const categoryName = category.charAt(0).toUpperCase() + category.slice(1);
|
|
217
|
+
console.log(chalk.white.bold(`\n${categoryName}:`));
|
|
218
|
+
|
|
219
|
+
for (const script of scripts) {
|
|
220
|
+
const installed = existsSync(join(targetDir, script.file));
|
|
221
|
+
const status = installed ? chalk.green(' [installed]') : '';
|
|
222
|
+
|
|
223
|
+
console.log(` ${script.name}${status}`);
|
|
224
|
+
console.log(chalk.dim(` ${script.description}`));
|
|
225
|
+
console.log(chalk.dim(` File: ${script.file}`));
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
console.log('');
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
export default runInstallScripts;
|
|
@@ -0,0 +1,220 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Install Skill Command
|
|
3
|
+
*
|
|
4
|
+
* Install individual skills to a project's .claude/skills/ folder
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import chalk from 'chalk';
|
|
8
|
+
import inquirer from 'inquirer';
|
|
9
|
+
import ora from 'ora';
|
|
10
|
+
import { existsSync, mkdirSync, writeFileSync, readFileSync, readdirSync, cpSync } from 'fs';
|
|
11
|
+
import { join, dirname } from 'path';
|
|
12
|
+
import { fileURLToPath } from 'url';
|
|
13
|
+
import { showHeader, showSuccess, showError, showWarning, showInfo } from '../cli/menu.js';
|
|
14
|
+
|
|
15
|
+
const __filename = fileURLToPath(import.meta.url);
|
|
16
|
+
const __dirname = dirname(__filename);
|
|
17
|
+
|
|
18
|
+
// Skills directory in the package
|
|
19
|
+
const SKILLS_DIR = join(__dirname, '..', '..', 'templates', 'skills');
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* Get available skills from the package
|
|
23
|
+
*/
|
|
24
|
+
function getAvailableSkills() {
|
|
25
|
+
const skills = [];
|
|
26
|
+
|
|
27
|
+
try {
|
|
28
|
+
if (!existsSync(SKILLS_DIR)) {
|
|
29
|
+
return skills;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
const dirs = readdirSync(SKILLS_DIR, { withFileTypes: true });
|
|
33
|
+
|
|
34
|
+
for (const dir of dirs) {
|
|
35
|
+
if (dir.isDirectory()) {
|
|
36
|
+
const manifestPath = join(SKILLS_DIR, dir.name, 'skill.json');
|
|
37
|
+
const skillPath = join(SKILLS_DIR, dir.name, 'skill.md');
|
|
38
|
+
|
|
39
|
+
if (existsSync(manifestPath) && existsSync(skillPath)) {
|
|
40
|
+
try {
|
|
41
|
+
const manifest = JSON.parse(readFileSync(manifestPath, 'utf8'));
|
|
42
|
+
skills.push({
|
|
43
|
+
name: manifest.name || dir.name,
|
|
44
|
+
description: manifest.description || 'No description',
|
|
45
|
+
category: manifest.category || 'general',
|
|
46
|
+
portability: manifest.portability || 100,
|
|
47
|
+
directory: dir.name,
|
|
48
|
+
});
|
|
49
|
+
} catch (e) {
|
|
50
|
+
// Skip invalid manifests
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
} catch (e) {
|
|
56
|
+
// Return empty array on error
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
return skills;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
/**
|
|
63
|
+
* Get installed skills in a project
|
|
64
|
+
*/
|
|
65
|
+
function getInstalledSkills(projectPath) {
|
|
66
|
+
const skillsDir = join(projectPath, '.claude', 'skills');
|
|
67
|
+
const installed = [];
|
|
68
|
+
|
|
69
|
+
try {
|
|
70
|
+
if (!existsSync(skillsDir)) {
|
|
71
|
+
return installed;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
const dirs = readdirSync(skillsDir, { withFileTypes: true });
|
|
75
|
+
|
|
76
|
+
for (const dir of dirs) {
|
|
77
|
+
if (dir.isDirectory()) {
|
|
78
|
+
const skillPath = join(skillsDir, dir.name, 'skill.md');
|
|
79
|
+
if (existsSync(skillPath)) {
|
|
80
|
+
installed.push(dir.name);
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
} catch (e) {
|
|
85
|
+
// Return empty array on error
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
return installed;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
/**
|
|
92
|
+
* Install a skill to the project
|
|
93
|
+
*/
|
|
94
|
+
function installSkill(skillName, projectPath) {
|
|
95
|
+
const sourcePath = join(SKILLS_DIR, skillName);
|
|
96
|
+
const targetPath = join(projectPath, '.claude', 'skills', skillName);
|
|
97
|
+
|
|
98
|
+
// Create target directory
|
|
99
|
+
mkdirSync(targetPath, { recursive: true });
|
|
100
|
+
|
|
101
|
+
// Copy all files recursively
|
|
102
|
+
cpSync(sourcePath, targetPath, { recursive: true });
|
|
103
|
+
|
|
104
|
+
return true;
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
/**
|
|
108
|
+
* Main install-skill command
|
|
109
|
+
*/
|
|
110
|
+
export async function installSkillCommand(options = {}) {
|
|
111
|
+
const projectPath = options.project || process.cwd();
|
|
112
|
+
|
|
113
|
+
showHeader();
|
|
114
|
+
|
|
115
|
+
console.log(chalk.cyan('\n Install Skills\n'));
|
|
116
|
+
|
|
117
|
+
// Check if .claude directory exists
|
|
118
|
+
const claudeDir = join(projectPath, '.claude');
|
|
119
|
+
if (!existsSync(claudeDir)) {
|
|
120
|
+
showError('No .claude directory found. Run `ccasp init` first.');
|
|
121
|
+
return;
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
// Get available and installed skills
|
|
125
|
+
const availableSkills = getAvailableSkills();
|
|
126
|
+
const installedSkills = getInstalledSkills(projectPath);
|
|
127
|
+
|
|
128
|
+
if (availableSkills.length === 0) {
|
|
129
|
+
showWarning('No skills available in the package.');
|
|
130
|
+
return;
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
// Show skill list
|
|
134
|
+
console.log(chalk.white(' Available Skills:\n'));
|
|
135
|
+
|
|
136
|
+
for (const skill of availableSkills) {
|
|
137
|
+
const installed = installedSkills.includes(skill.directory);
|
|
138
|
+
const status = installed ? chalk.green('✓ installed') : chalk.gray('not installed');
|
|
139
|
+
|
|
140
|
+
console.log(
|
|
141
|
+
` ${chalk.cyan(skill.name.padEnd(20))} ${status}`
|
|
142
|
+
);
|
|
143
|
+
console.log(
|
|
144
|
+
` ${chalk.gray(skill.description)}`
|
|
145
|
+
);
|
|
146
|
+
console.log();
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
// Filter to uninstalled skills
|
|
150
|
+
const uninstalledSkills = availableSkills.filter(
|
|
151
|
+
(s) => !installedSkills.includes(s.directory)
|
|
152
|
+
);
|
|
153
|
+
|
|
154
|
+
if (uninstalledSkills.length === 0) {
|
|
155
|
+
showSuccess('All available skills are already installed!');
|
|
156
|
+
return;
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
// Ask which skills to install
|
|
160
|
+
const { selectedSkills } = await inquirer.prompt([
|
|
161
|
+
{
|
|
162
|
+
type: 'checkbox',
|
|
163
|
+
name: 'selectedSkills',
|
|
164
|
+
message: 'Select skills to install:',
|
|
165
|
+
choices: uninstalledSkills.map((skill) => ({
|
|
166
|
+
name: `${skill.name} - ${skill.description}`,
|
|
167
|
+
value: skill.directory,
|
|
168
|
+
checked: false,
|
|
169
|
+
})),
|
|
170
|
+
},
|
|
171
|
+
]);
|
|
172
|
+
|
|
173
|
+
if (selectedSkills.length === 0) {
|
|
174
|
+
showInfo('No skills selected.');
|
|
175
|
+
return;
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
// Install selected skills
|
|
179
|
+
const spinner = ora('Installing skills...').start();
|
|
180
|
+
|
|
181
|
+
try {
|
|
182
|
+
for (const skillName of selectedSkills) {
|
|
183
|
+
spinner.text = `Installing ${skillName}...`;
|
|
184
|
+
installSkill(skillName, projectPath);
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
spinner.succeed(`Installed ${selectedSkills.length} skill(s)`);
|
|
188
|
+
|
|
189
|
+
console.log(chalk.green('\n ✓ Skills installed successfully!\n'));
|
|
190
|
+
|
|
191
|
+
console.log(chalk.yellow(' To use a skill, restart Claude Code CLI and use:'));
|
|
192
|
+
for (const skillName of selectedSkills) {
|
|
193
|
+
console.log(chalk.cyan(` skill: "${skillName}"`));
|
|
194
|
+
}
|
|
195
|
+
console.log();
|
|
196
|
+
} catch (error) {
|
|
197
|
+
spinner.fail('Installation failed');
|
|
198
|
+
showError(`Error: ${error.message}`);
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
/**
|
|
203
|
+
* List available skills (non-interactive)
|
|
204
|
+
*/
|
|
205
|
+
export function listSkills() {
|
|
206
|
+
const skills = getAvailableSkills();
|
|
207
|
+
|
|
208
|
+
console.log(chalk.cyan('\n Available CCASP Skills:\n'));
|
|
209
|
+
|
|
210
|
+
for (const skill of skills) {
|
|
211
|
+
console.log(` ${chalk.white(skill.name)}`);
|
|
212
|
+
console.log(` ${chalk.gray(skill.description)}`);
|
|
213
|
+
console.log(` Category: ${chalk.yellow(skill.category)} | Portability: ${chalk.green(skill.portability + '%')}`);
|
|
214
|
+
console.log();
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
return skills;
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
export default installSkillCommand;
|