@codexapi/codexclaude 2.0.24 → 2.0.26

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/CUSTOMIZATIONS.md CHANGED
@@ -5,10 +5,10 @@
5
5
  ## Runtime
6
6
 
7
7
  - Customer-facing app name: `MagnetAPI.org Codex CLI`
8
- - Local launcher version: `2.0.24`
9
- - Bundled official runtime dependency: `@openai/codex@0.144.4`
8
+ - Local launcher version: `2.0.26`
9
+ - Bundled official runtime dependency: `@openai/codex@0.145.0`
10
10
  - Required install command: `npm install -g @codexapi/codexclaude@latest`
11
- - Hosted fallback: `npm install -g https://codexapi.pro/downloads/codexapi-codexclaude-2.0.24.tgz`
11
+ - Hosted fallback: `npm install -g https://codexapi.pro/downloads/codexapi-codexclaude-2.0.26.tgz`
12
12
  - Bundled runtime version is managed internally and must not be used for customer update prompts.
13
13
  - Launcher update checks may call the CodexAPI.pro version endpoint and `@codexapi/codexclaude` npm metadata only.
14
14
  - The launcher must never check `@openai/codex` npm metadata or OpenAI GitHub releases for update notices.
@@ -25,8 +25,10 @@
25
25
  - Passes unknown commands directly to the bundled runtime after config is applied.
26
26
  - Provides `codexclaude changelog` using the managed version endpoint.
27
27
  - Does not expose separate `codexclaude status` or `codexclaude usage` commands; wallet information remains a compact pre-launch line.
28
- - Version `2.0.24` is forced by the backend minimum version and older clients must show an update-required message.
29
- - Mandatory updates present `Upgrade Now` in an interactive terminal, invoke npm with an argument array and no shell interpolation, then stop cleanly so the customer can start `codexclaude` again.
28
+ - Version `2.0.25` is forced by the backend minimum version and older clients must show an update-required message.
29
+ - Mandatory updates present `Upgrade Now` in an interactive terminal, invoke npm with an argument array and no shell interpolation, then relaunch the requested action automatically.
30
+ - The npm package manifest exposes only `codexclaude`, preventing npm from colliding with a native `codex` or `claude` command before postinstall runs.
31
+ - Global installation creates optional `codex` and `claude` aliases only when no existing command is present in the npm prefix or anywhere on `PATH`; native clients must never be overwritten.
30
32
 
31
33
  ## Provider Config
32
34
 
@@ -44,13 +46,13 @@ The launcher writes a model provider named `codexapi`:
44
46
  ## Runtime Defaults
45
47
 
46
48
  - Default model: `gpt-5.6` displayed as `GPT-5.6`
47
- - Supported launcher choices: `gpt-5.6`, `gpt-5.6-sol-max`, `gpt-5.6-sol-ultra`, `gpt-5.6-sol`, `gpt-5.5`, `claude-opus-4-8`, `claude-sonnet-5`, and `claude-fable-5`
49
+ - Supported launcher choices: `gpt-5.6`, `gpt-5.6-sol-max`, `gpt-5.6-sol-ultra`, `gpt-5.6-sol`, `gpt-5.5`, `claude-opus-4-8`, `claude-sonnet-5`, `claude-fable-5`, and `gpt-5.6-terra`
48
50
  - Default reasoning effort displayed locally: `xhigh`; SOL Max and SOL Ultra retain their explicit premium labels.
49
51
  - Reasoning hint sent in launcher env: model-specific
50
52
  - Approval policy: `never`
51
53
  - Sandbox mode: `danger-full-access`
52
54
  - Display wording for permissions: `Full Access` in launcher-owned copy
53
- - Local model catalog: `~/.codexclaude/model_catalog.json`; this keeps the native `/model` picker limited to the supported choices and prevents fallback metadata warnings for GPT-5.6 SOL, SOL Max, SOL Ultra, Opus 4.8, Sonnet 5, and Fable 5.
55
+ - Local model catalog: `~/.codexclaude/model_catalog.json`; this keeps the native `/model` picker limited to the supported choices and prevents fallback metadata warnings for GPT-5.6 Terra, SOL, SOL Max, SOL Ultra, Opus 4.8, Sonnet 5, and Fable 5.
54
56
  - Service tier: omitted by default; `/fast` remains user-controlled and billed server-side when active.
55
57
  - TUI status line: `model-with-reasoning`, `fast-mode`, `current-dir`
56
58
  - Fable 5 stays visible to the user while the backend applies its server-managed route and billing policy.
@@ -63,7 +65,7 @@ Before launching the runtime, the launcher calls `/api/v1/wallet/status`, then `
63
65
  Expected status line:
64
66
 
65
67
  ```text
66
- MagnetAPI.org Codex CLI v2.0.24 · gpt-5.6 xhigh · ~/project · Wallet $20.00
68
+ MagnetAPI.org Codex CLI v2.0.26 · gpt-5.6 xhigh · ~/project · Wallet $20.00
67
69
  ```
68
70
 
69
71
  ## Upgrade Checklist
@@ -81,8 +83,9 @@ When updating the bundled runtime:
81
83
  9. Keep `clearUpstreamUpdateCache()` deleting `~/.codex/version.json`.
82
84
  10. Keep direct platform binary launch and do not fall back to the upstream npm wrapper.
83
85
  11. Keep update checks limited to `/api/v1/codexclaude/version` and `@codexapi/codexclaude` npm metadata.
84
- 12. Keep the interactive `Upgrade Now` flow installing `@codexapi/codexclaude@latest` without a shell.
85
- 13. Keep the managed `MODELS` map and local model catalog, including SOL Max and SOL Ultra.
86
- 14. Keep bearer username auth and the `X-CodexAPI-*` headers.
87
- 15. Update `README.md`, `CUSTOMIZATIONS.md`, and `codexclaude.md`.
88
- 16. Run `node --check bin/codexclaude.js`, a temporary-home setup test, `npm pack --dry-run`, and endpoint validation before publishing.
86
+ 12. Keep the interactive `Upgrade Now` flow installing `@codexapi/codexclaude@latest` without a shell and relaunching automatically.
87
+ 13. Keep `codexclaude` as the only manifest-owned command and preserve the conditional, non-overwriting `codex` and `claude` postinstall aliases.
88
+ 14. Keep the managed `MODELS` map and local model catalog, including Terra, SOL Max, and SOL Ultra.
89
+ 15. Keep bearer username auth and the `X-CodexAPI-*` headers.
90
+ 16. Update `README.md`, `CUSTOMIZATIONS.md`, and `codexclaude.md`.
91
+ 17. Run syntax checks, temporary-home setup, alias-preservation tests, `npm pack --dry-run`, and endpoint validation before publishing.
package/README.md CHANGED
@@ -1,8 +1,8 @@
1
1
  # codexclaude
2
2
 
3
- `codexclaude` installs the MagnetAPI.org Codex CLI for customers who want one coding CLI that can use GPT-5.6, GPT-5.6 SOL, GPT-5.6 SOL Max, GPT-5.6 SOL Ultra, ChatGPT-5.5, Opus 4.8, Sonnet 5, or Fable 5 against the same Token Wallet.
3
+ `codexclaude` installs the MagnetAPI.org Codex CLI for customers who want one coding CLI that can use GPT-5.6, GPT-5.6 Terra, GPT-5.6 SOL, GPT-5.6 SOL Max, GPT-5.6 SOL Ultra, ChatGPT-5.5, Opus 4.8, Sonnet 5, or Fable 5 against the same Token Wallet.
4
4
 
5
- Version `2.0.24` is a required client sync release. It bundles official Codex runtime dependency `@openai/codex@0.144.4`, launches the platform-native runtime binary directly, disables upstream OpenAI update prompts, and applies account, wallet, model, Full Access, GPT-5.6/xhigh defaults, and managed model metadata before each coding session starts. Model menus no longer display wallet multiplier notices; billing remains managed by the server.
5
+ Version `2.0.26` fixes upgrades on systems that already have a native `codex` or `claude` command. It bundles official Codex runtime dependency `@openai/codex@0.145.0`, launches the platform-native runtime binary directly, disables upstream OpenAI update prompts, and applies account, wallet, model, Full Access, GPT-5.6/xhigh defaults, and managed model metadata before each coding session starts.
6
6
 
7
7
  ## Install Or Update
8
8
 
@@ -16,7 +16,7 @@ This does not delete local session history. The update replaces the `codexclaude
16
16
 
17
17
  The launcher checks CodexAPI.pro's managed version endpoint and the `@codexapi/codexclaude` npm package metadata only. It must never check `@openai/codex` npm metadata or OpenAI GitHub releases for customer update prompts.
18
18
 
19
- Version `2.0.24` is currently enforced as the minimum supported version. A compatible older launcher presents `Upgrade Now`; selecting it installs `@codexapi/codexclaude@latest`, confirms completion, and asks the customer to start `codexclaude` again. Non-interactive terminals print the same npm command instead of hanging for input.
19
+ Version `2.0.25` is currently enforced as the minimum supported version. A compatible older launcher presents `Upgrade Now`; selecting it installs `@codexapi/codexclaude@latest` and relaunches the requested action automatically. Non-interactive terminals print the same npm command instead of hanging for input.
20
20
 
21
21
  ## First Login
22
22
 
@@ -44,7 +44,17 @@ Switch model:
44
44
  codexclaude model
45
45
  ```
46
46
 
47
- Available model labels are `GPT-5.6`, `GPT-5.6 SOL Max`, `GPT-5.6 SOL Ultra`, `GPT-5.6 SOL`, `ChatGPT-5.5`, `Opus 4.8`, `Sonnet 5`, and `Fable 5`. All models use a Responses-compatible endpoint and the same customer Token Wallet.
47
+ Available model labels are `GPT-5.6`, `GPT-5.6 SOL Max`, `GPT-5.6 SOL Ultra`, `GPT-5.6 SOL`, `ChatGPT-5.5`, `Opus 4.8`, `Sonnet 5`, `Fable 5`, and `GPT-5.6 Terra`. All models use a Responses-compatible endpoint and the same customer Token Wallet.
48
+
49
+ ## Launch Commands
50
+
51
+ The npm package owns only the collision-free `codexclaude` command. During a global install, its postinstall step creates optional `codex` and `claude` aliases only when those command names are unused. Native Codex CLI and Claude Code commands are always preserved. This avoids npm `EEXIST` failures and never requires `--force`.
52
+
53
+ ```bash
54
+ codexclaude
55
+ codex
56
+ claude
57
+ ```
48
58
 
49
59
  Show current launcher changes:
50
60
 
@@ -57,17 +67,17 @@ codexclaude changelog
57
67
  Before launching the coding runtime, the app prints a compact status line like:
58
68
 
59
69
  ```text
60
- MagnetAPI.org Codex CLI v2.0.24 · gpt-5.6 xhigh · ~/project · Wallet $20.00
70
+ MagnetAPI.org Codex CLI v2.0.26 · gpt-5.6 xhigh · ~/project · Wallet $20.00
61
71
  ```
62
72
 
63
73
  ## Preserved Customizations
64
74
 
65
75
  - Dashboard Username or Email Address plus password login for CodexAPI.pro, ChatPlus.chat, MyAPI.world, and MagnetAPI.org.
66
- - GPT-5.6, GPT-5.6 SOL Max, GPT-5.6 SOL Ultra, GPT-5.6 SOL, ChatGPT-5.5, Opus 4.8, Sonnet 5, or Fable 5 model selection, with GPT-5.6/xhigh as the default.
76
+ - GPT-5.6, GPT-5.6 Terra, GPT-5.6 SOL Max, GPT-5.6 SOL Ultra, GPT-5.6 SOL, ChatGPT-5.5, Opus 4.8, Sonnet 5, or Fable 5 model selection, with GPT-5.6/xhigh as the default.
67
77
  - Service-specific Responses-compatible provider for the dashboard account that logged in.
68
78
  - Full Access defaults: approval policy `never` and sandbox mode `danger-full-access`.
69
79
  - Model-specific visible reasoning in the local UI while the API server keeps upstream runtime effort server-managed.
70
- - A local `~/.codexclaude/model_catalog.json` file so the native `/model` picker lists only the supported MagnetAPI.org Codex CLI choices, including SOL Max and SOL Ultra.
80
+ - A local `~/.codexclaude/model_catalog.json` file so the native `/model` picker lists only the supported MagnetAPI.org Codex CLI choices, including Terra, SOL Max, and SOL Ultra.
71
81
  - No default fast service tier. Fast mode is billed only when the user enables it inside the client.
72
82
  - Token Wallet balance lookup before launch without exposing separate `status` or `usage` launcher commands.
73
83
  - Backend-identifying request headers so the API can enforce account and plan rules server-side.
@@ -7,11 +7,13 @@ import { homedir } from "node:os";
7
7
  import path from "node:path";
8
8
  import readline from "node:readline/promises";
9
9
  import { stdin as input, stdout as output } from "node:process";
10
+ import { fileURLToPath } from "node:url";
11
+ import { installSafeCommandAliases } from "../scripts/install-safe-aliases.js";
10
12
 
11
13
  const require = createRequire(import.meta.url);
12
14
 
13
- const APP_VERSION = "2.0.24";
14
- const CODEX_VERSION = "0.144.4";
15
+ const APP_VERSION = "2.0.26";
16
+ const CODEX_VERSION = "0.145.0";
15
17
  const APP_DISPLAY_NAME = "MagnetAPI.org Codex CLI";
16
18
  const DEFAULT_MODEL_ID = "gpt-5.6";
17
19
  const DEFAULT_DISPLAY_REASONING_EFFORT = "xhigh";
@@ -120,10 +122,17 @@ const MODELS = {
120
122
  aliases: ["8", "fable", "fable-5", "fabel", "fabel-5", "claude-fable-5", "claude-fabel-5"],
121
123
  premium: true,
122
124
  },
125
+ "gpt-5.6-terra": {
126
+ id: "gpt-5.6-terra",
127
+ label: "GPT-5.6 Terra",
128
+ aliases: ["9", "terra", "gpt-5.6-terra", "gpt56-terra"],
129
+ reasoningEffort: "xhigh",
130
+ },
123
131
  };
124
132
 
125
133
  async function main() {
126
134
  ensureExecutable();
135
+ ensureSafeCommandAliases();
127
136
  const [command = "start", ...args] = process.argv.slice(2);
128
137
  if (["-v", "--version", "version"].includes(command)) {
129
138
  console.log(`${APP_DISPLAY_NAME} v${APP_VERSION}`);
@@ -177,7 +186,7 @@ ${APP_DISPLAY_NAME} v${APP_VERSION}
177
186
 
178
187
  Commands:
179
188
  codexclaude login Login with dashboard username/email and password
180
- codexclaude model Select GPT-5.6, SOL modes, Opus 4.8, Sonnet 5, or Fable 5
189
+ codexclaude model Select GPT-5.6, Terra, SOL modes, Opus 4.8, Sonnet 5, or Fable 5
181
190
  codexclaude changelog Show the latest CodexAPI.pro launcher changes
182
191
  codexclaude setup Rewrite ~/.codex/config.toml with Full Access defaults
183
192
  codexclaude start Start ${APP_DISPLAY_NAME} with --search
@@ -476,7 +485,20 @@ async function runMandatoryUpgrade(metadata) {
476
485
  `Hosted fallback: ${HOSTED_UPDATE_COMMAND}`,
477
486
  );
478
487
  }
479
- console.log(`\nUpgrade complete. Start ${APP_DISPLAY_NAME} again by running: codexclaude`);
488
+ console.log(`\nUpgrade complete. Restarting ${APP_DISPLAY_NAME} now...`);
489
+ const relaunchArgs = process.argv.slice(2);
490
+ const relaunchCommand = process.platform === "win32" ? "codexclaude.cmd" : "codexclaude";
491
+ try {
492
+ const relaunchExitCode = await spawnAndWait(relaunchCommand, relaunchArgs);
493
+ if (relaunchExitCode !== 0) {
494
+ throw new Error(`updated client exited with code ${relaunchExitCode}`);
495
+ }
496
+ } catch (error) {
497
+ throw new Error(
498
+ `The update installed successfully, but automatic restart failed: ${error.message}. ` +
499
+ "Run codexclaude to continue.",
500
+ );
501
+ }
480
502
  }
481
503
 
482
504
  async function spawnAndWait(command, args) {
@@ -774,6 +796,9 @@ function modelCatalogDescription(modelId) {
774
796
  if (modelId === "gpt-5.6-sol") {
775
797
  return "GPT-5.6 SOL native coding route with local coding tools and wallet billing.";
776
798
  }
799
+ if (modelId === "gpt-5.6-terra") {
800
+ return "GPT-5.6 Terra coding route with local coding tools and wallet billing.";
801
+ }
777
802
  if (modelId === "claude-opus-4-8") {
778
803
  return "Opus 4.8 coding route with local coding tools and wallet billing.";
779
804
  }
@@ -1001,6 +1026,9 @@ function modelStatusName(model) {
1001
1026
  if (model === "gpt-5.6-sol") {
1002
1027
  return "gpt-5.6-sol";
1003
1028
  }
1029
+ if (model === "gpt-5.6-terra") {
1030
+ return "gpt-5.6-terra";
1031
+ }
1004
1032
  if (model === "claude-opus-4-8") {
1005
1033
  return "opus-4.8";
1006
1034
  }
@@ -1040,6 +1068,9 @@ function normalizeConfig(config) {
1040
1068
  if (["gpt-5-6-sol", "sol"].includes(normalized.model)) {
1041
1069
  normalized.model = "gpt-5.6-sol";
1042
1070
  }
1071
+ if (["gpt-5-6-terra", "gpt56-terra", "terra"].includes(normalized.model)) {
1072
+ normalized.model = "gpt-5.6-terra";
1073
+ }
1043
1074
  if (["gpt-5-6", "gpt56", "chatgpt-5.6", "chatgpt-5-6"].includes(normalized.model)) {
1044
1075
  normalized.model = "gpt-5.6";
1045
1076
  }
@@ -1186,6 +1217,36 @@ function ensureExecutable() {
1186
1217
  }
1187
1218
  }
1188
1219
 
1220
+ function ensureSafeCommandAliases() {
1221
+ const prefix = installedGlobalPrefix();
1222
+ if (!prefix) {
1223
+ return;
1224
+ }
1225
+ installSafeCommandAliases({
1226
+ isGlobalInstall: true,
1227
+ prefix,
1228
+ quiet: true,
1229
+ });
1230
+ }
1231
+
1232
+ function installedGlobalPrefix() {
1233
+ const packageRoot = path.resolve(path.dirname(fileURLToPath(import.meta.url)), "..");
1234
+ const segments = packageRoot.split(path.sep);
1235
+ const nodeModulesIndex = segments.lastIndexOf("node_modules");
1236
+ if (nodeModulesIndex < 0 || nodeModulesIndex >= segments.length - 2) {
1237
+ return null;
1238
+ }
1239
+ const scope = segments[nodeModulesIndex + 1];
1240
+ if (scope !== "@codexapi") {
1241
+ return null;
1242
+ }
1243
+ const prefixSegments = process.platform === "win32"
1244
+ ? segments.slice(0, nodeModulesIndex)
1245
+ : segments.slice(0, Math.max(0, nodeModulesIndex - 1));
1246
+ const prefix = prefixSegments.join(path.sep) || path.parse(packageRoot).root;
1247
+ return prefix;
1248
+ }
1249
+
1189
1250
  main().catch((error) => {
1190
1251
  console.error(`codexclaude: ${error.message}`);
1191
1252
  process.exit(1);
package/codexclaude.md CHANGED
@@ -5,12 +5,12 @@ This file is the durable handoff for the `@codexapi/codexclaude` package in `/ro
5
5
  ## Current Release
6
6
 
7
7
  - Package name: `@codexapi/codexclaude`
8
- - Launcher version: `2.0.24`
8
+ - Launcher version: `2.0.26`
9
9
  - Customer-facing app name: `MagnetAPI.org Codex CLI`
10
- - Bundled runtime dependency: `@openai/codex@0.144.4`
10
+ - Bundled runtime dependency: `@openai/codex@0.145.0`
11
11
  - Required install command: `npm install -g @codexapi/codexclaude@latest`
12
- - Hosted fallback: `npm install -g https://codexapi.pro/downloads/codexapi-codexclaude-2.0.24.tgz`
13
- - Backend minimum version: `2.0.24`
12
+ - Hosted fallback: `npm install -g https://codexapi.pro/downloads/codexapi-codexclaude-2.0.26.tgz`
13
+ - Backend minimum version: `2.0.25`
14
14
  - Default visible model: `GPT-5.6`
15
15
  - Default model slug: `gpt-5.6`
16
16
  - Default visible reasoning effort: `xhigh`; premium SOL Max and SOL Ultra retain their explicit `max` and `ultra` labels.
@@ -25,13 +25,13 @@ This file is the durable handoff for the `@codexapi/codexclaude` package in `/ro
25
25
  The launcher must present itself as:
26
26
 
27
27
  ```text
28
- MagnetAPI.org Codex CLI v2.0.24
28
+ MagnetAPI.org Codex CLI v2.0.26
29
29
  ```
30
30
 
31
31
  Normal pre-launch status should look like:
32
32
 
33
33
  ```text
34
- MagnetAPI.org Codex CLI v2.0.24 · gpt-5.6 xhigh · ~/project · Wallet $20.00
34
+ MagnetAPI.org Codex CLI v2.0.26 · gpt-5.6 xhigh · ~/project · Wallet $20.00
35
35
  ```
36
36
 
37
37
  Do not show OpenAI update notices, OpenAI npm install commands, OpenAI release links, or the upstream runtime version in launcher-owned output. The package still depends on the official runtime internally, but the customer update surface is ours.
@@ -46,6 +46,7 @@ The launcher command `codexclaude model` must list these customer-visible models
46
46
  - `claude-opus-4-8` displayed as `Opus 4.8`
47
47
  - `claude-sonnet-5` displayed as `Sonnet 5`
48
48
  - `claude-fable-5` displayed as `Fable 5`
49
+ - `gpt-5.6-terra` displayed as `GPT-5.6 Terra`
49
50
 
50
51
  GPT-5.6 must be the default when a new config is created or a legacy config contains an unsupported Gemini/Deepseek value. It is displayed with `xhigh` reasoning while the API servers execute Codex-family requests through the managed GPT-5.6 Terra/xhigh signed-in target. The selected model slug must stay in `~/.codex/config.toml`; do not rewrite customer-facing model selections locally. `gpt-5.6-sol-max` and `gpt-5.6-sol-ultra` remain distinct for customer choice, usage display, and wallet billing.
51
52
 
@@ -56,7 +57,9 @@ GPT-5.6 must be the default when a new config is created or a legacy config cont
56
57
  - `https://codexapi.pro/api/v1/codexclaude/version`
57
58
  - `https://registry.npmjs.org/@codexapi%2Fcodexclaude/latest`
58
59
 
59
- It must not check `@openai/codex` npm metadata, OpenAI GitHub releases, or any upstream OpenAI update endpoint. Version `2.0.24` is a forced release: the backend `minimumVersion` equals `2.0.24`. Compatible older launchers offer an interactive `Upgrade Now` action that invokes `npm install -g @codexapi/codexclaude@latest` without shell interpolation. Non-interactive terminals print the exact update command and exit instead of waiting for input. After a successful update, the old process exits and tells the customer to start `codexclaude` again.
60
+ It must not check `@openai/codex` npm metadata, OpenAI GitHub releases, or any upstream OpenAI update endpoint. Version `2.0.25` remains the enforced minimum release while `2.0.26` is the current latest release. Compatible older launchers offer an interactive `Upgrade Now` action that invokes `npm install -g @codexapi/codexclaude@latest` without shell interpolation. Non-interactive terminals print the exact update command and exit instead of waiting for input. After a successful interactive update, the launcher starts the requested action again automatically.
61
+
62
+ The npm package manifest owns only `codexclaude`. This is deliberate: npm creates manifest binaries before postinstall, so claiming `codex` there causes an `EEXIST` upgrade failure on machines with native Codex CLI. During a global installation, postinstall may create optional `codex` and `claude` aliases only when neither the target npm prefix nor any directory on `PATH` already contains the command. Existing native clients are preserved and no install path requires `--force`.
60
63
 
61
64
  The launcher writes `check_for_update_on_startup = false` and removes `~/.codex/version.json` so the bundled runtime does not display stale upstream update prompts. The launcher also resolves the platform-native runtime binary directly from the optional package (`@openai/codex-linux-x64`, `@openai/codex-darwin-arm64`, and so on). Do not fall back to the upstream npm wrapper, because that wrapper can re-enable upstream managed update behavior.
62
65
 
@@ -84,7 +87,7 @@ base_url = "<service Responses URL>"
84
87
  experimental_bearer_token = "<customer System Token/API username>"
85
88
  wire_api = "responses"
86
89
  supports_websockets = false
87
- http_headers = { "X-CodexAPI-Client" = "codexclaude", "X-CodexAPI-Client-Version" = "2.0.24", "X-CodexAPI-Selected-Model" = "<selected model>" }
90
+ http_headers = { "X-CodexAPI-Client" = "codexclaude", "X-CodexAPI-Client-Version" = "2.0.26", "X-CodexAPI-Selected-Model" = "<selected model>" }
88
91
 
89
92
  [tui]
90
93
  status_line = ["model-with-reasoning", "fast-mode", "current-dir"]
@@ -92,7 +95,7 @@ status_line_use_colors = true
92
95
  terminal_title = ["project-name", "model-with-reasoning", "run-state"]
93
96
  ```
94
97
 
95
- The generated model catalog must contain full metadata for every supported slug, including `gpt-5.6`, `gpt-5.6-sol-max`, and `gpt-5.6-sol-ultra`. This prevents fallback metadata warnings such as:
98
+ The generated model catalog must contain full metadata for every supported slug, including `gpt-5.6`, `gpt-5.6-terra`, `gpt-5.6-sol-max`, and `gpt-5.6-sol-ultra`. This prevents fallback metadata warnings such as:
96
99
 
97
100
  ```text
98
101
  Model metadata for `claude-opus-4-8` not found. Defaulting to fallback metadata; this can degrade performance and cause issues.
@@ -132,12 +135,13 @@ When updating the bundled runtime dependency:
132
135
  8. Preserve Full Access defaults and the local model catalog.
133
136
  9. Preserve direct platform-native binary launch.
134
137
  10. Preserve update checks through our version endpoint and `@codexapi/codexclaude` npm metadata only.
135
- 11. Preserve the interactive `Upgrade Now` flow and shell-free npm invocation.
136
- 12. Preserve deletion of `~/.codex/version.json` and `check_for_update_on_startup = false`.
137
- 13. Update customer setup scripts on CodexAPI.pro, ChatPlus.chat, MyAPI.world, MagnetAPI.org, and VIP pages to use the current release.
138
- 14. Update backend `CODEXCLAUDE_LATEST_VERSION`, `CODEXCLAUDE_MIN_VERSION`, and hosted tarball URL.
139
- 15. Update this file, `README.md`, and `CUSTOMIZATIONS.md`.
140
- 16. Run validation and publish.
138
+ 11. Preserve the interactive `Upgrade Now` flow, shell-free npm invocation, and automatic relaunch.
139
+ 12. Preserve `codexclaude` as the only manifest-owned binary and the conditional native-client-safe `codex` and `claude` postinstall aliases.
140
+ 13. Preserve deletion of `~/.codex/version.json` and `check_for_update_on_startup = false`.
141
+ 14. Update customer setup scripts on CodexAPI.pro, ChatPlus.chat, MyAPI.world, MagnetAPI.org, and VIP pages to use the current release.
142
+ 15. Update backend `CODEXCLAUDE_LATEST_VERSION`, `CODEXCLAUDE_MIN_VERSION`, and hosted tarball URL.
143
+ 16. Update this file, `README.md`, and `CUSTOMIZATIONS.md`.
144
+ 17. Run validation and publish.
141
145
 
142
146
  ## Validation Commands
143
147
 
@@ -155,7 +159,7 @@ tmp_home="$(mktemp -d)"
155
159
  mkdir -p "$tmp_home/.codexclaude"
156
160
  cat > "$tmp_home/.codexclaude/config.json" <<'JSON'
157
161
  {
158
- "version": "2.0.24",
162
+ "version": "2.0.26",
159
163
  "serviceId": "codexapi",
160
164
  "serviceLabel": "CodexAPI.pro",
161
165
  "apiOrigin": "https://codexapi.pro",
@@ -187,15 +191,29 @@ Verify the generated model catalog contains only:
187
191
  - `claude-opus-4-8`
188
192
  - `claude-sonnet-5`
189
193
  - `claude-fable-5`
194
+ - `gpt-5.6-terra`
190
195
 
191
196
  After packaging, copy the tarball to the public downloads directories, restart the backend, and verify:
192
197
 
193
198
  ```bash
194
199
  curl -fsS "https://codexapi.pro/api/v1/codexclaude/version?current=2.0.17"
195
- curl -fsSI "https://codexapi.pro/downloads/codexapi-codexclaude-2.0.24.tgz"
200
+ curl -fsSI "https://codexapi.pro/downloads/codexapi-codexclaude-2.0.26.tgz"
196
201
  ```
197
202
 
198
- The version endpoint must report `latestVersion = 2.0.24`, `minimumVersion = 2.0.24`, and `updateRequired = true` for old clients.
203
+ The version endpoint must report `latestVersion = 2.0.26`, `minimumVersion = 2.0.25`, and `updateRequired = true` only for clients below the minimum.
204
+
205
+ ## Version 2.0.26 Changes
206
+
207
+ - Fixed npm `EEXIST` upgrades on systems that already have native Codex CLI installed.
208
+ - Limited package-manifest ownership to `codexclaude`.
209
+ - Kept optional `codex` and `claude` convenience aliases without replacing native clients.
210
+
211
+ ## Version 2.0.25 Changes
212
+
213
+ - Updated the bundled runtime dependency to `@openai/codex@0.145.0`.
214
+ - Added `GPT-5.6 Terra` to the managed `/model` catalog.
215
+ - Added `codex` as a managed launch alias and a conditional `claude` alias that preserves native Claude Code.
216
+ - Changed mandatory updates to relaunch the requested action automatically after installation.
199
217
 
200
218
  ## Version 2.0.24 Changes
201
219
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@codexapi/codexclaude",
3
- "version": "2.0.24",
3
+ "version": "2.0.26",
4
4
  "description": "MagnetAPI.org Codex CLI for GPT-5.6, Opus 4.8, Sonnet 5, and Fable 5.",
5
5
  "license": "Apache-2.0",
6
6
  "type": "module",
@@ -9,15 +9,20 @@
9
9
  },
10
10
  "files": [
11
11
  "bin",
12
+ "scripts",
12
13
  "README.md",
13
14
  "CUSTOMIZATIONS.md",
14
15
  "codexclaude.md"
15
16
  ],
17
+ "scripts": {
18
+ "postinstall": "node scripts/install-safe-aliases.js",
19
+ "test": "node --test test/*.test.js"
20
+ },
16
21
  "engines": {
17
22
  "node": ">=20"
18
23
  },
19
24
  "dependencies": {
20
- "@openai/codex": "0.144.4"
25
+ "@openai/codex": "0.145.0"
21
26
  },
22
27
  "publishConfig": {
23
28
  "access": "public"
@@ -0,0 +1,169 @@
1
+ #!/usr/bin/env node
2
+
3
+ import {
4
+ chmodSync,
5
+ existsSync,
6
+ lstatSync,
7
+ mkdirSync,
8
+ symlinkSync,
9
+ writeFileSync,
10
+ } from "node:fs";
11
+ import path from "node:path";
12
+ import { fileURLToPath } from "node:url";
13
+
14
+ const packageRoot = path.resolve(path.dirname(fileURLToPath(import.meta.url)), "..");
15
+ const launcherPath = path.join(packageRoot, "bin", "codexclaude.js");
16
+
17
+ export function installSafeCommandAliases(options = {}) {
18
+ return {
19
+ status: "complete",
20
+ aliases: {
21
+ codex: installSafeAlias("codex", options),
22
+ claude: installSafeAlias("claude", options),
23
+ },
24
+ };
25
+ }
26
+
27
+ export function installSafeCodexAlias(options = {}) {
28
+ return installSafeAlias("codex", options);
29
+ }
30
+
31
+ export function installSafeClaudeAlias(options = {}) {
32
+ return installSafeAlias("claude", options);
33
+ }
34
+
35
+ function installSafeAlias(command, options = {}) {
36
+ const isGlobalInstall =
37
+ options.isGlobalInstall ??
38
+ String(process.env.npm_config_global || "").toLowerCase() === "true";
39
+ const quiet = Boolean(options.quiet);
40
+ if (!isGlobalInstall || isTruthy(process.env.CODEXCLAUDE_SKIP_COMMAND_ALIASES)) {
41
+ return { status: "skipped" };
42
+ }
43
+
44
+ const prefix = String(options.prefix || process.env.npm_config_prefix || "").trim();
45
+ if (!prefix) {
46
+ if (!quiet) {
47
+ console.warn(`codexclaude: skipped the optional ${command} alias because npm did not provide its global prefix.`);
48
+ }
49
+ return { status: "missing-prefix" };
50
+ }
51
+
52
+ const binDir = process.platform === "win32" ? prefix : path.join(prefix, "bin");
53
+ const aliasPaths = commandAliasPaths(binDir, command);
54
+ const existingCommand = findCommandOnPath(command, aliasPaths);
55
+ const existingAlias = aliasPaths.find((candidate) => existsSync(candidate));
56
+
57
+ if (existingCommand || existingAlias) {
58
+ const preserved = existingCommand || existingAlias;
59
+ if (!quiet) {
60
+ console.log(`codexclaude: preserved the existing ${command} command at ${preserved}.`);
61
+ }
62
+ return { status: "preserved", path: preserved };
63
+ }
64
+
65
+ try {
66
+ mkdirSync(binDir, { recursive: true });
67
+ if (process.platform === "win32") {
68
+ installWindowsAliases(aliasPaths);
69
+ } else {
70
+ symlinkSync(launcherPath, aliasPaths[0]);
71
+ chmodSync(aliasPaths[0], 0o755);
72
+ }
73
+ if (!quiet) {
74
+ console.log(`codexclaude: installed the optional ${command} launch alias.`);
75
+ }
76
+ return { status: "installed", paths: aliasPaths.filter((candidate) => existsSync(candidate)) };
77
+ } catch (error) {
78
+ if (!quiet) {
79
+ console.warn(`codexclaude: could not install the optional ${command} alias (${error.message}).`);
80
+ }
81
+ return { status: "failed", error: error.message };
82
+ }
83
+ }
84
+
85
+ function commandAliasPaths(directory, command) {
86
+ if (process.platform === "win32") {
87
+ return [
88
+ path.join(directory, command),
89
+ path.join(directory, `${command}.cmd`),
90
+ path.join(directory, `${command}.ps1`),
91
+ path.join(directory, `${command}.exe`),
92
+ ];
93
+ }
94
+ return [path.join(directory, command)];
95
+ }
96
+
97
+ function findCommandOnPath(command, ignoredPaths) {
98
+ const ignored = new Set(ignoredPaths.map(normalizePath));
99
+ const pathEntries = String(process.env.PATH || "")
100
+ .split(path.delimiter)
101
+ .map((entry) => entry.trim())
102
+ .filter(Boolean);
103
+ const names =
104
+ process.platform === "win32"
105
+ ? [command, `${command}.exe`, `${command}.cmd`, `${command}.bat`, `${command}.ps1`]
106
+ : [command];
107
+ for (const entry of pathEntries) {
108
+ for (const name of names) {
109
+ const candidate = path.resolve(entry, name);
110
+ if (ignored.has(normalizePath(candidate)) || !existsSync(candidate)) {
111
+ continue;
112
+ }
113
+ try {
114
+ if (lstatSync(candidate).isFile() || lstatSync(candidate).isSymbolicLink()) {
115
+ return candidate;
116
+ }
117
+ } catch {
118
+ // Ignore a path entry that disappears while npm is installing.
119
+ }
120
+ }
121
+ }
122
+ return null;
123
+ }
124
+
125
+ function installWindowsAliases(paths) {
126
+ const [shellPath, cmdPath, ps1Path] = paths;
127
+ const node = quoteForCmd(process.execPath);
128
+ const launcher = quoteForCmd(launcherPath);
129
+ writeFileSync(
130
+ shellPath,
131
+ `#!/bin/sh\nexec "${escapeForShell(process.execPath)}" "${escapeForShell(launcherPath)}" "$@"\n`,
132
+ { encoding: "utf8", mode: 0o755 },
133
+ );
134
+ writeFileSync(
135
+ cmdPath,
136
+ `@ECHO off\r\n${node} ${launcher} %*\r\n`,
137
+ { encoding: "utf8" },
138
+ );
139
+ writeFileSync(
140
+ ps1Path,
141
+ `& '${escapeForPowerShell(process.execPath)}' '${escapeForPowerShell(launcherPath)}' @args\nexit $LASTEXITCODE\n`,
142
+ { encoding: "utf8" },
143
+ );
144
+ }
145
+
146
+ function normalizePath(value) {
147
+ const resolved = path.resolve(value);
148
+ return process.platform === "win32" ? resolved.toLowerCase() : resolved;
149
+ }
150
+
151
+ function quoteForCmd(value) {
152
+ return `"${String(value).replaceAll('"', '""')}"`;
153
+ }
154
+
155
+ function escapeForPowerShell(value) {
156
+ return String(value).replaceAll("'", "''");
157
+ }
158
+
159
+ function escapeForShell(value) {
160
+ return String(value).replaceAll("\\", "\\\\").replaceAll('"', '\\"').replaceAll("$", "\\$").replaceAll("`", "\\`");
161
+ }
162
+
163
+ function isTruthy(value) {
164
+ return ["1", "true", "yes", "on"].includes(String(value || "").trim().toLowerCase());
165
+ }
166
+
167
+ if (path.resolve(process.argv[1] || "") === fileURLToPath(import.meta.url)) {
168
+ installSafeCommandAliases();
169
+ }