@codihaus/claude-skills 1.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.
Files changed (46) hide show
  1. package/README.md +167 -0
  2. package/bin/cli.js +58 -0
  3. package/package.json +46 -0
  4. package/skills/_quality-attributes.md +392 -0
  5. package/skills/_registry.md +189 -0
  6. package/skills/debrief/SKILL.md +647 -0
  7. package/skills/debrief/references/change-request-template.md +124 -0
  8. package/skills/debrief/references/file-patterns.md +173 -0
  9. package/skills/debrief/references/group-codes.md +72 -0
  10. package/skills/debrief/references/research-queries.md +106 -0
  11. package/skills/debrief/references/use-case-template.md +141 -0
  12. package/skills/debrief/scripts/generate_questionnaire.py +195 -0
  13. package/skills/dev-arch/SKILL.md +747 -0
  14. package/skills/dev-changelog/SKILL.md +378 -0
  15. package/skills/dev-coding/SKILL.md +470 -0
  16. package/skills/dev-coding-backend/SKILL.md +361 -0
  17. package/skills/dev-coding-frontend/SKILL.md +534 -0
  18. package/skills/dev-coding-frontend/references/nextjs.md +477 -0
  19. package/skills/dev-review/SKILL.md +548 -0
  20. package/skills/dev-scout/SKILL.md +723 -0
  21. package/skills/dev-scout/references/feature-patterns.md +210 -0
  22. package/skills/dev-scout/references/file-patterns.md +252 -0
  23. package/skills/dev-scout/references/tech-detection.md +211 -0
  24. package/skills/dev-scout/scripts/scout-analyze.sh +280 -0
  25. package/skills/dev-specs/SKILL.md +577 -0
  26. package/skills/dev-specs/references/checklist.md +176 -0
  27. package/skills/dev-specs/references/spec-templates.md +460 -0
  28. package/skills/dev-test/SKILL.md +364 -0
  29. package/skills/utils/diagram/SKILL.md +205 -0
  30. package/skills/utils/diagram/references/common-errors.md +305 -0
  31. package/skills/utils/diagram/references/diagram-types.md +636 -0
  32. package/skills/utils/docs-graph/SKILL.md +204 -0
  33. package/skills/utils/gemini/SKILL.md +292 -0
  34. package/skills/utils/gemini/scripts/gemini-scan.py +340 -0
  35. package/skills/utils/gemini/scripts/setup.sh +169 -0
  36. package/src/commands/add.js +64 -0
  37. package/src/commands/doctor.js +179 -0
  38. package/src/commands/init.js +251 -0
  39. package/src/commands/list.js +88 -0
  40. package/src/commands/remove.js +60 -0
  41. package/src/commands/update.js +72 -0
  42. package/src/index.js +26 -0
  43. package/src/utils/config.js +272 -0
  44. package/src/utils/deps.js +599 -0
  45. package/src/utils/skills.js +253 -0
  46. package/templates/CLAUDE.md.template +58 -0
@@ -0,0 +1,179 @@
1
+ /**
2
+ * doctor command
3
+ *
4
+ * Check system dependencies and project setup.
5
+ */
6
+
7
+ import chalk from 'chalk';
8
+ import ora from 'ora';
9
+ import inquirer from 'inquirer';
10
+ import path from 'path';
11
+ import fs from 'fs-extra';
12
+
13
+ import {
14
+ checkGlobalDeps,
15
+ checkProjectDeps,
16
+ printDepsReport,
17
+ installProjectDeps
18
+ } from '../utils/deps.js';
19
+ import { getInstalledSkills } from '../utils/skills.js';
20
+
21
+ export async function doctor(options) {
22
+ const projectPath = process.cwd();
23
+
24
+ console.log(chalk.bold('\n🩺 Claude Skills Doctor\n'));
25
+ console.log(chalk.gray(`Checking: ${projectPath}\n`));
26
+
27
+ let hasIssues = false;
28
+
29
+ // 1. Check global dependencies
30
+ console.log(chalk.cyan('1. System Dependencies'));
31
+ console.log('─'.repeat(40));
32
+
33
+ const globalDeps = await checkGlobalDeps();
34
+ printDepsReport(globalDeps);
35
+
36
+ if (globalDeps.hasErrors) {
37
+ hasIssues = true;
38
+ console.log(chalk.red('āŒ Required dependencies missing'));
39
+ } else if (globalDeps.hasWarnings) {
40
+ console.log(chalk.yellow('āš ļø Some recommended dependencies missing'));
41
+ } else {
42
+ console.log(chalk.green('āœ… All system dependencies OK'));
43
+ }
44
+
45
+ // 2. Check .claude folder
46
+ console.log('\n' + chalk.cyan('2. Claude Code Setup'));
47
+ console.log('─'.repeat(40));
48
+
49
+ const claudePath = path.join(projectPath, '.claude');
50
+ const skillsPath = path.join(claudePath, 'skills');
51
+ const settingsPath = path.join(claudePath, 'settings.local.json');
52
+
53
+ const checks = [
54
+ {
55
+ name: '.claude folder',
56
+ path: claudePath,
57
+ exists: await fs.pathExists(claudePath)
58
+ },
59
+ {
60
+ name: '.claude/skills folder',
61
+ path: skillsPath,
62
+ exists: await fs.pathExists(skillsPath)
63
+ },
64
+ {
65
+ name: 'settings.local.json',
66
+ path: settingsPath,
67
+ exists: await fs.pathExists(settingsPath)
68
+ },
69
+ {
70
+ name: 'CLAUDE.md',
71
+ path: path.join(projectPath, 'CLAUDE.md'),
72
+ exists: await fs.pathExists(path.join(projectPath, 'CLAUDE.md'))
73
+ }
74
+ ];
75
+
76
+ for (const check of checks) {
77
+ const icon = check.exists ? chalk.green('āœ“') : chalk.red('āœ—');
78
+ console.log(` ${icon} ${check.name}`);
79
+ }
80
+
81
+ const missingSetup = checks.filter(c => !c.exists);
82
+ if (missingSetup.length > 0) {
83
+ hasIssues = true;
84
+ console.log(chalk.yellow('\n Run `claude-skills init` to set up missing items'));
85
+ }
86
+
87
+ // 3. Check installed skills
88
+ console.log('\n' + chalk.cyan('3. Installed Skills'));
89
+ console.log('─'.repeat(40));
90
+
91
+ const installed = await getInstalledSkills(projectPath);
92
+
93
+ if (installed.length === 0) {
94
+ console.log(chalk.yellow(' No skills installed'));
95
+ hasIssues = true;
96
+ } else {
97
+ const skillsOnly = installed.filter(s => s.type !== 'config');
98
+ console.log(` ${chalk.green('āœ“')} ${skillsOnly.length} skills installed`);
99
+
100
+ // Check for core skills
101
+ const coreSkills = ['debrief', 'dev-scout', 'dev-specs', 'dev-coding', 'dev-review'];
102
+ const installedNames = skillsOnly.map(s => s.name);
103
+ const missingCore = coreSkills.filter(s => !installedNames.includes(s));
104
+
105
+ if (missingCore.length > 0) {
106
+ console.log(chalk.yellow(` āš ļø Missing core skills: ${missingCore.join(', ')}`));
107
+ }
108
+ }
109
+
110
+ // 4. Check project dependencies
111
+ console.log('\n' + chalk.cyan('4. Project Dependencies'));
112
+ console.log('─'.repeat(40));
113
+
114
+ const projectDeps = await checkProjectDeps(projectPath);
115
+
116
+ if (projectDeps.noPackageJson) {
117
+ console.log(chalk.gray(' No package.json (not a Node.js project)'));
118
+ } else {
119
+ for (const dep of projectDeps.npm) {
120
+ const icon = dep.status === 'ok' ? chalk.green('āœ“') : chalk.yellow('ā—‹');
121
+ console.log(` ${icon} ${dep.name} - ${dep.purpose}`);
122
+ }
123
+
124
+ if (projectDeps.missing.length > 0 && options.fix) {
125
+ console.log('');
126
+ const { install } = await inquirer.prompt([{
127
+ type: 'confirm',
128
+ name: 'install',
129
+ message: 'Install missing dependencies?',
130
+ default: true
131
+ }]);
132
+
133
+ if (install) {
134
+ await installProjectDeps(projectPath, projectDeps.missing);
135
+ }
136
+ }
137
+ }
138
+
139
+ // 5. Check for common issues
140
+ console.log('\n' + chalk.cyan('5. Common Issues'));
141
+ console.log('─'.repeat(40));
142
+
143
+ // Check .gitignore
144
+ const gitignorePath = path.join(projectPath, '.gitignore');
145
+ if (await fs.pathExists(gitignorePath)) {
146
+ const content = await fs.readFile(gitignorePath, 'utf-8');
147
+ if (content.includes('settings.local.json')) {
148
+ console.log(` ${chalk.green('āœ“')} settings.local.json in .gitignore`);
149
+ } else {
150
+ console.log(` ${chalk.yellow('ā—‹')} settings.local.json not in .gitignore`);
151
+ }
152
+ }
153
+
154
+ // Check for .env
155
+ const envPath = path.join(projectPath, '.env');
156
+ if (await fs.pathExists(envPath)) {
157
+ const content = await fs.readFile(envPath, 'utf-8');
158
+ if (content.includes('GEMINI_API_KEY')) {
159
+ console.log(` ${chalk.green('āœ“')} GEMINI_API_KEY configured`);
160
+ } else {
161
+ console.log(` ${chalk.gray('ā—‹')} GEMINI_API_KEY not set (optional for large codebase scanning)`);
162
+ }
163
+ }
164
+
165
+ // Summary
166
+ console.log('\n' + '─'.repeat(40));
167
+
168
+ if (hasIssues) {
169
+ console.log(chalk.yellow('\nāš ļø Some issues found. See above for details.\n'));
170
+
171
+ if (options.fix) {
172
+ console.log(chalk.cyan('Attempted to fix issues where possible.'));
173
+ } else {
174
+ console.log(chalk.gray('Run `claude-skills doctor --fix` to attempt automatic fixes.\n'));
175
+ }
176
+ } else {
177
+ console.log(chalk.green('\nāœ… Everything looks good!\n'));
178
+ }
179
+ }
@@ -0,0 +1,251 @@
1
+ /**
2
+ * init command
3
+ *
4
+ * Initialize Claude Skills in a project.
5
+ */
6
+
7
+ import chalk from 'chalk';
8
+ import ora from 'ora';
9
+ import inquirer from 'inquirer';
10
+ import path from 'path';
11
+ import fs from 'fs-extra';
12
+
13
+ import {
14
+ checkGlobalDeps,
15
+ checkProjectDeps,
16
+ printDepsReport,
17
+ installProjectDeps,
18
+ installPythonDeps
19
+ } from '../utils/deps.js';
20
+ import {
21
+ getAvailableSkills,
22
+ getInstalledSkills,
23
+ copySkillsToProject
24
+ } from '../utils/skills.js';
25
+ import {
26
+ setupSettings,
27
+ setupHooks,
28
+ setupClaudeMd,
29
+ updateGitignore
30
+ } from '../utils/config.js';
31
+
32
+ export async function init(options) {
33
+ const projectPath = process.cwd();
34
+
35
+ console.log(chalk.bold('\nšŸš€ Claude Skills Initialization\n'));
36
+ console.log(chalk.gray(`Project: ${projectPath}\n`));
37
+
38
+ // Step 1: Check global dependencies
39
+ if (!options.noDeps) {
40
+ const spinner = ora('Checking system dependencies...').start();
41
+ const globalDeps = await checkGlobalDeps();
42
+ spinner.stop();
43
+
44
+ printDepsReport(globalDeps);
45
+
46
+ if (globalDeps.hasErrors) {
47
+ console.log(chalk.red('\nāŒ Required dependencies missing. Please install them first.\n'));
48
+ process.exit(1);
49
+ }
50
+
51
+ if (globalDeps.hasWarnings && !options.yes) {
52
+ const { proceed } = await inquirer.prompt([{
53
+ type: 'confirm',
54
+ name: 'proceed',
55
+ message: 'Some recommended dependencies are missing. Continue anyway?',
56
+ default: true
57
+ }]);
58
+
59
+ if (!proceed) {
60
+ console.log(chalk.yellow('Initialization cancelled.'));
61
+ process.exit(0);
62
+ }
63
+ }
64
+
65
+ // Offer to install missing Python packages
66
+ const missingPython = globalDeps.python?.filter(p => !p.installed) || [];
67
+ if (missingPython.length > 0 && !options.yes) {
68
+ const { installPython } = await inquirer.prompt([{
69
+ type: 'confirm',
70
+ name: 'installPython',
71
+ message: `Install missing Python packages (${missingPython.map(p => p.name).join(', ')})?`,
72
+ default: true
73
+ }]);
74
+
75
+ if (installPython) {
76
+ await installPythonDeps(missingPython);
77
+ }
78
+ }
79
+ }
80
+
81
+ // Step 2: Check if already initialized
82
+ const installed = await getInstalledSkills(projectPath);
83
+ if (installed.length > 0 && !options.yes) {
84
+ console.log(chalk.yellow(`\nāš ļø Skills already installed (${installed.length} found)`));
85
+
86
+ const { action } = await inquirer.prompt([{
87
+ type: 'list',
88
+ name: 'action',
89
+ message: 'What would you like to do?',
90
+ choices: [
91
+ { name: 'Update to latest version', value: 'update' },
92
+ { name: 'Reinstall (overwrite)', value: 'reinstall' },
93
+ { name: 'Cancel', value: 'cancel' }
94
+ ]
95
+ }]);
96
+
97
+ if (action === 'cancel') {
98
+ console.log(chalk.yellow('Initialization cancelled.'));
99
+ process.exit(0);
100
+ }
101
+
102
+ if (action === 'update') {
103
+ // TODO: Implement update logic
104
+ console.log(chalk.cyan('Updating skills...'));
105
+ }
106
+ }
107
+
108
+ // Step 3: Select skills to install
109
+ const available = await getAvailableSkills();
110
+ const skillsOnly = available.filter(s => s.type !== 'config');
111
+
112
+ let skillsToInstall = null; // null means all
113
+
114
+ if (options.skills) {
115
+ skillsToInstall = options.skills.split(',').map(s => s.trim());
116
+ console.log(chalk.cyan(`\nInstalling selected skills: ${skillsToInstall.join(', ')}`));
117
+ } else if (!options.all && !options.yes) {
118
+ const { selectSkills } = await inquirer.prompt([{
119
+ type: 'confirm',
120
+ name: 'selectSkills',
121
+ message: 'Install all skills? (No to select specific ones)',
122
+ default: true
123
+ }]);
124
+
125
+ if (!selectSkills) {
126
+ const { selected } = await inquirer.prompt([{
127
+ type: 'checkbox',
128
+ name: 'selected',
129
+ message: 'Select skills to install:',
130
+ choices: skillsOnly.map(s => ({
131
+ name: `${s.name} - ${s.description || 'No description'}`,
132
+ value: s.name,
133
+ checked: true
134
+ }))
135
+ }]);
136
+
137
+ skillsToInstall = selected;
138
+ }
139
+ }
140
+
141
+ // Step 4: Copy skills
142
+ const spinner = ora('Installing skills...').start();
143
+
144
+ try {
145
+ const { copied, errors } = await copySkillsToProject(projectPath, skillsToInstall);
146
+
147
+ if (errors.length > 0) {
148
+ spinner.warn(`Installed ${copied.length} skills with ${errors.length} errors`);
149
+ for (const err of errors) {
150
+ console.log(chalk.red(` āœ— ${err.name}: ${err.error}`));
151
+ }
152
+ } else {
153
+ spinner.succeed(`Installed ${copied.length} skills`);
154
+ }
155
+ } catch (e) {
156
+ spinner.fail('Failed to install skills');
157
+ console.error(chalk.red(e.message));
158
+ process.exit(1);
159
+ }
160
+
161
+ // Step 5: Set up settings
162
+ const settingsSpinner = ora('Setting up Claude Code configuration...').start();
163
+
164
+ try {
165
+ await setupSettings(projectPath);
166
+ settingsSpinner.succeed('Claude Code settings configured');
167
+ } catch (e) {
168
+ settingsSpinner.warn('Failed to set up settings');
169
+ }
170
+
171
+ // Step 6: Set up hooks
172
+ if (!options.noHooks) {
173
+ const hooksSpinner = ora('Setting up hooks...').start();
174
+
175
+ try {
176
+ const result = await setupHooks(projectPath);
177
+ if (result) {
178
+ hooksSpinner.succeed('Hooks configured');
179
+ } else {
180
+ hooksSpinner.info('Hooks skipped');
181
+ }
182
+ } catch (e) {
183
+ hooksSpinner.warn('Failed to set up hooks');
184
+ }
185
+ }
186
+
187
+ // Step 7: Set up CLAUDE.md
188
+ const claudeSpinner = ora('Setting up CLAUDE.md...').start();
189
+
190
+ try {
191
+ const result = await setupClaudeMd(projectPath);
192
+ claudeSpinner.succeed(`CLAUDE.md ${result.action}`);
193
+ } catch (e) {
194
+ claudeSpinner.warn('Failed to set up CLAUDE.md');
195
+ }
196
+
197
+ // Step 8: Update .gitignore
198
+ const gitSpinner = ora('Updating .gitignore...').start();
199
+
200
+ try {
201
+ const result = await updateGitignore(projectPath);
202
+ gitSpinner.succeed(`.gitignore ${result.action}`);
203
+ } catch (e) {
204
+ gitSpinner.warn('Failed to update .gitignore');
205
+ }
206
+
207
+ // Step 9: Check project dependencies
208
+ if (!options.noDeps) {
209
+ console.log('');
210
+ const projectSpinner = ora('Checking project dependencies...').start();
211
+ const projectDeps = await checkProjectDeps(projectPath);
212
+ projectSpinner.stop();
213
+
214
+ if (projectDeps.missing.length > 0) {
215
+ console.log(chalk.yellow('\nāš ļø Some optional dependencies are missing:\n'));
216
+
217
+ for (const dep of projectDeps.missing) {
218
+ const cmd = dep.type === 'pip'
219
+ ? chalk.cyan(`pip install ${dep.name}`)
220
+ : chalk.cyan(`npm install -D ${dep.name}`);
221
+ console.log(` ${dep.name} - ${dep.purpose}`);
222
+ console.log(` ${cmd}\n`);
223
+ }
224
+
225
+ if (!options.yes) {
226
+ const { install } = await inquirer.prompt([{
227
+ type: 'confirm',
228
+ name: 'install',
229
+ message: 'Install missing dependencies now?',
230
+ default: false
231
+ }]);
232
+
233
+ if (install) {
234
+ await installProjectDeps(projectPath, projectDeps.missing);
235
+ }
236
+ }
237
+ }
238
+ }
239
+
240
+ // Done!
241
+ console.log(chalk.green('\nāœ… Claude Skills initialized successfully!\n'));
242
+
243
+ console.log(chalk.bold('Next steps:'));
244
+ console.log('');
245
+ console.log(' 1. Start Claude Code in this project');
246
+ console.log(' 2. Try a skill: ' + chalk.cyan('/debrief "your project idea"'));
247
+ console.log(' 3. See all skills: ' + chalk.cyan('/help'));
248
+ console.log('');
249
+ console.log(chalk.gray('Docs: .claude/skills/_registry.md'));
250
+ console.log('');
251
+ }
@@ -0,0 +1,88 @@
1
+ /**
2
+ * list command
3
+ *
4
+ * List available and installed skills.
5
+ */
6
+
7
+ import chalk from 'chalk';
8
+
9
+ import { getAvailableSkills, getInstalledSkills } from '../utils/skills.js';
10
+
11
+ export async function list(options) {
12
+ const projectPath = process.cwd();
13
+
14
+ console.log(chalk.bold('\nšŸ“‹ Claude Skills\n'));
15
+
16
+ const available = await getAvailableSkills();
17
+ const installed = await getInstalledSkills(projectPath);
18
+
19
+ const installedNames = new Set(installed.map(s => s.name));
20
+
21
+ if (options.installed) {
22
+ // Show only installed
23
+ console.log(chalk.cyan('Installed Skills:\n'));
24
+
25
+ if (installed.length === 0) {
26
+ console.log(chalk.gray(' No skills installed. Run `claude-skills init` to install.\n'));
27
+ return;
28
+ }
29
+
30
+ for (const skill of installed) {
31
+ if (skill.type === 'config') continue;
32
+
33
+ console.log(` ${chalk.green('ā—')} ${skill.name}`);
34
+ console.log(chalk.gray(` v${skill.version || 'unknown'} - ${skill.description || ''}`));
35
+ }
36
+ } else {
37
+ // Show all available with install status
38
+ console.log(chalk.cyan('Available Skills:\n'));
39
+
40
+ // Group by category
41
+ const mainSkills = available.filter(s => !s.category && s.type !== 'config');
42
+ const utilSkills = available.filter(s => s.category === 'utils');
43
+ const configFiles = available.filter(s => s.type === 'config');
44
+
45
+ // Main skills
46
+ console.log(chalk.bold(' Main Skills:'));
47
+ for (const skill of mainSkills) {
48
+ const isInstalled = installedNames.has(skill.name);
49
+ const icon = isInstalled ? chalk.green('ā—') : chalk.gray('ā—‹');
50
+ const status = isInstalled ? chalk.green(' (installed)') : '';
51
+
52
+ console.log(` ${icon} /${skill.name}${status}`);
53
+ console.log(chalk.gray(` v${skill.version || '?'} - ${skill.description || ''}`));
54
+ }
55
+
56
+ // Utility skills
57
+ if (utilSkills.length > 0) {
58
+ console.log('');
59
+ console.log(chalk.bold(' Utility Skills:'));
60
+ for (const skill of utilSkills) {
61
+ const isInstalled = installedNames.has(skill.name);
62
+ const icon = isInstalled ? chalk.green('ā—') : chalk.gray('ā—‹');
63
+ const status = isInstalled ? chalk.green(' (installed)') : '';
64
+
65
+ console.log(` ${icon} /${skill.name}${status}`);
66
+ console.log(chalk.gray(` v${skill.version || '?'} - ${skill.description || ''}`));
67
+ }
68
+ }
69
+
70
+ // Config files
71
+ console.log('');
72
+ console.log(chalk.bold(' Config Files:'));
73
+ for (const file of configFiles) {
74
+ const isInstalled = installedNames.has(file.name);
75
+ const icon = isInstalled ? chalk.green('ā—') : chalk.gray('ā—‹');
76
+ console.log(` ${icon} ${file.name}`);
77
+ }
78
+ }
79
+
80
+ console.log('');
81
+
82
+ // Summary
83
+ const skillCount = available.filter(s => s.type !== 'config').length;
84
+ const installedCount = installed.filter(s => s.type !== 'config').length;
85
+
86
+ console.log(chalk.gray(`${installedCount}/${skillCount} skills installed`));
87
+ console.log('');
88
+ }
@@ -0,0 +1,60 @@
1
+ /**
2
+ * remove command
3
+ *
4
+ * Remove a skill from the project.
5
+ */
6
+
7
+ import chalk from 'chalk';
8
+ import ora from 'ora';
9
+ import inquirer from 'inquirer';
10
+
11
+ import { getInstalledSkills, removeSkillFromProject } from '../utils/skills.js';
12
+
13
+ export async function remove(skillName) {
14
+ const projectPath = process.cwd();
15
+
16
+ console.log(chalk.bold(`\nāž– Removing skill: ${skillName}\n`));
17
+
18
+ // Check if skill is installed
19
+ const installed = await getInstalledSkills(projectPath);
20
+ const skill = installed.find(s => s.name === skillName);
21
+
22
+ if (!skill) {
23
+ console.log(chalk.yellow(`āš ļø Skill not installed: ${skillName}\n`));
24
+ process.exit(0);
25
+ }
26
+
27
+ // Confirm removal
28
+ const { confirm } = await inquirer.prompt([{
29
+ type: 'confirm',
30
+ name: 'confirm',
31
+ message: `Remove ${skillName}?`,
32
+ default: false
33
+ }]);
34
+
35
+ if (!confirm) {
36
+ console.log(chalk.yellow('Removal cancelled.\n'));
37
+ process.exit(0);
38
+ }
39
+
40
+ // Remove the skill
41
+ const spinner = ora(`Removing ${skillName}...`).start();
42
+
43
+ try {
44
+ const result = await removeSkillFromProject(projectPath, skillName);
45
+
46
+ if (!result.success) {
47
+ spinner.fail(`Failed to remove ${skillName}`);
48
+ console.log(chalk.red(result.error));
49
+ process.exit(1);
50
+ }
51
+
52
+ spinner.succeed(`Removed ${skillName}`);
53
+ } catch (e) {
54
+ spinner.fail('Removal failed');
55
+ console.error(chalk.red(e.message));
56
+ process.exit(1);
57
+ }
58
+
59
+ console.log(chalk.green(`\nāœ… ${skillName} removed.\n`));
60
+ }
@@ -0,0 +1,72 @@
1
+ /**
2
+ * update command
3
+ *
4
+ * Update installed skills to latest version.
5
+ */
6
+
7
+ import chalk from 'chalk';
8
+ import ora from 'ora';
9
+
10
+ import { checkForUpdates, copySkillsToProject, getInstalledSkills } from '../utils/skills.js';
11
+
12
+ export async function update(options) {
13
+ const projectPath = process.cwd();
14
+
15
+ console.log(chalk.bold('\nšŸ“¦ Claude Skills Update\n'));
16
+
17
+ // Check for installed skills
18
+ const installed = await getInstalledSkills(projectPath);
19
+
20
+ if (installed.length === 0) {
21
+ console.log(chalk.yellow('No skills installed. Run `claude-skills init` first.\n'));
22
+ process.exit(0);
23
+ }
24
+
25
+ console.log(chalk.gray(`Found ${installed.length} installed skills\n`));
26
+
27
+ // Check for updates
28
+ const spinner = ora('Checking for updates...').start();
29
+ const updates = await checkForUpdates(projectPath);
30
+ spinner.stop();
31
+
32
+ if (updates.length === 0) {
33
+ console.log(chalk.green('āœ… All skills are up to date!\n'));
34
+ process.exit(0);
35
+ }
36
+
37
+ console.log(chalk.cyan(`Found ${updates.length} update(s) available:\n`));
38
+
39
+ for (const update of updates) {
40
+ console.log(` ${update.name}`);
41
+ console.log(chalk.gray(` ${update.current} → ${update.available}`));
42
+ console.log('');
43
+ }
44
+
45
+ if (options.check) {
46
+ console.log(chalk.gray('Run `claude-skills update` to install updates.\n'));
47
+ process.exit(0);
48
+ }
49
+
50
+ // Apply updates
51
+ const updateSpinner = ora('Updating skills...').start();
52
+
53
+ try {
54
+ const skillNames = updates.map(u => u.name);
55
+ const { copied, errors } = await copySkillsToProject(projectPath, skillNames);
56
+
57
+ if (errors.length > 0) {
58
+ updateSpinner.warn(`Updated ${copied.length} skills with ${errors.length} errors`);
59
+ for (const err of errors) {
60
+ console.log(chalk.red(` āœ— ${err.name}: ${err.error}`));
61
+ }
62
+ } else {
63
+ updateSpinner.succeed(`Updated ${copied.length} skills`);
64
+ }
65
+ } catch (e) {
66
+ updateSpinner.fail('Update failed');
67
+ console.error(chalk.red(e.message));
68
+ process.exit(1);
69
+ }
70
+
71
+ console.log(chalk.green('\nāœ… Update complete!\n'));
72
+ }
package/src/index.js ADDED
@@ -0,0 +1,26 @@
1
+ /**
2
+ * Claude Skills
3
+ *
4
+ * Programmatic API for managing Claude Code skills.
5
+ */
6
+
7
+ export {
8
+ checkGlobalDeps,
9
+ checkProjectDeps,
10
+ installProjectDeps
11
+ } from './utils/deps.js';
12
+
13
+ export {
14
+ getAvailableSkills,
15
+ getInstalledSkills,
16
+ copySkillsToProject,
17
+ removeSkillFromProject,
18
+ checkForUpdates
19
+ } from './utils/skills.js';
20
+
21
+ export {
22
+ setupSettings,
23
+ setupHooks,
24
+ setupClaudeMd,
25
+ updateGitignore
26
+ } from './utils/config.js';