ai-account-switch 1.1.0 → 1.2.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/README.md CHANGED
@@ -1,5 +1,7 @@
1
1
  # AI Account Switch (ais)
2
2
 
3
+ English | [简体中文](README_ZH.md)
4
+
3
5
  A cross-platform CLI tool to manage and switch between Claude/Codex account configurations for different projects.
4
6
 
5
7
  ## Features
@@ -15,7 +17,27 @@ A cross-platform CLI tool to manage and switch between Claude/Codex account conf
15
17
 
16
18
  ## Installation
17
19
 
18
- ### Option 1: Download Pre-built Binary (Recommended)
20
+ ### Option 1: Global npm Installation (Recommended)
21
+
22
+ ```bash
23
+ npm install -g ai-account-switch
24
+ ```
25
+
26
+ After installation, the `ais` command will be available globally.
27
+
28
+ **Note**: If you encounter "command not found" after installation, you may need to add npm's global bin directory to your PATH:
29
+
30
+ ```bash
31
+ # Check npm global bin path
32
+ npm config get prefix
33
+
34
+ # Add to PATH (Linux/macOS)
35
+ export PATH="$PATH:$(npm config get prefix)/bin"
36
+
37
+ # On Windows, add to system PATH: %APPDATA%\npm
38
+ ```
39
+
40
+ ### Option 2: Download Pre-built Binary
19
41
 
20
42
  Download the latest release for your platform from the [Releases page](https://github.com/yourusername/ai-agent-user-swith/releases):
21
43
 
@@ -36,7 +58,7 @@ chmod +x /usr/local/bin/ais
36
58
  **Windows:**
37
59
  Download `ais-win.exe` from the releases page and add it to your PATH.
38
60
 
39
- ### Option 2: Install from Source
61
+ ### Option 3: Install from Source
40
62
 
41
63
  ```bash
42
64
  # Clone the repository
@@ -50,15 +72,7 @@ npm install
50
72
  npm link
51
73
  ```
52
74
 
53
- ### Option 3: Global npm Installation
54
-
55
- ```bash
56
- npm install -g ai-account-switch
57
- ```
58
-
59
- After installation, the `ais` command will be available globally.
60
-
61
- **Note**: See [NPM_PUBLISH.md](NPM_PUBLISH.md) for publishing instructions if you're a maintainer.
75
+ **For Maintainers**: See [NPM_PUBLISH.md](NPM_PUBLISH.md) for publishing instructions.
62
76
 
63
77
  ## Usage
64
78
 
@@ -100,6 +114,7 @@ You'll be prompted to enter:
100
114
  - Organization ID (optional)
101
115
  - Email (optional)
102
116
  - Description (optional)
117
+ - Custom environment variables (optional, e.g., `CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC=1`)
103
118
 
104
119
  #### 2. List All Accounts
105
120
 
@@ -202,7 +217,8 @@ When you run `ais use`, the tool automatically creates `.claude/settings.local.j
202
217
  "env": {
203
218
  "ANTHROPIC_AUTH_TOKEN": "your-api-key",
204
219
  "ANTHROPIC_BASE_URL": "your-api-url",
205
- "ANTHROPIC_ORGANIZATION_ID": "your-org-id"
220
+ "ANTHROPIC_ORGANIZATION_ID": "your-org-id",
221
+ "CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC": "1"
206
222
  },
207
223
  "permissions": {
208
224
  "allow": [],
@@ -214,6 +230,17 @@ When you run `ais use`, the tool automatically creates `.claude/settings.local.j
214
230
 
215
231
  This ensures Claude Code CLI automatically uses the correct account for your project.
216
232
 
233
+ #### Custom Environment Variables
234
+
235
+ You can add custom environment variables when creating an account. Common examples:
236
+
237
+ - `CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC=1` - Disable non-essential network traffic
238
+ - `HTTP_PROXY=http://proxy.example.com:8080` - Set HTTP proxy
239
+ - `HTTPS_PROXY=https://proxy.example.com:8080` - Set HTTPS proxy
240
+ - Any other environment variables needed for your setup
241
+
242
+ These custom variables are automatically included in the generated `.claude/settings.local.json` file.
243
+
217
244
  ## Examples
218
245
 
219
246
  ### Example 1: Setting Up Multiple Accounts
@@ -328,6 +355,40 @@ Make sure you've added at least one account:
328
355
  ais add
329
356
  ```
330
357
 
358
+ ### Claude Code uses wrong account
359
+
360
+ If Claude Code is using a different account than expected:
361
+
362
+ 1. Run diagnostics:
363
+ ```bash
364
+ ais doctor
365
+ ```
366
+
367
+ 2. Check if global Claude config is overriding project config:
368
+ - If `~/.claude/settings.json` contains `env.ANTHROPIC_AUTH_TOKEN`, it may conflict
369
+ - **Solution**: Remove the `env` section from global config, or only keep `permissions`
370
+
371
+ 3. Ensure you're starting Claude Code from your project directory or subdirectory
372
+
373
+ 4. Regenerate project config:
374
+ ```bash
375
+ ais use <your-account-name>
376
+ ```
377
+
378
+ ### Project config not found in subdirectory
379
+
380
+ The tool should work in any subdirectory. If it doesn't:
381
+
382
+ ```bash
383
+ # Make sure you're within a configured project
384
+ cd /path/to/your/project
385
+ ais use <account>
386
+
387
+ # Then try from subdirectory
388
+ cd src/
389
+ ais current # Should show your account
390
+ ```
391
+
331
392
  ## Contributing
332
393
 
333
394
  Contributions are welcome! Feel free to:
@@ -341,6 +402,14 @@ MIT License - feel free to use this tool in your projects!
341
402
 
342
403
  ## Changelog
343
404
 
405
+ ### v1.2.0
406
+ - Added custom environment variables support for accounts
407
+ - Added `ais doctor` command for configuration diagnostics
408
+ - Enhanced `ais help` with all new features
409
+ - Updated installation documentation (npm as recommended method)
410
+ - Improved PATH configuration instructions
411
+ - Display custom env variables in `ais list` and `ais info`
412
+
344
413
  ### v1.1.0
345
414
  - Added smart directory detection (works in any subdirectory)
346
415
  - Automatic Claude Code `.claude/settings.local.json` generation
package/README_ZH.md ADDED
@@ -0,0 +1,482 @@
1
+ # AI Account Switch (ais)
2
+
3
+ [English](README.md) | 简体中文
4
+
5
+ 一个跨平台的命令行工具,用于管理和切换不同项目的 Claude/Codex 账户配置。
6
+
7
+ ## 特性
8
+
9
+ - **跨平台支持**:在 macOS、Linux 和 Windows 上无缝运行
10
+ - **多账户管理**:存储和管理多个 AI 服务账户
11
+ - **项目级配置**:每个项目可以使用不同的账户
12
+ - **智能目录检测**:在项目的任何子目录中都能工作(类似 git)
13
+ - **Claude Code 集成**:自动生成 `.claude/settings.local.json` 配置文件
14
+ - **安全存储**:账户凭证仅存储在本地
15
+ - **交互式命令行**:所有操作都有易用的交互式提示
16
+ - **多种账户类型**:支持 Claude、Codex 和其他 AI 服务
17
+
18
+ ## 安装
19
+
20
+ ### 方式 1:全局 npm 安装(推荐)
21
+
22
+ ```bash
23
+ npm install -g ai-account-switch
24
+ ```
25
+
26
+ 安装后,`ais` 命令将在全局可用。
27
+
28
+ **注意**:如果安装后提示"命令未找到",可能需要将 npm 的全局 bin 目录添加到 PATH:
29
+
30
+ ```bash
31
+ # 查看 npm 全局 bin 路径
32
+ npm config get prefix
33
+
34
+ # 添加到 PATH (Linux/macOS)
35
+ export PATH="$PATH:$(npm config get prefix)/bin"
36
+
37
+ # Windows 上,添加到系统 PATH:%APPDATA%\npm
38
+ ```
39
+
40
+ ### 方式 2:下载预编译二进制文件
41
+
42
+ 从 [Releases 页面](https://github.com/yourusername/ai-agent-user-swith/releases) 下载适合你平台的最新版本:
43
+
44
+ **macOS:**
45
+ ```bash
46
+ # 下载并安装
47
+ curl -L https://github.com/yourusername/ai-agent-user-swith/releases/latest/download/ais-macos -o /usr/local/bin/ais
48
+ chmod +x /usr/local/bin/ais
49
+ ```
50
+
51
+ **Linux:**
52
+ ```bash
53
+ # 下载并安装
54
+ curl -L https://github.com/yourusername/ai-agent-user-swith/releases/latest/download/ais-linux -o /usr/local/bin/ais
55
+ chmod +x /usr/local/bin/ais
56
+ ```
57
+
58
+ **Windows:**
59
+ 从 releases 页面下载 `ais-win.exe` 并添加到系统 PATH。
60
+
61
+ ### 方式 3:从源码安装
62
+
63
+ ```bash
64
+ # 克隆仓库
65
+ git clone https://github.com/yourusername/ai-agent-user-swith.git
66
+ cd ai-agent-user-swith
67
+
68
+ # 安装依赖
69
+ npm install
70
+
71
+ # 全局链接 CLI 工具
72
+ npm link
73
+ ```
74
+
75
+ **维护者说明**:请查看 [NPM_PUBLISH.md](NPM_PUBLISH.md) 了解发布说明。
76
+
77
+ ## 使用方法
78
+
79
+ ### 命令概览
80
+
81
+ | 命令 | 别名 | 描述 |
82
+ |------|------|------|
83
+ | `ais add [name]` | - | 添加新的账户配置 |
84
+ | `ais list` | `ls` | 列出所有可用账户 |
85
+ | `ais use [name]` | - | 为当前项目设置账户 |
86
+ | `ais info` | - | 显示当前项目的账户信息 |
87
+ | `ais current` | - | 显示当前账户名称 |
88
+ | `ais remove [name]` | `rm` | 删除账户 |
89
+ | `ais paths` | - | 显示配置文件路径 |
90
+ | `ais doctor` | - | 诊断 Claude Code 配置问题 |
91
+ | `ais export <name>` | - | 导出账户为 JSON 格式 |
92
+ | `ais help` | - | 显示帮助信息 |
93
+ | `ais --version` | - | 显示版本号 |
94
+
95
+ ### 快速开始
96
+
97
+ #### 1. 添加账户
98
+
99
+ 交互式添加第一个账户:
100
+
101
+ ```bash
102
+ ais add
103
+ ```
104
+
105
+ 或直接指定名称:
106
+
107
+ ```bash
108
+ ais add my-claude-account
109
+ ```
110
+
111
+ 系统将提示你输入:
112
+ - 账户类型(Claude、Codex、其他)
113
+ - API Key
114
+ - API URL(可选)
115
+ - Organization ID(可选)
116
+ - Email(可选)
117
+ - 描述(可选)
118
+ - 自定义环境变量(可选,例如 `CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC=1`)
119
+
120
+ #### 2. 列出所有账户
121
+
122
+ 查看所有已配置的账户:
123
+
124
+ ```bash
125
+ ais list
126
+ # 或
127
+ ais ls
128
+ ```
129
+
130
+ 当前项目激活的账户将用绿色圆点标记。
131
+
132
+ #### 3. 为当前项目切换账户
133
+
134
+ 设置当前项目使用的账户:
135
+
136
+ ```bash
137
+ ais use my-claude-account
138
+ ```
139
+
140
+ 或交互式选择:
141
+
142
+ ```bash
143
+ ais use
144
+ ```
145
+
146
+ **注意**:此命令会自动生成 `.claude/settings.local.json` 文件用于 Claude Code CLI 集成。
147
+ 你可以在项目的任何子目录中运行此命令 - 它会自动找到项目根目录。
148
+
149
+ #### 4. 查看当前项目信息
150
+
151
+ 查看当前项目激活的账户:
152
+
153
+ ```bash
154
+ ais info
155
+ ```
156
+
157
+ 或仅显示账户名称:
158
+
159
+ ```bash
160
+ ais current
161
+ ```
162
+
163
+ **注意**:这些命令可以在项目的任何子目录中使用,类似 git 命令的工作方式。
164
+
165
+ #### 5. 删除账户
166
+
167
+ 删除不再需要的账户:
168
+
169
+ ```bash
170
+ ais remove old-account
171
+ # 或
172
+ ais rm
173
+ ```
174
+
175
+ ### 高级用法
176
+
177
+ #### 显示配置路径
178
+
179
+ 查看配置文件的存储位置:
180
+
181
+ ```bash
182
+ ais paths
183
+ ```
184
+
185
+ #### 诊断配置问题
186
+
187
+ 如果 Claude Code 使用了错误的账户,运行诊断:
188
+
189
+ ```bash
190
+ ais doctor
191
+ ```
192
+
193
+ 此命令会检查:
194
+ - 当前目录和项目根目录
195
+ - AIS 项目配置
196
+ - Claude Code 配置
197
+ - 全局 Claude 配置
198
+ - 提供解决建议
199
+
200
+ #### 导出账户配置
201
+
202
+ 以 JSON 格式导出账户配置:
203
+
204
+ ```bash
205
+ ais export my-claude-account
206
+ ```
207
+
208
+ ## 配置
209
+
210
+ ### 全局配置
211
+
212
+ 所有账户都存储在用户主目录的全局配置中:
213
+
214
+ - **macOS/Linux**: `~/.ai-account-switch/config.json`
215
+ - **Windows**: `%USERPROFILE%\.ai-account-switch\config.json`
216
+
217
+ ### 项目配置
218
+
219
+ 每个项目将其活动账户引用存储在:
220
+
221
+ ```
222
+ ./.ais-project-config
223
+ ```
224
+
225
+ 此文件在运行 `ais use` 时自动创建,应添加到 `.gitignore` 中。
226
+
227
+ ### Claude Code 集成
228
+
229
+ 运行 `ais use` 时,工具会自动创建 `.claude/settings.local.json`,结构如下:
230
+
231
+ ```json
232
+ {
233
+ "env": {
234
+ "ANTHROPIC_AUTH_TOKEN": "your-api-key",
235
+ "ANTHROPIC_BASE_URL": "your-api-url",
236
+ "ANTHROPIC_ORGANIZATION_ID": "your-org-id",
237
+ "CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC": "1"
238
+ },
239
+ "permissions": {
240
+ "allow": [],
241
+ "deny": [],
242
+ "ask": []
243
+ }
244
+ }
245
+ ```
246
+
247
+ 这确保 Claude Code CLI 自动使用项目的正确账户。
248
+
249
+ #### 自定义环境变量
250
+
251
+ 在创建账户时可以添加自定义环境变量。常见示例:
252
+
253
+ - `CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC=1` - 禁用非必要网络流量
254
+ - `HTTP_PROXY=http://proxy.example.com:8080` - 设置 HTTP 代理
255
+ - `HTTPS_PROXY=https://proxy.example.com:8080` - 设置 HTTPS 代理
256
+ - 其他你需要的环境变量
257
+
258
+ 这些自定义变量会自动包含在生成的 `.claude/settings.local.json` 文件中。
259
+
260
+ ## 使用示例
261
+
262
+ ### 示例 1:设置多个账户
263
+
264
+ ```bash
265
+ # 添加个人 Claude 账户
266
+ ais add personal-claude
267
+
268
+ # 添加工作 Claude 账户
269
+ ais add work-claude
270
+
271
+ # 添加 Codex 账户
272
+ ais add codex-dev
273
+
274
+ # 列出所有账户
275
+ ais list
276
+ ```
277
+
278
+ ### 示例 2:为不同项目使用不同账户
279
+
280
+ ```bash
281
+ # 在个人项目中
282
+ cd ~/my-personal-project
283
+ ais use personal-claude
284
+
285
+ # 在工作项目中
286
+ cd ~/work/company-project
287
+ ais use work-claude
288
+
289
+ # 检查激活的账户
290
+ ais info
291
+ ```
292
+
293
+ ### 示例 3:管理账户
294
+
295
+ ```bash
296
+ # 查看所有账户
297
+ ais list
298
+
299
+ # 检查当前账户
300
+ ais current
301
+
302
+ # 导出账户配置
303
+ ais export personal-claude
304
+
305
+ # 删除旧账户
306
+ ais remove old-account
307
+
308
+ # 查看配置位置
309
+ ais paths
310
+ ```
311
+
312
+ ### 示例 4:诊断问题
313
+
314
+ ```bash
315
+ # 如果 Claude Code 使用了错误的账户
316
+ cd ~/your-project
317
+ ais doctor
318
+
319
+ # 根据诊断建议操作
320
+ # 然后重新设置账户
321
+ ais use correct-account
322
+ ```
323
+
324
+ ## 安全注意事项
325
+
326
+ - API 密钥仅存储在本地机器上
327
+ - 全局配置文件包含敏感凭证
328
+ - 始终将 `.ais-project-config` 添加到 `.gitignore`
329
+ - 切勿将账户凭证提交到版本控制
330
+ - 显示 API 密钥时会进行掩码处理(仅显示前 4 位和后 4 位字符)
331
+
332
+ ## 平台兼容性
333
+
334
+ | 平台 | 状态 | 备注 |
335
+ |------|------|------|
336
+ | macOS | ✅ 完全支持 | 已在 macOS 10.15+ 上测试 |
337
+ | Linux | ✅ 完全支持 | 已在 Ubuntu 20.04+ 上测试 |
338
+ | Windows | ✅ 完全支持 | 已在 Windows 10+ 上测试 |
339
+
340
+ ## 系统要求
341
+
342
+ - Node.js >= 14.0.0
343
+ - npm >= 6.0.0
344
+
345
+ ## 项目结构
346
+
347
+ ```
348
+ ai-agent-user-swith/
349
+ ├── bin/
350
+ │ └── ais.js # 可执行入口点
351
+ ├── src/
352
+ │ ├── index.js # 主 CLI 程序
353
+ │ ├── commands.js # 命令实现
354
+ │ └── config.js # 配置管理器
355
+ ├── .github/
356
+ │ └── workflows/
357
+ │ └── release.yml # GitHub Actions 自动发布
358
+ ├── package.json
359
+ ├── .gitignore
360
+ ├── .npmignore
361
+ ├── README.md # 英文文档
362
+ ├── README_ZH.md # 中文文档
363
+ ├── NPM_PUBLISH.md # npm 发布指南
364
+ └── RELEASE.md # 发布指南
365
+ ```
366
+
367
+ ## 故障排除
368
+
369
+ ### 命令未找到:ais
370
+
371
+ 如果安装后出现此错误,确保已链接包:
372
+
373
+ ```bash
374
+ npm link
375
+ ```
376
+
377
+ ### 权限被拒绝
378
+
379
+ 在 Unix 系统上,确保 bin 文件可执行:
380
+
381
+ ```bash
382
+ chmod +x bin/ais.js
383
+ ```
384
+
385
+ ### 未找到账户
386
+
387
+ 确保你已添加至少一个账户:
388
+
389
+ ```bash
390
+ ais add
391
+ ```
392
+
393
+ ### Claude Code 使用了错误的账户
394
+
395
+ 如果 Claude Code 使用了非预期的账户:
396
+
397
+ 1. 运行诊断:
398
+ ```bash
399
+ ais doctor
400
+ ```
401
+
402
+ 2. 检查全局 Claude 配置是否覆盖了项目配置:
403
+ - 如果 `~/.claude/settings.json` 包含 `env.ANTHROPIC_AUTH_TOKEN`,可能会冲突
404
+ - **解决方案**:从全局配置中删除 `env` 部分,或仅保留 `permissions`
405
+
406
+ 3. 确保从项目目录或子目录启动 Claude Code
407
+
408
+ 4. 重新生成项目配置:
409
+ ```bash
410
+ ais use <你的账户名>
411
+ ```
412
+
413
+ ### 在子目录中未找到项目配置
414
+
415
+ 工具应该在任何子目录中工作。如果不行:
416
+
417
+ ```bash
418
+ # 确保你在已配置的项目中
419
+ cd /path/to/your/project
420
+ ais use <account>
421
+
422
+ # 然后从子目录尝试
423
+ cd src/
424
+ ais current # 应该显示你的账户
425
+ ```
426
+
427
+ ## 贡献
428
+
429
+ 欢迎贡献!你可以:
430
+ - 报告 bug
431
+ - 建议新功能
432
+ - 提交 pull request
433
+
434
+ ## 许可证
435
+
436
+ MIT License - 欢迎在你的项目中使用此工具!
437
+
438
+ ## 更新日志
439
+
440
+ ### v1.2.0
441
+ - 添加账户自定义环境变量支持
442
+ - 添加 `ais doctor` 命令用于配置诊断
443
+ - 增强 `ais help` 显示所有新功能
444
+ - 更新安装文档(npm 作为推荐安装方式)
445
+ - 改进 PATH 配置说明
446
+ - 在 `ais list` 和 `ais info` 中显示自定义环境变量
447
+
448
+ ### v1.1.0
449
+ - 添加智能目录检测(在任何子目录中工作)
450
+ - 自动生成 Claude Code `.claude/settings.local.json` 配置
451
+ - 在 `ais info` 命令中显示项目根目录
452
+ - 改进跨平台兼容性
453
+
454
+ ### v1.0.0
455
+ - 初始版本
456
+ - 基本账户管理(添加、列出、删除)
457
+ - 项目级账户切换
458
+ - 跨平台支持
459
+ - 交互式 CLI 提示
460
+ - 账户导出功能
461
+
462
+ ## 未来增强
463
+
464
+ 未来版本的潜在功能:
465
+ - 账户验证
466
+ - 批量导入/导出
467
+ - 账户模板
468
+ - 环境变量导出
469
+ - 账户共享(加密)
470
+ - 云同步支持
471
+ - 账户使用统计
472
+
473
+ ## 支持
474
+
475
+ 如果遇到任何问题或有疑问:
476
+ 1. 查看故障排除部分
477
+ 2. 查看现有 issues
478
+ 3. 创建新 issue 并提供详细信息
479
+
480
+ ---
481
+
482
+ **祝你与 AI 助手编码愉快!** 🤖
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ai-account-switch",
3
- "version": "1.1.0",
3
+ "version": "1.2.0",
4
4
  "description": "A cross-platform CLI tool to manage and switch Claude/Codex account configurations",
5
5
  "main": "src/index.js",
6
6
  "bin": {
package/src/commands.js CHANGED
@@ -76,9 +76,64 @@ async function addAccount(name, options) {
76
76
  name: 'description',
77
77
  message: 'Enter description (optional):',
78
78
  default: ''
79
+ },
80
+ {
81
+ type: 'confirm',
82
+ name: 'addCustomEnv',
83
+ message: 'Add custom environment variables? (e.g., CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC)',
84
+ default: false
79
85
  }
80
86
  ]);
81
87
 
88
+ // Handle custom environment variables
89
+ if (accountData.addCustomEnv) {
90
+ accountData.customEnv = {};
91
+ let addMore = true;
92
+
93
+ console.log(chalk.cyan('\n💡 Examples: CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC=1, HTTP_PROXY=http://proxy.com\n'));
94
+
95
+ while (addMore) {
96
+ const envInput = await inquirer.prompt([
97
+ {
98
+ type: 'input',
99
+ name: 'key',
100
+ message: 'Environment variable name (e.g., CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC):',
101
+ validate: (input) => {
102
+ if (!input.trim()) return 'Variable name is required';
103
+ if (!/^[A-Z_][A-Z0-9_]*$/.test(input.trim())) {
104
+ return 'Invalid format. Use uppercase letters, numbers, and underscores (e.g., MY_VAR)';
105
+ }
106
+ return true;
107
+ }
108
+ },
109
+ {
110
+ type: 'input',
111
+ name: 'value',
112
+ message: 'Environment variable value:',
113
+ validate: (input) => input.trim() !== '' || 'Value is required'
114
+ }
115
+ ]);
116
+
117
+ accountData.customEnv[envInput.key.trim()] = envInput.value.trim();
118
+
119
+ const { continueAdding } = await inquirer.prompt([
120
+ {
121
+ type: 'confirm',
122
+ name: 'continueAdding',
123
+ message: 'Add another environment variable?',
124
+ default: false
125
+ }
126
+ ]);
127
+
128
+ addMore = continueAdding;
129
+ }
130
+
131
+ console.log(chalk.green(`\n✓ Added ${Object.keys(accountData.customEnv).length} custom environment variable(s)\n`));
132
+ }
133
+
134
+ // Remove the addCustomEnv flag before saving
135
+ delete accountData.addCustomEnv;
136
+
82
137
  // Save account
83
138
  config.addAccount(name, accountData);
84
139
  console.log(chalk.green(`✓ Account '${name}' added successfully!`));
@@ -111,6 +166,9 @@ function listAccounts() {
111
166
  console.log(` API Key: ${maskApiKey(account.apiKey)}`);
112
167
  if (account.email) console.log(` Email: ${account.email}`);
113
168
  if (account.description) console.log(` Description: ${account.description}`);
169
+ if (account.customEnv && Object.keys(account.customEnv).length > 0) {
170
+ console.log(` Custom Env: ${Object.keys(account.customEnv).join(', ')}`);
171
+ }
114
172
  console.log(` Created: ${new Date(account.createdAt).toLocaleString()}`);
115
173
  console.log('');
116
174
  });
@@ -185,6 +243,12 @@ function showInfo() {
185
243
  if (projectAccount.organizationId) console.log(`${chalk.cyan('Organization ID:')} ${projectAccount.organizationId}`);
186
244
  if (projectAccount.email) console.log(`${chalk.cyan('Email:')} ${projectAccount.email}`);
187
245
  if (projectAccount.description) console.log(`${chalk.cyan('Description:')} ${projectAccount.description}`);
246
+ if (projectAccount.customEnv && Object.keys(projectAccount.customEnv).length > 0) {
247
+ console.log(`${chalk.cyan('Custom Environment Variables:')}`);
248
+ Object.entries(projectAccount.customEnv).forEach(([key, value]) => {
249
+ console.log(` ${chalk.gray('•')} ${key}: ${value}`);
250
+ });
251
+ }
188
252
  console.log(`${chalk.cyan('Set At:')} ${new Date(projectAccount.setAt).toLocaleString()}`);
189
253
  console.log(`${chalk.cyan('Project Root:')} ${projectAccount.projectRoot}`);
190
254
  console.log(`${chalk.cyan('Current Directory:')} ${process.cwd()}\n`);
@@ -261,11 +325,24 @@ function showCurrent() {
261
325
  */
262
326
  function showPaths() {
263
327
  const paths = config.getConfigPaths();
328
+ const projectRoot = config.findProjectRoot();
264
329
 
265
330
  console.log(chalk.bold('\n📂 Configuration Paths:\n'));
266
- console.log(`${chalk.cyan('Global config file:')} ${chalk.yellow(paths.global)}`);
267
- console.log(`${chalk.cyan('Global config directory:')} ${chalk.yellow(paths.globalDir)}`);
268
- console.log(`${chalk.cyan('Project config file:')} ${chalk.yellow(paths.project)}\n`);
331
+ console.log(`${chalk.cyan('Global config file:')} ${paths.global}`);
332
+ console.log(`${chalk.cyan('Global config directory:')} ${paths.globalDir}`);
333
+ console.log(`${chalk.cyan('Project config file:')} ${paths.project}`);
334
+
335
+ if (projectRoot) {
336
+ const claudeConfigPath = require('path').join(projectRoot, '.claude', 'settings.local.json');
337
+ const fs = require('fs');
338
+ console.log(`${chalk.cyan('Claude config file:')} ${claudeConfigPath}`);
339
+ console.log(`${chalk.cyan('Claude config exists:')} ${fs.existsSync(claudeConfigPath) ? chalk.green('✓ Yes') : chalk.red('✗ No')}`);
340
+ console.log(`${chalk.cyan('Project root:')} ${projectRoot}`);
341
+ console.log(`${chalk.cyan('Current directory:')} ${process.cwd()}`);
342
+ } else {
343
+ console.log(chalk.yellow('\n⚠ Not in a configured project directory'));
344
+ }
345
+ console.log('');
269
346
  }
270
347
 
271
348
  /**
@@ -297,6 +374,126 @@ function maskApiKey(apiKey) {
297
374
  return apiKey.substring(0, 4) + '****' + apiKey.substring(apiKey.length - 4);
298
375
  }
299
376
 
377
+ /**
378
+ * Diagnose Claude Code configuration issues
379
+ */
380
+ function doctor() {
381
+ const path = require('path');
382
+ const fs = require('fs');
383
+ const os = require('os');
384
+
385
+ console.log(chalk.bold.cyan('\n🔍 Claude Code Configuration Diagnostics\n'));
386
+
387
+ // Check current directory
388
+ console.log(chalk.bold('1. Current Directory:'));
389
+ console.log(` ${process.cwd()}\n`);
390
+
391
+ // Check project root
392
+ const projectRoot = config.findProjectRoot();
393
+ console.log(chalk.bold('2. Project Root Detection:'));
394
+ if (projectRoot) {
395
+ console.log(chalk.green(` ✓ Found project root: ${projectRoot}`));
396
+ } else {
397
+ console.log(chalk.yellow(' ⚠ No project root found (not in a configured project)'));
398
+ console.log(chalk.gray(' Run "ais use <account>" in your project root first\n'));
399
+ return;
400
+ }
401
+
402
+ // Check ais project config
403
+ const aisConfigPath = path.join(projectRoot, '.ais-project-config');
404
+ console.log(chalk.bold('\n3. AIS Project Configuration:'));
405
+ if (fs.existsSync(aisConfigPath)) {
406
+ console.log(chalk.green(` ✓ Config exists: ${aisConfigPath}`));
407
+ try {
408
+ const aisConfig = JSON.parse(fs.readFileSync(aisConfigPath, 'utf8'));
409
+ console.log(` Account: ${chalk.cyan(aisConfig.activeAccount)}`);
410
+ } catch (e) {
411
+ console.log(chalk.red(` ✗ Error reading config: ${e.message}`));
412
+ }
413
+ } else {
414
+ console.log(chalk.red(` ✗ Config not found: ${aisConfigPath}`));
415
+ }
416
+
417
+ // Check Claude config
418
+ const claudeDir = path.join(projectRoot, '.claude');
419
+ const claudeConfigPath = path.join(claudeDir, 'settings.local.json');
420
+
421
+ console.log(chalk.bold('\n4. Claude Code Configuration:'));
422
+ console.log(` Expected location: ${claudeConfigPath}`);
423
+
424
+ if (fs.existsSync(claudeConfigPath)) {
425
+ console.log(chalk.green(' ✓ Claude config exists'));
426
+ try {
427
+ const claudeConfig = JSON.parse(fs.readFileSync(claudeConfigPath, 'utf8'));
428
+
429
+ if (claudeConfig.env && claudeConfig.env.ANTHROPIC_AUTH_TOKEN) {
430
+ const token = claudeConfig.env.ANTHROPIC_AUTH_TOKEN;
431
+ const masked = token.substring(0, 6) + '****' + token.substring(token.length - 4);
432
+ console.log(` API Token: ${masked}`);
433
+ }
434
+
435
+ if (claudeConfig.env && claudeConfig.env.ANTHROPIC_BASE_URL) {
436
+ console.log(` API URL: ${claudeConfig.env.ANTHROPIC_BASE_URL}`);
437
+ }
438
+
439
+ if (claudeConfig.env && claudeConfig.env.ANTHROPIC_ORGANIZATION_ID) {
440
+ console.log(` Org ID: ${claudeConfig.env.ANTHROPIC_ORGANIZATION_ID}`);
441
+ }
442
+ } catch (e) {
443
+ console.log(chalk.red(` ✗ Error reading Claude config: ${e.message}`));
444
+ }
445
+ } else {
446
+ console.log(chalk.red(' ✗ Claude config not found'));
447
+ console.log(chalk.yellow(' Run "ais use <account>" to generate it'));
448
+ }
449
+
450
+ // Check global Claude config
451
+ const globalClaudeConfig = path.join(os.homedir(), '.claude', 'settings.json');
452
+ console.log(chalk.bold('\n5. Global Claude Configuration:'));
453
+ console.log(` Location: ${globalClaudeConfig}`);
454
+
455
+ if (fs.existsSync(globalClaudeConfig)) {
456
+ console.log(chalk.yellow(' ⚠ Global config exists (may override project config in some cases)'));
457
+ try {
458
+ const globalConfig = JSON.parse(fs.readFileSync(globalClaudeConfig, 'utf8'));
459
+ if (globalConfig.env && globalConfig.env.ANTHROPIC_AUTH_TOKEN) {
460
+ const token = globalConfig.env.ANTHROPIC_AUTH_TOKEN;
461
+ const masked = token.substring(0, 6) + '****' + token.substring(token.length - 4);
462
+ console.log(` Global API Token: ${masked}`);
463
+ }
464
+ if (globalConfig.env && globalConfig.env.ANTHROPIC_BASE_URL) {
465
+ console.log(` Global API URL: ${globalConfig.env.ANTHROPIC_BASE_URL}`);
466
+ }
467
+ } catch (e) {
468
+ console.log(chalk.red(` ✗ Error reading global config: ${e.message}`));
469
+ }
470
+ } else {
471
+ console.log(chalk.green(' ✓ No global config (good - project config will be used)'));
472
+ }
473
+
474
+ // Recommendations
475
+ console.log(chalk.bold('\n6. Recommendations:'));
476
+
477
+ if (projectRoot && process.cwd() !== projectRoot) {
478
+ console.log(chalk.yellow(` ⚠ You are in a subdirectory (${path.relative(projectRoot, process.cwd())})`));
479
+ console.log(chalk.cyan(' • Claude Code should still find the project config'));
480
+ console.log(chalk.cyan(' • Make sure to start Claude Code from this directory or parent directories'));
481
+ }
482
+
483
+ if (fs.existsSync(globalClaudeConfig)) {
484
+ console.log(chalk.yellow(' ⚠ Global Claude config exists:'));
485
+ console.log(chalk.cyan(' • Project config should take precedence'));
486
+ console.log(chalk.cyan(' • If issues persist, consider removing global env settings'));
487
+ console.log(chalk.gray(` • File: ${globalClaudeConfig}`));
488
+ }
489
+
490
+ console.log(chalk.bold('\n7. Next Steps:'));
491
+ console.log(chalk.cyan(' • Start Claude Code from your project directory or subdirectory'));
492
+ console.log(chalk.cyan(' • Check which account Claude Code is using'));
493
+ console.log(chalk.cyan(' • If wrong account is used, run: ais use <correct-account>'));
494
+ console.log('');
495
+ }
496
+
300
497
  module.exports = {
301
498
  addAccount,
302
499
  listAccounts,
@@ -305,5 +502,6 @@ module.exports = {
305
502
  removeAccount,
306
503
  showCurrent,
307
504
  showPaths,
308
- exportAccount
505
+ exportAccount,
506
+ doctor
309
507
  };
package/src/config.js CHANGED
@@ -191,6 +191,13 @@ class ConfigManager {
191
191
  claudeConfig.env.ANTHROPIC_ORGANIZATION_ID = account.organizationId;
192
192
  }
193
193
 
194
+ // Add custom environment variables if specified
195
+ if (account.customEnv && typeof account.customEnv === 'object') {
196
+ Object.keys(account.customEnv).forEach(key => {
197
+ claudeConfig.env[key] = account.customEnv[key];
198
+ });
199
+ }
200
+
194
201
  // Preserve existing permissions if any
195
202
  if (!claudeConfig.permissions) {
196
203
  claudeConfig.permissions = existingConfig.permissions || {
package/src/index.js CHANGED
@@ -10,7 +10,8 @@ const {
10
10
  removeAccount,
11
11
  showCurrent,
12
12
  showPaths,
13
- exportAccount
13
+ exportAccount,
14
+ doctor
14
15
  } = require('./commands');
15
16
 
16
17
  // Package info
@@ -71,6 +72,12 @@ program
71
72
  .description('Export account configuration as JSON')
72
73
  .action(exportAccount);
73
74
 
75
+ // Diagnostic command
76
+ program
77
+ .command('doctor')
78
+ .description('Diagnose Claude Code configuration issues')
79
+ .action(doctor);
80
+
74
81
  // Help command
75
82
  program
76
83
  .command('help')
@@ -81,13 +88,14 @@ program
81
88
  console.log(' ais <command> [options]\n');
82
89
 
83
90
  console.log(chalk.bold('COMMANDS:'));
84
- console.log(' add [name] Add a new account configuration');
91
+ console.log(' add [name] Add a new account configuration (with custom env vars)');
85
92
  console.log(' list, ls List all available accounts');
86
93
  console.log(' use [name] Set the account for current project');
87
94
  console.log(' info Show current project\'s account info');
88
95
  console.log(' current Show current account name');
89
96
  console.log(' remove, rm Remove an account');
90
97
  console.log(' paths Show configuration file paths');
98
+ console.log(' doctor Diagnose Claude Code configuration issues');
91
99
  console.log(' export <name> Export account as JSON');
92
100
  console.log(' help Display this help message');
93
101
  console.log(' version Show version number\n');
@@ -103,12 +111,21 @@ program
103
111
  console.log(' ais use my-claude-account\n');
104
112
  console.log(chalk.gray(' # Show current project info'));
105
113
  console.log(' ais info\n');
114
+ console.log(chalk.gray(' # Diagnose configuration issues'));
115
+ console.log(' ais doctor\n');
106
116
  console.log(chalk.gray(' # Remove an account'));
107
117
  console.log(' ais remove my-old-account\n');
108
118
 
119
+ console.log(chalk.bold('FEATURES:'));
120
+ console.log(' • Custom environment variables support');
121
+ console.log(' • Automatic Claude Code .claude/settings.local.json generation');
122
+ console.log(' • Smart directory detection (works in any subdirectory)');
123
+ console.log(' • Configuration diagnostics with doctor command\n');
124
+
109
125
  console.log(chalk.bold('CONFIGURATION:'));
110
126
  console.log(' Global config: ~/.ai-account-switch/config.json');
111
- console.log(' Project config: ./.ais-project-config\n');
127
+ console.log(' Project config: ./.ais-project-config');
128
+ console.log(' Claude config: ./.claude/settings.local.json\n');
112
129
 
113
130
  console.log(chalk.bold('CROSS-PLATFORM:'));
114
131
  console.log(' Works on macOS, Linux, and Windows');
@@ -1,19 +0,0 @@
1
- {
2
- "permissions": {
3
- "allow": [
4
- "Bash(node:*)",
5
- "Bash(npm --version)",
6
- "Bash(chmod:*)",
7
- "Bash(npm install)",
8
- "Bash(npm link)",
9
- "Bash(ais:*)",
10
- "WebSearch",
11
- "WebFetch(domain:www.vibesparking.com)",
12
- "Read(//Users/deanwang/.claude/**)",
13
- "Read(//Users/deanwang/IdeaProjects/githubProject/team-nav/**)",
14
- "Bash(cat:*)"
15
- ],
16
- "deny": [],
17
- "ask": []
18
- }
19
- }