@minniexcode/codex-switch 0.0.12 → 0.1.1

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.
Files changed (36) hide show
  1. package/README.AI.md +37 -6
  2. package/README.CN.md +45 -11
  3. package/README.md +45 -13
  4. package/dist/app/add-provider.js +22 -24
  5. package/dist/app/edit-provider.js +34 -55
  6. package/dist/app/get-current-profile.js +15 -3
  7. package/dist/app/get-status.js +11 -8
  8. package/dist/app/list-config-profiles.js +3 -1
  9. package/dist/app/list-providers.js +10 -4
  10. package/dist/app/remove-provider.js +52 -19
  11. package/dist/app/run-doctor.js +29 -28
  12. package/dist/app/setup-codex.js +3 -3
  13. package/dist/app/show-config.js +3 -1
  14. package/dist/app/switch-provider.js +36 -5
  15. package/dist/cli/output.js +36 -18
  16. package/dist/commands/handlers.js +2 -2
  17. package/dist/commands/help.js +3 -3
  18. package/dist/commands/registry.js +35 -30
  19. package/dist/domain/config.js +250 -185
  20. package/dist/domain/providers.js +23 -0
  21. package/dist/domain/runtime-state.js +15 -15
  22. package/dist/domain/setup.js +3 -1
  23. package/dist/interaction/interactive.js +2 -2
  24. package/dist/runtime/codex-version.js +7 -0
  25. package/dist/storage/config-repo.js +6 -14
  26. package/docs/Design/codex-switch-v0.1.0-design.md +152 -0
  27. package/docs/Design/codex-switch-v0.1.1-design.md +33 -0
  28. package/docs/PRD/codex-switch-prd-v0.1.0.md +217 -205
  29. package/docs/Reference/codex-config-reference.md +41 -0
  30. package/docs/Reference/codex-config-reference.zh-CN.md +41 -0
  31. package/docs/Tests/testing.md +31 -78
  32. package/docs/cli-usage.md +86 -27
  33. package/docs/codex-switch-command-design.md +649 -649
  34. package/docs/codex-switch-product-overview.md +81 -80
  35. package/docs/codex-switch-technical-architecture.md +1115 -1115
  36. package/package.json +51 -51
@@ -1,649 +1,649 @@
1
- # codex-switch 命令设计说明
2
-
3
- > 状态说明:这份文档是历史跨版本参考,不是当前 release contract。
4
- > 当前事实源请改看 [`docs/cli-usage.md`](./cli-usage.md)、[`docs/PRD/codex-switch-prd-v0.0.12.md`](./PRD/codex-switch-prd-v0.0.12.md)、[`docs/Design/codex-switch-v0.0.12-design.md`](./Design/codex-switch-v0.0.12-design.md)。
5
-
6
- ## 文档信息
7
-
8
- - 文档类型:命令设计文档
9
- - 适用范围:`codex-switch` MVP
10
- - 关联文档:
11
- - [`PRD/codex-switch-prd.md`](./PRD/codex-switch-prd.md)
12
- - [`codex-switch-technical-architecture.md`](./codex-switch-technical-architecture.md)
13
-
14
- ## 1. 文档目标
15
-
16
- 这份文档把 `codex-switch` 的每个 CLI 命令拆开描述,重点沉淀下面这些内容:
17
-
18
- - 命令用途
19
- - 输入参数
20
- - 成功输出
21
- - 失败错误码
22
- - 关键行为语义
23
- - 对 AI / 自动化调用的注意事项
24
-
25
- 这份文档是 PRD 的命令规格落地版,也是技术架构文档的命令视角补充。
26
-
27
- ## 1.1 与 `cc-switch` / `codex-auth` 的命令形态差异
28
-
29
- 为了帮助后续继续演进,这里先明确三者的命令/交互边界:
30
-
31
- - `codex-switch`
32
- - 目标是稳定 CLI 命令
33
- - 聚焦 provider/profile 切换、导入导出、诊断、回滚
34
- - `codex-auth`
35
- - 更偏账号 / auth 管理 CLI
36
- - 对本项目的参考点是命令组织方式
37
- - `cc-switch`
38
- - 更偏 GUI / 桌面管理器
39
- - 即使内部也有切换逻辑,用户主入口不是命令行,而是桌面界面
40
-
41
- 这意味着 `codex-switch` 的命令设计原则应继续保持:
42
-
43
- - 参数显式
44
- - 输出稳定
45
- - 能被 AI 和脚本直接消费
46
- - 交互只作为 TTY 中的人类增强层,而不是自动化契约
47
-
48
- ## 2. 公共命令约定
49
-
50
- ### 2.1 命令入口
51
-
52
- 统一命令名:
53
-
54
- ```bash
55
- codexs
56
- ```
57
-
58
- ### 2.2 公共参数
59
-
60
- 所有支持的命令共享以下全局参数:
61
-
62
- - `--json`
63
- - 返回统一 JSON envelope
64
- - `--codex-dir <path>`
65
- - 指定目标工作目录
66
-
67
- ### 2.3 JSON 输出结构
68
-
69
- 统一 envelope:
70
-
71
- ```json
72
- {
73
- "ok": true,
74
- "command": "list",
75
- "data": {},
76
- "warnings": [],
77
- "error": null
78
- }
79
- ```
80
-
81
- 失败时:
82
-
83
- ```json
84
- {
85
- "ok": false,
86
- "command": "list",
87
- "data": null,
88
- "warnings": [],
89
- "error": {
90
- "code": "PROVIDERS_NOT_FOUND",
91
- "message": "providers.json does not exist.",
92
- "details": {
93
- "file": "C:\\Users\\name\\.codex\\providers.json"
94
- }
95
- }
96
- }
97
- ```
98
-
99
- ### 2.4 固定错误码
100
-
101
- 当前命令层统一使用:
102
-
103
- - `CONFIG_NOT_FOUND`
104
- - `PROVIDERS_NOT_FOUND`
105
- - `PROVIDERS_PARSE_ERROR`
106
- - `PROVIDER_NOT_FOUND`
107
- - `PROFILE_NOT_FOUND`
108
- - `BACKUP_FAILED`
109
- - `CODEX_LOGIN_FAILED`
110
- - `ROLLBACK_FAILED`
111
- - `INVALID_IMPORT_FILE`
112
-
113
- ### 2.5 渐进式交互约定
114
-
115
- - `--json` 一律禁用交互
116
- - 非 TTY 一律不进入交互
117
- - 交互主要服务于人类高频写命令,不改变自动化显式参数契约
118
- - 用户取消 prompt、`Ctrl+C`、或确认选择否时,不应产生任何文件写入
119
-
120
- ## 3. 命令清单概览
121
-
122
- ```bash
123
- codexs list
124
- codexs current
125
- codexs switch <provider>
126
- codexs status
127
- codexs import <file>
128
- codexs export <file>
129
- codexs add <provider>
130
- codexs remove <provider>
131
- codexs doctor
132
- codexs rollback
133
- ```
134
-
135
- ## 4. 命令逐项设计
136
-
137
- ### 4.1 `codexs list`
138
-
139
- #### 目标
140
-
141
- 列出当前 `providers.json` 中的 provider 清单。
142
-
143
- #### 输入
144
-
145
- ```bash
146
- codexs list [--json] [--codex-dir <path>]
147
- ```
148
-
149
- #### 成功输出
150
-
151
- 默认输出示意:
152
-
153
- ```text
154
- freemodel -> freemodel
155
- packycode -> packycode tags=daily note=primary
156
- ```
157
-
158
- JSON 输出示意:
159
-
160
- ```json
161
- {
162
- "ok": true,
163
- "command": "list",
164
- "data": {
165
- "providers": [
166
- {
167
- "name": "freemodel",
168
- "profile": "freemodel",
169
- "note": null,
170
- "tags": []
171
- }
172
- ],
173
- "count": 1
174
- },
175
- "warnings": [],
176
- "error": null
177
- }
178
- ```
179
-
180
- #### 失败错误码
181
-
182
- - `PROVIDERS_NOT_FOUND`
183
- - `PROVIDERS_PARSE_ERROR`
184
-
185
- #### AI 调用建议
186
-
187
- - 优先使用 `--json`
188
- - 不要依赖默认输出格式做机器解析
189
-
190
- ### 4.2 `codexs current`
191
-
192
- #### 目标
193
-
194
- 返回当前 `config.toml` 顶层 `profile`。
195
-
196
- #### 输入
197
-
198
- ```bash
199
- codexs current [--json] [--codex-dir <path>]
200
- ```
201
-
202
- #### 成功输出
203
-
204
- 默认:
205
-
206
- ```text
207
- Current profile: packycode
208
- ```
209
-
210
- JSON:
211
-
212
- ```json
213
- {
214
- "ok": true,
215
- "command": "current",
216
- "data": {
217
- "profile": "packycode"
218
- },
219
- "warnings": [],
220
- "error": null
221
- }
222
- ```
223
-
224
- #### 失败错误码
225
-
226
- - `CONFIG_NOT_FOUND`
227
- - `PROFILE_NOT_FOUND`
228
-
229
- ### 4.3 `codexs status`
230
-
231
- #### 目标
232
-
233
- 给出本地配置的浅状态概览。
234
-
235
- #### 输入
236
-
237
- ```bash
238
- codexs status [--json] [--codex-dir <path>]
239
- ```
240
-
241
- #### 当前返回字段
242
-
243
- - `codexDir`
244
- - `configExists`
245
- - `providersExists`
246
- - `currentProfile`
247
- - `currentProfileMapped`
248
- - `provider`
249
-
250
- #### 成功输出
251
-
252
- JSON 示例:
253
-
254
- ```json
255
- {
256
- "ok": true,
257
- "command": "status",
258
- "data": {
259
- "codexDir": "C:\\Users\\name\\.codex",
260
- "configExists": true,
261
- "providersExists": true,
262
- "currentProfile": "packycode",
263
- "currentProfileMapped": true,
264
- "provider": "packycode"
265
- },
266
- "warnings": [],
267
- "error": null
268
- }
269
- ```
270
-
271
- #### 设计说明
272
-
273
- - `status` 是概览,不做深度建议
274
- - 深度问题检测交给 `doctor`
275
-
276
- ### 4.4 `codexs switch <provider>`
277
-
278
- #### 目标
279
-
280
- 切换到指定 provider,并默认同步更新登录状态。
281
-
282
- #### 输入
283
-
284
- ```bash
285
- codexs switch <provider> [--no-login] [--json] [--codex-dir <path>]
286
- ```
287
-
288
- #### 交互行为
289
-
290
- - 当 `<provider>` 缺失且当前是 TTY 时,先从 `providers.json` 读取 provider 列表,再用选择器选择 provider
291
- - 当 `<provider>` 已显式传入时,不额外确认
292
- - `--no-login` 仍保持显式 flag,不进入提问
293
-
294
- #### 前置校验
295
-
296
- - `providers.json` 必须存在
297
- - provider 必须存在
298
- - provider 对应的 `profile` 必须存在于 `config.toml`
299
-
300
- #### 执行步骤
301
-
302
- 1. 读取 provider 数据
303
- 2. 校验 profile
304
- 3. 备份 `config.toml`
305
- 4. 如果存在,备份 `auth.json`
306
- 5. 更新顶层 `profile`
307
- 6. 默认执行 `codex login --with-api-key`
308
- 7. 成功则保存为最近一次备份
309
- 8. 失败则按 manifest 回滚
310
-
311
- #### 成功输出
312
-
313
- JSON 示例:
314
-
315
- ```json
316
- {
317
- "ok": true,
318
- "command": "switch",
319
- "data": {
320
- "provider": "freemodel",
321
- "profile": "freemodel",
322
- "loginPerformed": true,
323
- "backupPath": "C:\\Users\\name\\.codex\\backups\\20260511-221550-switch"
324
- },
325
- "warnings": [],
326
- "error": null
327
- }
328
- ```
329
-
330
- #### 失败错误码
331
-
332
- - `PROVIDER_NOT_FOUND`
333
- - `PROFILE_NOT_FOUND`
334
- - `BACKUP_FAILED`
335
- - `CODEX_LOGIN_FAILED`
336
- - `ROLLBACK_FAILED`
337
-
338
- #### 注意事项
339
-
340
- - `--no-login` 仅跳过登录,不跳过备份和 profile 修改
341
- - 登录失败时当前实现会附带 `rollbackApplied: true`
342
-
343
- ### 4.5 `codexs import <file>`
344
-
345
- #### 目标
346
-
347
- 整体替换当前 `providers.json`。
348
-
349
- #### 输入
350
-
351
- ```bash
352
- codexs import <file> [--json] [--codex-dir <path>]
353
- ```
354
-
355
- #### 行为语义
356
-
357
- - 只支持整体替换
358
- - 不支持 merge
359
- - 写入前备份当前 `providers.json`
360
- - 路径参数必须显式传入
361
- - TTY 中实际替换前增加一次确认
362
-
363
- #### 成功输出
364
-
365
- ```json
366
- {
367
- "ok": true,
368
- "command": "import",
369
- "data": {
370
- "importedProviders": ["imported"],
371
- "backupPath": "C:\\Users\\name\\.codex\\backups\\20260511-221457-import"
372
- },
373
- "warnings": [],
374
- "error": null
375
- }
376
- ```
377
-
378
- #### 失败错误码
379
-
380
- - `INVALID_IMPORT_FILE`
381
- - `BACKUP_FAILED`
382
- - `ROLLBACK_FAILED`
383
-
384
- ### 4.6 `codexs export <file>`
385
-
386
- #### 目标
387
-
388
- 导出当前 `providers.json` 到指定位置。
389
-
390
- #### 输入
391
-
392
- ```bash
393
- codexs export <file> [--force] [--json] [--codex-dir <path>]
394
- ```
395
-
396
- #### 行为语义
397
-
398
- - 默认不覆盖已有文件
399
- - 传 `--force` 后允许覆盖
400
- - 路径参数必须显式传入
401
- - 当目标文件已存在、当前是 TTY 且未传 `--force` 时,可通过确认后继续覆盖
402
-
403
- #### 成功输出
404
-
405
- ```json
406
- {
407
- "ok": true,
408
- "command": "export",
409
- "data": {
410
- "exportedTo": "C:\\path\\providers-export.json",
411
- "count": 3
412
- },
413
- "warnings": [],
414
- "error": null
415
- }
416
- ```
417
-
418
- #### 失败错误码
419
-
420
- - `INVALID_IMPORT_FILE`
421
- - `PROVIDERS_NOT_FOUND`
422
- - `PROVIDERS_PARSE_ERROR`
423
-
424
- ### 4.7 `codexs add <provider>`
425
-
426
- #### 目标
427
-
428
- 新增一条 provider 记录。
429
-
430
- #### 输入
431
-
432
- ```bash
433
- codexs add <provider> \
434
- --profile <name> \
435
- --api-key <key> \
436
- [--base-url <url>] \
437
- [--note <text>] \
438
- [--tag <tag>] \
439
- [--json] \
440
- [--codex-dir <path>]
441
- ```
442
-
443
- #### 行为语义
444
-
445
- - provider 名必须唯一
446
- - 写入前备份旧 `providers.json`
447
- - 显式参数模式保持可用
448
- - 当缺少必填字段且 stdin/stdout 都是 TTY 时,允许渐进式提问
449
- - `--json` 或非 TTY 场景下仍要求显式传入必填参数
450
- - `profile` 优先从 `config.toml` 已有 profile 列表里选择,获取失败时退回文本输入
451
- - `apiKey` 使用隐藏输入并要求二次确认
452
-
453
- #### 成功输出
454
-
455
- ```json
456
- {
457
- "ok": true,
458
- "command": "add",
459
- "data": {
460
- "provider": "temp",
461
- "profile": "freemodel",
462
- "backupPath": "C:\\Users\\name\\.codex\\backups\\20260511-221457-add"
463
- },
464
- "warnings": [],
465
- "error": null
466
- }
467
- ```
468
-
469
- #### 失败错误码
470
-
471
- - `INVALID_IMPORT_FILE`
472
- - `BACKUP_FAILED`
473
- - `ROLLBACK_FAILED`
474
-
475
- ### 4.8 `codexs remove <provider>`
476
-
477
- #### 目标
478
-
479
- 删除一条 provider 记录。
480
-
481
- #### 输入
482
-
483
- ```bash
484
- codexs remove <provider> [--force] [--json] [--codex-dir <path>]
485
- ```
486
-
487
- #### 行为语义
488
-
489
- - TTY 中若缺少 `<provider>`,允许先选择 provider
490
- - TTY 中始终需要确认,确认文案必须带 provider 名
491
- - TTY 中即使未传 `--force`,也可通过确认完成删除
492
- - 非 TTY 或 `--json` 场景下仍要求显式 `<provider> --force`
493
- - 先备份再删除
494
-
495
- #### 失败错误码
496
-
497
- - `PROVIDER_NOT_FOUND`
498
- - `INVALID_IMPORT_FILE`
499
- - `BACKUP_FAILED`
500
- - `ROLLBACK_FAILED`
501
-
502
- ### 4.9 `codexs doctor`
503
-
504
- #### 目标
505
-
506
- 返回结构化问题列表,而不是只给一个总体状态。
507
-
508
- #### 输入
509
-
510
- ```bash
511
- codexs doctor [--json] [--codex-dir <path>]
512
- ```
513
-
514
- #### 当前诊断项
515
-
516
- - `config.toml` 是否存在
517
- - `providers.json` 是否存在
518
- - `providers.json` 是否可解析
519
- - provider 的 profile 是否存在
520
- - `codex` CLI 是否可执行
521
-
522
- #### 当前返回结构
523
-
524
- ```json
525
- {
526
- "ok": true,
527
- "command": "doctor",
528
- "data": {
529
- "healthy": false,
530
- "issues": [
531
- {
532
- "code": "CODEX_LOGIN_FAILED",
533
- "message": "codex CLI is not available.",
534
- "cause": "spawnSync codex EPERM"
535
- }
536
- ],
537
- "codexDir": "C:\\Users\\name\\.codex"
538
- },
539
- "warnings": ["doctor found 1 issue(s)"],
540
- "error": null
541
- }
542
- ```
543
-
544
- #### 说明
545
-
546
- - 当前实现把 codex CLI 缺失归到 `CODEX_LOGIN_FAILED`
547
- - 后续可按需要拆分更细错误码
548
-
549
- ### 4.10 `codexs rollback`
550
-
551
- #### 目标
552
-
553
- 恢复最近一次备份对应的文件状态。
554
-
555
- #### 输入
556
-
557
- ```bash
558
- codexs rollback [--json] [--codex-dir <path>]
559
- ```
560
-
561
- #### 行为语义
562
-
563
- - 读取 `backups/latest.json`
564
- - 恢复 manifest 中记录的文件
565
- - 如果最近一次备份包含 `auth.json`,一并恢复
566
- - TTY 中执行前会展示备份目录和受影响文件摘要,并请求确认
567
-
568
- #### 成功输出
569
-
570
- ```json
571
- {
572
- "ok": true,
573
- "command": "rollback",
574
- "data": {
575
- "restoredFiles": ["config.toml", "auth.json"],
576
- "backupPath": "C:\\Users\\name\\.codex\\backups\\20260511-221550-switch"
577
- },
578
- "warnings": [],
579
- "error": null
580
- }
581
- ```
582
-
583
- #### 失败错误码
584
-
585
- - `ROLLBACK_FAILED`
586
-
587
- ## 5. 默认输出与敏感信息策略
588
-
589
- 默认输出遵循:
590
-
591
- - 不打印完整 `apiKey`
592
- - 不打印无关调试信息
593
- - 成功时尽量只返回命令核心结果
594
-
595
- JSON 输出也遵循相同策略:
596
-
597
- - `error.details` 不应包含完整 `apiKey`
598
- - 主要返回路径、命令对象、回滚状态等可操作信息
599
-
600
- ## 6. AI / 自动化调用建议
601
-
602
- 对 AI 代理或自动化脚本,推荐以下调用约定:
603
-
604
- - 一律使用 `--json`
605
- - 严格按 `error.code` 判断失败类型
606
- - 对 `switch` 命令关注:
607
- - `provider`
608
- - `profile`
609
- - `loginPerformed`
610
- - `backupPath`
611
- - `rollbackApplied`
612
- - 对 `doctor` 命令关注:
613
- - `healthy`
614
- - `issues[]`
615
-
616
- 推荐模式:
617
-
618
- 1. 先调用 `status --json`
619
- 2. 再调用 `doctor --json`
620
- 3. 满足前置条件后调用 `switch --json`
621
- 4. 失败时根据错误码决定是否提示用户手动执行 `rollback`
622
-
623
- ## 7. 后续命令演进建议
624
-
625
- 如果继续扩展命令面,建议新增命令时遵守下面三条:
626
-
627
- - 不破坏当前 JSON envelope
628
- - 不复用语义不匹配的错误码
629
- - 所有写命令默认纳入备份与回滚模型
630
-
631
- 未来候选命令:
632
-
633
- - `codexs show <provider>`
634
- - `codexs edit <provider>`
635
- - `codexs backups list`
636
- - `codexs rollback <backup-id>`
637
- - `codexs import --merge`
638
-
639
- ## 8. 结论
640
-
641
- `codex-switch` 当前命令设计已经具备下面几个工程特征:
642
-
643
- - 命令面稳定
644
- - 参数风格统一
645
- - JSON 输出可机器解析
646
- - 写操作具备安全语义
647
- - 错误码已可作为 AI 调用契约
648
-
649
- 这意味着它已经不再只是“能切换配置的脚本集合”,而是一套具备持续演进空间的 CLI 命令体系。
1
+ # codex-switch 命令设计说明
2
+
3
+ > 状态说明:这份文档是历史跨版本参考,不是当前 release contract。
4
+ > 当前事实源请改看 [`docs/cli-usage.md`](./cli-usage.md)、[`docs/PRD/codex-switch-prd-v0.1.1.md`](./PRD/codex-switch-prd-v0.1.1.md)、[`docs/Design/codex-switch-v0.1.1-design.md`](./Design/codex-switch-v0.1.1-design.md)。
5
+
6
+ ## 文档信息
7
+
8
+ - 文档类型:命令设计文档
9
+ - 适用范围:`codex-switch` MVP
10
+ - 关联文档:
11
+ - [`PRD/codex-switch-prd.md`](./PRD/codex-switch-prd.md)
12
+ - [`codex-switch-technical-architecture.md`](./codex-switch-technical-architecture.md)
13
+
14
+ ## 1. 文档目标
15
+
16
+ 这份文档把 `codex-switch` 的每个 CLI 命令拆开描述,重点沉淀下面这些内容:
17
+
18
+ - 命令用途
19
+ - 输入参数
20
+ - 成功输出
21
+ - 失败错误码
22
+ - 关键行为语义
23
+ - 对 AI / 自动化调用的注意事项
24
+
25
+ 这份文档是 PRD 的命令规格落地版,也是技术架构文档的命令视角补充。
26
+
27
+ ## 1.1 与 `cc-switch` / `codex-auth` 的命令形态差异
28
+
29
+ 为了帮助后续继续演进,这里先明确三者的命令/交互边界:
30
+
31
+ - `codex-switch`
32
+ - 目标是稳定 CLI 命令
33
+ - 聚焦 provider/profile 切换、导入导出、诊断、回滚
34
+ - `codex-auth`
35
+ - 更偏账号 / auth 管理 CLI
36
+ - 对本项目的参考点是命令组织方式
37
+ - `cc-switch`
38
+ - 更偏 GUI / 桌面管理器
39
+ - 即使内部也有切换逻辑,用户主入口不是命令行,而是桌面界面
40
+
41
+ 这意味着 `codex-switch` 的命令设计原则应继续保持:
42
+
43
+ - 参数显式
44
+ - 输出稳定
45
+ - 能被 AI 和脚本直接消费
46
+ - 交互只作为 TTY 中的人类增强层,而不是自动化契约
47
+
48
+ ## 2. 公共命令约定
49
+
50
+ ### 2.1 命令入口
51
+
52
+ 统一命令名:
53
+
54
+ ```bash
55
+ codexs
56
+ ```
57
+
58
+ ### 2.2 公共参数
59
+
60
+ 所有支持的命令共享以下全局参数:
61
+
62
+ - `--json`
63
+ - 返回统一 JSON envelope
64
+ - `--codex-dir <path>`
65
+ - 指定目标工作目录
66
+
67
+ ### 2.3 JSON 输出结构
68
+
69
+ 统一 envelope:
70
+
71
+ ```json
72
+ {
73
+ "ok": true,
74
+ "command": "list",
75
+ "data": {},
76
+ "warnings": [],
77
+ "error": null
78
+ }
79
+ ```
80
+
81
+ 失败时:
82
+
83
+ ```json
84
+ {
85
+ "ok": false,
86
+ "command": "list",
87
+ "data": null,
88
+ "warnings": [],
89
+ "error": {
90
+ "code": "PROVIDERS_NOT_FOUND",
91
+ "message": "providers.json does not exist.",
92
+ "details": {
93
+ "file": "C:\\Users\\name\\.codex\\providers.json"
94
+ }
95
+ }
96
+ }
97
+ ```
98
+
99
+ ### 2.4 固定错误码
100
+
101
+ 当前命令层统一使用:
102
+
103
+ - `CONFIG_NOT_FOUND`
104
+ - `PROVIDERS_NOT_FOUND`
105
+ - `PROVIDERS_PARSE_ERROR`
106
+ - `PROVIDER_NOT_FOUND`
107
+ - `PROFILE_NOT_FOUND`
108
+ - `BACKUP_FAILED`
109
+ - `CODEX_LOGIN_FAILED`
110
+ - `ROLLBACK_FAILED`
111
+ - `INVALID_IMPORT_FILE`
112
+
113
+ ### 2.5 渐进式交互约定
114
+
115
+ - `--json` 一律禁用交互
116
+ - 非 TTY 一律不进入交互
117
+ - 交互主要服务于人类高频写命令,不改变自动化显式参数契约
118
+ - 用户取消 prompt、`Ctrl+C`、或确认选择否时,不应产生任何文件写入
119
+
120
+ ## 3. 命令清单概览
121
+
122
+ ```bash
123
+ codexs list
124
+ codexs current
125
+ codexs switch <provider>
126
+ codexs status
127
+ codexs import <file>
128
+ codexs export <file>
129
+ codexs add <provider>
130
+ codexs remove <provider>
131
+ codexs doctor
132
+ codexs rollback
133
+ ```
134
+
135
+ ## 4. 命令逐项设计
136
+
137
+ ### 4.1 `codexs list`
138
+
139
+ #### 目标
140
+
141
+ 列出当前 `providers.json` 中的 provider 清单。
142
+
143
+ #### 输入
144
+
145
+ ```bash
146
+ codexs list [--json] [--codex-dir <path>]
147
+ ```
148
+
149
+ #### 成功输出
150
+
151
+ 默认输出示意:
152
+
153
+ ```text
154
+ freemodel -> freemodel
155
+ packycode -> packycode tags=daily note=primary
156
+ ```
157
+
158
+ JSON 输出示意:
159
+
160
+ ```json
161
+ {
162
+ "ok": true,
163
+ "command": "list",
164
+ "data": {
165
+ "providers": [
166
+ {
167
+ "name": "freemodel",
168
+ "profile": "freemodel",
169
+ "note": null,
170
+ "tags": []
171
+ }
172
+ ],
173
+ "count": 1
174
+ },
175
+ "warnings": [],
176
+ "error": null
177
+ }
178
+ ```
179
+
180
+ #### 失败错误码
181
+
182
+ - `PROVIDERS_NOT_FOUND`
183
+ - `PROVIDERS_PARSE_ERROR`
184
+
185
+ #### AI 调用建议
186
+
187
+ - 优先使用 `--json`
188
+ - 不要依赖默认输出格式做机器解析
189
+
190
+ ### 4.2 `codexs current`
191
+
192
+ #### 目标
193
+
194
+ 返回当前 `config.toml` 顶层 `profile`。
195
+
196
+ #### 输入
197
+
198
+ ```bash
199
+ codexs current [--json] [--codex-dir <path>]
200
+ ```
201
+
202
+ #### 成功输出
203
+
204
+ 默认:
205
+
206
+ ```text
207
+ Current profile: packycode
208
+ ```
209
+
210
+ JSON:
211
+
212
+ ```json
213
+ {
214
+ "ok": true,
215
+ "command": "current",
216
+ "data": {
217
+ "profile": "packycode"
218
+ },
219
+ "warnings": [],
220
+ "error": null
221
+ }
222
+ ```
223
+
224
+ #### 失败错误码
225
+
226
+ - `CONFIG_NOT_FOUND`
227
+ - `PROFILE_NOT_FOUND`
228
+
229
+ ### 4.3 `codexs status`
230
+
231
+ #### 目标
232
+
233
+ 给出本地配置的浅状态概览。
234
+
235
+ #### 输入
236
+
237
+ ```bash
238
+ codexs status [--json] [--codex-dir <path>]
239
+ ```
240
+
241
+ #### 当前返回字段
242
+
243
+ - `codexDir`
244
+ - `configExists`
245
+ - `providersExists`
246
+ - `currentProfile`
247
+ - `currentProfileMapped`
248
+ - `provider`
249
+
250
+ #### 成功输出
251
+
252
+ JSON 示例:
253
+
254
+ ```json
255
+ {
256
+ "ok": true,
257
+ "command": "status",
258
+ "data": {
259
+ "codexDir": "C:\\Users\\name\\.codex",
260
+ "configExists": true,
261
+ "providersExists": true,
262
+ "currentProfile": "packycode",
263
+ "currentProfileMapped": true,
264
+ "provider": "packycode"
265
+ },
266
+ "warnings": [],
267
+ "error": null
268
+ }
269
+ ```
270
+
271
+ #### 设计说明
272
+
273
+ - `status` 是概览,不做深度建议
274
+ - 深度问题检测交给 `doctor`
275
+
276
+ ### 4.4 `codexs switch <provider>`
277
+
278
+ #### 目标
279
+
280
+ 切换到指定 provider,并默认同步更新登录状态。
281
+
282
+ #### 输入
283
+
284
+ ```bash
285
+ codexs switch <provider> [--no-login] [--json] [--codex-dir <path>]
286
+ ```
287
+
288
+ #### 交互行为
289
+
290
+ - 当 `<provider>` 缺失且当前是 TTY 时,先从 `providers.json` 读取 provider 列表,再用选择器选择 provider
291
+ - 当 `<provider>` 已显式传入时,不额外确认
292
+ - `--no-login` 仍保持显式 flag,不进入提问
293
+
294
+ #### 前置校验
295
+
296
+ - `providers.json` 必须存在
297
+ - provider 必须存在
298
+ - provider 对应的 `profile` 必须存在于 `config.toml`
299
+
300
+ #### 执行步骤
301
+
302
+ 1. 读取 provider 数据
303
+ 2. 校验 profile
304
+ 3. 备份 `config.toml`
305
+ 4. 如果存在,备份 `auth.json`
306
+ 5. 更新顶层 `profile`
307
+ 6. 默认执行 `codex login --with-api-key`
308
+ 7. 成功则保存为最近一次备份
309
+ 8. 失败则按 manifest 回滚
310
+
311
+ #### 成功输出
312
+
313
+ JSON 示例:
314
+
315
+ ```json
316
+ {
317
+ "ok": true,
318
+ "command": "switch",
319
+ "data": {
320
+ "provider": "freemodel",
321
+ "profile": "freemodel",
322
+ "loginPerformed": true,
323
+ "backupPath": "C:\\Users\\name\\.codex\\backups\\20260511-221550-switch"
324
+ },
325
+ "warnings": [],
326
+ "error": null
327
+ }
328
+ ```
329
+
330
+ #### 失败错误码
331
+
332
+ - `PROVIDER_NOT_FOUND`
333
+ - `PROFILE_NOT_FOUND`
334
+ - `BACKUP_FAILED`
335
+ - `CODEX_LOGIN_FAILED`
336
+ - `ROLLBACK_FAILED`
337
+
338
+ #### 注意事项
339
+
340
+ - `--no-login` 仅跳过登录,不跳过备份和 profile 修改
341
+ - 登录失败时当前实现会附带 `rollbackApplied: true`
342
+
343
+ ### 4.5 `codexs import <file>`
344
+
345
+ #### 目标
346
+
347
+ 整体替换当前 `providers.json`。
348
+
349
+ #### 输入
350
+
351
+ ```bash
352
+ codexs import <file> [--json] [--codex-dir <path>]
353
+ ```
354
+
355
+ #### 行为语义
356
+
357
+ - 只支持整体替换
358
+ - 不支持 merge
359
+ - 写入前备份当前 `providers.json`
360
+ - 路径参数必须显式传入
361
+ - TTY 中实际替换前增加一次确认
362
+
363
+ #### 成功输出
364
+
365
+ ```json
366
+ {
367
+ "ok": true,
368
+ "command": "import",
369
+ "data": {
370
+ "importedProviders": ["imported"],
371
+ "backupPath": "C:\\Users\\name\\.codex\\backups\\20260511-221457-import"
372
+ },
373
+ "warnings": [],
374
+ "error": null
375
+ }
376
+ ```
377
+
378
+ #### 失败错误码
379
+
380
+ - `INVALID_IMPORT_FILE`
381
+ - `BACKUP_FAILED`
382
+ - `ROLLBACK_FAILED`
383
+
384
+ ### 4.6 `codexs export <file>`
385
+
386
+ #### 目标
387
+
388
+ 导出当前 `providers.json` 到指定位置。
389
+
390
+ #### 输入
391
+
392
+ ```bash
393
+ codexs export <file> [--force] [--json] [--codex-dir <path>]
394
+ ```
395
+
396
+ #### 行为语义
397
+
398
+ - 默认不覆盖已有文件
399
+ - 传 `--force` 后允许覆盖
400
+ - 路径参数必须显式传入
401
+ - 当目标文件已存在、当前是 TTY 且未传 `--force` 时,可通过确认后继续覆盖
402
+
403
+ #### 成功输出
404
+
405
+ ```json
406
+ {
407
+ "ok": true,
408
+ "command": "export",
409
+ "data": {
410
+ "exportedTo": "C:\\path\\providers-export.json",
411
+ "count": 3
412
+ },
413
+ "warnings": [],
414
+ "error": null
415
+ }
416
+ ```
417
+
418
+ #### 失败错误码
419
+
420
+ - `INVALID_IMPORT_FILE`
421
+ - `PROVIDERS_NOT_FOUND`
422
+ - `PROVIDERS_PARSE_ERROR`
423
+
424
+ ### 4.7 `codexs add <provider>`
425
+
426
+ #### 目标
427
+
428
+ 新增一条 provider 记录。
429
+
430
+ #### 输入
431
+
432
+ ```bash
433
+ codexs add <provider> \
434
+ --profile <name> \
435
+ --api-key <key> \
436
+ [--base-url <url>] \
437
+ [--note <text>] \
438
+ [--tag <tag>] \
439
+ [--json] \
440
+ [--codex-dir <path>]
441
+ ```
442
+
443
+ #### 行为语义
444
+
445
+ - provider 名必须唯一
446
+ - 写入前备份旧 `providers.json`
447
+ - 显式参数模式保持可用
448
+ - 当缺少必填字段且 stdin/stdout 都是 TTY 时,允许渐进式提问
449
+ - `--json` 或非 TTY 场景下仍要求显式传入必填参数
450
+ - `profile` 优先从 `config.toml` 已有 profile 列表里选择,获取失败时退回文本输入
451
+ - `apiKey` 使用隐藏输入并要求二次确认
452
+
453
+ #### 成功输出
454
+
455
+ ```json
456
+ {
457
+ "ok": true,
458
+ "command": "add",
459
+ "data": {
460
+ "provider": "temp",
461
+ "profile": "freemodel",
462
+ "backupPath": "C:\\Users\\name\\.codex\\backups\\20260511-221457-add"
463
+ },
464
+ "warnings": [],
465
+ "error": null
466
+ }
467
+ ```
468
+
469
+ #### 失败错误码
470
+
471
+ - `INVALID_IMPORT_FILE`
472
+ - `BACKUP_FAILED`
473
+ - `ROLLBACK_FAILED`
474
+
475
+ ### 4.8 `codexs remove <provider>`
476
+
477
+ #### 目标
478
+
479
+ 删除一条 provider 记录。
480
+
481
+ #### 输入
482
+
483
+ ```bash
484
+ codexs remove <provider> [--force] [--json] [--codex-dir <path>]
485
+ ```
486
+
487
+ #### 行为语义
488
+
489
+ - TTY 中若缺少 `<provider>`,允许先选择 provider
490
+ - TTY 中始终需要确认,确认文案必须带 provider 名
491
+ - TTY 中即使未传 `--force`,也可通过确认完成删除
492
+ - 非 TTY 或 `--json` 场景下仍要求显式 `<provider> --force`
493
+ - 先备份再删除
494
+
495
+ #### 失败错误码
496
+
497
+ - `PROVIDER_NOT_FOUND`
498
+ - `INVALID_IMPORT_FILE`
499
+ - `BACKUP_FAILED`
500
+ - `ROLLBACK_FAILED`
501
+
502
+ ### 4.9 `codexs doctor`
503
+
504
+ #### 目标
505
+
506
+ 返回结构化问题列表,而不是只给一个总体状态。
507
+
508
+ #### 输入
509
+
510
+ ```bash
511
+ codexs doctor [--json] [--codex-dir <path>]
512
+ ```
513
+
514
+ #### 当前诊断项
515
+
516
+ - `config.toml` 是否存在
517
+ - `providers.json` 是否存在
518
+ - `providers.json` 是否可解析
519
+ - provider 的 profile 是否存在
520
+ - `codex` CLI 是否可执行
521
+
522
+ #### 当前返回结构
523
+
524
+ ```json
525
+ {
526
+ "ok": true,
527
+ "command": "doctor",
528
+ "data": {
529
+ "healthy": false,
530
+ "issues": [
531
+ {
532
+ "code": "CODEX_LOGIN_FAILED",
533
+ "message": "codex CLI is not available.",
534
+ "cause": "spawnSync codex EPERM"
535
+ }
536
+ ],
537
+ "codexDir": "C:\\Users\\name\\.codex"
538
+ },
539
+ "warnings": ["doctor found 1 issue(s)"],
540
+ "error": null
541
+ }
542
+ ```
543
+
544
+ #### 说明
545
+
546
+ - 当前实现把 codex CLI 缺失归到 `CODEX_LOGIN_FAILED`
547
+ - 后续可按需要拆分更细错误码
548
+
549
+ ### 4.10 `codexs rollback`
550
+
551
+ #### 目标
552
+
553
+ 恢复最近一次备份对应的文件状态。
554
+
555
+ #### 输入
556
+
557
+ ```bash
558
+ codexs rollback [--json] [--codex-dir <path>]
559
+ ```
560
+
561
+ #### 行为语义
562
+
563
+ - 读取 `backups/latest.json`
564
+ - 恢复 manifest 中记录的文件
565
+ - 如果最近一次备份包含 `auth.json`,一并恢复
566
+ - TTY 中执行前会展示备份目录和受影响文件摘要,并请求确认
567
+
568
+ #### 成功输出
569
+
570
+ ```json
571
+ {
572
+ "ok": true,
573
+ "command": "rollback",
574
+ "data": {
575
+ "restoredFiles": ["config.toml", "auth.json"],
576
+ "backupPath": "C:\\Users\\name\\.codex\\backups\\20260511-221550-switch"
577
+ },
578
+ "warnings": [],
579
+ "error": null
580
+ }
581
+ ```
582
+
583
+ #### 失败错误码
584
+
585
+ - `ROLLBACK_FAILED`
586
+
587
+ ## 5. 默认输出与敏感信息策略
588
+
589
+ 默认输出遵循:
590
+
591
+ - 不打印完整 `apiKey`
592
+ - 不打印无关调试信息
593
+ - 成功时尽量只返回命令核心结果
594
+
595
+ JSON 输出也遵循相同策略:
596
+
597
+ - `error.details` 不应包含完整 `apiKey`
598
+ - 主要返回路径、命令对象、回滚状态等可操作信息
599
+
600
+ ## 6. AI / 自动化调用建议
601
+
602
+ 对 AI 代理或自动化脚本,推荐以下调用约定:
603
+
604
+ - 一律使用 `--json`
605
+ - 严格按 `error.code` 判断失败类型
606
+ - 对 `switch` 命令关注:
607
+ - `provider`
608
+ - `profile`
609
+ - `loginPerformed`
610
+ - `backupPath`
611
+ - `rollbackApplied`
612
+ - 对 `doctor` 命令关注:
613
+ - `healthy`
614
+ - `issues[]`
615
+
616
+ 推荐模式:
617
+
618
+ 1. 先调用 `status --json`
619
+ 2. 再调用 `doctor --json`
620
+ 3. 满足前置条件后调用 `switch --json`
621
+ 4. 失败时根据错误码决定是否提示用户手动执行 `rollback`
622
+
623
+ ## 7. 后续命令演进建议
624
+
625
+ 如果继续扩展命令面,建议新增命令时遵守下面三条:
626
+
627
+ - 不破坏当前 JSON envelope
628
+ - 不复用语义不匹配的错误码
629
+ - 所有写命令默认纳入备份与回滚模型
630
+
631
+ 未来候选命令:
632
+
633
+ - `codexs show <provider>`
634
+ - `codexs edit <provider>`
635
+ - `codexs backups list`
636
+ - `codexs rollback <backup-id>`
637
+ - `codexs import --merge`
638
+
639
+ ## 8. 结论
640
+
641
+ `codex-switch` 当前命令设计已经具备下面几个工程特征:
642
+
643
+ - 命令面稳定
644
+ - 参数风格统一
645
+ - JSON 输出可机器解析
646
+ - 写操作具备安全语义
647
+ - 错误码已可作为 AI 调用契约
648
+
649
+ 这意味着它已经不再只是“能切换配置的脚本集合”,而是一套具备持续演进空间的 CLI 命令体系。