ai-account-switch 1.9.0 โ†’ 1.11.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.
@@ -0,0 +1,728 @@
1
+ const chalk = require('chalk');
2
+ const inquirer = require('inquirer');
3
+ const fs = require('fs');
4
+ const path = require('path');
5
+ const os = require('os');
6
+ const ConfigManager = require('../config');
7
+ const { maskEnvValue } = require('./helpers');
8
+
9
+ const config = new ConfigManager();
10
+
11
+ /**
12
+ * Get Claude user config path (using ConfigManager's method for consistency)
13
+ */
14
+ function getClaudeUserConfigPath() {
15
+ const claudeConfigPath = config.getClaudeUserConfigPath();
16
+
17
+ // If config exists, return it; otherwise, use default path
18
+ if (claudeConfigPath) {
19
+ return claudeConfigPath;
20
+ }
21
+
22
+ // Fallback to default location
23
+ const home = process.env.HOME || process.env.USERPROFILE;
24
+ if (!home) return null;
25
+
26
+ return path.join(home, '.claude', 'settings.json');
27
+ }
28
+
29
+ /**
30
+ * Read Claude project config (.claude/settings.local.json)
31
+ */
32
+ function readClaudeProjectConfig(projectRoot = process.cwd()) {
33
+ const claudeConfigFile = path.join(projectRoot, '.claude', 'settings.local.json');
34
+
35
+ if (!fs.existsSync(claudeConfigFile)) {
36
+ return { env: {} };
37
+ }
38
+
39
+ try {
40
+ const data = fs.readFileSync(claudeConfigFile, 'utf8');
41
+ const config = JSON.parse(data);
42
+ // Ensure env property exists
43
+ if (!config.env) {
44
+ config.env = {};
45
+ }
46
+ return config;
47
+ } catch (error) {
48
+ return { env: {} };
49
+ }
50
+ }
51
+
52
+ /**
53
+ * Write Claude project config
54
+ */
55
+ function writeClaudeProjectConfig(claudeConfig, projectRoot = process.cwd()) {
56
+ const claudeDir = path.join(projectRoot, '.claude');
57
+ const claudeConfigFile = path.join(claudeDir, 'settings.local.json');
58
+
59
+ // Create .claude directory if it doesn't exist
60
+ if (!fs.existsSync(claudeDir)) {
61
+ fs.mkdirSync(claudeDir, { recursive: true });
62
+ }
63
+
64
+ // Read existing config and merge with new env
65
+ let existingConfig = {};
66
+ if (fs.existsSync(claudeConfigFile)) {
67
+ try {
68
+ const data = fs.readFileSync(claudeConfigFile, 'utf8');
69
+ existingConfig = JSON.parse(data);
70
+ } catch (error) {
71
+ // If parsing fails, start fresh
72
+ }
73
+ }
74
+
75
+ // Merge env property
76
+ existingConfig.env = claudeConfig.env || {};
77
+
78
+ fs.writeFileSync(claudeConfigFile, JSON.stringify(existingConfig, null, 2), 'utf8');
79
+ }
80
+
81
+ /**
82
+ * Read Claude user config (~/.claude.json or ~/.config/claude/config.json)
83
+ */
84
+ function readClaudeUserConfig() {
85
+ const claudeConfigPath = getClaudeUserConfigPath();
86
+
87
+ if (!claudeConfigPath || !fs.existsSync(claudeConfigPath)) {
88
+ return { env: {} };
89
+ }
90
+
91
+ try {
92
+ const data = fs.readFileSync(claudeConfigPath, 'utf8');
93
+ const config = JSON.parse(data);
94
+ // Ensure env property exists
95
+ if (!config.env) {
96
+ config.env = {};
97
+ }
98
+ return config;
99
+ } catch (error) {
100
+ return { env: {} };
101
+ }
102
+ }
103
+
104
+ /**
105
+ * Write Claude user config
106
+ */
107
+ function writeClaudeUserConfig(claudeConfig) {
108
+ const claudeConfigPath = getClaudeUserConfigPath();
109
+
110
+ if (!claudeConfigPath) {
111
+ throw new Error('Could not determine Claude config path');
112
+ }
113
+
114
+ // Create directory if it doesn't exist
115
+ const claudeConfigDir = path.dirname(claudeConfigPath);
116
+ if (!fs.existsSync(claudeConfigDir)) {
117
+ fs.mkdirSync(claudeConfigDir, { recursive: true });
118
+ }
119
+
120
+ // Read existing config and merge with new env
121
+ let existingConfig = {};
122
+ if (fs.existsSync(claudeConfigPath)) {
123
+ try {
124
+ const data = fs.readFileSync(claudeConfigPath, 'utf8');
125
+ existingConfig = JSON.parse(data);
126
+ } catch (error) {
127
+ // If parsing fails, start fresh
128
+ }
129
+ }
130
+
131
+ // Merge env property
132
+ existingConfig.env = claudeConfig.env || {};
133
+
134
+ fs.writeFileSync(claudeConfigPath, JSON.stringify(existingConfig, null, 2), 'utf8');
135
+ }
136
+
137
+ /**
138
+ * List environment variables from both project and user configs
139
+ */
140
+ async function listEnv() {
141
+ try {
142
+ const projectRoot = config.findProjectRoot();
143
+ const projectConfig = projectRoot ? readClaudeProjectConfig(projectRoot) : null;
144
+ const userConfig = readClaudeUserConfig();
145
+
146
+ console.log(chalk.bold.cyan('\n๐Ÿ“‹ Environment Variables (็Žฏๅขƒๅ˜้‡)\n'));
147
+
148
+ // Project-level environment variables
149
+ if (projectRoot) {
150
+ console.log(chalk.bold('Project Level (้กน็›ฎ็บงๅˆซ):'));
151
+ console.log(` ${chalk.cyan('Path:')} ${projectRoot}`);
152
+ console.log(` ${chalk.cyan('Config:')} ${path.join(projectRoot, '.claude', 'settings.local.json')}\n`);
153
+
154
+ const projectEnv = projectConfig.env || {};
155
+ if (Object.keys(projectEnv).length > 0) {
156
+ console.log(chalk.bold(' Variables (ๅ˜้‡):'));
157
+ Object.entries(projectEnv).forEach(([key, value]) => {
158
+ const maskedValue = maskEnvValue(key, value);
159
+ console.log(` ${chalk.cyan(key)} = ${chalk.yellow(maskedValue)}`);
160
+ });
161
+ } else {
162
+ console.log(chalk.yellow(' No environment variables configured (ๆœช้…็ฝฎ็Žฏๅขƒๅ˜้‡)'));
163
+ }
164
+ console.log('');
165
+ } else {
166
+ console.log(chalk.yellow('Not in a project directory (ๆœชๅœจ้กน็›ฎ็›ฎๅฝ•ไธญ)\n'));
167
+ }
168
+
169
+ // User-level environment variables
170
+ console.log(chalk.bold('User Level (็”จๆˆท็บงๅˆซ):'));
171
+ const claudeConfigPath = getClaudeUserConfigPath();
172
+ console.log(` ${chalk.cyan('Config:')} ${claudeConfigPath}\n`);
173
+
174
+ const userEnv = userConfig.env || {};
175
+ if (Object.keys(userEnv).length > 0) {
176
+ console.log(chalk.bold(' Variables (ๅ˜้‡):'));
177
+ Object.entries(userEnv).forEach(([key, value]) => {
178
+ const maskedValue = maskEnvValue(key, value);
179
+ console.log(` ${chalk.cyan(key)} = ${chalk.yellow(maskedValue)}`);
180
+ });
181
+ } else {
182
+ console.log(chalk.yellow(' No environment variables configured (ๆœช้…็ฝฎ็Žฏๅขƒๅ˜้‡)'));
183
+ }
184
+ console.log('');
185
+ } catch (error) {
186
+ console.error(chalk.red('โœ— Error listing environment variables:'), error.message);
187
+ }
188
+ }
189
+
190
+ /**
191
+ * Add or update environment variable
192
+ */
193
+ async function addEnv() {
194
+ try {
195
+ const projectRoot = config.findProjectRoot();
196
+
197
+ const { level } = await inquirer.prompt([
198
+ {
199
+ type: 'list',
200
+ name: 'level',
201
+ message: 'Select configuration level (่ฏท้€‰ๆ‹ฉ้…็ฝฎ็บงๅˆซ):',
202
+ choices: projectRoot
203
+ ? [
204
+ { name: 'Project (้กน็›ฎ) - Only for current project (ไป…ๅฝ“ๅ‰้กน็›ฎ)', value: 'project' },
205
+ { name: 'User (็”จๆˆท) - For all projects (ๆ‰€ๆœ‰้กน็›ฎ)', value: 'user' }
206
+ ]
207
+ : [
208
+ { name: 'User (็”จๆˆท) - For all projects (ๆ‰€ๆœ‰้กน็›ฎ)', value: 'user' }
209
+ ]
210
+ }
211
+ ]);
212
+
213
+ let existingEnv;
214
+ let configPath;
215
+ let isUserLevel = level === 'user';
216
+
217
+ if (isUserLevel) {
218
+ const userConfig = readClaudeUserConfig();
219
+ existingEnv = userConfig.env || {};
220
+ configPath = getClaudeUserConfigPath();
221
+ } else {
222
+ const projectConfig = readClaudeProjectConfig(projectRoot);
223
+ existingEnv = projectConfig.env || {};
224
+ configPath = path.join(projectRoot, '.claude', 'settings.local.json');
225
+ }
226
+
227
+ // Show existing variables
228
+ if (Object.keys(existingEnv).length > 0) {
229
+ console.log(chalk.cyan('\n๐Ÿ“‹ Existing environment variables (็Žฐๆœ‰็Žฏๅขƒๅ˜้‡):\n'));
230
+ Object.entries(existingEnv).forEach(([key, value]) => {
231
+ const maskedValue = maskEnvValue(key, value);
232
+ console.log(` ${chalk.gray('โ€ข')} ${chalk.cyan(key)} = ${chalk.yellow(maskedValue)}`);
233
+ });
234
+ console.log('');
235
+ }
236
+
237
+ const { key, value } = await inquirer.prompt([
238
+ {
239
+ type: 'input',
240
+ name: 'key',
241
+ message: 'Enter environment variable name (่ฏท่พ“ๅ…ฅ็Žฏๅขƒๅ˜้‡ๅ็งฐ):',
242
+ validate: (input) => {
243
+ if (!input.trim()) {
244
+ return 'Environment variable name is required (็Žฏๅขƒๅ˜้‡ๅ็งฐไธ่ƒฝไธบ็ฉบ)';
245
+ }
246
+ if (!/^[A-Z_][A-Z0-9_]*$/.test(input.trim())) {
247
+ return 'Invalid variable name. Use uppercase letters, numbers, and underscores (e.g., MY_VAR) (ๅ˜้‡ๅๆ— ๆ•ˆใ€‚่ฏทไฝฟ็”จๅคงๅ†™ๅญ—ๆฏใ€ๆ•ฐๅญ—ๅ’Œไธ‹ๅˆ’็บฟ,ไพ‹ๅฆ‚: MY_VAR)';
248
+ }
249
+ return true;
250
+ }
251
+ },
252
+ {
253
+ type: 'input',
254
+ name: 'value',
255
+ message: 'Enter environment variable value (่ฏท่พ“ๅ…ฅ็Žฏๅขƒๅ˜้‡ๅ€ผ):',
256
+ validate: (input) => input.trim() !== '' || 'Environment variable value is required (็Žฏๅขƒๅ˜้‡ๅ€ผไธ่ƒฝไธบ็ฉบ)'
257
+ }
258
+ ]);
259
+
260
+ const envKey = key.trim();
261
+ const envValue = value.trim();
262
+
263
+ // Check if variable already exists
264
+ if (existingEnv[envKey]) {
265
+ const { overwrite } = await inquirer.prompt([
266
+ {
267
+ type: 'confirm',
268
+ name: 'overwrite',
269
+ message: `Variable '${envKey}' already exists with value '${existingEnv[envKey]}'. Overwrite? (ๅ˜้‡ '${envKey}' ๅทฒๅญ˜ๅœจ,ๅ€ผไธบ '${existingEnv[envKey]}'ใ€‚ๆ˜ฏๅฆ่ฆ†็›–?)`,
270
+ default: false
271
+ }
272
+ ]);
273
+
274
+ if (!overwrite) {
275
+ console.log(chalk.yellow('Operation cancelled. (ๆ“ไฝœๅทฒๅ–ๆถˆใ€‚)'));
276
+ return;
277
+ }
278
+ }
279
+
280
+ // Update the config
281
+ if (isUserLevel) {
282
+ const userConfig = readClaudeUserConfig();
283
+ userConfig.env = userConfig.env || {};
284
+ userConfig.env[envKey] = envValue;
285
+ writeClaudeUserConfig(userConfig);
286
+ } else {
287
+ const projectConfig = readClaudeProjectConfig(projectRoot);
288
+ projectConfig.env = projectConfig.env || {};
289
+ projectConfig.env[envKey] = envValue;
290
+ writeClaudeProjectConfig(projectConfig, projectRoot);
291
+ }
292
+
293
+ console.log(chalk.green(`\nโœ“ Environment variable '${envKey}' added successfully at ${level} level! (็Žฏๅขƒๅ˜้‡ '${envKey}' ๅœจ${level === 'project' ? '้กน็›ฎ' : '็”จๆˆท'}็บงๅˆซๆทปๅŠ ๆˆๅŠŸ!)`));
294
+ console.log(` ${chalk.cyan('Config file (้…็ฝฎๆ–‡ไปถ):')} ${configPath}\n`);
295
+ } catch (error) {
296
+ console.error(chalk.red('โœ— Error adding environment variable:'), error.message);
297
+ }
298
+ }
299
+
300
+ /**
301
+ * Set environment variable (non-interactive, for scripts)
302
+ */
303
+ async function setEnv(key, value, options = {}) {
304
+ try {
305
+ const level = options.level || 'user';
306
+ const isUserLevel = level === 'user';
307
+
308
+ if (!key || !value) {
309
+ console.log(chalk.red('โœ— Key and value are required (้”ฎๅ’Œๅ€ผ้ƒฝๆ˜ฏๅฟ…้œ€็š„)'));
310
+ console.log(chalk.cyan('Usage: ais env set <key> <value> [--level=project|user]'));
311
+ return;
312
+ }
313
+
314
+ // Validate key format
315
+ if (!/^[A-Z_][A-Z0-9_]*$/.test(key)) {
316
+ console.log(chalk.red(`โœ— Invalid variable name '${key}'. Use uppercase letters, numbers, and underscores (e.g., MY_VAR)`));
317
+ return;
318
+ }
319
+
320
+ let configPath;
321
+
322
+ if (isUserLevel) {
323
+ const userConfig = readClaudeUserConfig();
324
+ userConfig.env = userConfig.env || {};
325
+ userConfig.env[key] = value;
326
+ writeClaudeUserConfig(userConfig);
327
+ configPath = getClaudeUserConfigPath();
328
+ } else {
329
+ const projectRoot = config.findProjectRoot();
330
+ if (!projectRoot) {
331
+ console.log(chalk.red('โœ— Not in a project directory. Use --level=user or run from a project directory'));
332
+ return;
333
+ }
334
+ const projectConfig = readClaudeProjectConfig(projectRoot);
335
+ projectConfig.env = projectConfig.env || {};
336
+ projectConfig.env[key] = value;
337
+ writeClaudeProjectConfig(projectConfig, projectRoot);
338
+ configPath = path.join(projectRoot, '.claude', 'settings.local.json');
339
+ }
340
+
341
+ console.log(chalk.green(`โœ“ Environment variable '${key}' set successfully at ${level} level!`));
342
+ console.log(` ${chalk.cyan('Config file:')} ${configPath}`);
343
+ } catch (error) {
344
+ console.error(chalk.red('โœ— Error setting environment variable:'), error.message);
345
+ }
346
+ }
347
+
348
+ /**
349
+ * Remove environment variable
350
+ */
351
+ async function removeEnv() {
352
+ try {
353
+ const projectRoot = config.findProjectRoot();
354
+
355
+ const { level } = await inquirer.prompt([
356
+ {
357
+ type: 'list',
358
+ name: 'level',
359
+ message: 'Select configuration level (่ฏท้€‰ๆ‹ฉ้…็ฝฎ็บงๅˆซ):',
360
+ choices: projectRoot
361
+ ? [
362
+ { name: 'Project (้กน็›ฎ) - Only for current project (ไป…ๅฝ“ๅ‰้กน็›ฎ)', value: 'project' },
363
+ { name: 'User (็”จๆˆท) - For all projects (ๆ‰€ๆœ‰้กน็›ฎ)', value: 'user' }
364
+ ]
365
+ : [
366
+ { name: 'User (็”จๆˆท) - For all projects (ๆ‰€ๆœ‰้กน็›ฎ)', value: 'user' }
367
+ ]
368
+ }
369
+ ]);
370
+
371
+ let existingEnv;
372
+ let isUserLevel = level === 'user';
373
+
374
+ if (isUserLevel) {
375
+ const userConfig = readClaudeUserConfig();
376
+ existingEnv = userConfig.env || {};
377
+ } else {
378
+ const projectConfig = readClaudeProjectConfig(projectRoot);
379
+ existingEnv = projectConfig.env || {};
380
+ }
381
+
382
+ if (Object.keys(existingEnv).length === 0) {
383
+ console.log(chalk.yellow(`No environment variables configured at ${level} level (${level === 'project' ? '้กน็›ฎ' : '็”จๆˆท'}็บงๅˆซๆœช้…็ฝฎ็Žฏๅขƒๅ˜้‡)`));
384
+ return;
385
+ }
386
+
387
+ const { key } = await inquirer.prompt([
388
+ {
389
+ type: 'list',
390
+ name: 'key',
391
+ message: 'Select environment variable to remove (่ฏท้€‰ๆ‹ฉ่ฆๅˆ ้™ค็š„็Žฏๅขƒๅ˜้‡):',
392
+ choices: Object.keys(existingEnv)
393
+ }
394
+ ]);
395
+
396
+ const { confirm } = await inquirer.prompt([
397
+ {
398
+ type: 'confirm',
399
+ name: 'confirm',
400
+ message: `Remove environment variable '${key}'? (็กฎๅฎš่ฆๅˆ ้™ค็Žฏๅขƒๅ˜้‡ '${key}' ๅ—?)`,
401
+ default: false
402
+ }
403
+ ]);
404
+
405
+ if (!confirm) {
406
+ console.log(chalk.yellow('Operation cancelled. (ๆ“ไฝœๅทฒๅ–ๆถˆใ€‚)'));
407
+ return;
408
+ }
409
+
410
+ // Remove the variable
411
+ if (isUserLevel) {
412
+ const userConfig = readClaudeUserConfig();
413
+ delete userConfig.env[key];
414
+ writeClaudeUserConfig(userConfig);
415
+ } else {
416
+ const projectConfig = readClaudeProjectConfig(projectRoot);
417
+ delete projectConfig.env[key];
418
+ writeClaudeProjectConfig(projectConfig, projectRoot);
419
+ }
420
+
421
+ console.log(chalk.green(`โœ“ Environment variable '${key}' removed successfully from ${level} level! (็Žฏๅขƒๅ˜้‡ '${key}' ไปŽ${level === 'project' ? '้กน็›ฎ' : '็”จๆˆท'}็บงๅˆซๅˆ ้™คๆˆๅŠŸ!)\n`));
422
+ } catch (error) {
423
+ console.error(chalk.red('โœ— Error removing environment variable:'), error.message);
424
+ }
425
+ }
426
+
427
+ /**
428
+ * Remove environment variable by key (non-interactive)
429
+ */
430
+ async function unsetEnv(key, options = {}) {
431
+ try {
432
+ const level = options.level || 'user';
433
+ const isUserLevel = level === 'user';
434
+
435
+ if (!key) {
436
+ console.log(chalk.red('โœ— Key is required (้”ฎๆ˜ฏๅฟ…้œ€็š„)'));
437
+ console.log(chalk.cyan('Usage: ais env unset <key> [--level=project|user]'));
438
+ return;
439
+ }
440
+
441
+ let configPath;
442
+
443
+ if (isUserLevel) {
444
+ const userConfig = readClaudeUserConfig();
445
+ if (!userConfig.env || !userConfig.env[key]) {
446
+ console.log(chalk.yellow(`Environment variable '${key}' not found at user level`));
447
+ return;
448
+ }
449
+ delete userConfig.env[key];
450
+ writeClaudeUserConfig(userConfig);
451
+ configPath = getClaudeUserConfigPath();
452
+ } else {
453
+ const projectRoot = config.findProjectRoot();
454
+ if (!projectRoot) {
455
+ console.log(chalk.red('โœ— Not in a project directory. Use --level=user or run from a project directory'));
456
+ return;
457
+ }
458
+ const projectConfig = readClaudeProjectConfig(projectRoot);
459
+ if (!projectConfig.env || !projectConfig.env[key]) {
460
+ console.log(chalk.yellow(`Environment variable '${key}' not found at project level`));
461
+ return;
462
+ }
463
+ delete projectConfig.env[key];
464
+ writeClaudeProjectConfig(projectConfig, projectRoot);
465
+ configPath = path.join(projectRoot, '.claude', 'settings.local.json');
466
+ }
467
+
468
+ console.log(chalk.green(`โœ“ Environment variable '${key}' removed successfully from ${level} level!`));
469
+ console.log(` ${chalk.cyan('Config file:')} ${configPath}`);
470
+ } catch (error) {
471
+ console.error(chalk.red('โœ— Error unsetting environment variable:'), error.message);
472
+ }
473
+ }
474
+
475
+ /**
476
+ * Show environment variable value
477
+ */
478
+ async function showEnv(key, options = {}) {
479
+ try {
480
+ const level = options.level;
481
+ const projectRoot = config.findProjectRoot();
482
+
483
+ let found = false;
484
+ let foundLevel = '';
485
+
486
+ // Search in project config first if not specified or if project level requested
487
+ if (!level || level === 'project') {
488
+ if (projectRoot) {
489
+ const projectConfig = readClaudeProjectConfig(projectRoot);
490
+ if (projectConfig.env && projectConfig.env[key]) {
491
+ console.log(chalk.cyan(`\n๐Ÿ“‹ Environment Variable: ${key}`));
492
+ console.log(`${chalk.cyan('Level:')} Project (้กน็›ฎ)`);
493
+ console.log(`${chalk.cyan('Value:')} ${maskEnvValue(key, projectConfig.env[key])}`);
494
+ console.log(`${chalk.cyan('Config:')} ${path.join(projectRoot, '.claude', 'settings.local.json')}`);
495
+ console.log('');
496
+ found = true;
497
+ foundLevel = 'project';
498
+ }
499
+ }
500
+ }
501
+
502
+ // Search in user config if not found in project or if user level requested
503
+ if (!found && (!level || level === 'user')) {
504
+ const userConfig = readClaudeUserConfig();
505
+ if (userConfig.env && userConfig.env[key]) {
506
+ console.log(chalk.cyan(`\n๐Ÿ“‹ Environment Variable: ${key}`));
507
+ console.log(`${chalk.cyan('Level:')} User (็”จๆˆท)`);
508
+ console.log(`${chalk.cyan('Value:')} ${maskEnvValue(key, userConfig.env[key])}`);
509
+ console.log(`${chalk.cyan('Config:')} ${getClaudeUserConfigPath()}`);
510
+ console.log('');
511
+ found = true;
512
+ foundLevel = 'user';
513
+ }
514
+ }
515
+
516
+ if (!found) {
517
+ console.log(chalk.yellow(`Environment variable '${key}' not found`));
518
+ if (level) {
519
+ console.log(` ${chalk.cyan('Level:')} ${level}`);
520
+ }
521
+ }
522
+ } catch (error) {
523
+ console.error(chalk.red('โœ— Error showing environment variable:'), error.message);
524
+ }
525
+ }
526
+
527
+ /**
528
+ * Clear all environment variables at a level
529
+ */
530
+ async function clearEnv(options = {}) {
531
+ try {
532
+ const level = options.level || 'user';
533
+ const isUserLevel = level === 'user';
534
+
535
+ const { confirm } = await inquirer.prompt([
536
+ {
537
+ type: 'confirm',
538
+ name: 'confirm',
539
+ message: `Clear all environment variables at ${level} level? This cannot be undone. (็กฎๅฎš่ฆๆธ…็ฉบ${level === 'project' ? '้กน็›ฎ' : '็”จๆˆท'}็บงๅˆซ็š„ๆ‰€ๆœ‰็Žฏๅขƒๅ˜้‡ๅ—? ๆญคๆ“ไฝœๆ— ๆณ•ๆ’ค้”€ใ€‚)`,
540
+ default: false
541
+ }
542
+ ]);
543
+
544
+ if (!confirm) {
545
+ console.log(chalk.yellow('Operation cancelled. (ๆ“ไฝœๅทฒๅ–ๆถˆใ€‚)'));
546
+ return;
547
+ }
548
+
549
+ if (isUserLevel) {
550
+ const userConfig = readClaudeUserConfig();
551
+ userConfig.env = {};
552
+ writeClaudeUserConfig(userConfig);
553
+ console.log(chalk.green('โœ“ All user-level environment variables cleared successfully! (ๆ‰€ๆœ‰็”จๆˆท็บงๅˆซ็š„็Žฏๅขƒๅ˜้‡ๅทฒๆธ…็ฉบ!)'));
554
+ } else {
555
+ const projectRoot = config.findProjectRoot();
556
+ if (!projectRoot) {
557
+ console.log(chalk.red('โœ— Not in a project directory'));
558
+ return;
559
+ }
560
+ const projectConfig = readClaudeProjectConfig(projectRoot);
561
+ projectConfig.env = {};
562
+ writeClaudeProjectConfig(projectConfig, projectRoot);
563
+ console.log(chalk.green('โœ“ All project-level environment variables cleared successfully! (ๆ‰€ๆœ‰้กน็›ฎ็บงๅˆซ็š„็Žฏๅขƒๅ˜้‡ๅทฒๆธ…็ฉบ!)'));
564
+ }
565
+ console.log('');
566
+ } catch (error) {
567
+ console.error(chalk.red('โœ— Error clearing environment variables:'), error.message);
568
+ }
569
+ }
570
+
571
+ /**
572
+ * Edit environment variables interactively
573
+ */
574
+ async function editEnv(options = {}) {
575
+ try {
576
+ const level = options.level || 'user';
577
+ const projectRoot = config.findProjectRoot();
578
+
579
+ if (level === 'project' && !projectRoot) {
580
+ console.log(chalk.red('โœ— Not in a project directory'));
581
+ return;
582
+ }
583
+
584
+ let envVars;
585
+ let isUserLevel = level === 'user';
586
+
587
+ if (isUserLevel) {
588
+ const userConfig = readClaudeUserConfig();
589
+ envVars = { ...userConfig.env } || {};
590
+ } else {
591
+ const projectConfig = readClaudeProjectConfig(projectRoot);
592
+ envVars = { ...projectConfig.env } || {};
593
+ }
594
+
595
+ console.log(chalk.cyan(`\n๐Ÿ“ Editing ${level}-level environment variables (็ผ–่พ‘${level === 'project' ? '้กน็›ฎ' : '็”จๆˆท'}็บงๅˆซ็Žฏๅขƒๅ˜้‡)\n`));
596
+
597
+ while (true) {
598
+ console.log(chalk.bold('Current environment variables (ๅฝ“ๅ‰็Žฏๅขƒๅ˜้‡):'));
599
+ const keys = Object.keys(envVars);
600
+ if (keys.length === 0) {
601
+ console.log(chalk.gray(' (None)'));
602
+ } else {
603
+ keys.forEach((key, index) => {
604
+ console.log(` ${index + 1}. ${chalk.cyan(key)} = ${chalk.yellow(maskEnvValue(key, envVars[key]))}`);
605
+ });
606
+ }
607
+ console.log('');
608
+
609
+ const { action } = await inquirer.prompt([
610
+ {
611
+ type: 'list',
612
+ name: 'action',
613
+ message: 'Select action (่ฏท้€‰ๆ‹ฉๆ“ไฝœ):',
614
+ choices: [
615
+ { name: 'Add new variable (ๆทปๅŠ ๆ–ฐๅ˜้‡)', value: 'add' },
616
+ { name: 'Edit variable (็ผ–่พ‘ๅ˜้‡)', value: 'edit' },
617
+ { name: 'Remove variable (ๅˆ ้™คๅ˜้‡)', value: 'remove' },
618
+ { name: 'Save and exit (ไฟๅญ˜ๅนถ้€€ๅ‡บ)', value: 'save' },
619
+ { name: 'Cancel (ๅ–ๆถˆ)', value: 'cancel' }
620
+ ]
621
+ }
622
+ ]);
623
+
624
+ if (action === 'save') {
625
+ if (isUserLevel) {
626
+ const userConfig = readClaudeUserConfig();
627
+ userConfig.env = envVars;
628
+ writeClaudeUserConfig(userConfig);
629
+ } else {
630
+ const projectConfig = readClaudeProjectConfig(projectRoot);
631
+ projectConfig.env = envVars;
632
+ writeClaudeProjectConfig(projectConfig, projectRoot);
633
+ }
634
+ console.log(chalk.green('โœ“ Environment variables saved successfully! (็Žฏๅขƒๅ˜้‡ไฟๅญ˜ๆˆๅŠŸ!)\n'));
635
+ return;
636
+ }
637
+
638
+ if (action === 'cancel') {
639
+ console.log(chalk.yellow('Operation cancelled. Changes not saved. (ๆ“ไฝœๅทฒๅ–ๆถˆใ€‚ๆ›ดๆ”นๆœชไฟๅญ˜ใ€‚)\n'));
640
+ return;
641
+ }
642
+
643
+ if (action === 'add') {
644
+ const { key, value } = await inquirer.prompt([
645
+ {
646
+ type: 'input',
647
+ name: 'key',
648
+ message: 'Enter variable name (่ฏท่พ“ๅ…ฅๅ˜้‡ๅ):',
649
+ validate: (input) => {
650
+ if (!input.trim()) return 'Variable name is required';
651
+ if (!/^[A-Z_][A-Z0-9_]*$/.test(input.trim())) {
652
+ return 'Invalid format. Use uppercase letters, numbers, and underscores';
653
+ }
654
+ if (envVars[input.trim()]) return 'Variable already exists';
655
+ return true;
656
+ }
657
+ },
658
+ {
659
+ type: 'input',
660
+ name: 'value',
661
+ message: 'Enter variable value (่ฏท่พ“ๅ…ฅๅ˜้‡ๅ€ผ):',
662
+ validate: (input) => input.trim() !== '' || 'Value is required'
663
+ }
664
+ ]);
665
+ envVars[key.trim()] = value.trim();
666
+ } else if (action === 'edit') {
667
+ if (keys.length === 0) {
668
+ console.log(chalk.yellow('No variables to edit.\n'));
669
+ continue;
670
+ }
671
+ const { key } = await inquirer.prompt([
672
+ {
673
+ type: 'list',
674
+ name: 'key',
675
+ message: 'Select variable to edit (่ฏท้€‰ๆ‹ฉ่ฆ็ผ–่พ‘็š„ๅ˜้‡):',
676
+ choices: keys
677
+ }
678
+ ]);
679
+ const { value } = await inquirer.prompt([
680
+ {
681
+ type: 'input',
682
+ name: 'value',
683
+ message: `Enter new value for ${key}:`,
684
+ default: envVars[key]
685
+ }
686
+ ]);
687
+ envVars[key] = value.trim();
688
+ } else if (action === 'remove') {
689
+ if (keys.length === 0) {
690
+ console.log(chalk.yellow('No variables to remove.\n'));
691
+ continue;
692
+ }
693
+ const { key } = await inquirer.prompt([
694
+ {
695
+ type: 'list',
696
+ name: 'key',
697
+ message: 'Select variable to remove (่ฏท้€‰ๆ‹ฉ่ฆๅˆ ้™ค็š„ๅ˜้‡):',
698
+ choices: keys
699
+ }
700
+ ]);
701
+ const { confirm } = await inquirer.prompt([
702
+ {
703
+ type: 'confirm',
704
+ name: 'confirm',
705
+ message: `Remove variable '${key}'?`,
706
+ default: false
707
+ }
708
+ ]);
709
+ if (confirm) {
710
+ delete envVars[key];
711
+ }
712
+ }
713
+ }
714
+ } catch (error) {
715
+ console.error(chalk.red('โœ— Error editing environment variables:'), error.message);
716
+ }
717
+ }
718
+
719
+ module.exports = {
720
+ listEnv,
721
+ addEnv,
722
+ setEnv,
723
+ removeEnv,
724
+ unsetEnv,
725
+ showEnv,
726
+ clearEnv,
727
+ editEnv
728
+ };