@minniexcode/codex-switch 0.1.0 → 0.1.2

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 (68) hide show
  1. package/README.AI.md +141 -110
  2. package/README.CN.md +215 -179
  3. package/README.md +224 -183
  4. package/dist/app/add-provider.js +16 -23
  5. package/dist/app/bridge.js +2 -1
  6. package/dist/app/edit-provider.js +30 -65
  7. package/dist/app/get-current-profile.js +15 -3
  8. package/dist/app/get-status.js +11 -8
  9. package/dist/app/list-config-profiles.js +3 -1
  10. package/dist/app/list-providers.js +10 -4
  11. package/dist/app/remove-provider.js +52 -19
  12. package/dist/app/run-doctor.js +26 -29
  13. package/dist/app/setup-codex.js +3 -3
  14. package/dist/app/show-config.js +3 -1
  15. package/dist/app/switch-provider.js +38 -6
  16. package/dist/cli/output.js +29 -19
  17. package/dist/commands/handlers.js +3 -2
  18. package/dist/commands/help.js +3 -3
  19. package/dist/commands/registry.js +29 -29
  20. package/dist/domain/config.js +293 -209
  21. package/dist/domain/providers.js +8 -0
  22. package/dist/domain/runtime-state.js +15 -15
  23. package/dist/domain/setup.js +3 -1
  24. package/dist/interaction/interactive.js +2 -2
  25. package/dist/runtime/codex-version.js +7 -0
  26. package/dist/runtime/copilot-adapter.js +326 -70
  27. package/dist/runtime/copilot-bridge-worker.js +27 -2
  28. package/dist/runtime/copilot-bridge.js +192 -10
  29. package/dist/runtime/copilot-cli.js +7 -0
  30. package/dist/runtime/copilot-installer.js +59 -1
  31. package/dist/runtime/copilot-sdk-loader.js +4 -1
  32. package/dist/storage/config-repo.js +6 -14
  33. package/docs/Design/codex-switch-v0.1.0-design.md +32 -152
  34. package/docs/Design/codex-switch-v0.1.1-design.md +22 -0
  35. package/docs/Design/codex-switch-v0.1.2-design.md +65 -0
  36. package/docs/PRD/codex-switch-prd-v0.1.0.md +65 -217
  37. package/docs/PRD/codex-switch-prd-v0.1.1.md +26 -0
  38. package/docs/PRD/codex-switch-prd-v0.1.2.md +41 -0
  39. package/docs/Reference/codex-config-reference.md +41 -0
  40. package/docs/Reference/codex-config-reference.zh-CN.md +41 -0
  41. package/docs/Tests/testing.md +1 -1
  42. package/docs/cli-usage.md +290 -223
  43. package/docs/codex-switch-command-design.md +2 -2
  44. package/docs/codex-switch-product-overview.md +18 -13
  45. package/docs/codex-switch-product-research.md +2 -2
  46. package/docs/codex-switch-technical-architecture.md +84 -1115
  47. package/package.json +2 -2
  48. package/docs/Design/codex-switch-copilot-integration-design.md +0 -517
  49. package/docs/Design/codex-switch-v0.0.10-design.md +0 -669
  50. package/docs/Design/codex-switch-v0.0.11-design.md +0 -824
  51. package/docs/Design/codex-switch-v0.0.12-design.md +0 -343
  52. package/docs/Design/codex-switch-v0.0.4-design.md +0 -874
  53. package/docs/Design/codex-switch-v0.0.5-design.md +0 -932
  54. package/docs/Design/codex-switch-v0.0.6-design.md +0 -708
  55. package/docs/Design/codex-switch-v0.0.7-design.md +0 -862
  56. package/docs/Design/codex-switch-v0.0.8-design.md +0 -132
  57. package/docs/Design/codex-switch-v0.0.9-design.md +0 -182
  58. package/docs/Design/codex-switch-v0.0.9-to-v0.0.12-roadmap.md +0 -413
  59. package/docs/PRD/codex-switch-prd-v0.0.10.md +0 -406
  60. package/docs/PRD/codex-switch-prd-v0.0.11.md +0 -577
  61. package/docs/PRD/codex-switch-prd-v0.0.12.md +0 -279
  62. package/docs/PRD/codex-switch-prd-v0.0.5-to-v0.1.0.md +0 -446
  63. package/docs/PRD/codex-switch-prd-v0.0.8.md +0 -62
  64. package/docs/PRD/codex-switch-prd-v0.0.9.md +0 -166
  65. package/docs/PRD/codex-switch-prd.md +0 -650
  66. package/docs/Tests/test-report-0.0.5.md +0 -163
  67. package/docs/Tests/test-report-0.0.7.md +0 -118
  68. package/docs/Tests/testing-bridge-v0.0.9.md +0 -367
@@ -85,11 +85,15 @@ function renderHumanSuccess(command, data, warnings) {
85
85
  lines.push("No providers configured.");
86
86
  }
87
87
  else {
88
- const currentProfile = typeof data?.currentProfile === "string" ? data.currentProfile : null;
88
+ const currentModel = typeof data?.currentModel === "string" ? data.currentModel : null;
89
+ const currentModelProvider = typeof data?.currentModelProvider === "string" ? data.currentModelProvider : null;
89
90
  const activeProviderResolvable = data?.activeProviderResolvable !== false;
90
91
  const activeCandidates = Array.isArray(data?.activeProviderCandidates) ? data?.activeProviderCandidates : [];
91
- if (currentProfile) {
92
- lines.push(`Current profile: ${currentProfile}`);
92
+ if (currentModel) {
93
+ lines.push(`Current model: ${currentModel}`);
94
+ }
95
+ if (currentModelProvider) {
96
+ lines.push(`Current model provider: ${currentModelProvider}`);
93
97
  if (!activeProviderResolvable && activeCandidates.length > 1) {
94
98
  lines.push(`Current provider: ambiguous (${activeCandidates.join(", ")})`);
95
99
  }
@@ -103,7 +107,7 @@ function renderHumanSuccess(command, data, warnings) {
103
107
  : "";
104
108
  const note = provider.note ? ` note=${provider.note}` : "";
105
109
  const current = provider.isActive ? " current" : "";
106
- lines.push(`${provider.name} [${String(provider.providerType ?? "direct")}]${current} -> ${provider.profile}${tags}${note}`);
110
+ lines.push(`${provider.name} [${String(provider.providerType ?? "direct")}]${current} -> ${provider.modelProvider}${provider.model ? ` model=${provider.model}` : ""}${tags}${note}`);
107
111
  }
108
112
  }
109
113
  break;
@@ -125,13 +129,18 @@ function renderHumanSuccess(command, data, warnings) {
125
129
  break;
126
130
  }
127
131
  case "current":
128
- lines.push(`Current profile: ${String(data?.profile ?? "")}`);
132
+ lines.push(`Current model: ${String(data?.model ?? "")}`);
133
+ lines.push(`Current model provider: ${String(data?.modelProvider ?? "")}`);
134
+ if (data?.provider) {
135
+ lines.push(`Managed provider: ${String(data.provider)}`);
136
+ }
129
137
  break;
130
138
  case "status":
131
139
  lines.push("Status summary:");
132
140
  lines.push(` target runtime: ${String(data?.codexDir ?? "")}`);
133
141
  lines.push(` tool home: ${String(data?.storage?.toolHome?.root ?? "")}`);
134
- lines.push(` current profile: ${String(data?.currentProfile ?? "(none)")}`);
142
+ lines.push(` current model: ${String(data?.currentModel ?? "(none)")}`);
143
+ lines.push(` current model provider: ${String(data?.currentModelProvider ?? "(none)")}`);
135
144
  lines.push(` mapped provider: ${renderStatusMappedProvider(data)}`);
136
145
  lines.push(` provider path: ${renderStatusProviderPath(data)}`);
137
146
  lines.push(` runtime health: ${renderStatusHealth(data)}`);
@@ -139,7 +148,9 @@ function renderHumanSuccess(command, data, warnings) {
139
148
  lines.push(` next step: ${renderStatusNextStep(data, warnings)}`);
140
149
  break;
141
150
  case "config-show": {
142
- lines.push(`activeProfile: ${String(data?.activeProfile ?? "")}`);
151
+ lines.push(`currentModel: ${String(data?.currentModel ?? "")}`);
152
+ lines.push(`currentModelProvider: ${String(data?.currentModelProvider ?? "")}`);
153
+ lines.push(`legacyProfile: ${String(data?.legacyProfile ?? "")}`);
143
154
  const profiles = data?.profiles ?? [];
144
155
  for (const profile of profiles) {
145
156
  lines.push(`${String(profile.name)} managed=${String(profile.managed)} active=${String(profile.isActive)} source=${String(profile.source)} model=${String(profile.model ?? "")} modelProvider=${String(profile.modelProvider ?? "")} baseUrl=${String(profile.baseUrl ?? "")}`);
@@ -154,7 +165,8 @@ function renderHumanSuccess(command, data, warnings) {
154
165
  break;
155
166
  }
156
167
  case "switch":
157
- lines.push(`Switched to provider ${String(data?.provider ?? "")} using profile ${String(data?.profile ?? "")}.`);
168
+ lines.push(`Switched to provider ${String(data?.provider ?? "")} using model provider ${String(data?.modelProvider ?? data?.profile ?? "")}.`);
169
+ lines.push(`Model: ${String(data?.model ?? "")}`);
158
170
  lines.push(`Backup: ${String(data?.backupPath ?? "")}`);
159
171
  break;
160
172
  case "import":
@@ -183,7 +195,7 @@ function renderHumanSuccess(command, data, warnings) {
183
195
  }
184
196
  lines.push(`login launched: ${String(data?.loginLaunched ?? false)}`);
185
197
  lines.push(`auth ready: ${String(data?.authReady ?? false)}`);
186
- lines.push("next step: run `codexs add <provider> --copilot --profile <name>` and then `codexs switch <provider>`.");
198
+ lines.push("next step: run `codexs add <provider> --copilot --profile <model-provider-id>` and then `codexs switch <provider>`.");
187
199
  break;
188
200
  case "migrate":
189
201
  lines.push(`Migrated providers in ${String(data?.codexDir ?? "")} using ${String(data?.strategy ?? "")}.`);
@@ -262,12 +274,6 @@ function renderStatusHealth(data) {
262
274
  if (!activeProviderResolvable || liveState.reason === "shared-profile") {
263
275
  return "active provider ambiguous";
264
276
  }
265
- if (issues.some((issue) => issue.code === "UNMANAGED_ACTIVE_PROFILE")) {
266
- return "active profile unmanaged";
267
- }
268
- if (issues.some((issue) => issue.code === "ACTIVE_PROVIDER_UNRESOLVED")) {
269
- return "active provider ambiguous";
270
- }
271
277
  if (issues.some((issue) => issue.code === "PROVIDER_BASE_URL_MISMATCH")) {
272
278
  return "provider projection drift";
273
279
  }
@@ -317,6 +323,9 @@ function renderStatusNextStep(data, warnings) {
317
323
  if (!data?.provider) {
318
324
  return "run `codexs switch <provider>` after adding or adopting a managed provider";
319
325
  }
326
+ if (Array.isArray(data?.issues) && (data?.issues).some((issue) => issue.code === "LEGACY_PROFILE_SELECTOR" || issue.code === "LEGACY_PROFILE_SECTION" || issue.code === "LEGACY_MODEL_PROVIDER_ENV_KEY")) {
327
+ return "run `codexs switch <provider>` to reproject the active route and clean legacy fields";
328
+ }
320
329
  return "run `codexs doctor` if you need a deeper diagnostic pass";
321
330
  }
322
331
  /**
@@ -337,10 +346,11 @@ function renderDoctorIssueNextStep(issue) {
337
346
  case "BRIDGE_HEALTHCHECK_FAILED":
338
347
  return "reselect the provider with `codexs switch <provider>` or inspect bridge state";
339
348
  case "UNMANAGED_ACTIVE_PROFILE":
340
- return "switch to a managed provider or adopt the active profile with `codexs migrate`";
341
- case "ACTIVE_PROVIDER_UNRESOLVED":
342
- case "SHARED_PROFILE_REFERENCE":
343
- return "make provider-to-profile mappings unique before relying on current-provider detection";
349
+ return "switch to a managed provider or adopt the active route with `codexs migrate`";
350
+ case "LEGACY_PROFILE_SELECTOR":
351
+ case "LEGACY_PROFILE_SECTION":
352
+ case "LEGACY_MODEL_PROVIDER_ENV_KEY":
353
+ return "rerun `codexs switch <provider>` to project top-level model/model_provider and remove legacy fields";
344
354
  case "PROVIDER_BASE_URL_MISMATCH":
345
355
  return "rerun `codexs edit <provider> --base-url <url>` or `codexs switch <provider>` to repair the runtime projection";
346
356
  default:
@@ -95,7 +95,7 @@ async function handleRegisteredCommand(ctx, parsed, runtime = (0, prompt_1.creat
95
95
  });
96
96
  }
97
97
  case "current":
98
- return (0, get_current_profile_1.getCurrentProfile)(paths.configPath);
98
+ return (0, get_current_profile_1.getCurrentProfile)(paths.configPath, paths.providersPath);
99
99
  case "status":
100
100
  return (0, get_status_1.getStatus)(paths.codexDir, paths.configPath, paths.providersPath, paths.authPath, {
101
101
  runtimeDir: paths.runtimeDir,
@@ -156,6 +156,7 @@ async function handleRegisteredCommand(ctx, parsed, runtime = (0, prompt_1.creat
156
156
  supportedUpstreams: ["copilot", "github-copilot"],
157
157
  });
158
158
  }
159
+ (0, copilot_installer_1.assertCopilotNodeRuntimeSupported)();
159
160
  const installed = (0, copilot_installer_1.probeCopilotSdkInstall)(paths.runtimesDir);
160
161
  let installedNow = false;
161
162
  if (!installed.installed) {
@@ -495,7 +496,7 @@ async function handleRegisteredCommand(ctx, parsed, runtime = (0, prompt_1.creat
495
496
  providersPath: paths.providersPath,
496
497
  configPath: paths.configPath,
497
498
  providerName,
498
- switchToProfile,
499
+ switchToProvider: switchToProfile,
499
500
  });
500
501
  }
501
502
  case "doctor":
@@ -29,7 +29,7 @@ function buildHelpText(commandName) {
29
29
  return [
30
30
  "codex-switch",
31
31
  "",
32
- "Manage and switch local Codex provider/profile configuration safely.",
32
+ "Manage and switch local Codex provider/model-provider routing safely.",
33
33
  "Primary workflows: direct providers use init -> add -> switch -> status -> doctor.",
34
34
  "Primary workflows: Copilot providers use init -> login copilot -> add --copilot -> switch -> status -> doctor.",
35
35
  "Advanced adopt flows use migrate only when you already have Codex runtime state to import.",
@@ -65,12 +65,12 @@ function buildHelpText(commandName) {
65
65
  "",
66
66
  "Examples:",
67
67
  " codexs init",
68
- " codexs add packycode --profile packycode --api-key sk-xxx",
68
+ " codexs add packycode --profile packycode --model gpt-5 --api-key sk-xxx --base-url https://api.example/v1",
69
69
  " codexs switch packycode",
70
70
  " codexs status",
71
71
  " codexs doctor",
72
72
  " codexs login copilot",
73
- " codexs add copilot-main --copilot --profile copilot-main",
73
+ " codexs add copilot-main --copilot --profile copilot-main --model gpt-5",
74
74
  " codexs migrate",
75
75
  " codexs config show",
76
76
  " codexs backups list",
@@ -20,11 +20,11 @@ exports.COMMANDS = [
20
20
  tokens: ["config", "show"],
21
21
  handler: handlers_1.handleRegisteredCommand,
22
22
  group: "read",
23
- summary: "Show the structured config profile view.",
23
+ summary: "Show the current route summary and legacy profile view.",
24
24
  usage: ["codexs config show [profile] [--json] [--codex-dir <path>]"],
25
25
  details: [
26
- "Returns all recognizable config profiles by default, including unmanaged and orphaned references.",
27
- "Passing [profile] narrows the response to one profile while preserving the same shape.",
26
+ "Returns current top-level model/model_provider together with recognizable legacy profile sections.",
27
+ "Passing [profile] narrows the legacy profile view to one section while preserving the same shape.",
28
28
  ],
29
29
  examples: ["codexs config show", "codexs config show packycode --json"],
30
30
  },
@@ -33,11 +33,11 @@ exports.COMMANDS = [
33
33
  tokens: ["config", "list-profiles"],
34
34
  handler: handlers_1.handleRegisteredCommand,
35
35
  group: "read",
36
- summary: "List recognizable config profiles with managed-state hints.",
36
+ summary: "List recognizable legacy config profiles with managed-state hints.",
37
37
  usage: ["codexs config list-profiles [--json] [--codex-dir <path>]"],
38
38
  details: [
39
- "Lists managed, unmanaged, and orphaned config profiles in one stable view.",
40
- "Use config show for richer single-profile details.",
39
+ "Lists managed, unmanaged, and orphaned legacy profile sections in one stable view.",
40
+ "Use config show for the current route summary and richer single-profile details.",
41
41
  ],
42
42
  examples: ["codexs config list-profiles", "codexs config list-profiles --json"],
43
43
  },
@@ -123,7 +123,7 @@ exports.COMMANDS = [
123
123
  summary: "Adopt existing Codex runtime profiles into managed providers.json state.",
124
124
  usage: ["codexs migrate [--json] [--codex-dir <path>] [--merge|--overwrite]"],
125
125
  details: [
126
- "Reads config.toml profiles, collects complete provider records, then writes providers.json under managed backup flow.",
126
+ "Reads legacy config.toml profiles, collects complete provider records, then writes providers.json under managed backup flow.",
127
127
  "TTY mode can collect missing provider details and choose merge or overwrite when providers.json already exists.",
128
128
  "Migrate adopts only runtime profiles that already expose model, model_provider, and matching base_url.",
129
129
  "Non-TTY and --json runs still fail fast because migrate profile selection and provider details remain interactive in this release.",
@@ -141,7 +141,7 @@ exports.COMMANDS = [
141
141
  details: [
142
142
  "setup no longer performs initialization or migration work.",
143
143
  "Use init for the primary fresh-install workflow.",
144
- "Use migrate only when adopting from existing config.toml profiles.",
144
+ "Use migrate only when adopting from existing legacy config.toml profiles.",
145
145
  ],
146
146
  examples: ["codexs help init", "codexs help migrate"],
147
147
  },
@@ -150,11 +150,11 @@ exports.COMMANDS = [
150
150
  tokens: ["list"],
151
151
  handler: handlers_1.handleRegisteredCommand,
152
152
  group: "read",
153
- summary: "List managed providers with profile, type, and current-state hints.",
153
+ summary: "List managed providers with model-provider routing and current-state hints.",
154
154
  usage: ["codexs list [--json] [--codex-dir <path>]"],
155
155
  details: [
156
- "Reads providers.json and prints provider-to-profile mappings together with provider type.",
157
- "When the active profile is shared by multiple providers, list surfaces the ambiguity instead of inventing one current provider.",
156
+ "Reads providers.json and prints provider-to-model-provider mappings together with provider type.",
157
+ "When the active model_provider is shared by multiple providers, list surfaces the ambiguity instead of inventing one current provider.",
158
158
  "Use --json for machine-readable automation output.",
159
159
  ],
160
160
  examples: ["codexs list", "codexs list --json"],
@@ -178,9 +178,9 @@ exports.COMMANDS = [
178
178
  tokens: ["current"],
179
179
  handler: handlers_1.handleRegisteredCommand,
180
180
  group: "read",
181
- summary: "Show the active top-level profile from config.toml.",
181
+ summary: "Show the active top-level model/model_provider route from config.toml.",
182
182
  usage: ["codexs current [--json] [--codex-dir <path>]"],
183
- details: ["Reads the currently active top-level profile.", "Fails when config.toml is missing or has no top-level profile."],
183
+ details: ["Reads the currently active top-level model and model_provider.", "Fails when config.toml is missing or has no top-level model_provider."],
184
184
  examples: ["codexs current", "codexs current --json"],
185
185
  },
186
186
  {
@@ -191,7 +191,7 @@ exports.COMMANDS = [
191
191
  summary: "Show tool-home, target-runtime, provider-path, and runtime-health status.",
192
192
  usage: ["codexs status [--json] [--codex-dir <path>]"],
193
193
  details: [
194
- "Reports the target Codex runtime, tool-home storage roles, current profile, and whether the live profile is mapped.",
194
+ "Reports the target Codex runtime, tool-home storage roles, current model, current model_provider, and whether the live route is mapped.",
195
195
  "When the active provider uses a local runtime bridge, status also reports bridge, Copilot SDK, and upstream auth state.",
196
196
  "Surfaces dual-path config consistency signals without mutating any files.",
197
197
  "Organizes the human-readable view around current state, health impact, and next step.",
@@ -206,14 +206,15 @@ exports.COMMANDS = [
206
206
  group: "write",
207
207
  summary: "Update fields on a single provider record.",
208
208
  usage: [
209
- "codexs edit <provider> [--profile <name>] [--api-key <key>] [--base-url <url>] [--note <text>] [--tag <tag> ...] [--json] [--codex-dir <path>]",
210
- "codexs edit <provider> --profile <name> --create-profile --model <name> --base-url <url>",
209
+ "codexs edit <provider> [--profile <model-provider-id>] [--api-key <key>] [--base-url <url>] [--model <name>] [--note <text>] [--tag <tag> ...] [--json] [--codex-dir <path>]",
210
+ "codexs edit <provider> --profile <model-provider-id> --model <name> --base-url <url>",
211
211
  ],
212
212
  details: [
213
213
  "Passed flags replace only the selected fields and keep the rest unchanged.",
214
214
  "TTY mode can first select a provider, then prompt for fields when no editable options were provided.",
215
215
  "Interactive tags use preset multi-select only.",
216
- "When rebinding to a missing profile, --create-profile requires both --model and --base-url.",
216
+ "--profile is a CLI alias for the stored model_provider id.",
217
+ "When rebinding to a new direct model_provider id, the command must be able to project base_url from --base-url, the provider record, or an existing model_providers section.",
217
218
  "Backs up providers.json and config.toml before writing.",
218
219
  ],
219
220
  examples: ["codexs edit packycode --note primary", "codexs edit packycode --tag daily --tag paid --json"],
@@ -225,27 +226,26 @@ exports.COMMANDS = [
225
226
  group: "write",
226
227
  summary: "Add a managed provider for the primary direct or Copilot workflows.",
227
228
  usage: [
228
- "codexs add <provider> --profile <name> --api-key <key> [--base-url <url>] [--note <text>] [--tag <tag> ...]",
229
- "codexs add <provider> --copilot --profile <name> [--bridge-host <host>] [--bridge-port <port>] [--bridge-api-key <secret>] [--install-copilot-sdk]",
230
- "codexs add <provider> --profile <name> --api-key <key> --create-profile --model <name> --base-url <url>",
231
- "codexs add [--profile <name>] [--api-key <key>] [--base-url <url>] [--note <text>] [--tag <tag> ...]",
229
+ "codexs add <provider> --profile <model-provider-id> --model <name> --api-key <key> [--base-url <url>] [--note <text>] [--tag <tag> ...]",
230
+ "codexs add <provider> --copilot --profile <model-provider-id> --model <name> [--bridge-host <host>] [--bridge-port <port>] [--bridge-api-key <secret>]",
231
+ "codexs add [--profile <model-provider-id>] [--model <name>] [--api-key <key>] [--base-url <url>] [--note <text>] [--tag <tag> ...]",
232
232
  ],
233
233
  details: [
234
234
  "Prompts only for missing required values when stdin/stdout are TTYs and --json is not set.",
235
- "Interactive add collects provider name, profile, and apiKey progressively as plain text inputs.",
235
+ "Interactive add collects provider name, model_provider id, model, and apiKey progressively as plain text inputs.",
236
236
  "Confirm API key when prompted interactively because the hidden prompt asks twice before writing.",
237
237
  "Interactive tags use preset multi-select only.",
238
238
  "Automation and non-TTY environments must pass all required values explicitly.",
239
- "Creating a missing direct-provider profile section requires --create-profile together with --model and --base-url.",
240
- "Creating a missing Copilot profile section requires --create-profile together with --model; the local bridge base_url is derived automatically.",
239
+ "--profile is a CLI alias for the stored model_provider id.",
240
+ "The command projects only model_providers sections and does not create legacy profiles sections.",
241
241
  "Use --copilot to create a GitHub Copilot bridge provider backed by the official SDK.",
242
242
  "Copilot providers require SDK install and login readiness to already be satisfied via codexs login copilot.",
243
243
  "For Copilot providers, provider apiKey stores only the local bridge secret; upstream GitHub Copilot auth stays shared in the official runtime login.",
244
244
  "--install-copilot-sdk is kept only as a rejected compatibility flag that points to codexs login copilot.",
245
245
  ],
246
246
  examples: [
247
- "codexs add packycode --profile packycode --api-key sk-xxx",
248
- "codexs add copilot-main --copilot --profile copilot-main",
247
+ "codexs add packycode --profile packycode --model gpt-5 --api-key sk-xxx --base-url https://api.example/v1",
248
+ "codexs add copilot-main --copilot --profile copilot-main --model gpt-5",
249
249
  "codexs add",
250
250
  ],
251
251
  },
@@ -273,12 +273,12 @@ exports.COMMANDS = [
273
273
  handler: handlers_1.handleRegisteredCommand,
274
274
  group: "write",
275
275
  summary: "Remove a provider from providers.json.",
276
- usage: ["codexs remove <provider> [--force] [--switch-to <profile>] [--json] [--codex-dir <path>]"],
276
+ usage: ["codexs remove <provider> [--force] [--switch-to <provider>] [--json] [--codex-dir <path>]"],
277
277
  details: [
278
278
  "TTY mode can select a missing provider interactively and always asks for deletion confirmation.",
279
279
  "Non-TTY and --json automation still require both <provider> and --force.",
280
280
  "The confirmation prompt includes the provider name and cancels without writing when declined.",
281
- "When removing the last provider linked to the active profile, pass --switch-to first.",
281
+ "When removing the only provider linked to the active model_provider route, pass --switch-to <provider-name> first.",
282
282
  "Backs up providers.json and config.toml before removing the record.",
283
283
  ],
284
284
  examples: ["codexs remove freemodel", "codexs remove freemodel --force --json"],
@@ -332,7 +332,7 @@ exports.COMMANDS = [
332
332
  summary: "Run issue-first diagnostics across tool-home and target-runtime state.",
333
333
  usage: ["codexs doctor [--json] [--codex-dir <path>]"],
334
334
  details: [
335
- "Checks the expected config files, provider/profile consistency, and Codex CLI availability.",
335
+ "Checks the expected config files, provider/model-provider consistency, and Codex CLI availability.",
336
336
  "Copilot bridge providers add runtime dependency, auth, and bridge health diagnostics.",
337
337
  "Returns structured issues so users and AI agents can act on them.",
338
338
  ],