@paulduvall/claude-dev-toolkit 0.0.1-alpha.1
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 +254 -0
- package/bin/claude-commands +132 -0
- package/lib/claude-code-compatibility.js +545 -0
- package/lib/command-selector.js +245 -0
- package/lib/config.js +182 -0
- package/lib/context-utils.js +80 -0
- package/lib/dependency-validator.js +354 -0
- package/lib/error-factory.js +394 -0
- package/lib/error-handler-utils.js +432 -0
- package/lib/error-recovery-system.js +563 -0
- package/lib/failure-recovery-installer.js +370 -0
- package/lib/hook-installer-core.js +330 -0
- package/lib/hook-installer.js +187 -0
- package/lib/hook-metadata-service.js +352 -0
- package/lib/hook-validator.js +358 -0
- package/lib/installation-configuration.js +380 -0
- package/lib/installation-instruction-generator.js +564 -0
- package/lib/installer.js +68 -0
- package/lib/package-manager-service.js +270 -0
- package/lib/permission-error-handler.js +543 -0
- package/lib/platform-utils.js +491 -0
- package/lib/setup-wizard-ui.js +245 -0
- package/lib/setup-wizard.js +355 -0
- package/lib/system-requirements-checker.js +558 -0
- package/lib/utils.js +15 -0
- package/lib/validation-utils.js +320 -0
- package/lib/version-validator-service.js +326 -0
- package/package.json +73 -0
- package/scripts/postinstall.js +182 -0
- package/scripts/validate.js +94 -0
|
@@ -0,0 +1,564 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Installation Instruction Generator
|
|
3
|
+
*
|
|
4
|
+
* Generates platform-specific installation instructions and recovery guidance.
|
|
5
|
+
* Extracted from DependencyValidator as part of Phase 1 bloater refactoring.
|
|
6
|
+
*
|
|
7
|
+
* Features:
|
|
8
|
+
* - Cross-platform installation instructions
|
|
9
|
+
* - Package manager integration
|
|
10
|
+
* - Download link management
|
|
11
|
+
* - Alternative installation methods
|
|
12
|
+
* - Recovery and troubleshooting guidance
|
|
13
|
+
*/
|
|
14
|
+
|
|
15
|
+
const PackageManagerService = require('./package-manager-service');
|
|
16
|
+
const PlatformUtils = require('./platform-utils');
|
|
17
|
+
|
|
18
|
+
class InstallationInstructionGenerator {
|
|
19
|
+
constructor() {
|
|
20
|
+
this.packageManagerService = new PackageManagerService();
|
|
21
|
+
this.platformUtils = new PlatformUtils();
|
|
22
|
+
this.config = {
|
|
23
|
+
downloadLinks: this._createDownloadLinks()
|
|
24
|
+
};
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* Create download links for common tools
|
|
29
|
+
* @returns {Object} Download links by tool and platform
|
|
30
|
+
* @private
|
|
31
|
+
*/
|
|
32
|
+
_createDownloadLinks() {
|
|
33
|
+
return {
|
|
34
|
+
git: {
|
|
35
|
+
linux: 'https://git-scm.com/download/linux',
|
|
36
|
+
darwin: 'https://git-scm.com/download/mac',
|
|
37
|
+
win32: 'https://git-scm.com/download/win'
|
|
38
|
+
},
|
|
39
|
+
node: {
|
|
40
|
+
all: 'https://nodejs.org/en/download/'
|
|
41
|
+
},
|
|
42
|
+
python: {
|
|
43
|
+
all: 'https://www.python.org/downloads/'
|
|
44
|
+
},
|
|
45
|
+
docker: {
|
|
46
|
+
linux: 'https://docs.docker.com/engine/install/',
|
|
47
|
+
darwin: 'https://docs.docker.com/desktop/install/mac-install/',
|
|
48
|
+
win32: 'https://docs.docker.com/desktop/install/windows-install/'
|
|
49
|
+
}
|
|
50
|
+
};
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
/**
|
|
54
|
+
* Generate installation instructions for missing dependency
|
|
55
|
+
* @param {Object} dependency - Missing dependency
|
|
56
|
+
* @param {string} platform - Target platform (optional)
|
|
57
|
+
* @returns {Object} Installation instructions
|
|
58
|
+
*/
|
|
59
|
+
generateInstallationInstructions(dependency, platform = process.platform) {
|
|
60
|
+
const context = this._createInstructionContext(dependency, platform);
|
|
61
|
+
const instructions = this._initializeInstructions(platform);
|
|
62
|
+
|
|
63
|
+
this._addPlatformPackageManagers(instructions, context);
|
|
64
|
+
this._setDefaultPackageManager(instructions);
|
|
65
|
+
this._handleNpmPackageSpecific(instructions, context);
|
|
66
|
+
this._addAlternativeInstallationMethods(instructions, dependency, platform);
|
|
67
|
+
|
|
68
|
+
return instructions;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
/**
|
|
72
|
+
* Generate recovery suggestions for failed dependencies
|
|
73
|
+
* @param {Object} failedDependency - Dependency that failed validation
|
|
74
|
+
* @returns {Object} Recovery suggestions
|
|
75
|
+
*/
|
|
76
|
+
generateRecoverySuggestions(failedDependency) {
|
|
77
|
+
const suggestions = {
|
|
78
|
+
immediate: [],
|
|
79
|
+
alternative: [],
|
|
80
|
+
troubleshooting: []
|
|
81
|
+
};
|
|
82
|
+
|
|
83
|
+
if (failedDependency.error) {
|
|
84
|
+
switch (failedDependency.error.code) {
|
|
85
|
+
case 'NOT_FOUND':
|
|
86
|
+
suggestions.immediate.push(`Try: Install ${failedDependency.name} using your package manager`);
|
|
87
|
+
suggestions.immediate.push(`Solution: Add ${failedDependency.name} to your system PATH`);
|
|
88
|
+
suggestions.alternative.push(`Use portable version of ${failedDependency.name}`);
|
|
89
|
+
suggestions.alternative.push(`Install via different package manager`);
|
|
90
|
+
break;
|
|
91
|
+
|
|
92
|
+
case 'VERSION_MISMATCH':
|
|
93
|
+
suggestions.immediate.push(`Try: Update ${failedDependency.name} to newer version`);
|
|
94
|
+
suggestions.immediate.push(`Solution: Use version manager to install required version`);
|
|
95
|
+
suggestions.alternative.push(`Install specific version manually`);
|
|
96
|
+
break;
|
|
97
|
+
|
|
98
|
+
default:
|
|
99
|
+
suggestions.immediate.push(`Try: Reinstall ${failedDependency.name}`);
|
|
100
|
+
suggestions.immediate.push(`Solution: Check system configuration`);
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
// Add general troubleshooting guidance
|
|
105
|
+
suggestions.troubleshooting = [
|
|
106
|
+
'Next steps for troubleshooting: Check system logs and package manager status',
|
|
107
|
+
'Verify internet connectivity for downloads',
|
|
108
|
+
'Try running commands with elevated privileges',
|
|
109
|
+
'Check for conflicting software installations'
|
|
110
|
+
];
|
|
111
|
+
|
|
112
|
+
return suggestions;
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
/**
|
|
116
|
+
* Generate installation instructions for multiple dependencies
|
|
117
|
+
* @param {Array} dependencies - List of dependencies to install
|
|
118
|
+
* @param {string} platform - Target platform
|
|
119
|
+
* @returns {Object} Batch installation instructions
|
|
120
|
+
*/
|
|
121
|
+
generateBatchInstallationInstructions(dependencies, platform = process.platform) {
|
|
122
|
+
const batchInstructions = {
|
|
123
|
+
platform: platform,
|
|
124
|
+
dependencies: dependencies.map(dep => dep.name),
|
|
125
|
+
packageManagerOptions: [],
|
|
126
|
+
bulkCommands: [],
|
|
127
|
+
individualInstructions: []
|
|
128
|
+
};
|
|
129
|
+
|
|
130
|
+
// Generate individual instructions
|
|
131
|
+
for (const dependency of dependencies) {
|
|
132
|
+
const individualInstructions = this.generateInstallationInstructions(dependency, platform);
|
|
133
|
+
batchInstructions.individualInstructions.push({
|
|
134
|
+
dependency: dependency.name,
|
|
135
|
+
instructions: individualInstructions
|
|
136
|
+
});
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
// Generate bulk installation commands
|
|
140
|
+
const packageManagers = this.packageManagerService.getPackageManagersForPlatform(platform);
|
|
141
|
+
for (const pm of packageManagers) {
|
|
142
|
+
const packages = dependencies.map(dep =>
|
|
143
|
+
this.packageManagerService.getPackageName(dep.name, pm.name, platform)
|
|
144
|
+
);
|
|
145
|
+
|
|
146
|
+
if (packages.length > 0) {
|
|
147
|
+
const bulkCommand = this._generateBulkInstallCommand(pm, packages);
|
|
148
|
+
batchInstructions.bulkCommands.push({
|
|
149
|
+
packageManager: pm.name,
|
|
150
|
+
command: bulkCommand,
|
|
151
|
+
packages: packages
|
|
152
|
+
});
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
return batchInstructions;
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
/**
|
|
160
|
+
* Generate upgrade instructions for outdated dependencies
|
|
161
|
+
* @param {Object} dependency - Dependency to upgrade
|
|
162
|
+
* @param {string} currentVersion - Current version
|
|
163
|
+
* @param {string} targetVersion - Target version
|
|
164
|
+
* @param {string} platform - Target platform
|
|
165
|
+
* @returns {Object} Upgrade instructions
|
|
166
|
+
*/
|
|
167
|
+
generateUpgradeInstructions(dependency, currentVersion, targetVersion, platform = process.platform) {
|
|
168
|
+
const upgradeInstructions = {
|
|
169
|
+
dependency: dependency.name,
|
|
170
|
+
currentVersion: currentVersion,
|
|
171
|
+
targetVersion: targetVersion,
|
|
172
|
+
platform: platform,
|
|
173
|
+
upgradeSteps: [],
|
|
174
|
+
verificationSteps: [],
|
|
175
|
+
backupRecommendations: [],
|
|
176
|
+
troubleshootingTips: []
|
|
177
|
+
};
|
|
178
|
+
|
|
179
|
+
// Add backup recommendations
|
|
180
|
+
upgradeInstructions.backupRecommendations = [
|
|
181
|
+
`Backup current ${dependency.name} configuration if applicable`,
|
|
182
|
+
'Document current working setup before upgrading',
|
|
183
|
+
'Ensure you can rollback if needed'
|
|
184
|
+
];
|
|
185
|
+
|
|
186
|
+
// Generate upgrade commands
|
|
187
|
+
const packageManagers = this.packageManagerService.getAvailablePackageManagers(platform);
|
|
188
|
+
for (const pm of packageManagers) {
|
|
189
|
+
const upgradeCommand = this._generateUpgradeCommand(pm, dependency.name, platform);
|
|
190
|
+
if (upgradeCommand) {
|
|
191
|
+
upgradeInstructions.upgradeSteps.push({
|
|
192
|
+
packageManager: pm.name,
|
|
193
|
+
command: upgradeCommand,
|
|
194
|
+
description: `Upgrade ${dependency.name} using ${pm.name}`
|
|
195
|
+
});
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
// Add verification steps
|
|
200
|
+
upgradeInstructions.verificationSteps = [
|
|
201
|
+
`Run: ${dependency.name} --version`,
|
|
202
|
+
`Verify version shows ${targetVersion} or higher`,
|
|
203
|
+
'Test basic functionality to ensure upgrade was successful'
|
|
204
|
+
];
|
|
205
|
+
|
|
206
|
+
// Add troubleshooting tips
|
|
207
|
+
upgradeInstructions.troubleshootingTips = [
|
|
208
|
+
'Clear package manager cache if upgrade fails',
|
|
209
|
+
'Check for dependency conflicts',
|
|
210
|
+
'Restart terminal/shell after upgrade',
|
|
211
|
+
'Verify PATH environment variable is correct'
|
|
212
|
+
];
|
|
213
|
+
|
|
214
|
+
return upgradeInstructions;
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
/**
|
|
218
|
+
* Generate platform-specific installation guidance
|
|
219
|
+
* @param {string} platform - Target platform
|
|
220
|
+
* @returns {Object} Platform-specific guidance
|
|
221
|
+
*/
|
|
222
|
+
generatePlatformGuidance(platform) {
|
|
223
|
+
const guidance = {
|
|
224
|
+
platform: platform,
|
|
225
|
+
platformName: this.platformUtils.getPlatformName(platform),
|
|
226
|
+
packageManagers: [],
|
|
227
|
+
commonIssues: [],
|
|
228
|
+
bestPractices: [],
|
|
229
|
+
systemRequirements: {}
|
|
230
|
+
};
|
|
231
|
+
|
|
232
|
+
// Get package managers for platform
|
|
233
|
+
guidance.packageManagers = this.packageManagerService.getPackageManagersForPlatform(platform)
|
|
234
|
+
.map(pm => ({
|
|
235
|
+
name: pm.name,
|
|
236
|
+
description: this._getPackageManagerDescription(pm.name),
|
|
237
|
+
installationUrl: this._getPackageManagerInstallUrl(pm.name, platform)
|
|
238
|
+
}));
|
|
239
|
+
|
|
240
|
+
// Platform-specific guidance
|
|
241
|
+
switch (platform) {
|
|
242
|
+
case 'win32':
|
|
243
|
+
guidance.commonIssues = [
|
|
244
|
+
'PATH environment variable not updated',
|
|
245
|
+
'PowerShell execution policy restrictions',
|
|
246
|
+
'Windows Defender blocking downloads',
|
|
247
|
+
'Missing Visual C++ redistributables'
|
|
248
|
+
];
|
|
249
|
+
guidance.bestPractices = [
|
|
250
|
+
'Run commands as Administrator when necessary',
|
|
251
|
+
'Use PowerShell instead of Command Prompt',
|
|
252
|
+
'Install package manager first (Chocolatey, Winget)',
|
|
253
|
+
'Check Windows version compatibility'
|
|
254
|
+
];
|
|
255
|
+
break;
|
|
256
|
+
|
|
257
|
+
case 'darwin':
|
|
258
|
+
guidance.commonIssues = [
|
|
259
|
+
'Xcode Command Line Tools missing',
|
|
260
|
+
'System Integrity Protection (SIP) restrictions',
|
|
261
|
+
'Homebrew not installed or outdated',
|
|
262
|
+
'Architecture mismatch (Intel vs Apple Silicon)'
|
|
263
|
+
];
|
|
264
|
+
guidance.bestPractices = [
|
|
265
|
+
'Install Xcode Command Line Tools first',
|
|
266
|
+
'Use Homebrew for package management',
|
|
267
|
+
'Check architecture compatibility (x86_64 vs arm64)',
|
|
268
|
+
'Update shell profile (.zshrc) for PATH changes'
|
|
269
|
+
];
|
|
270
|
+
break;
|
|
271
|
+
|
|
272
|
+
case 'linux':
|
|
273
|
+
guidance.commonIssues = [
|
|
274
|
+
'Missing package repositories',
|
|
275
|
+
'Insufficient permissions',
|
|
276
|
+
'Outdated package lists',
|
|
277
|
+
'Missing dependencies'
|
|
278
|
+
];
|
|
279
|
+
guidance.bestPractices = [
|
|
280
|
+
'Update package lists before installing',
|
|
281
|
+
'Use distribution-specific package manager',
|
|
282
|
+
'Install development tools if compiling from source',
|
|
283
|
+
'Check distribution version compatibility'
|
|
284
|
+
];
|
|
285
|
+
break;
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
return guidance;
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
/**
|
|
292
|
+
* Create instruction generation context
|
|
293
|
+
* @param {Object} dependency - Dependency information
|
|
294
|
+
* @param {string} platform - Target platform
|
|
295
|
+
* @returns {Object} Instruction context
|
|
296
|
+
* @private
|
|
297
|
+
*/
|
|
298
|
+
_createInstructionContext(dependency, platform) {
|
|
299
|
+
return {
|
|
300
|
+
dependency,
|
|
301
|
+
platform,
|
|
302
|
+
platformManagers: this.packageManagerService.getPackageManagersForPlatform(platform),
|
|
303
|
+
dependencyMapping: this.packageManagerService.config.dependencyMappings[dependency.name]
|
|
304
|
+
};
|
|
305
|
+
}
|
|
306
|
+
|
|
307
|
+
/**
|
|
308
|
+
* Initialize empty instructions object
|
|
309
|
+
* @param {string} platform - Target platform
|
|
310
|
+
* @returns {Object} Empty instructions object
|
|
311
|
+
* @private
|
|
312
|
+
*/
|
|
313
|
+
_initializeInstructions(platform) {
|
|
314
|
+
return {
|
|
315
|
+
platform: platform,
|
|
316
|
+
packageManager: null,
|
|
317
|
+
commands: [],
|
|
318
|
+
packageManagerOptions: [],
|
|
319
|
+
globalInstall: null,
|
|
320
|
+
localInstall: null,
|
|
321
|
+
alternativeOptions: []
|
|
322
|
+
};
|
|
323
|
+
}
|
|
324
|
+
|
|
325
|
+
/**
|
|
326
|
+
* Add platform-specific package managers to instructions
|
|
327
|
+
* @param {Object} instructions - Instructions object to modify
|
|
328
|
+
* @param {Object} context - Instruction context
|
|
329
|
+
* @private
|
|
330
|
+
*/
|
|
331
|
+
_addPlatformPackageManagers(instructions, context) {
|
|
332
|
+
for (const pm of context.platformManagers) {
|
|
333
|
+
const packageName = this._resolvePackageName(pm, context);
|
|
334
|
+
const packageManagerOption = this._createPackageManagerOption(pm, packageName);
|
|
335
|
+
instructions.packageManagerOptions.push(packageManagerOption);
|
|
336
|
+
}
|
|
337
|
+
}
|
|
338
|
+
|
|
339
|
+
/**
|
|
340
|
+
* Resolve package name for specific package manager
|
|
341
|
+
* @param {Object} pm - Package manager configuration
|
|
342
|
+
* @param {Object} context - Instruction context
|
|
343
|
+
* @returns {string} Resolved package name
|
|
344
|
+
* @private
|
|
345
|
+
*/
|
|
346
|
+
_resolvePackageName(pm, context) {
|
|
347
|
+
const { dependency, platform, dependencyMapping } = context;
|
|
348
|
+
|
|
349
|
+
if (dependencyMapping && dependencyMapping[platform] && dependencyMapping[platform][pm.name]) {
|
|
350
|
+
return dependencyMapping[platform][pm.name];
|
|
351
|
+
}
|
|
352
|
+
|
|
353
|
+
return dependency.name;
|
|
354
|
+
}
|
|
355
|
+
|
|
356
|
+
/**
|
|
357
|
+
* Create package manager option object
|
|
358
|
+
* @param {Object} pm - Package manager configuration
|
|
359
|
+
* @param {string} packageName - Resolved package name
|
|
360
|
+
* @returns {Object} Package manager option
|
|
361
|
+
* @private
|
|
362
|
+
*/
|
|
363
|
+
_createPackageManagerOption(pm, packageName) {
|
|
364
|
+
return {
|
|
365
|
+
name: pm.name,
|
|
366
|
+
command: pm.install.replace('{package}', packageName),
|
|
367
|
+
check: pm.check.replace('{package}', packageName),
|
|
368
|
+
packageName: packageName
|
|
369
|
+
};
|
|
370
|
+
}
|
|
371
|
+
|
|
372
|
+
/**
|
|
373
|
+
* Set default package manager from available options
|
|
374
|
+
* @param {Object} instructions - Instructions object to modify
|
|
375
|
+
* @private
|
|
376
|
+
*/
|
|
377
|
+
_setDefaultPackageManager(instructions) {
|
|
378
|
+
if (instructions.packageManagerOptions.length > 0) {
|
|
379
|
+
const defaultPM = instructions.packageManagerOptions[0];
|
|
380
|
+
instructions.packageManager = defaultPM.name;
|
|
381
|
+
instructions.commands.push(defaultPM.command);
|
|
382
|
+
}
|
|
383
|
+
}
|
|
384
|
+
|
|
385
|
+
/**
|
|
386
|
+
* Handle npm package-specific instructions
|
|
387
|
+
* @param {Object} instructions - Instructions object to modify
|
|
388
|
+
* @param {Object} context - Instruction context
|
|
389
|
+
* @private
|
|
390
|
+
*/
|
|
391
|
+
_handleNpmPackageSpecific(instructions, context) {
|
|
392
|
+
if (context.dependency.type !== 'npm_package') return;
|
|
393
|
+
|
|
394
|
+
this._addNpmInstallOptions(instructions, context.dependency.name);
|
|
395
|
+
this._ensureNpmInOptions(instructions, context.dependency.name);
|
|
396
|
+
this._addNpmAlternatives(instructions, context.dependency.name);
|
|
397
|
+
}
|
|
398
|
+
|
|
399
|
+
/**
|
|
400
|
+
* Add npm install options (global/local)
|
|
401
|
+
* @param {Object} instructions - Instructions object to modify
|
|
402
|
+
* @param {string} packageName - Package name
|
|
403
|
+
* @private
|
|
404
|
+
*/
|
|
405
|
+
_addNpmInstallOptions(instructions, packageName) {
|
|
406
|
+
instructions.globalInstall = `npm install -g ${packageName}`;
|
|
407
|
+
instructions.localInstall = `npm install ${packageName}`;
|
|
408
|
+
}
|
|
409
|
+
|
|
410
|
+
/**
|
|
411
|
+
* Ensure npm is in package manager options
|
|
412
|
+
* @param {Object} instructions - Instructions object to modify
|
|
413
|
+
* @param {string} packageName - Package name
|
|
414
|
+
* @private
|
|
415
|
+
*/
|
|
416
|
+
_ensureNpmInOptions(instructions, packageName) {
|
|
417
|
+
const hasNpm = instructions.packageManagerOptions.some(pm => pm.name === 'npm');
|
|
418
|
+
if (!hasNpm) {
|
|
419
|
+
instructions.packageManagerOptions.unshift({
|
|
420
|
+
name: 'npm',
|
|
421
|
+
command: `npm install -g ${packageName}`
|
|
422
|
+
});
|
|
423
|
+
}
|
|
424
|
+
}
|
|
425
|
+
|
|
426
|
+
/**
|
|
427
|
+
* Add npm alternatives (yarn, pnpm)
|
|
428
|
+
* @param {Object} instructions - Instructions object to modify
|
|
429
|
+
* @param {string} packageName - Package name
|
|
430
|
+
* @private
|
|
431
|
+
*/
|
|
432
|
+
_addNpmAlternatives(instructions, packageName) {
|
|
433
|
+
instructions.packageManagerOptions.push(
|
|
434
|
+
{ name: 'yarn', command: `yarn global add ${packageName}` },
|
|
435
|
+
{ name: 'pnpm', command: `pnpm add -g ${packageName}` }
|
|
436
|
+
);
|
|
437
|
+
}
|
|
438
|
+
|
|
439
|
+
/**
|
|
440
|
+
* Add alternative installation methods (private)
|
|
441
|
+
* @param {Object} instructions - Instructions to enhance
|
|
442
|
+
* @param {Object} dependency - Dependency information
|
|
443
|
+
* @param {string} platform - Target platform
|
|
444
|
+
* @private
|
|
445
|
+
*/
|
|
446
|
+
_addAlternativeInstallationMethods(instructions, dependency, platform) {
|
|
447
|
+
this._addDownloadLinks(instructions, dependency, platform);
|
|
448
|
+
this._addDockerAlternative(instructions, dependency);
|
|
449
|
+
}
|
|
450
|
+
|
|
451
|
+
/**
|
|
452
|
+
* Add download links for dependencies (private)
|
|
453
|
+
* @param {Object} instructions - Instructions to enhance
|
|
454
|
+
* @param {Object} dependency - Dependency information
|
|
455
|
+
* @param {string} platform - Target platform
|
|
456
|
+
* @private
|
|
457
|
+
*/
|
|
458
|
+
_addDownloadLinks(instructions, dependency, platform) {
|
|
459
|
+
const links = this.config.downloadLinks[dependency.name];
|
|
460
|
+
if (!links) return;
|
|
461
|
+
|
|
462
|
+
if (links.all) {
|
|
463
|
+
instructions.alternativeOptions.push(`Download from: ${links.all}`);
|
|
464
|
+
} else if (links[platform]) {
|
|
465
|
+
instructions.alternativeOptions.push(`Download from: ${links[platform]}`);
|
|
466
|
+
}
|
|
467
|
+
}
|
|
468
|
+
|
|
469
|
+
/**
|
|
470
|
+
* Add Docker alternative for tools (private)
|
|
471
|
+
* @param {Object} instructions - Instructions to enhance
|
|
472
|
+
* @param {Object} dependency - Dependency information
|
|
473
|
+
* @private
|
|
474
|
+
*/
|
|
475
|
+
_addDockerAlternative(instructions, dependency) {
|
|
476
|
+
if (dependency.type === 'tool') {
|
|
477
|
+
instructions.alternativeOptions.push(`Use Docker container with ${dependency.name} pre-installed`);
|
|
478
|
+
}
|
|
479
|
+
}
|
|
480
|
+
|
|
481
|
+
/**
|
|
482
|
+
* Generate bulk install command for multiple packages
|
|
483
|
+
* @param {Object} packageManager - Package manager configuration
|
|
484
|
+
* @param {Array<string>} packages - List of packages
|
|
485
|
+
* @returns {string} Bulk install command
|
|
486
|
+
* @private
|
|
487
|
+
*/
|
|
488
|
+
_generateBulkInstallCommand(packageManager, packages) {
|
|
489
|
+
const packageList = packages.join(' ');
|
|
490
|
+
return packageManager.install.replace('{package}', packageList);
|
|
491
|
+
}
|
|
492
|
+
|
|
493
|
+
/**
|
|
494
|
+
* Generate upgrade command for a specific package
|
|
495
|
+
* @param {Object} packageManager - Package manager configuration
|
|
496
|
+
* @param {string} packageName - Package to upgrade
|
|
497
|
+
* @param {string} platform - Target platform
|
|
498
|
+
* @returns {string} Upgrade command
|
|
499
|
+
* @private
|
|
500
|
+
*/
|
|
501
|
+
_generateUpgradeCommand(packageManager, packageName, platform) {
|
|
502
|
+
const resolvedName = this.packageManagerService.getPackageName(packageName, packageManager.name, platform);
|
|
503
|
+
|
|
504
|
+
// Map package manager to upgrade commands
|
|
505
|
+
const upgradeCommands = {
|
|
506
|
+
'apt': `sudo apt-get update && sudo apt-get upgrade ${resolvedName}`,
|
|
507
|
+
'yum': `sudo yum update ${resolvedName}`,
|
|
508
|
+
'dnf': `sudo dnf update ${resolvedName}`,
|
|
509
|
+
'pacman': `sudo pacman -S ${resolvedName}`,
|
|
510
|
+
'brew': `brew upgrade ${resolvedName}`,
|
|
511
|
+
'chocolatey': `choco upgrade ${resolvedName}`,
|
|
512
|
+
'winget': `winget upgrade ${resolvedName}`,
|
|
513
|
+
'npm': `npm update -g ${resolvedName}`,
|
|
514
|
+
'yarn': `yarn global upgrade ${resolvedName}`,
|
|
515
|
+
'pnpm': `pnpm update -g ${resolvedName}`
|
|
516
|
+
};
|
|
517
|
+
|
|
518
|
+
return upgradeCommands[packageManager.name] || null;
|
|
519
|
+
}
|
|
520
|
+
|
|
521
|
+
|
|
522
|
+
/**
|
|
523
|
+
* Get package manager description
|
|
524
|
+
* @param {string} packageManagerName - Package manager name
|
|
525
|
+
* @returns {string} Description
|
|
526
|
+
* @private
|
|
527
|
+
*/
|
|
528
|
+
_getPackageManagerDescription(packageManagerName) {
|
|
529
|
+
const descriptions = {
|
|
530
|
+
'apt': 'Advanced Package Tool - Debian/Ubuntu package manager',
|
|
531
|
+
'yum': 'Yellowdog Updater Modified - Red Hat package manager',
|
|
532
|
+
'dnf': 'Dandified YUM - Modern Red Hat package manager',
|
|
533
|
+
'pacman': 'Package Manager - Arch Linux package manager',
|
|
534
|
+
'brew': 'Homebrew - macOS package manager',
|
|
535
|
+
'chocolatey': 'Chocolatey - Windows package manager',
|
|
536
|
+
'winget': 'Windows Package Manager - Microsoft package manager',
|
|
537
|
+
'npm': 'Node Package Manager - JavaScript package manager',
|
|
538
|
+
'yarn': 'Yarn - Fast JavaScript package manager',
|
|
539
|
+
'pnpm': 'pnpm - Efficient JavaScript package manager'
|
|
540
|
+
};
|
|
541
|
+
return descriptions[packageManagerName] || `${packageManagerName} package manager`;
|
|
542
|
+
}
|
|
543
|
+
|
|
544
|
+
/**
|
|
545
|
+
* Get package manager installation URL
|
|
546
|
+
* @param {string} packageManagerName - Package manager name
|
|
547
|
+
* @param {string} platform - Target platform
|
|
548
|
+
* @returns {string} Installation URL
|
|
549
|
+
* @private
|
|
550
|
+
*/
|
|
551
|
+
_getPackageManagerInstallUrl(packageManagerName, platform) {
|
|
552
|
+
const installUrls = {
|
|
553
|
+
'brew': 'https://brew.sh/',
|
|
554
|
+
'chocolatey': 'https://chocolatey.org/install',
|
|
555
|
+
'winget': 'https://docs.microsoft.com/en-us/windows/package-manager/winget/',
|
|
556
|
+
'npm': 'https://nodejs.org/en/download/',
|
|
557
|
+
'yarn': 'https://yarnpkg.com/getting-started/install',
|
|
558
|
+
'pnpm': 'https://pnpm.io/installation'
|
|
559
|
+
};
|
|
560
|
+
return installUrls[packageManagerName] || null;
|
|
561
|
+
}
|
|
562
|
+
}
|
|
563
|
+
|
|
564
|
+
module.exports = InstallationInstructionGenerator;
|
package/lib/installer.js
ADDED
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
// Installation logic for Claude Dev Toolkit
|
|
2
|
+
const fs = require('fs');
|
|
3
|
+
const path = require('path');
|
|
4
|
+
const os = require('os');
|
|
5
|
+
const { ensureDirectory } = require('./utils');
|
|
6
|
+
|
|
7
|
+
module.exports = {
|
|
8
|
+
install: async (options = {}) => {
|
|
9
|
+
const claudeDir = path.join(os.homedir(), '.claude', 'commands');
|
|
10
|
+
const packageDir = path.join(__dirname, '..');
|
|
11
|
+
|
|
12
|
+
console.log('š Installing Claude Custom Commands...\n');
|
|
13
|
+
|
|
14
|
+
// Ensure directories exist
|
|
15
|
+
ensureDirectory(claudeDir);
|
|
16
|
+
ensureDirectory(path.join(claudeDir, 'active'));
|
|
17
|
+
ensureDirectory(path.join(claudeDir, 'experimental'));
|
|
18
|
+
|
|
19
|
+
let installedCount = 0;
|
|
20
|
+
|
|
21
|
+
// Install active commands
|
|
22
|
+
if (options.active || options.all || (!options.active && !options.experimental)) {
|
|
23
|
+
const activeSource = path.join(packageDir, 'commands', 'active');
|
|
24
|
+
const activeTarget = path.join(claudeDir, 'active');
|
|
25
|
+
|
|
26
|
+
if (fs.existsSync(activeSource)) {
|
|
27
|
+
const activeFiles = fs.readdirSync(activeSource).filter(f => f.endsWith('.md'));
|
|
28
|
+
activeFiles.forEach(file => {
|
|
29
|
+
fs.copyFileSync(
|
|
30
|
+
path.join(activeSource, file),
|
|
31
|
+
path.join(activeTarget, file)
|
|
32
|
+
);
|
|
33
|
+
});
|
|
34
|
+
installedCount += activeFiles.length;
|
|
35
|
+
console.log(`ā
Installed ${activeFiles.length} active commands`);
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
// Install experimental commands
|
|
40
|
+
if (options.experimental || options.all) {
|
|
41
|
+
const expSource = path.join(packageDir, 'commands', 'experiments');
|
|
42
|
+
const expTarget = path.join(claudeDir, 'experiments');
|
|
43
|
+
|
|
44
|
+
if (fs.existsSync(expSource)) {
|
|
45
|
+
const expFiles = fs.readdirSync(expSource).filter(f => f.endsWith('.md'));
|
|
46
|
+
expFiles.forEach(file => {
|
|
47
|
+
fs.copyFileSync(
|
|
48
|
+
path.join(expSource, file),
|
|
49
|
+
path.join(expTarget, file)
|
|
50
|
+
);
|
|
51
|
+
});
|
|
52
|
+
installedCount += expFiles.length;
|
|
53
|
+
console.log(`ā
Installed ${expFiles.length} experimental commands`);
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
console.log(`\nš Installation complete! ${installedCount} commands installed.`);
|
|
58
|
+
console.log('\nNext steps:');
|
|
59
|
+
console.log('⢠Try: claude-commands list');
|
|
60
|
+
console.log('⢠Use commands in Claude Code: /xhelp');
|
|
61
|
+
|
|
62
|
+
return {
|
|
63
|
+
success: true,
|
|
64
|
+
installedPath: claudeDir,
|
|
65
|
+
commandsInstalled: installedCount
|
|
66
|
+
};
|
|
67
|
+
}
|
|
68
|
+
};
|