@lenne.tech/cli 1.6.3 → 1.6.5

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}?`, true);
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,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicGx1Z2luLXV0aWxzLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vc3JjL2xpYi9wbHVnaW4tdXRpbHMudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7Ozs7Ozs7Ozs7O0FBNklBLDhDQXlCQztBQVNELG9EQXNHQztBQVFELGdEQXVDQztBQVNELGdEQXdGQztBQVFELGdEQStFQztBQVVELDRDQW1EQztBQXpqQkQ7OztHQUdHO0FBQ0gsaURBQXlDO0FBQ3pDLDJCQUEwRTtBQUMxRSwyQkFBNkI7QUFDN0IsK0JBQTRCO0FBRTVCLDZDQUFrRDtBQUNsRCw2Q0FBNkM7QUFDN0MsaURBSXdCO0FBZ0Z4Qjs7R0FFRztBQUNVLFFBQUEscUJBQXFCLEdBQW1CO0lBQ25ELE1BQU0sRUFBRSxFQUFFO0lBQ1YsUUFBUSxFQUFFLEVBQUU7SUFDWixLQUFLLEVBQUUsQ0FBQztJQUNSLFVBQVUsRUFBRSxFQUFFO0lBQ2QsV0FBVyxFQUFFLEVBQUU7SUFDZixNQUFNLEVBQUUsRUFBRTtDQUNYLENBQUM7QUFFRjs7R0FFRztBQUNVLFFBQUEsb0JBQW9CLEdBQUcsQ0FBQyxDQUFDO0FBRXRDOzs7R0FHRztBQUNVLFFBQUEsbUJBQW1CLEdBQXNDO0lBQ3BFLGdCQUFnQixFQUFFO1FBQ2hCLE9BQU8sRUFBRTtZQUNQO2dCQUNFLFdBQVcsRUFBRSw2REFBNkQ7Z0JBQzFFLElBQUksRUFBRSxpQkFBaUI7Z0JBQ3ZCLEtBQUssRUFBRSxHQUFHO2FBQ1g7U0FDRjtRQUNELFlBQVksRUFBRTtZQUNaO2dCQUNFLFlBQVksRUFBRSxrQ0FBa0M7Z0JBQ2hELFdBQVcsRUFBRSw0QkFBNEI7Z0JBQ3pDLGNBQWMsRUFBRSxzREFBc0Q7YUFDdkU7U0FDRjtLQUNGO0NBQ0YsQ0FBQztBQUVGOzs7OztHQUtHO0FBQ0gsU0FBZ0IsaUJBQWlCLENBQUMsR0FBVyxFQUFFLFFBQVEsR0FBRyxFQUFFO0lBQzFELE1BQU0sT0FBTyxHQUFhLEVBQUUsQ0FBQztJQUM3QixJQUFJLENBQUMs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
@@ -0,0 +1,175 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.addAliasBlockToShellConfig = addAliasBlockToShellConfig;
4
+ exports.addAliasToShellConfig = addAliasToShellConfig;
5
+ exports.addEnvVarToShellConfig = addEnvVarToShellConfig;
6
+ exports.checkAliasInFile = checkAliasInFile;
7
+ exports.checkEnvVarInFile = checkEnvVarInFile;
8
+ exports.detectShellConfigs = detectShellConfigs;
9
+ exports.getPreferredShellConfig = getPreferredShellConfig;
10
+ /**
11
+ * Shell configuration utilities for CLI commands
12
+ * Handles detection and modification of shell config files (.zshrc, .bashrc, etc.)
13
+ */
14
+ const fs_1 = require("fs");
15
+ const os_1 = require("os");
16
+ const path_1 = require("path");
17
+ /**
18
+ * Known shell configuration files in order of preference
19
+ */
20
+ const SHELL_CONFIG_FILES = [
21
+ { file: '.zshrc', shell: 'zsh' },
22
+ { file: '.bashrc', shell: 'bash' },
23
+ { file: '.bash_profile', shell: 'bash' },
24
+ { file: '.profile', shell: 'sh' },
25
+ ];
26
+ /**
27
+ * Add multiple aliases to a shell config file as a block
28
+ * @param configPath - Full path to the shell config file
29
+ * @param aliases - Array of alias definitions
30
+ * @param blockComment - Comment header for the block
31
+ * @returns true if successful, false otherwise
32
+ */
33
+ function addAliasBlockToShellConfig(configPath, aliases, blockComment = 'Claude Code shortcuts - Added by lenne.tech CLI') {
34
+ try {
35
+ const lines = [`\n# ${blockComment}`];
36
+ for (const { alias, command } of aliases) {
37
+ lines.push(`alias ${alias}='${command}'`);
38
+ }
39
+ lines.push('');
40
+ (0, fs_1.appendFileSync)(configPath, lines.join('\n'), 'utf-8');
41
+ return true;
42
+ }
43
+ catch (_a) {
44
+ return false;
45
+ }
46
+ }
47
+ /**
48
+ * Add an alias to a shell config file
49
+ * @param configPath - Full path to the shell config file
50
+ * @param alias - Alias name
51
+ * @param command - Command the alias expands to
52
+ * @param comment - Optional comment to add before the alias
53
+ * @returns true if successful, false otherwise
54
+ */
55
+ function addAliasToShellConfig(configPath, alias, command, comment = 'Added by lenne.tech CLI') {
56
+ try {
57
+ const lineToAdd = `\n# ${comment}\nalias ${alias}='${command}'\n`;
58
+ (0, fs_1.appendFileSync)(configPath, lineToAdd, 'utf-8');
59
+ return true;
60
+ }
61
+ catch (_a) {
62
+ return false;
63
+ }
64
+ }
65
+ /**
66
+ * Add an environment variable export to a shell config file
67
+ * @param configPath - Full path to the shell config file
68
+ * @param envName - Name of the environment variable
69
+ * @param envValue - Value to set
70
+ * @param comment - Optional comment to add before the export
71
+ * @returns true if successful, false otherwise
72
+ */
73
+ function addEnvVarToShellConfig(configPath, envName, envValue, comment = 'Added by lenne.tech CLI') {
74
+ try {
75
+ const lineToAdd = `\n# ${comment}\nexport ${envName}=${envValue}\n`;
76
+ (0, fs_1.appendFileSync)(configPath, lineToAdd, 'utf-8');
77
+ return true;
78
+ }
79
+ catch (_a) {
80
+ return false;
81
+ }
82
+ }
83
+ /**
84
+ * Check if an alias is already defined in a shell config file
85
+ * @param configPath - Full path to the shell config file
86
+ * @param alias - Alias name to check
87
+ * @returns true if the alias exists in the file
88
+ */
89
+ function checkAliasInFile(configPath, alias) {
90
+ try {
91
+ if (!(0, fs_1.existsSync)(configPath)) {
92
+ return false;
93
+ }
94
+ const content = (0, fs_1.readFileSync)(configPath, 'utf-8');
95
+ // Check for alias definition (with single or double quotes)
96
+ const patterns = [
97
+ `alias ${alias}=`,
98
+ `alias ${alias} =`,
99
+ ];
100
+ return patterns.some(p => content.includes(p));
101
+ }
102
+ catch (_a) {
103
+ return false;
104
+ }
105
+ }
106
+ /**
107
+ * Check if an environment variable is already set in a shell config file
108
+ * Checks for common export formats (with/without quotes)
109
+ * @param configPath - Full path to the shell config file
110
+ * @param envName - Name of the environment variable
111
+ * @param envValue - Expected value
112
+ * @returns true if the export exists in the file
113
+ */
114
+ function checkEnvVarInFile(configPath, envName, envValue) {
115
+ try {
116
+ if (!(0, fs_1.existsSync)(configPath)) {
117
+ return false;
118
+ }
119
+ const content = (0, fs_1.readFileSync)(configPath, 'utf-8');
120
+ // Check for existing export (with or without quotes)
121
+ const patterns = [
122
+ `export ${envName}=${envValue}`,
123
+ `export ${envName}="${envValue}"`,
124
+ `export ${envName}='${envValue}'`,
125
+ ];
126
+ return patterns.some(p => content.includes(p));
127
+ }
128
+ catch (_a) {
129
+ return false;
130
+ }
131
+ }
132
+ /**
133
+ * Detect available shell configuration files for the current user
134
+ * Prioritizes the current shell's config file
135
+ * @returns Array of shell config file info, sorted by preference
136
+ */
137
+ function detectShellConfigs() {
138
+ const home = (0, os_1.homedir)();
139
+ const configs = [];
140
+ // Check current shell from environment
141
+ const currentShell = process.env.SHELL ? (0, path_1.basename)(process.env.SHELL) : null;
142
+ for (const { file, shell } of SHELL_CONFIG_FILES) {
143
+ const fullPath = (0, path_1.join)(home, file);
144
+ const fileExists = (0, fs_1.existsSync)(fullPath);
145
+ // Prioritize current shell's config
146
+ if (fileExists || (currentShell && currentShell === shell)) {
147
+ configs.push({
148
+ exists: fileExists,
149
+ path: fullPath,
150
+ shell,
151
+ });
152
+ }
153
+ }
154
+ // If no configs found, suggest creating .zshrc or .bashrc based on current shell
155
+ if (configs.length === 0) {
156
+ const defaultShell = currentShell || 'zsh';
157
+ const defaultFile = defaultShell === 'bash' ? '.bashrc' : '.zshrc';
158
+ configs.push({
159
+ exists: false,
160
+ path: (0, path_1.join)(home, defaultFile),
161
+ shell: defaultShell,
162
+ });
163
+ }
164
+ return configs;
165
+ }
166
+ /**
167
+ * Get the preferred shell config file for the current user
168
+ * Returns the first existing config, or suggests a default
169
+ * @returns The preferred shell config file info, or null if none found
170
+ */
171
+ function getPreferredShellConfig() {
172
+ const configs = detectShellConfigs();
173
+ return configs.find(c => c.exists) || configs[0] || null;
174
+ }
175
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic2hlbGwtY29uZmlnLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vc3JjL2xpYi9zaGVsbC1jb25maWcudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7QUFpREEsZ0VBZ0JDO0FBVUQsc0RBYUM7QUFVRCx3REFhQztBQVFELDRDQWVDO0FBVUQsOENBZ0JDO0FBT0QsZ0RBaUNDO0FBT0QsMERBR0M7QUFsTkQ7OztHQUdHO0FBQ0gsMkJBQThEO0FBQzlELDJCQUE2QjtBQUM3QiwrQkFBc0M7QUEwQnRDOztHQUVHO0FBQ0gsTUFBTSxrQkFBa0IsR0FBMkM7SUFDakUsRUFBRSxJQUFJLEVBQUUsUUFBUSxFQUFFLEtBQUssRUFBRSxLQUFLLEVBQUU7SUFDaEMsRUFBRSxJQUFJLEVBQUUsU0FBUyxFQUFFLEtBQUssRUFBRSxNQUFNLEVBQUU7SUFDbEMsRUFBRSxJQUFJLEVBQUUsZUFBZSxFQUFFLEtBQUssRUFBRSxNQUFNLEVBQUU7SUFDeEMsRUFBRSxJQUFJLEVBQUUsVUFBVSxFQUFFLEtBQUssRUFBRSxJQUFJLEVBQUU7Q0FDbEMsQ0FBQztBQUVGOzs7Ozs7R0FNRztBQUNILFNBQWdCLDBCQUEwQixDQUN4QyxVQUFrQixFQUNsQixPQUFxQixFQUNyQixZQUFZLEdBQUcsaURBQWlEO0lBRWhFLElBQUksQ0FBQztRQUNILE1BQU0sS0FBSyxHQUFHLENBQUMsT0FBTyxZQUFZLEVBQUUsQ0FBQyxDQUFDO1FBQ3RDLEtBQUssTUFBTSxFQUFFLEtBQUssRUFBRSxPQUFPLEVBQUUsSUFBSSxPQUFPLEVBQUUsQ0FBQztZQUN6QyxLQUFLLENBQUMsSUFBSSxDQUFDLFNBQVMsS0FBSyxLQUFLLE9BQU8sR0FBRyxDQUFDLENBQUM7UUFDNUMsQ0FBQztRQUNELEtBQUssQ0FBQyxJQUFJLENBQUMsRUFBRSxDQUFDLENBQUM7UUFDZixJQUFBLG1CQUFjLEVBQUMsVUFBVSxFQUFFLEtBQUssQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLEVBQUUsT0FBTyxDQUFD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