@lenne.tech/cli 1.6.2 → 1.6.4

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.
@@ -0,0 +1,453 @@
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
+ exports.PLUGIN_POST_INSTALL = exports.MAX_COMMANDS_TO_SHOW = exports.EMPTY_PLUGIN_CONTENTS = void 0;
13
+ exports.findMarkdownFiles = findMarkdownFiles;
14
+ exports.handleMissingEnvVars = handleMissingEnvVars;
15
+ exports.printPluginSummary = printPluginSummary;
16
+ exports.processPostInstall = processPostInstall;
17
+ exports.readPluginContents = readPluginContents;
18
+ exports.setupPermissions = setupPermissions;
19
+ /**
20
+ * Plugin utilities for Claude Code plugin management
21
+ * Handles reading plugin contents, permissions, and post-installation setup
22
+ */
23
+ const child_process_1 = require("child_process");
24
+ const fs_1 = require("fs");
25
+ const os_1 = require("os");
26
+ const path_1 = require("path");
27
+ const claude_cli_1 = require("./claude-cli");
28
+ const json_utils_1 = require("./json-utils");
29
+ const shell_config_1 = require("./shell-config");
30
+ /**
31
+ * Empty plugin contents constant (used for failed installations)
32
+ */
33
+ exports.EMPTY_PLUGIN_CONTENTS = {
34
+ agents: [],
35
+ commands: [],
36
+ hooks: 0,
37
+ mcpServers: [],
38
+ permissions: [],
39
+ skills: [],
40
+ };
41
+ /**
42
+ * Maximum number of commands to show in plugin summary before truncating
43
+ */
44
+ exports.MAX_COMMANDS_TO_SHOW = 5;
45
+ /**
46
+ * Post-installation configurations for specific plugins
47
+ * These define additional setup steps needed after plugin installation
48
+ */
49
+ exports.PLUGIN_POST_INSTALL = {
50
+ 'typescript-lsp': {
51
+ envVars: [
52
+ {
53
+ description: 'Enable LSP tools in Claude Code (required for LSP features)',
54
+ name: 'ENABLE_LSP_TOOL',
55
+ value: '1',
56
+ },
57
+ ],
58
+ requirements: [
59
+ {
60
+ checkCommand: 'which typescript-language-server',
61
+ description: 'TypeScript language server',
62
+ installCommand: 'npm install -g typescript-language-server typescript',
63
+ },
64
+ ],
65
+ },
66
+ };
67
+ /**
68
+ * Recursively find all .md files in a directory and convert to command names
69
+ * @param dir - Directory to search
70
+ * @param basePath - Base path for relative path calculation
71
+ * @returns Array of command names (e.g., '/git:commit-message')
72
+ */
73
+ function findMarkdownFiles(dir, basePath = '') {
74
+ const results = [];
75
+ if (!(0, fs_1.existsSync)(dir))
76
+ return results;
77
+ try {
78
+ const entries = (0, fs_1.readdirSync)(dir, { withFileTypes: true });
79
+ for (const entry of entries) {
80
+ const fullPath = (0, path_1.join)(dir, entry.name);
81
+ const relativePath = basePath ? `${basePath}/${entry.name}` : entry.name;
82
+ if (entry.isDirectory()) {
83
+ results.push(...findMarkdownFiles(fullPath, relativePath));
84
+ }
85
+ else if (entry.isFile() && entry.name.endsWith('.md')) {
86
+ // Convert path to command name (e.g., "git/commit-message.md" -> "/git:commit-message")
87
+ const commandName = relativePath
88
+ .replace(/\.md$/, '')
89
+ .replace(/\//g, ':');
90
+ results.push(`/${commandName}`);
91
+ }
92
+ }
93
+ }
94
+ catch (_a) {
95
+ // Directory read failed, return empty results
96
+ }
97
+ return results;
98
+ }
99
+ /**
100
+ * Handle missing environment variables from plugin installations
101
+ * Checks shell config, prompts user to add missing vars, and provides manual instructions
102
+ * @param missingEnvVars - Map of env var name to PluginEnvVar
103
+ * @param toolbox - Toolbox with print and prompt functions
104
+ * @returns Result indicating if vars were needed and if they were configured
105
+ */
106
+ function handleMissingEnvVars(missingEnvVars, toolbox) {
107
+ return __awaiter(this, void 0, void 0, function* () {
108
+ const { print: { error, info, success, warning }, prompt, } = toolbox;
109
+ const result = {
110
+ configured: false,
111
+ needed: false,
112
+ };
113
+ if (missingEnvVars.size === 0) {
114
+ return result;
115
+ }
116
+ // Get preferred shell config
117
+ const targetConfig = (0, shell_config_1.getPreferredShellConfig)();
118
+ // Check which env vars are truly missing (not in file either)
119
+ const envVarsToAdd = [];
120
+ const envVarsAlreadyInFile = [];
121
+ for (const envVar of missingEnvVars.values()) {
122
+ if (targetConfig && (0, shell_config_1.checkEnvVarInFile)(targetConfig.path, envVar.name, envVar.value)) {
123
+ envVarsAlreadyInFile.push(envVar);
124
+ }
125
+ else {
126
+ envVarsToAdd.push(envVar);
127
+ }
128
+ }
129
+ // Show already configured vars
130
+ if (envVarsAlreadyInFile.length > 0) {
131
+ info('');
132
+ for (const envVar of envVarsAlreadyInFile) {
133
+ info(`${envVar.name} already configured in ${targetConfig === null || targetConfig === void 0 ? void 0 : targetConfig.path}`);
134
+ }
135
+ info(`Run 'source ${targetConfig === null || targetConfig === void 0 ? void 0 : targetConfig.path}' or restart your terminal to apply.`);
136
+ }
137
+ // Handle vars that need to be added
138
+ if (envVarsToAdd.length > 0) {
139
+ result.needed = true;
140
+ info('');
141
+ warning('Environment variables required:');
142
+ for (const envVar of envVarsToAdd) {
143
+ info(` ${envVar.name}=${envVar.value}`);
144
+ info(` ${envVar.description}`);
145
+ }
146
+ if (targetConfig) {
147
+ // Ask user if they want to add the env vars automatically
148
+ const shouldAdd = yield prompt.confirm(`Add ${envVarsToAdd.length > 1 ? 'these variables' : envVarsToAdd[0].name} to ${targetConfig.path}?`);
149
+ if (shouldAdd) {
150
+ let allAdded = true;
151
+ for (const envVar of envVarsToAdd) {
152
+ const added = (0, shell_config_1.addEnvVarToShellConfig)(targetConfig.path, envVar.name, envVar.value);
153
+ if (added) {
154
+ success(` Added ${envVar.name}=${envVar.value} to ${targetConfig.path}`);
155
+ }
156
+ else {
157
+ error(` Failed to add ${envVar.name} to ${targetConfig.path}`);
158
+ allAdded = false;
159
+ }
160
+ }
161
+ if (allAdded) {
162
+ result.configured = true;
163
+ info('');
164
+ info(`Run 'source ${targetConfig.path}' or restart your terminal to apply changes.`);
165
+ }
166
+ }
167
+ else {
168
+ info('');
169
+ info('To add manually, run:');
170
+ for (const envVar of envVarsToAdd) {
171
+ info(` echo 'export ${envVar.name}=${envVar.value}' >> ${targetConfig.path}`);
172
+ }
173
+ }
174
+ }
175
+ else {
176
+ info('');
177
+ info('Add manually to your shell profile:');
178
+ for (const envVar of envVarsToAdd) {
179
+ info(` export ${envVar.name}=${envVar.value}`);
180
+ }
181
+ }
182
+ }
183
+ return result;
184
+ });
185
+ }
186
+ /**
187
+ * Print plugin summary with skills, commands, agents, etc.
188
+ * @param pluginName - Name of the plugin
189
+ * @param contents - Plugin contents
190
+ * @param info - Info print function from toolbox
191
+ */
192
+ function printPluginSummary(pluginName, contents, info) {
193
+ const isLspPlugin = pluginName.endsWith('-lsp');
194
+ const hasContent = contents.skills.length > 0 || contents.commands.length > 0 || contents.agents.length > 0;
195
+ if (hasContent || isLspPlugin) {
196
+ info('');
197
+ info(`${pluginName}:`);
198
+ // Show LSP indicator for LSP plugins
199
+ if (isLspPlugin) {
200
+ info(` Type: Language Server (LSP)`);
201
+ }
202
+ // Alphabetical order: Agents, Commands, Hooks, MCP Servers, Skills
203
+ if (contents.agents.length > 0) {
204
+ info(` Agents (${contents.agents.length}): ${contents.agents.join(', ')}`);
205
+ }
206
+ if (contents.commands.length > 0) {
207
+ const shown = contents.commands.slice(0, exports.MAX_COMMANDS_TO_SHOW);
208
+ const remaining = contents.commands.length - exports.MAX_COMMANDS_TO_SHOW;
209
+ const commandsStr = remaining > 0
210
+ ? `${shown.join(', ')} and ${remaining} more`
211
+ : shown.join(', ');
212
+ info(` Commands (${contents.commands.length}): ${commandsStr}`);
213
+ }
214
+ if (contents.hooks > 0) {
215
+ info(` Hooks: ${contents.hooks} auto-detection hooks`);
216
+ }
217
+ if (contents.mcpServers.length > 0) {
218
+ info(` MCP Servers (${contents.mcpServers.length}): ${contents.mcpServers.join(', ')}`);
219
+ }
220
+ if (contents.skills.length > 0) {
221
+ info(` Skills (${contents.skills.length}): ${contents.skills.join(', ')}`);
222
+ }
223
+ }
224
+ }
225
+ /**
226
+ * Process post-installation requirements for a plugin
227
+ * Checks and installs required dependencies, reports missing env vars
228
+ * @param pluginName - Name of the plugin
229
+ * @param toolbox - Extended Gluegun toolbox
230
+ * @returns Post-install result with success status and details
231
+ */
232
+ function processPostInstall(pluginName, toolbox) {
233
+ const { print: { spin, warning }, } = toolbox;
234
+ const result = {
235
+ envVarsMissing: [],
236
+ requirementsInstalled: [],
237
+ requirementsMissing: [],
238
+ success: true,
239
+ };
240
+ const postInstall = exports.PLUGIN_POST_INSTALL[pluginName];
241
+ if (!postInstall) {
242
+ return result;
243
+ }
244
+ // Check and install requirements
245
+ if (postInstall.requirements) {
246
+ for (const req of postInstall.requirements) {
247
+ // If checkCommand is provided, verify if requirement is already met
248
+ if (req.checkCommand) {
249
+ const checkSpinner = spin(`Checking ${req.description}`);
250
+ if ((0, claude_cli_1.checkCommandExists)(req.checkCommand)) {
251
+ checkSpinner.succeed(`${req.description} already installed`);
252
+ continue;
253
+ }
254
+ // Try to install
255
+ checkSpinner.text = `Installing ${req.description}`;
256
+ try {
257
+ (0, child_process_1.execSync)(req.installCommand, {
258
+ encoding: 'utf-8',
259
+ stdio: ['pipe', 'pipe', 'pipe'],
260
+ });
261
+ // Verify installation
262
+ if ((0, claude_cli_1.checkCommandExists)(req.checkCommand)) {
263
+ checkSpinner.succeed(`${req.description} installed`);
264
+ result.requirementsInstalled.push(req.description);
265
+ }
266
+ else {
267
+ checkSpinner.fail(`${req.description} installation may have failed`);
268
+ result.requirementsMissing.push(req.description);
269
+ result.success = false;
270
+ }
271
+ }
272
+ catch (err) {
273
+ checkSpinner.fail(`Failed to install ${req.description}`);
274
+ warning(` Command: ${req.installCommand}`);
275
+ warning(` Error: ${err.message}`);
276
+ result.requirementsMissing.push(req.description);
277
+ result.success = false;
278
+ }
279
+ }
280
+ else {
281
+ // No checkCommand provided - always run installCommand
282
+ const installSpinner = spin(`Running ${req.description}`);
283
+ try {
284
+ (0, child_process_1.execSync)(req.installCommand, {
285
+ encoding: 'utf-8',
286
+ stdio: ['pipe', 'pipe', 'pipe'],
287
+ });
288
+ installSpinner.succeed(`${req.description} completed`);
289
+ result.requirementsInstalled.push(req.description);
290
+ }
291
+ catch (err) {
292
+ installSpinner.fail(`Failed: ${req.description}`);
293
+ warning(` Command: ${req.installCommand}`);
294
+ warning(` Error: ${err.message}`);
295
+ result.requirementsMissing.push(req.description);
296
+ result.success = false;
297
+ }
298
+ }
299
+ }
300
+ }
301
+ // Check environment variables
302
+ if (postInstall.envVars) {
303
+ for (const envVar of postInstall.envVars) {
304
+ const currentValue = process.env[envVar.name];
305
+ if (currentValue !== envVar.value) {
306
+ result.envVarsMissing.push(envVar);
307
+ }
308
+ }
309
+ }
310
+ return result;
311
+ }
312
+ /**
313
+ * Read plugin contents from installed plugin directory
314
+ * @param marketplaceName - Name of the marketplace
315
+ * @param pluginName - Name of the plugin
316
+ * @returns Plugin contents with skills, commands, agents, hooks, etc.
317
+ */
318
+ function readPluginContents(marketplaceName, pluginName) {
319
+ const pluginDir = (0, path_1.join)((0, os_1.homedir)(), '.claude', 'plugins', 'marketplaces', marketplaceName, 'plugins', pluginName);
320
+ const result = {
321
+ agents: [],
322
+ commands: [],
323
+ hooks: 0,
324
+ mcpServers: [],
325
+ permissions: [],
326
+ skills: [],
327
+ };
328
+ // Read skills
329
+ const skillsDir = (0, path_1.join)(pluginDir, 'skills');
330
+ if ((0, fs_1.existsSync)(skillsDir)) {
331
+ try {
332
+ result.skills = (0, fs_1.readdirSync)(skillsDir, { withFileTypes: true })
333
+ .filter(dirent => dirent.isDirectory())
334
+ .map(dirent => dirent.name);
335
+ }
336
+ catch (_a) {
337
+ // Skills directory read failed
338
+ }
339
+ }
340
+ // Read agents
341
+ const agentsDir = (0, path_1.join)(pluginDir, 'agents');
342
+ if ((0, fs_1.existsSync)(agentsDir)) {
343
+ try {
344
+ result.agents = (0, fs_1.readdirSync)(agentsDir, { withFileTypes: true })
345
+ .filter(dirent => dirent.isFile() && dirent.name.endsWith('.md'))
346
+ .map(dirent => dirent.name.replace(/\.md$/, ''));
347
+ }
348
+ catch (_b) {
349
+ // Agents directory read failed
350
+ }
351
+ }
352
+ // Read commands
353
+ const commandsDir = (0, path_1.join)(pluginDir, 'commands');
354
+ result.commands = findMarkdownFiles(commandsDir);
355
+ // Read hooks
356
+ const hooksPath = (0, path_1.join)(pluginDir, 'hooks', 'hooks.json');
357
+ const hooksContent = safeReadJson(hooksPath);
358
+ if (hooksContent === null || hooksContent === void 0 ? void 0 : hooksContent.hooks) {
359
+ // Count hooks across all event types
360
+ for (const eventHooks of Object.values(hooksContent.hooks)) {
361
+ if (Array.isArray(eventHooks)) {
362
+ for (const hookGroup of eventHooks) {
363
+ if (hookGroup.hooks && Array.isArray(hookGroup.hooks)) {
364
+ result.hooks += hookGroup.hooks.length;
365
+ }
366
+ }
367
+ }
368
+ }
369
+ }
370
+ // Read MCP servers
371
+ const mcpPath = (0, path_1.join)(pluginDir, '.mcp.json');
372
+ const mcpContent = safeReadJson(mcpPath);
373
+ if (mcpContent === null || mcpContent === void 0 ? void 0 : mcpContent.mcpServers) {
374
+ result.mcpServers = Object.keys(mcpContent.mcpServers);
375
+ }
376
+ // Read permissions
377
+ const permissionsPath = (0, path_1.join)(pluginDir, 'permissions.json');
378
+ const pluginPerms = safeReadJson(permissionsPath);
379
+ if (pluginPerms === null || pluginPerms === void 0 ? void 0 : pluginPerms.permissions) {
380
+ result.permissions = pluginPerms.permissions.map(p => p.pattern);
381
+ }
382
+ return result;
383
+ }
384
+ /**
385
+ * Setup permissions in settings.json
386
+ * Only adds new permissions, does not remove existing ones
387
+ * (User may have customized permissions that should be preserved)
388
+ * @param requiredPermissions - Array of permission patterns to add
389
+ * @param error - Error print function from toolbox
390
+ * @returns Result with added and existing permissions
391
+ */
392
+ function setupPermissions(requiredPermissions, error) {
393
+ const settingsPath = (0, path_1.join)((0, os_1.homedir)(), '.claude', 'settings.json');
394
+ try {
395
+ // Read existing settings
396
+ let settings = {};
397
+ if ((0, fs_1.existsSync)(settingsPath)) {
398
+ const content = (0, fs_1.readFileSync)(settingsPath, 'utf-8');
399
+ const parsed = (0, json_utils_1.safeJsonParse)(content);
400
+ if (parsed) {
401
+ settings = parsed;
402
+ }
403
+ }
404
+ // Ensure permissions.allow exists
405
+ if (!settings.permissions) {
406
+ settings.permissions = {};
407
+ }
408
+ const perms = settings.permissions;
409
+ if (!perms.allow) {
410
+ perms.allow = [];
411
+ }
412
+ const currentAllowList = perms.allow;
413
+ // Determine what to add
414
+ const added = [];
415
+ const existing = [];
416
+ requiredPermissions.forEach(perm => {
417
+ if (currentAllowList.includes(perm)) {
418
+ existing.push(perm);
419
+ }
420
+ else {
421
+ added.push(perm);
422
+ }
423
+ });
424
+ // Add new permissions
425
+ if (added.length > 0) {
426
+ perms.allow = [...currentAllowList, ...added];
427
+ (0, fs_1.writeFileSync)(settingsPath, JSON.stringify(settings, null, 2));
428
+ }
429
+ return { added, existing, success: true };
430
+ }
431
+ catch (err) {
432
+ error(`Could not configure permissions: ${err.message}`);
433
+ return { added: [], existing: [], success: false };
434
+ }
435
+ }
436
+ /**
437
+ * Safely read and parse a JSON file
438
+ * @param filePath - Path to the JSON file
439
+ * @returns Parsed object or null if reading/parsing fails
440
+ */
441
+ function safeReadJson(filePath) {
442
+ try {
443
+ if (!(0, fs_1.existsSync)(filePath)) {
444
+ return null;
445
+ }
446
+ const content = (0, fs_1.readFileSync)(filePath, 'utf-8');
447
+ return (0, json_utils_1.safeJsonParse)(content);
448
+ }
449
+ catch (_a) {
450
+ return null;
451
+ }
452
+ }
453
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicGx1Z2luLXV0aWxzLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vc3JjL2xpYi9wbHVnaW4tdXRpbHMudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7Ozs7Ozs7Ozs7O0FBNklBLDhDQXlCQztBQVNELG9EQXFHQztBQVFELGdEQXVDQztBQVNELGdEQXdGQztBQVFELGdEQStFQztBQVVELDRDQW1EQztBQXhqQkQ7OztHQUdHO0FBQ0gsaURBQXlDO0FBQ3pDLDJCQUEwRTtBQUMxRSwyQkFBNkI7QUFDN0IsK0JBQTRCO0FBRTVCLDZDQUFrRDtBQUNsRCw2Q0FBNkM7QUFDN0MsaURBSXdCO0FBZ0Z4Qjs7R0FFRztBQUNVLFFBQUEscUJBQXFCLEdBQW1CO0lBQ25ELE1BQU0sRUFBRSxFQUFFO0lBQ1YsUUFBUSxFQUFFLEVBQUU7SUFDWixLQUFLLEVBQUUsQ0FBQztJQUNSLFVBQVUsRUFBRSxFQUFFO0lBQ2QsV0FBVyxFQUFFLEVBQUU7SUFDZixNQUFNLEVBQUUsRUFBRTtDQUNYLENBQUM7QUFFRjs7R0FFRztBQUNVLFFBQUEsb0JBQW9CLEdBQUcsQ0FBQyxDQUFDO0FBRXRDOzs7R0FHRztBQUNVLFFBQUEsbUJBQW1CLEdBQXNDO0lBQ3BFLGdCQUFnQixFQUFFO1FBQ2hCLE9BQU8sRUFBRTtZQUNQO2dCQUNFLFdBQVcsRUFBRSw2REFBNkQ7Z0JBQzFFLElBQUksRUFBRSxpQkFBaUI7Z0JBQ3ZCLEtBQUssRUFBRSxHQUFHO2FBQ1g7U0FDRjtRQUNELFlBQVksRUFBRTtZQUNaO2dCQUNFLFlBQVksRUFBRSxrQ0FBa0M7Z0JBQ2hELFdBQVcsRUFBRSw0QkFBNEI7Z0JBQ3pDLGNBQWMsRUFBRSxzREFBc0Q7YUFDdkU7U0FDRjtLQUNGO0NBQ0YsQ0FBQztBQUVGOzs7OztHQUtHO0FBQ0gsU0FBZ0IsaUJBQWlCLENBQUMsR0FBVyxFQUFFLFFBQVEsR0FBRyxFQUFFO0lBQzFELE1BQU0sT0FBTyxHQUFhLEVBQUUsQ0FBQztJQUM3QixJQUFJLENBQUMs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
@@ -0,0 +1,110 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.addEnvVarToShellConfig = addEnvVarToShellConfig;
4
+ exports.checkEnvVarInFile = checkEnvVarInFile;
5
+ exports.detectShellConfigs = detectShellConfigs;
6
+ exports.getPreferredShellConfig = getPreferredShellConfig;
7
+ /**
8
+ * Shell configuration utilities for CLI commands
9
+ * Handles detection and modification of shell config files (.zshrc, .bashrc, etc.)
10
+ */
11
+ const fs_1 = require("fs");
12
+ const os_1 = require("os");
13
+ const path_1 = require("path");
14
+ /**
15
+ * Known shell configuration files in order of preference
16
+ */
17
+ const SHELL_CONFIG_FILES = [
18
+ { file: '.zshrc', shell: 'zsh' },
19
+ { file: '.bashrc', shell: 'bash' },
20
+ { file: '.bash_profile', shell: 'bash' },
21
+ { file: '.profile', shell: 'sh' },
22
+ ];
23
+ /**
24
+ * Add an environment variable export to a shell config file
25
+ * @param configPath - Full path to the shell config file
26
+ * @param envName - Name of the environment variable
27
+ * @param envValue - Value to set
28
+ * @param comment - Optional comment to add before the export
29
+ * @returns true if successful, false otherwise
30
+ */
31
+ function addEnvVarToShellConfig(configPath, envName, envValue, comment = 'Added by lenne.tech CLI') {
32
+ try {
33
+ const lineToAdd = `\n# ${comment}\nexport ${envName}=${envValue}\n`;
34
+ (0, fs_1.appendFileSync)(configPath, lineToAdd, 'utf-8');
35
+ return true;
36
+ }
37
+ catch (_a) {
38
+ return false;
39
+ }
40
+ }
41
+ /**
42
+ * Check if an environment variable is already set in a shell config file
43
+ * Checks for common export formats (with/without quotes)
44
+ * @param configPath - Full path to the shell config file
45
+ * @param envName - Name of the environment variable
46
+ * @param envValue - Expected value
47
+ * @returns true if the export exists in the file
48
+ */
49
+ function checkEnvVarInFile(configPath, envName, envValue) {
50
+ try {
51
+ if (!(0, fs_1.existsSync)(configPath)) {
52
+ return false;
53
+ }
54
+ const content = (0, fs_1.readFileSync)(configPath, 'utf-8');
55
+ // Check for existing export (with or without quotes)
56
+ const patterns = [
57
+ `export ${envName}=${envValue}`,
58
+ `export ${envName}="${envValue}"`,
59
+ `export ${envName}='${envValue}'`,
60
+ ];
61
+ return patterns.some(p => content.includes(p));
62
+ }
63
+ catch (_a) {
64
+ return false;
65
+ }
66
+ }
67
+ /**
68
+ * Detect available shell configuration files for the current user
69
+ * Prioritizes the current shell's config file
70
+ * @returns Array of shell config file info, sorted by preference
71
+ */
72
+ function detectShellConfigs() {
73
+ const home = (0, os_1.homedir)();
74
+ const configs = [];
75
+ // Check current shell from environment
76
+ const currentShell = process.env.SHELL ? (0, path_1.basename)(process.env.SHELL) : null;
77
+ for (const { file, shell } of SHELL_CONFIG_FILES) {
78
+ const fullPath = (0, path_1.join)(home, file);
79
+ const fileExists = (0, fs_1.existsSync)(fullPath);
80
+ // Prioritize current shell's config
81
+ if (fileExists || (currentShell && currentShell === shell)) {
82
+ configs.push({
83
+ exists: fileExists,
84
+ path: fullPath,
85
+ shell,
86
+ });
87
+ }
88
+ }
89
+ // If no configs found, suggest creating .zshrc or .bashrc based on current shell
90
+ if (configs.length === 0) {
91
+ const defaultShell = currentShell || 'zsh';
92
+ const defaultFile = defaultShell === 'bash' ? '.bashrc' : '.zshrc';
93
+ configs.push({
94
+ exists: false,
95
+ path: (0, path_1.join)(home, defaultFile),
96
+ shell: defaultShell,
97
+ });
98
+ }
99
+ return configs;
100
+ }
101
+ /**
102
+ * Get the preferred shell config file for the current user
103
+ * Returns the first existing config, or suggests a default
104
+ * @returns The preferred shell config file info, or null if none found
105
+ */
106
+ function getPreferredShellConfig() {
107
+ const configs = detectShellConfigs();
108
+ return configs.find(c => c.exists) || configs[0] || null;
109
+ }
110
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic2hlbGwtY29uZmlnLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vc3JjL2xpYi9zaGVsbC1jb25maWcudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7QUFzQ0Esd0RBYUM7QUFVRCw4Q0FnQkM7QUFPRCxnREFpQ0M7QUFPRCwwREFHQztBQS9IRDs7O0dBR0c7QUFDSCwyQkFBOEQ7QUFDOUQsMkJBQTZCO0FBQzdCLCtCQUFzQztBQWN0Qzs7R0FFRztBQUNILE1BQU0sa0JBQWtCLEdBQTJDO0lBQ2pFLEVBQUUsSUFBSSxFQUFFLFFBQVEsRUFBRSxLQUFLLEVBQUUsS0FBSyxFQUFFO0lBQ2hDLEVBQUUsSUFBSSxFQUFFLFNBQVMsRUFBRSxLQUFLLEVBQUUsTUFBTSxFQUFFO0lBQ2xDLEVBQUUsSUFBSSxFQUFFLGVBQWUsRUFBRSxLQUFLLEVBQUUsTUFBTSxFQUFFO0lBQ3hDLEVBQUUsSUFBSSxFQUFFLFVBQVUsRUFBRSxLQUFLLEVBQUUsSUFBSSxFQUFFO0NBQ2xDLENBQUM7QUFFRjs7Ozs7OztHQU9HO0FBQ0gsU0FBZ0Isc0JBQXNCLENBQ3BDLFVBQWtCLEVBQ2xCLE9BQWUsRUFDZixRQUFnQixFQUNoQixPQUFPLEdBQUcseUJBQXlCO0lBRW5DLElBQUksQ0FBQztRQUNILE1BQU0sU0FBUyxHQUFHLE9BQU8sT0FBTyxZQUFZLE9BQU8sSUFBSSxRQUFRLElBQUksQ0FBQztRQUNwRSxJQUFBLG1CQUFjLEVBQUMsVUFBVSxFQUFFLFNBQVMsRUFBRSxPQUFPLENBQUMsQ0FBQztRQUMvQyxPQUFPLElBQUksQ0FBQztJQUNkLENBQUM7SUFBQyxXQUFNLENBQUM7UUFDUCxPQUFPLEtBQUssQ0FBQztJQUNmLENBQUM7QUFDSCxDQUFDO0FBRUQ7Ozs7Ozs7R0FPRztBQUNILFNBQWdCLGlCQUFpQixDQUFDLFVBQWtCLEVBQUUsT0FBZSxFQUFFLFFBQWdCO0lBQ3JGLElBQUksQ0FBQztRQUNILElBQUksQ0FBQyxJQUFBLGVBQVUsRUFBQyxVQUFVLENB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
package/docs/commands.md CHANGED
@@ -844,14 +844,45 @@ lt starter chrome-extension [name]
844
844
 
845
845
  ### `lt claude plugins`
846
846
 
847
- Manages Claude Code plugins.
847
+ Installs and manages Claude Code plugins from multiple marketplaces.
848
848
 
849
849
  **Usage:**
850
850
  ```bash
851
- lt claude plugins
851
+ lt claude plugins [plugin-name] [options]
852
852
  ```
853
853
 
854
- Lists and manages installed Claude Code plugins.
854
+ **Parameters:**
855
+ | Parameter | Description |
856
+ |-----------|-------------|
857
+ | `plugin-name` | Optional. Name of a specific plugin to install |
858
+
859
+ **Options:**
860
+ | Option | Description |
861
+ |--------|-------------|
862
+ | `--list` | List available plugins from all marketplaces |
863
+ | `--uninstall` | Uninstall a plugin |
864
+
865
+ **Plugin Sources:**
866
+ - [lenne-tech marketplace](https://github.com/lenneTech/claude-code) - lenne.Tech plugins for NestJS development
867
+ - [claude-plugins-official](https://github.com/anthropics/claude-plugins-official) - Official Anthropic plugins (e.g., typescript-lsp)
868
+
869
+ **Default Behavior:**
870
+ When run without a plugin name, all lenne.Tech plugins plus recommended external plugins (like `typescript-lsp`) are installed automatically.
871
+
872
+ **Examples:**
873
+ ```bash
874
+ # Install all recommended plugins (lenne.Tech + recommended external)
875
+ lt claude plugins
876
+
877
+ # Install a specific plugin
878
+ lt claude plugins typescript-lsp
879
+
880
+ # List available plugins
881
+ lt claude plugins --list
882
+
883
+ # Uninstall a plugin
884
+ lt claude plugins lt-dev --uninstall
885
+ ```
855
886
 
856
887
  ---
857
888
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lenne.tech/cli",
3
- "version": "1.6.2",
3
+ "version": "1.6.4",
4
4
  "description": "lenne.Tech CLI: lt",
5
5
  "keywords": [
6
6
  "lenne.Tech",