@lenne.tech/cli 1.2.0 → 1.3.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/build/commands/claude/install-plugin.js +339 -0
- package/package.json +1 -1
- package/build/commands/claude/install-commands.js +0 -337
- package/build/commands/claude/install-mcps.js +0 -258
- package/build/commands/claude/install-skills.js +0 -693
- package/build/lib/mcp-registry.js +0 -80
- package/build/templates/claude-commands/code-cleanup.md +0 -82
- package/build/templates/claude-commands/commit-message.md +0 -21
- package/build/templates/claude-commands/create-story.md +0 -435
- package/build/templates/claude-commands/mr-description-clipboard.md +0 -48
- package/build/templates/claude-commands/mr-description.md +0 -33
- package/build/templates/claude-commands/sec-review.md +0 -62
- package/build/templates/claude-commands/skill-optimize.md +0 -481
- package/build/templates/claude-commands/test-generate.md +0 -45
- package/build/templates/claude-skills/building-stories-with-tdd/SKILL.md +0 -265
- package/build/templates/claude-skills/building-stories-with-tdd/code-quality.md +0 -276
- package/build/templates/claude-skills/building-stories-with-tdd/database-indexes.md +0 -182
- package/build/templates/claude-skills/building-stories-with-tdd/examples.md +0 -1383
- package/build/templates/claude-skills/building-stories-with-tdd/handling-existing-tests.md +0 -197
- package/build/templates/claude-skills/building-stories-with-tdd/reference.md +0 -1427
- package/build/templates/claude-skills/building-stories-with-tdd/security-review.md +0 -307
- package/build/templates/claude-skills/building-stories-with-tdd/workflow.md +0 -1004
- package/build/templates/claude-skills/generating-nest-servers/SKILL.md +0 -303
- package/build/templates/claude-skills/generating-nest-servers/configuration.md +0 -285
- package/build/templates/claude-skills/generating-nest-servers/declare-keyword-warning.md +0 -133
- package/build/templates/claude-skills/generating-nest-servers/description-management.md +0 -226
- package/build/templates/claude-skills/generating-nest-servers/examples.md +0 -893
- package/build/templates/claude-skills/generating-nest-servers/framework-guide.md +0 -259
- package/build/templates/claude-skills/generating-nest-servers/quality-review.md +0 -864
- package/build/templates/claude-skills/generating-nest-servers/reference.md +0 -487
- package/build/templates/claude-skills/generating-nest-servers/security-rules.md +0 -371
- package/build/templates/claude-skills/generating-nest-servers/verification-checklist.md +0 -262
- package/build/templates/claude-skills/generating-nest-servers/workflow-process.md +0 -1061
- package/build/templates/claude-skills/using-lt-cli/SKILL.md +0 -284
- package/build/templates/claude-skills/using-lt-cli/examples.md +0 -546
- package/build/templates/claude-skills/using-lt-cli/reference.md +0 -513
|
@@ -1,337 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
3
|
-
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
4
|
-
return new (P || (P = Promise))(function (resolve, reject) {
|
|
5
|
-
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
6
|
-
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
7
|
-
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
8
|
-
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
9
|
-
});
|
|
10
|
-
};
|
|
11
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
|
-
const os_1 = require("os");
|
|
13
|
-
const path_1 = require("path");
|
|
14
|
-
/**
|
|
15
|
-
* Get command description from .md frontmatter
|
|
16
|
-
*/
|
|
17
|
-
function getCommandDescription(commandPath, filesystem) {
|
|
18
|
-
if (!filesystem.exists(commandPath)) {
|
|
19
|
-
return 'No description available';
|
|
20
|
-
}
|
|
21
|
-
const content = filesystem.read(commandPath);
|
|
22
|
-
const frontmatterMatch = content.match(/^---\n([\s\S]*?)\n---/);
|
|
23
|
-
if (!frontmatterMatch) {
|
|
24
|
-
return 'No description available';
|
|
25
|
-
}
|
|
26
|
-
const frontmatter = frontmatterMatch[1];
|
|
27
|
-
const descMatch = frontmatter.match(/description:\s*([^\n]+)/);
|
|
28
|
-
return descMatch ? descMatch[1].trim() : 'No description available';
|
|
29
|
-
}
|
|
30
|
-
/**
|
|
31
|
-
* Compare semantic versions
|
|
32
|
-
* Returns true if sourceVersion >= targetVersion
|
|
33
|
-
*/
|
|
34
|
-
function isVersionNewer(sourceVersion, targetVersion) {
|
|
35
|
-
const parseSemver = (version) => {
|
|
36
|
-
return version.split('.').map(n => parseInt(n, 10) || 0);
|
|
37
|
-
};
|
|
38
|
-
const source = parseSemver(sourceVersion);
|
|
39
|
-
const target = parseSemver(targetVersion);
|
|
40
|
-
// Compare major, minor, patch
|
|
41
|
-
for (let i = 0; i < 3; i++) {
|
|
42
|
-
if (source[i] > target[i]) {
|
|
43
|
-
return true;
|
|
44
|
-
}
|
|
45
|
-
if (source[i] < target[i]) {
|
|
46
|
-
return false;
|
|
47
|
-
}
|
|
48
|
-
}
|
|
49
|
-
// Versions are equal
|
|
50
|
-
return true;
|
|
51
|
-
}
|
|
52
|
-
/**
|
|
53
|
-
* Parse frontmatter from markdown file and extract version
|
|
54
|
-
*/
|
|
55
|
-
function parseVersion(content) {
|
|
56
|
-
const frontmatterMatch = content.match(/^---\n([\s\S]*?)\n---/);
|
|
57
|
-
if (!frontmatterMatch) {
|
|
58
|
-
return null;
|
|
59
|
-
}
|
|
60
|
-
const frontmatter = frontmatterMatch[1];
|
|
61
|
-
const versionMatch = frontmatter.match(/version:\s*([^\n]+)/);
|
|
62
|
-
return versionMatch ? versionMatch[1].trim() : null;
|
|
63
|
-
}
|
|
64
|
-
/**
|
|
65
|
-
* Install Claude Commands to ~/.claude/commands/ or .claude/commands/
|
|
66
|
-
*/
|
|
67
|
-
const NewCommand = {
|
|
68
|
-
alias: ['commands', 'ic'],
|
|
69
|
-
description: 'Installs Claude Custom Commands to ~/.claude/commands/ or .claude/commands/ for Claude Code integration. Use --global for global installation, --project for project-specific installation.',
|
|
70
|
-
hidden: false,
|
|
71
|
-
name: 'install-commands',
|
|
72
|
-
run: (toolbox) => __awaiter(void 0, void 0, void 0, function* () {
|
|
73
|
-
var _a;
|
|
74
|
-
// Retrieve the tools we need
|
|
75
|
-
const { filesystem, parameters, print: { error, info, spin, success }, prompt, } = toolbox;
|
|
76
|
-
try {
|
|
77
|
-
// Get the CLI installation directory
|
|
78
|
-
const cliRoot = (0, path_1.join)(__dirname, '..', '..');
|
|
79
|
-
const commandsTemplateDir = (0, path_1.join)(cliRoot, 'templates', 'claude-commands');
|
|
80
|
-
// Check if claude-commands directory exists
|
|
81
|
-
if (!filesystem.exists(commandsTemplateDir)) {
|
|
82
|
-
error('Claude commands directory not found in CLI installation.');
|
|
83
|
-
info(`Expected location: ${commandsTemplateDir}`);
|
|
84
|
-
info('Please reinstall the CLI or report this issue.');
|
|
85
|
-
return;
|
|
86
|
-
}
|
|
87
|
-
// Get all available commands (*.md files, excluding README.md)
|
|
88
|
-
const allFiles = filesystem.list(commandsTemplateDir) || [];
|
|
89
|
-
const availableCommands = allFiles.filter(file => file.endsWith('.md') && file !== 'README.md');
|
|
90
|
-
if (availableCommands.length === 0) {
|
|
91
|
-
error('No commands found in CLI installation.');
|
|
92
|
-
return;
|
|
93
|
-
}
|
|
94
|
-
// Determine installation scope
|
|
95
|
-
const cwd = filesystem.cwd();
|
|
96
|
-
let scope = 'global';
|
|
97
|
-
let commandsDir = (0, path_1.join)((0, os_1.homedir)(), '.claude', 'commands');
|
|
98
|
-
const skipInteractive = parameters.options.y || parameters.options.yes || parameters.options['no-interactive'];
|
|
99
|
-
// Check if user specified scope
|
|
100
|
-
if (parameters.options.global) {
|
|
101
|
-
scope = 'global';
|
|
102
|
-
commandsDir = (0, path_1.join)((0, os_1.homedir)(), '.claude', 'commands');
|
|
103
|
-
}
|
|
104
|
-
else if (parameters.options.project) {
|
|
105
|
-
scope = 'project';
|
|
106
|
-
commandsDir = (0, path_1.join)(cwd, '.claude', 'commands');
|
|
107
|
-
}
|
|
108
|
-
else {
|
|
109
|
-
// Detect if we're in a project
|
|
110
|
-
let packageJsonPath = null;
|
|
111
|
-
let searchDir = cwd;
|
|
112
|
-
// Search up to 3 levels for package.json
|
|
113
|
-
for (let i = 0; i < 3; i++) {
|
|
114
|
-
const testPath = (0, path_1.join)(searchDir, 'package.json');
|
|
115
|
-
if (filesystem.exists(testPath)) {
|
|
116
|
-
packageJsonPath = testPath;
|
|
117
|
-
break;
|
|
118
|
-
}
|
|
119
|
-
const parent = (0, path_1.join)(searchDir, '..');
|
|
120
|
-
if (parent === searchDir)
|
|
121
|
-
break; // Reached root
|
|
122
|
-
searchDir = parent;
|
|
123
|
-
}
|
|
124
|
-
// If in a project, ask where to install
|
|
125
|
-
if (packageJsonPath && !skipInteractive) {
|
|
126
|
-
info('');
|
|
127
|
-
info(`Detected project at: ${searchDir}`);
|
|
128
|
-
const installToProject = yield prompt.confirm('Install commands to this project only? (No = install globally for all projects)', false);
|
|
129
|
-
scope = installToProject ? 'project' : 'global';
|
|
130
|
-
if (scope === 'project') {
|
|
131
|
-
commandsDir = (0, path_1.join)(searchDir, '.claude', 'commands');
|
|
132
|
-
}
|
|
133
|
-
}
|
|
134
|
-
else if (packageJsonPath && skipInteractive) {
|
|
135
|
-
// In non-interactive mode with project detected, default to global
|
|
136
|
-
scope = 'global';
|
|
137
|
-
}
|
|
138
|
-
}
|
|
139
|
-
// Create commands directory if it doesn't exist
|
|
140
|
-
if (!filesystem.exists(commandsDir)) {
|
|
141
|
-
filesystem.dir(commandsDir);
|
|
142
|
-
}
|
|
143
|
-
info('');
|
|
144
|
-
info('Available commands:');
|
|
145
|
-
info('');
|
|
146
|
-
// Show all available commands with descriptions
|
|
147
|
-
availableCommands.forEach(cmd => {
|
|
148
|
-
const cmdPath = (0, path_1.join)(commandsTemplateDir, cmd);
|
|
149
|
-
const desc = getCommandDescription(cmdPath, filesystem);
|
|
150
|
-
const cmdName = cmd.replace('.md', '');
|
|
151
|
-
info(` • /${cmdName}`);
|
|
152
|
-
info(` ${desc}`);
|
|
153
|
-
info('');
|
|
154
|
-
});
|
|
155
|
-
let commandsToInstall = [];
|
|
156
|
-
// Check if specific commands provided as parameters
|
|
157
|
-
if (parameters.first && parameters.first !== 'all') {
|
|
158
|
-
// Non-interactive mode: install specific command(s)
|
|
159
|
-
const requestedCommands = parameters.array || [parameters.first];
|
|
160
|
-
// Add .md extension if not present
|
|
161
|
-
const requestedWithExt = requestedCommands.map(c => c.endsWith('.md') ? c : `${c}.md`);
|
|
162
|
-
// Validate requested commands
|
|
163
|
-
const invalidCommands = requestedWithExt.filter(c => !availableCommands.includes(c));
|
|
164
|
-
if (invalidCommands.length > 0) {
|
|
165
|
-
error(`Invalid command(s): ${invalidCommands.map(c => c.replace('.md', '')).join(', ')}`);
|
|
166
|
-
info('');
|
|
167
|
-
info('Available commands:');
|
|
168
|
-
availableCommands.forEach(c => {
|
|
169
|
-
const cmdName = c.replace('.md', '');
|
|
170
|
-
info(` • ${cmdName}`);
|
|
171
|
-
});
|
|
172
|
-
return;
|
|
173
|
-
}
|
|
174
|
-
commandsToInstall = requestedWithExt;
|
|
175
|
-
}
|
|
176
|
-
else if (parameters.first === 'all' || skipInteractive) {
|
|
177
|
-
// Install all commands without prompting
|
|
178
|
-
commandsToInstall = availableCommands;
|
|
179
|
-
if (skipInteractive) {
|
|
180
|
-
info('Installing all commands (non-interactive mode)...');
|
|
181
|
-
}
|
|
182
|
-
}
|
|
183
|
-
else {
|
|
184
|
-
// Interactive mode: ask if user wants all or select individually
|
|
185
|
-
const installAll = yield prompt.confirm('Install all commands?', true);
|
|
186
|
-
if (installAll) {
|
|
187
|
-
commandsToInstall = availableCommands;
|
|
188
|
-
}
|
|
189
|
-
else {
|
|
190
|
-
// Ask for each command
|
|
191
|
-
info('');
|
|
192
|
-
info('Select which commands to install:');
|
|
193
|
-
info('');
|
|
194
|
-
for (const cmd of availableCommands) {
|
|
195
|
-
const cmdName = cmd.replace('.md', '');
|
|
196
|
-
const shouldInstall = yield prompt.confirm(`Install /${cmdName}?`, true);
|
|
197
|
-
if (shouldInstall) {
|
|
198
|
-
commandsToInstall.push(cmd);
|
|
199
|
-
}
|
|
200
|
-
}
|
|
201
|
-
if (commandsToInstall.length === 0) {
|
|
202
|
-
info('No commands selected. Installation cancelled.');
|
|
203
|
-
return;
|
|
204
|
-
}
|
|
205
|
-
}
|
|
206
|
-
}
|
|
207
|
-
const installSpinner = spin(`Installing ${commandsToInstall.length} command(s) to ${scope === 'global' ? '~/.claude/commands/' : '.claude/commands/'}...`);
|
|
208
|
-
let copiedCount = 0;
|
|
209
|
-
let skippedCount = 0;
|
|
210
|
-
let updatedCount = 0;
|
|
211
|
-
const skippedFiles = [];
|
|
212
|
-
// Install each command
|
|
213
|
-
for (const cmd of commandsToInstall) {
|
|
214
|
-
const sourcePath = (0, path_1.join)(commandsTemplateDir, cmd);
|
|
215
|
-
const targetPath = (0, path_1.join)(commandsDir, cmd);
|
|
216
|
-
const sourceContent = filesystem.read(sourcePath);
|
|
217
|
-
// Check if target file exists
|
|
218
|
-
if (filesystem.exists(targetPath)) {
|
|
219
|
-
const targetContent = filesystem.read(targetPath);
|
|
220
|
-
// Parse versions from both files
|
|
221
|
-
const sourceVersion = parseVersion(sourceContent);
|
|
222
|
-
const targetVersion = parseVersion(targetContent);
|
|
223
|
-
// If both have versions, compare them
|
|
224
|
-
if (sourceVersion && targetVersion) {
|
|
225
|
-
if (isVersionNewer(sourceVersion, targetVersion)) {
|
|
226
|
-
// Source is newer or equal, update
|
|
227
|
-
filesystem.write(targetPath, sourceContent);
|
|
228
|
-
updatedCount++;
|
|
229
|
-
copiedCount++;
|
|
230
|
-
}
|
|
231
|
-
else {
|
|
232
|
-
// Target is newer, skip
|
|
233
|
-
skippedCount++;
|
|
234
|
-
const reason = `local version ${targetVersion} is newer than ${sourceVersion}`;
|
|
235
|
-
skippedFiles.push({ file: cmd, reason });
|
|
236
|
-
}
|
|
237
|
-
}
|
|
238
|
-
else if (sourceVersion && !targetVersion) {
|
|
239
|
-
// Source has version, target doesn't - update
|
|
240
|
-
filesystem.write(targetPath, sourceContent);
|
|
241
|
-
updatedCount++;
|
|
242
|
-
copiedCount++;
|
|
243
|
-
}
|
|
244
|
-
else {
|
|
245
|
-
// No version info, always update (backward compatibility)
|
|
246
|
-
filesystem.write(targetPath, sourceContent);
|
|
247
|
-
updatedCount++;
|
|
248
|
-
copiedCount++;
|
|
249
|
-
}
|
|
250
|
-
}
|
|
251
|
-
else {
|
|
252
|
-
// Target doesn't exist, create new
|
|
253
|
-
filesystem.write(targetPath, sourceContent);
|
|
254
|
-
copiedCount++;
|
|
255
|
-
}
|
|
256
|
-
}
|
|
257
|
-
if (copiedCount === 0 && skippedCount === 0) {
|
|
258
|
-
installSpinner.fail();
|
|
259
|
-
error('No command files were processed.');
|
|
260
|
-
return;
|
|
261
|
-
}
|
|
262
|
-
if (copiedCount === 0 && skippedCount > 0) {
|
|
263
|
-
installSpinner.succeed('All selected commands are already up to date!');
|
|
264
|
-
info('');
|
|
265
|
-
info(`Skipped: ${skippedCount} file(s)`);
|
|
266
|
-
info(`Location: ${commandsDir}`);
|
|
267
|
-
return;
|
|
268
|
-
}
|
|
269
|
-
installSpinner.succeed(`Successfully installed ${commandsToInstall.length} command(s)!`);
|
|
270
|
-
info('');
|
|
271
|
-
if (updatedCount > 0 && skippedCount > 0) {
|
|
272
|
-
success(`Updated ${updatedCount} file(s), skipped ${skippedCount} file(s)`);
|
|
273
|
-
}
|
|
274
|
-
else if (updatedCount > 0) {
|
|
275
|
-
success(`Updated ${updatedCount} file(s)`);
|
|
276
|
-
}
|
|
277
|
-
else {
|
|
278
|
-
success(`Created ${copiedCount} file(s)`);
|
|
279
|
-
}
|
|
280
|
-
info('');
|
|
281
|
-
info('Installed commands:');
|
|
282
|
-
commandsToInstall.forEach(cmd => {
|
|
283
|
-
const cmdPath = (0, path_1.join)(commandsTemplateDir, cmd);
|
|
284
|
-
const desc = getCommandDescription(cmdPath, filesystem);
|
|
285
|
-
const cmdName = cmd.replace('.md', '');
|
|
286
|
-
info(` • /${cmdName}`);
|
|
287
|
-
info(` ${desc.substring(0, 80)}${desc.length > 80 ? '...' : ''}`);
|
|
288
|
-
});
|
|
289
|
-
info('');
|
|
290
|
-
info('These commands are now available in Claude Code!');
|
|
291
|
-
// Show first installed command as example
|
|
292
|
-
const firstCmd = (_a = commandsToInstall[0]) === null || _a === void 0 ? void 0 : _a.replace('.md', '');
|
|
293
|
-
info(`Use them by typing the command name with a leading slash, e.g., /${firstCmd || 'command-name'}`);
|
|
294
|
-
info('');
|
|
295
|
-
info('Examples:');
|
|
296
|
-
// Show up to 5 commands as examples (or all if less than 5)
|
|
297
|
-
const exampleCount = Math.min(commandsToInstall.length, 5);
|
|
298
|
-
for (let i = 0; i < exampleCount; i++) {
|
|
299
|
-
const cmd = commandsToInstall[i];
|
|
300
|
-
const cmdPath = (0, path_1.join)(commandsTemplateDir, cmd);
|
|
301
|
-
const desc = getCommandDescription(cmdPath, filesystem);
|
|
302
|
-
const cmdName = cmd.replace('.md', '');
|
|
303
|
-
info(` • /${cmdName} - ${desc}`);
|
|
304
|
-
}
|
|
305
|
-
info('');
|
|
306
|
-
info(`Location: ${commandsDir}`);
|
|
307
|
-
info(`Scope: ${scope === 'global' ? 'Global (all projects)' : 'Project-specific'}`);
|
|
308
|
-
if (skippedCount > 0) {
|
|
309
|
-
info('');
|
|
310
|
-
info(`Note: ${skippedCount} file(s) were skipped because your local versions are newer:`);
|
|
311
|
-
skippedFiles.forEach(({ file, reason }) => {
|
|
312
|
-
info(` • ${file} (${reason})`);
|
|
313
|
-
});
|
|
314
|
-
info('');
|
|
315
|
-
info('To force update, manually delete the files and run this command again.');
|
|
316
|
-
}
|
|
317
|
-
}
|
|
318
|
-
catch (err) {
|
|
319
|
-
error(`Failed to install command(s): ${err.message}`);
|
|
320
|
-
info('');
|
|
321
|
-
info('Troubleshooting:');
|
|
322
|
-
info(' • Ensure .claude directory exists and is writable');
|
|
323
|
-
info(' • Check file permissions');
|
|
324
|
-
info(' • Try running with sudo if permission issues persist');
|
|
325
|
-
// IMPORTANT: Must call process.exit() to properly close readline stream and terminate the process
|
|
326
|
-
// Without this, the command will hang after completion
|
|
327
|
-
process.exit(1);
|
|
328
|
-
}
|
|
329
|
-
// IMPORTANT: Must call process.exit() to properly close readline stream and terminate the process
|
|
330
|
-
// This is required when the command doesn't have additional prompts at the end
|
|
331
|
-
// (like install-skills does). Without this explicit exit, the readline stream remains open
|
|
332
|
-
// and the process hangs indefinitely.
|
|
333
|
-
process.exit(0);
|
|
334
|
-
}),
|
|
335
|
-
};
|
|
336
|
-
exports.default = NewCommand;
|
|
337
|
-
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5zdGFsbC1jb21tYW5kcy5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3NyYy9jb21tYW5kcy9jbGF1ZGUvaW5zdGFsbC1jb21tYW5kcy50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7Ozs7Ozs7OztBQUNBLDJCQUE2QjtBQUM3QiwrQkFBNEI7QUFJNUI7O0dBRUc7QUFDSCxTQUFTLHFCQUFxQixDQUFDLFdBQW1CLEVBQUUsVUFBZTtJQUNqRSxJQUFJLENBQUMsVUFBVSxDQUFDLE1BQU0sQ0FBQyxXQUFXLENBQUMsRUFBRSxDQUFDO1FBQ3BDLE9BQU8sMEJBQTBCLENBQUM7SUFDcEMsQ0FBQztJQUVELE1BQU0sT0FBTyxHQUFHLFVBQVUsQ0FBQyxJQUFJLENBQUMsV0FBVyxDQUFDLENBQUM7SUFDN0MsTUFBTSxnQkFBZ0IsR0FBRyxPQUFPLENBQUMsS0FBSyxDQUFDLHVCQUF1QixDQUFDLENBQUM7SUFDaEUsSUFBSSxDQUFDLGdCQUFnQixFQUFFLENBQUM7UUFDdEIsT0FBTywwQkFBMEIsQ0FBQztJQUNwQyxDQUFDO0lBRUQsTUFBTSxXQUFXLEdBQUcsZ0JBQWdCLENBQUMsQ0FBQyxDQUFDLENBQUM7SUFDeEMsTUFBTSxTQUFTLEdBQUcsV0FBVyxDQUFDLEtBQUssQ0FBQyx5QkFBeUIsQ0FBQyxDQUFDO0lBRS9ELE9BQU8sU0FBUyxDQUFDLENBQUMsQ0FBQyxTQUFTLENBQUMsQ0FBQyxDQUFDLENBQUMsSUFBSSxFQUFFLENBQUMsQ0FBQyxDQUFDLDBCQUEwQixDQUFDO0FBQ3RFLENBQUM7QUFFRDs7O0dBR0c7QUFDSCxTQUFTLGNBQWMsQ0FBQyxhQUFxQixFQUFFLGFBQXFCO0lBQ2xFLE1BQU0sV0FBVyxHQUFHLENBQUMsT0FBZSxFQUFZLEVBQUU7UUFDaEQsT0FBTyxPQUFPLENBQUMsS0FBSyxDQUFDLEdBQUcsQ0FBQyxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDLFFBQVEsQ0FBQyxDQUFDLEVBQUUsRUFB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
|
|
@@ -1,258 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
3
|
-
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
4
|
-
return new (P || (P = Promise))(function (resolve, reject) {
|
|
5
|
-
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
6
|
-
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
7
|
-
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
8
|
-
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
9
|
-
});
|
|
10
|
-
};
|
|
11
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
|
-
const child_process_1 = require("child_process");
|
|
13
|
-
const fs_1 = require("fs");
|
|
14
|
-
const os_1 = require("os");
|
|
15
|
-
const path_1 = require("path");
|
|
16
|
-
const mcp_registry_1 = require("../../lib/mcp-registry");
|
|
17
|
-
/**
|
|
18
|
-
* Find the claude CLI executable path
|
|
19
|
-
* Checks common installation locations
|
|
20
|
-
*/
|
|
21
|
-
function findClaudeCli() {
|
|
22
|
-
const possiblePaths = [
|
|
23
|
-
(0, path_1.join)((0, os_1.homedir)(), '.claude', 'local', 'claude'),
|
|
24
|
-
'/usr/local/bin/claude',
|
|
25
|
-
'/usr/bin/claude',
|
|
26
|
-
];
|
|
27
|
-
for (const p of possiblePaths) {
|
|
28
|
-
if ((0, fs_1.existsSync)(p)) {
|
|
29
|
-
return p;
|
|
30
|
-
}
|
|
31
|
-
}
|
|
32
|
-
// Try to find via 'which' command
|
|
33
|
-
try {
|
|
34
|
-
const result = (0, child_process_1.execSync)('which claude', { encoding: 'utf-8', stdio: ['pipe', 'pipe', 'pipe'] });
|
|
35
|
-
const path = result.trim();
|
|
36
|
-
if (path && (0, fs_1.existsSync)(path)) {
|
|
37
|
-
return path;
|
|
38
|
-
}
|
|
39
|
-
}
|
|
40
|
-
catch (_a) {
|
|
41
|
-
// Ignore errors
|
|
42
|
-
}
|
|
43
|
-
return null;
|
|
44
|
-
}
|
|
45
|
-
let claudePath = null;
|
|
46
|
-
/**
|
|
47
|
-
* Get claude CLI path (cached)
|
|
48
|
-
*/
|
|
49
|
-
function getClaudeCli() {
|
|
50
|
-
if (claudePath === null) {
|
|
51
|
-
claudePath = findClaudeCli();
|
|
52
|
-
}
|
|
53
|
-
return claudePath;
|
|
54
|
-
}
|
|
55
|
-
/**
|
|
56
|
-
* Install an MCP using claude mcp add command
|
|
57
|
-
*/
|
|
58
|
-
function installMcp(mcp) {
|
|
59
|
-
const cli = getClaudeCli();
|
|
60
|
-
if (!cli) {
|
|
61
|
-
return { error: 'Claude CLI not found', success: false };
|
|
62
|
-
}
|
|
63
|
-
try {
|
|
64
|
-
// Build the command with optional transport flag for remote MCPs
|
|
65
|
-
const transportFlag = mcp.transport ? `--transport ${mcp.transport} ` : '';
|
|
66
|
-
const command = `"${cli}" mcp add ${transportFlag}${mcp.command}`;
|
|
67
|
-
(0, child_process_1.execSync)(command, { encoding: 'utf-8', shell: '/bin/bash', stdio: 'inherit' });
|
|
68
|
-
return { success: true };
|
|
69
|
-
}
|
|
70
|
-
catch (err) {
|
|
71
|
-
return { error: err.message, success: false };
|
|
72
|
-
}
|
|
73
|
-
}
|
|
74
|
-
/**
|
|
75
|
-
* Check if an MCP is already installed by checking Claude's MCP list
|
|
76
|
-
*/
|
|
77
|
-
function isMcpInstalled(mcpId) {
|
|
78
|
-
const cli = getClaudeCli();
|
|
79
|
-
if (!cli)
|
|
80
|
-
return false;
|
|
81
|
-
try {
|
|
82
|
-
const result = (0, child_process_1.execSync)(`"${cli}" mcp list`, { encoding: 'utf-8', shell: '/bin/bash', stdio: ['pipe', 'pipe', 'pipe'] });
|
|
83
|
-
return result.includes(mcpId);
|
|
84
|
-
}
|
|
85
|
-
catch (_a) {
|
|
86
|
-
// If command fails, assume not installed
|
|
87
|
-
return false;
|
|
88
|
-
}
|
|
89
|
-
}
|
|
90
|
-
/**
|
|
91
|
-
* Install Claude MCPs (Model Context Protocol servers)
|
|
92
|
-
*/
|
|
93
|
-
const NewCommand = {
|
|
94
|
-
alias: ['mcps', 'im'],
|
|
95
|
-
description: 'Installs Claude MCPs (Model Context Protocol servers) for enhanced Claude Code capabilities. Use -y to skip interactive selection and install all MCPs.',
|
|
96
|
-
hidden: false,
|
|
97
|
-
name: 'install-mcps',
|
|
98
|
-
run: (toolbox) => __awaiter(void 0, void 0, void 0, function* () {
|
|
99
|
-
const { parameters, print: { error, info, spin, success, warning }, prompt, } = toolbox;
|
|
100
|
-
try {
|
|
101
|
-
// Check if claude CLI is available
|
|
102
|
-
const cli = getClaudeCli();
|
|
103
|
-
if (!cli) {
|
|
104
|
-
error('Claude CLI not found. Please install Claude Code first.');
|
|
105
|
-
info('');
|
|
106
|
-
info('Installation: https://docs.anthropic.com/en/docs/claude-code');
|
|
107
|
-
return;
|
|
108
|
-
}
|
|
109
|
-
const availableMcps = (0, mcp_registry_1.getAllMcps)();
|
|
110
|
-
if (availableMcps.length === 0) {
|
|
111
|
-
error('No MCPs defined in registry.');
|
|
112
|
-
info('Add MCPs to src/commands/claude/mcp-registry.ts');
|
|
113
|
-
return;
|
|
114
|
-
}
|
|
115
|
-
const skipInteractive = parameters.options.y || parameters.options.yes || parameters.options['no-interactive'];
|
|
116
|
-
// Show available MCPs
|
|
117
|
-
info('');
|
|
118
|
-
info('Available MCPs (Model Context Protocol servers):');
|
|
119
|
-
info('');
|
|
120
|
-
for (const mcp of availableMcps) {
|
|
121
|
-
const installed = isMcpInstalled(mcp.id);
|
|
122
|
-
const statusIcon = installed ? '✓' : '○';
|
|
123
|
-
const statusText = installed ? ' (installed)' : '';
|
|
124
|
-
info(` ${statusIcon} ${mcp.name}${statusText}`);
|
|
125
|
-
info(` ${mcp.description}`);
|
|
126
|
-
if (mcp.category) {
|
|
127
|
-
info(` Category: ${mcp.category}`);
|
|
128
|
-
}
|
|
129
|
-
info('');
|
|
130
|
-
}
|
|
131
|
-
let mcpsToInstall = [];
|
|
132
|
-
// Check if specific MCPs provided as parameters
|
|
133
|
-
if (parameters.first && parameters.first !== 'all') {
|
|
134
|
-
// Non-interactive mode: install specific MCP(s)
|
|
135
|
-
const requestedMcps = parameters.array || [parameters.first];
|
|
136
|
-
// Validate requested MCPs
|
|
137
|
-
const invalidMcps = [];
|
|
138
|
-
const validMcps = [];
|
|
139
|
-
for (const mcpId of requestedMcps) {
|
|
140
|
-
const mcp = (0, mcp_registry_1.getMcpById)(mcpId);
|
|
141
|
-
if (mcp) {
|
|
142
|
-
validMcps.push(mcp);
|
|
143
|
-
}
|
|
144
|
-
else {
|
|
145
|
-
invalidMcps.push(mcpId);
|
|
146
|
-
}
|
|
147
|
-
}
|
|
148
|
-
if (invalidMcps.length > 0) {
|
|
149
|
-
error(`Invalid MCP(s): ${invalidMcps.join(', ')}`);
|
|
150
|
-
info('');
|
|
151
|
-
info('Available MCPs:');
|
|
152
|
-
availableMcps.forEach(m => {
|
|
153
|
-
info(` • ${m.id} - ${m.name}`);
|
|
154
|
-
});
|
|
155
|
-
return;
|
|
156
|
-
}
|
|
157
|
-
mcpsToInstall = validMcps;
|
|
158
|
-
}
|
|
159
|
-
else if (parameters.first === 'all' || skipInteractive) {
|
|
160
|
-
// Install all MCPs without prompting
|
|
161
|
-
mcpsToInstall = availableMcps;
|
|
162
|
-
if (skipInteractive) {
|
|
163
|
-
info('Installing all MCPs (non-interactive mode)...');
|
|
164
|
-
}
|
|
165
|
-
}
|
|
166
|
-
else {
|
|
167
|
-
// Interactive mode: ask for each MCP
|
|
168
|
-
const installAll = yield prompt.confirm('Install all MCPs?', true);
|
|
169
|
-
if (installAll) {
|
|
170
|
-
mcpsToInstall = availableMcps;
|
|
171
|
-
}
|
|
172
|
-
else {
|
|
173
|
-
info('');
|
|
174
|
-
info('Select which MCPs to install:');
|
|
175
|
-
info('');
|
|
176
|
-
for (const mcp of availableMcps) {
|
|
177
|
-
const installed = isMcpInstalled(mcp.id);
|
|
178
|
-
if (installed) {
|
|
179
|
-
info(` ✓ ${mcp.name} is already installed, skipping...`);
|
|
180
|
-
continue;
|
|
181
|
-
}
|
|
182
|
-
const shouldInstall = yield prompt.confirm(`Install ${mcp.name}?`, true);
|
|
183
|
-
if (shouldInstall) {
|
|
184
|
-
mcpsToInstall.push(mcp);
|
|
185
|
-
}
|
|
186
|
-
}
|
|
187
|
-
if (mcpsToInstall.length === 0) {
|
|
188
|
-
info('No MCPs selected. Installation cancelled.');
|
|
189
|
-
return;
|
|
190
|
-
}
|
|
191
|
-
}
|
|
192
|
-
}
|
|
193
|
-
// Filter out already installed MCPs
|
|
194
|
-
const notInstalled = mcpsToInstall.filter(mcp => !isMcpInstalled(mcp.id));
|
|
195
|
-
const alreadyInstalled = mcpsToInstall.filter(mcp => isMcpInstalled(mcp.id));
|
|
196
|
-
if (alreadyInstalled.length > 0) {
|
|
197
|
-
info('');
|
|
198
|
-
info('Already installed:');
|
|
199
|
-
alreadyInstalled.forEach(mcp => {
|
|
200
|
-
info(` ✓ ${mcp.name}`);
|
|
201
|
-
});
|
|
202
|
-
}
|
|
203
|
-
if (notInstalled.length === 0) {
|
|
204
|
-
info('');
|
|
205
|
-
success('All selected MCPs are already installed!');
|
|
206
|
-
return;
|
|
207
|
-
}
|
|
208
|
-
info('');
|
|
209
|
-
const installSpinner = spin(`Installing ${notInstalled.length} MCP(s)...`);
|
|
210
|
-
installSpinner.stop();
|
|
211
|
-
let installedCount = 0;
|
|
212
|
-
let failedCount = 0;
|
|
213
|
-
const failedMcps = [];
|
|
214
|
-
for (const mcp of notInstalled) {
|
|
215
|
-
info('');
|
|
216
|
-
info(`Installing ${mcp.name}...`);
|
|
217
|
-
const result = installMcp(mcp);
|
|
218
|
-
if (result.success) {
|
|
219
|
-
success(` ✓ ${mcp.name} installed successfully`);
|
|
220
|
-
installedCount++;
|
|
221
|
-
}
|
|
222
|
-
else {
|
|
223
|
-
warning(` ✗ Failed to install ${mcp.name}`);
|
|
224
|
-
failedMcps.push({ error: result.error || 'Unknown error', mcp });
|
|
225
|
-
failedCount++;
|
|
226
|
-
}
|
|
227
|
-
}
|
|
228
|
-
info('');
|
|
229
|
-
if (installedCount > 0) {
|
|
230
|
-
success(`Successfully installed ${installedCount} MCP(s)!`);
|
|
231
|
-
}
|
|
232
|
-
if (failedCount > 0) {
|
|
233
|
-
warning(`Failed to install ${failedCount} MCP(s):`);
|
|
234
|
-
failedMcps.forEach(({ error: err, mcp }) => {
|
|
235
|
-
info(` • ${mcp.name}: ${err}`);
|
|
236
|
-
});
|
|
237
|
-
}
|
|
238
|
-
info('');
|
|
239
|
-
info('MCPs are now available in Claude Code!');
|
|
240
|
-
info('');
|
|
241
|
-
info('Manage MCPs with:');
|
|
242
|
-
info(' • claude mcp list - List installed MCPs');
|
|
243
|
-
info(' • claude mcp remove - Remove an MCP');
|
|
244
|
-
}
|
|
245
|
-
catch (err) {
|
|
246
|
-
error(`Failed to install MCP(s): ${err.message}`);
|
|
247
|
-
info('');
|
|
248
|
-
info('Troubleshooting:');
|
|
249
|
-
info(' • Ensure Claude CLI is installed and configured');
|
|
250
|
-
info(' • Check your internet connection');
|
|
251
|
-
info(' • Try running with sudo if permission issues persist');
|
|
252
|
-
process.exit(1);
|
|
253
|
-
}
|
|
254
|
-
process.exit(0);
|
|
255
|
-
}),
|
|
256
|
-
};
|
|
257
|
-
exports.default = NewCommand;
|
|
258
|
-
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5zdGFsbC1tY3BzLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vc3JjL2NvbW1hbmRzL2NsYXVkZS9pbnN0YWxsLW1jcHMudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7Ozs7Ozs7Ozs7QUFBQSxpREFBeUM7QUFDekMsMkJBQWdDO0FBRWhDLDJCQUE2QjtBQUM3QiwrQkFBNEI7QUFHNUIseURBQTBFO0FBRTFFOzs7R0FHRztBQUNILFNBQVMsYUFBYTtJQUNwQixNQUFNLGFBQWEsR0FBRztRQUNwQixJQUFBLFdBQUksRUFBQyxJQUFBLFlBQU8sR0FBRSxFQUFFLFNBQVMsRUFBRSxPQUFPLEVBQUUsUUFBUSxDQUFDO1FBQzdDLHVCQUF1QjtRQUN2QixpQkFBaUI7S0FDbEIsQ0FBQztJQUVGLEtBQUssTUFBTSxDQUFDLElBQUksYUFBYSxFQUFFLENBQUM7UUFDOUIsSUFBSSxJQUFBLGVBQVUsRUFBQyxDQUFDLENBQUMsRUFBRSxDQUFDO1lBQ2xCLE9BQU8sQ0FBQyxDQUFDO1FBQ1gsQ0FBQztJQUNILENBQUM7SUFFRCxrQ0FBa0M7SUFDbEMsSUFBSSxDQUFDO1FBQ0gsTUFBTSxNQUFNLEdBQUcsSUFBQSx3QkFBUSxFQUFDLGNBQWMsRUFBRSxFQUFFLFFBQVEsRUFBRSxPQUFPLEVBQUUsS0FBSyxFQUFFLENBQUMsTUFBTSxFQUFFLE1BQU0sRUFBRSxNQUFNLENBQUMsRUFBRSxDQUFDLENBQUM7UUFDaEcsTUFBTSxJQUFJLEdBQUcsTUFBTSxDQUFDLElBQUksRUFBRSxDQUFDO1FBQzNCLElBQUksSUFBSSxJQUFJLElBQUEsZUFBVSxFQUFDLElBQUksQ0FBQyxFQUFFLENBQUM7WUFDN0IsT0FBTyxJQUFJLENBQUM7UUFDZCxDQUFDO0lBQ0gsQ0FBQztJQUFDLFdBQU0sQ0FBQztRQUNQLGdCQUFnQjtJQUNsQixDQUFDO0lBRUQsT0FBTyxJQUFJLENBQUM7QUFDZCxDQUFDO0FBRUQsSUFBSSxVQUFVLEdBQWtCLElBQUksQ0FBQztBQUVy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
|