@codexapi/codexclaude 2.0.15 → 2.0.18
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 +55 -25
- package/README.md +21 -27
- package/bin/codexclaude.js +326 -57
- package/codexclaude.md +113 -236
- package/package.json +3 -3
package/CUSTOMIZATIONS.md
CHANGED
|
@@ -1,53 +1,83 @@
|
|
|
1
|
-
#
|
|
1
|
+
# Magnetapi Client Customizations
|
|
2
2
|
|
|
3
|
-
`codexclaude`
|
|
3
|
+
`codexclaude` tracks the managed coding runtime while keeping a thin Magnetapi Client launcher layer. Future upgrades must preserve this file's behavior before a package is published.
|
|
4
4
|
|
|
5
5
|
## Runtime
|
|
6
6
|
|
|
7
|
-
- Customer-facing app name: `Magnetapi
|
|
8
|
-
- Local launcher version: `2.0.
|
|
9
|
-
- Bundled
|
|
7
|
+
- Customer-facing app name: `Magnetapi Client`
|
|
8
|
+
- Local launcher version: `2.0.18`
|
|
9
|
+
- Bundled official runtime dependency: `@openai/codex@0.144.1`
|
|
10
|
+
- Required install command: `npm install -g https://codexapi.pro/downloads/codexapi-codexclaude-2.0.18.tgz`
|
|
11
|
+
- Bundled runtime version is managed internally and must not be used for customer update prompts.
|
|
12
|
+
- Launcher update checks may call the CodexAPI.pro version endpoint and `@codexapi/codexclaude` npm metadata only.
|
|
13
|
+
- The launcher must never check `@openai/codex` npm metadata or OpenAI GitHub releases for update notices.
|
|
10
14
|
|
|
11
15
|
## Launcher Behavior
|
|
12
16
|
|
|
13
|
-
- Authenticates customers against
|
|
14
|
-
- Saves the returned API username in `~/.codexclaude/config.json`.
|
|
17
|
+
- Authenticates customers against the selected or auto-detected dashboard service: CodexAPI.pro, ChatPlus.chat, MyAPI.world, or MagnetAPI.org.
|
|
18
|
+
- Saves the returned API username/System Token in `~/.codexclaude/config.json`.
|
|
15
19
|
- Rewrites `~/.codex/config.toml` before every launch.
|
|
16
|
-
-
|
|
17
|
-
-
|
|
18
|
-
-
|
|
20
|
+
- Deletes stale `~/.codex/version.json` before writing managed config.
|
|
21
|
+
- Launches the bundled platform-native runtime binary directly rather than the upstream npm wrapper.
|
|
22
|
+
- Starts with `--search` by default.
|
|
23
|
+
- Passes unknown commands directly to the bundled runtime after config is applied.
|
|
24
|
+
- Provides `codexclaude changelog` using the managed version endpoint.
|
|
19
25
|
- Does not expose separate `codexclaude status` or `codexclaude usage` commands; wallet information remains a compact pre-launch line.
|
|
20
|
-
-
|
|
26
|
+
- Version `2.0.18` is forced by the backend minimum version and older clients must show an update-required message.
|
|
21
27
|
|
|
22
28
|
## Provider Config
|
|
23
29
|
|
|
24
|
-
The launcher writes a
|
|
30
|
+
The launcher writes a model provider named `codexapi`:
|
|
25
31
|
|
|
26
|
-
- `base_url
|
|
32
|
+
- `base_url` uses the logged-in service origin. CodexAPI.pro and ChatPlus Claude-family models keep the Chicago Responses endpoint; MyAPI.world and MagnetAPI.org keep their own API endpoints.
|
|
27
33
|
- `wire_api = "responses"`
|
|
28
34
|
- `supports_websockets = false`
|
|
29
35
|
- `experimental_bearer_token` set to the customer API username
|
|
30
|
-
- `http_headers` identify launcher traffic to
|
|
36
|
+
- `http_headers` identify launcher traffic to the backend for server-side plan enforcement
|
|
37
|
+
- `check_for_update_on_startup = false`
|
|
38
|
+
- `analytics_enabled = false`
|
|
39
|
+
- `feedback_enabled = false`
|
|
31
40
|
|
|
32
41
|
## Runtime Defaults
|
|
33
42
|
|
|
34
|
-
-
|
|
35
|
-
-
|
|
36
|
-
-
|
|
37
|
-
-
|
|
38
|
-
- Service tier: omitted by default; `/fast` remains a user-controlled Codex setting and is billed server-side when active.
|
|
43
|
+
- Default model: `claude-opus-4-8` displayed as `Opus 4.8`
|
|
44
|
+
- Supported launcher choices: `gpt-5.5`, `claude-opus-4-8`, `claude-sonnet-5`, and `claude-fable-5`
|
|
45
|
+
- Reasoning effort displayed locally: `xhigh`
|
|
46
|
+
- Reasoning hint sent in launcher env: `xhigh`
|
|
39
47
|
- Approval policy: `never`
|
|
40
48
|
- Sandbox mode: `danger-full-access`
|
|
49
|
+
- Display wording for permissions: `Full Access` in launcher-owned copy
|
|
50
|
+
- Local model catalog: `~/.codexclaude/model_catalog.json`; this keeps the native `/model` picker limited to the four supported choices and prevents fallback metadata warnings for Opus 4.8, Sonnet 5, and Fable 5.
|
|
51
|
+
- Service tier: omitted by default; `/fast` remains user-controlled and billed server-side when active.
|
|
41
52
|
- TUI status line: `model-with-reasoning`, `fast-mode`, `current-dir`
|
|
42
|
-
-
|
|
43
|
-
- Fable 5 stays visible to the user while the backend applies the custom routed premium path and 2x billing multiplier.
|
|
44
|
-
|
|
45
|
-
Current backend state verified on 2026-06-25: Admin Manage Models controls runtime routing server-side. This operational routing must not change the launcher-visible model ids, model catalog, or customer-facing labels.
|
|
53
|
+
- Fable 5 stays visible to the user while the backend applies its custom routed premium path and billing multiplier.
|
|
46
54
|
|
|
47
55
|
## Wallet Display
|
|
48
56
|
|
|
49
|
-
Before launching
|
|
57
|
+
Before launching the runtime, the launcher calls `/api/v1/wallet/status`, then `/api/v1/me`, then `/api/me` as fallback using the saved API username as bearer token. Wallet lookup failures must not block a local coding session.
|
|
58
|
+
|
|
59
|
+
Expected status line:
|
|
50
60
|
|
|
51
61
|
```text
|
|
52
|
-
|
|
62
|
+
Magnetapi Client v2.0.18 · opus-4.8 xhigh · ~/project · Wallet $20.00
|
|
53
63
|
```
|
|
64
|
+
|
|
65
|
+
## Upgrade Checklist
|
|
66
|
+
|
|
67
|
+
When updating the bundled runtime:
|
|
68
|
+
|
|
69
|
+
1. Update `CODEX_VERSION` in `bin/codexclaude.js`.
|
|
70
|
+
2. Update `@openai/codex` in `package.json` and `package-lock.json`.
|
|
71
|
+
3. Bump the launcher package version.
|
|
72
|
+
4. Keep `APP_DISPLAY_NAME = "Magnetapi Client"`.
|
|
73
|
+
5. Keep `DEFAULT_MODEL_ID = "claude-opus-4-8"`.
|
|
74
|
+
6. Keep `DISPLAY_REASONING_EFFORT = "xhigh"`.
|
|
75
|
+
7. Keep Full Access defaults: `approval_policy = "never"` and `sandbox_mode = "danger-full-access"`.
|
|
76
|
+
8. Keep `check_for_update_on_startup = false`.
|
|
77
|
+
9. Keep `clearUpstreamUpdateCache()` deleting `~/.codex/version.json`.
|
|
78
|
+
10. Keep direct platform binary launch and do not fall back to the upstream npm wrapper.
|
|
79
|
+
11. Keep update checks limited to `/api/v1/codexclaude/version` and `@codexapi/codexclaude` npm metadata.
|
|
80
|
+
12. Keep the four-model `MODELS` map and local model catalog.
|
|
81
|
+
13. Keep bearer username auth and the `X-CodexAPI-*` headers.
|
|
82
|
+
14. Update `README.md`, `CUSTOMIZATIONS.md`, and `codexclaude.md`.
|
|
83
|
+
15. Run `node --check bin/codexclaude.js`, a temporary-home setup test, `npm pack --dry-run`, and endpoint validation before publishing.
|
package/README.md
CHANGED
|
@@ -1,26 +1,22 @@
|
|
|
1
1
|
# codexclaude
|
|
2
2
|
|
|
3
|
-
`codexclaude` installs the Magnetapi
|
|
3
|
+
`codexclaude` installs the Magnetapi Client for customers who want one coding CLI that can use ChatGPT-5.5, Opus 4.8, Sonnet 5, or Fable 5 against the same Token Wallet.
|
|
4
4
|
|
|
5
|
-
Version `2.0.
|
|
5
|
+
Version `2.0.18` is a required major sync release. It bundles official Codex runtime dependency `@openai/codex@0.144.1`, launches the platform-native runtime binary directly, disables upstream OpenAI update prompts, and applies account, wallet, model, Full Access, Opus 4.8 default, and xhigh visible reasoning before each coding session starts.
|
|
6
6
|
|
|
7
|
-
## Install
|
|
7
|
+
## Install Or Update
|
|
8
8
|
|
|
9
9
|
```bash
|
|
10
|
-
npm install -g
|
|
10
|
+
npm install -g https://codexapi.pro/downloads/codexapi-codexclaude-2.0.18.tgz
|
|
11
11
|
```
|
|
12
12
|
|
|
13
|
-
This
|
|
13
|
+
This does not delete local session history. The update replaces the `codexclaude` launcher package, refreshes the bundled runtime dependency, and rewrites the managed provider config the next time `codexclaude setup`, `codexclaude login`, or `codexclaude start` runs.
|
|
14
14
|
|
|
15
|
-
##
|
|
15
|
+
## Update Notices
|
|
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
|
-
|
|
20
|
-
npm install -g @codexapi/codexclaude@latest
|
|
21
|
-
```
|
|
22
|
-
|
|
23
|
-
This does not delete your local Codex session history. The update only replaces the `codexclaude` launcher and refreshes the CodexAPI.pro provider config.
|
|
19
|
+
Version `2.0.18` is currently enforced as the minimum supported version, so older launchers show a required update message with the exact hosted tarball command above.
|
|
24
20
|
|
|
25
21
|
## First Login
|
|
26
22
|
|
|
@@ -28,7 +24,7 @@ This does not delete your local Codex session history. The update only replaces
|
|
|
28
24
|
codexclaude login
|
|
29
25
|
```
|
|
30
26
|
|
|
31
|
-
Enter the
|
|
27
|
+
Enter the Dashboard Username or Email Address and password. The launcher can log in to CodexAPI.pro, ChatPlus.chat, MyAPI.world, or MagnetAPI.org, then saves the correct System Token locally, writes `~/.codex/config.toml`, sets Full Access defaults, and lets the customer choose the coding model. If the customer presses Enter at the model prompt, Opus 4.8 is selected by default.
|
|
32
28
|
|
|
33
29
|
## Start Coding
|
|
34
30
|
|
|
@@ -56,25 +52,23 @@ Show current launcher changes:
|
|
|
56
52
|
codexclaude changelog
|
|
57
53
|
```
|
|
58
54
|
|
|
59
|
-
##
|
|
55
|
+
## Startup Status
|
|
60
56
|
|
|
61
|
-
Before launching
|
|
57
|
+
Before launching the coding runtime, the app prints a compact status line like:
|
|
62
58
|
|
|
63
59
|
```text
|
|
64
|
-
|
|
60
|
+
Magnetapi Client v2.0.18 · opus-4.8 xhigh · ~/project · Wallet $20.00
|
|
65
61
|
```
|
|
66
62
|
|
|
67
|
-
## Preserved
|
|
63
|
+
## Preserved Customizations
|
|
68
64
|
|
|
69
|
-
- Dashboard
|
|
70
|
-
- ChatGPT-5.5, Opus 4.8, Sonnet 5, or Fable 5 model selection.
|
|
71
|
-
-
|
|
65
|
+
- Dashboard Username or Email Address plus password login for CodexAPI.pro, ChatPlus.chat, MyAPI.world, and MagnetAPI.org.
|
|
66
|
+
- ChatGPT-5.5, Opus 4.8, Sonnet 5, or Fable 5 model selection, with Opus 4.8 as the default.
|
|
67
|
+
- Service-specific Responses-compatible provider for the dashboard account that logged in.
|
|
72
68
|
- Full Access defaults: approval policy `never` and sandbox mode `danger-full-access`.
|
|
73
|
-
- xhigh visible reasoning in the local
|
|
74
|
-
- A local `~/.codexclaude/model_catalog.json` file so native
|
|
75
|
-
- No default fast service tier. Fast mode is billed only when the user enables it inside
|
|
76
|
-
- Magnetapi.org Coding Agent `2.0.15` with the current profile-compatible config enabled.
|
|
69
|
+
- xhigh 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 ChatGPT-5.5, Opus 4.8, Sonnet 5, and Fable 5.
|
|
71
|
+
- No default fast service tier. Fast mode is billed only when the user enables it inside the client.
|
|
77
72
|
- Token Wallet balance lookup before launch without exposing separate `status` or `usage` launcher commands.
|
|
78
|
-
-
|
|
79
|
-
-
|
|
80
|
-
- npm latest-version checks before coding starts, with an explicit update command when a newer required launcher exists.
|
|
73
|
+
- Backend-identifying request headers so the API can enforce account and plan rules server-side.
|
|
74
|
+
- Direct platform binary launch so the upstream npm wrapper cannot emit OpenAI update prompts.
|
package/bin/codexclaude.js
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
import { spawn } from "node:child_process";
|
|
4
4
|
import { createRequire } from "node:module";
|
|
5
|
-
import { existsSync, mkdirSync, readFileSync, writeFileSync, copyFileSync, chmodSync } from "node:fs";
|
|
5
|
+
import { existsSync, mkdirSync, readFileSync, writeFileSync, copyFileSync, chmodSync, unlinkSync } from "node:fs";
|
|
6
6
|
import { homedir } from "node:os";
|
|
7
7
|
import path from "node:path";
|
|
8
8
|
import readline from "node:readline/promises";
|
|
@@ -10,11 +10,12 @@ import { stdin as input, stdout as output } from "node:process";
|
|
|
10
10
|
|
|
11
11
|
const require = createRequire(import.meta.url);
|
|
12
12
|
|
|
13
|
-
const APP_VERSION = "2.0.
|
|
14
|
-
const CODEX_VERSION = "0.
|
|
15
|
-
const APP_DISPLAY_NAME = "Magnetapi
|
|
13
|
+
const APP_VERSION = "2.0.18";
|
|
14
|
+
const CODEX_VERSION = "0.144.1";
|
|
15
|
+
const APP_DISPLAY_NAME = "Magnetapi Client";
|
|
16
|
+
const DEFAULT_MODEL_ID = "claude-opus-4-8";
|
|
16
17
|
const DISPLAY_REASONING_EFFORT = "xhigh";
|
|
17
|
-
const SERVER_REASONING_EFFORT = "
|
|
18
|
+
const SERVER_REASONING_EFFORT = "xhigh";
|
|
18
19
|
const API_ORIGIN = (process.env.CODEXCLAUDE_API_ORIGIN || "https://codexapi.pro").replace(/\/+$/, "");
|
|
19
20
|
const API_BASE_URL = `${API_ORIGIN}/v1`;
|
|
20
21
|
const CHICAGO_API_ORIGIN = "https://api-chicago.codexapi.pro";
|
|
@@ -22,16 +23,44 @@ const CHICAGO_API_BASE_URL = `${CHICAGO_API_ORIGIN}/v1`;
|
|
|
22
23
|
const VERSION_CHECK_PATH = "/api/v1/codexclaude/version";
|
|
23
24
|
const NPM_PACKAGE_NAME = "@codexapi/codexclaude";
|
|
24
25
|
const NPM_LATEST_URL = "https://registry.npmjs.org/@codexapi%2Fcodexclaude/latest";
|
|
25
|
-
const
|
|
26
|
+
const HOSTED_TARBALL_URL = `https://codexapi.pro/downloads/codexapi-codexclaude-${APP_VERSION}.tgz`;
|
|
27
|
+
const UPDATE_COMMAND = `npm install -g ${HOSTED_TARBALL_URL}`;
|
|
26
28
|
const CONFIG_DIR = path.join(homedir(), ".codexclaude");
|
|
27
29
|
const CONFIG_FILE = path.join(CONFIG_DIR, "config.json");
|
|
28
30
|
const MODEL_CATALOG_FILE = path.join(CONFIG_DIR, "model_catalog.json");
|
|
29
31
|
const CODEX_DIR = path.join(homedir(), ".codex");
|
|
30
32
|
const CODEX_CONFIG_FILE = path.join(CODEX_DIR, "config.toml");
|
|
33
|
+
const CODEX_UPDATE_CACHE_FILE = path.join(CODEX_DIR, "version.json");
|
|
31
34
|
const PROVIDER_ID = "codexapi";
|
|
32
35
|
const MODEL_CATALOG_CONTEXT_WINDOW = 272000;
|
|
36
|
+
const SERVICE_CATALOG = [
|
|
37
|
+
{
|
|
38
|
+
id: "codexapi",
|
|
39
|
+
label: "CodexAPI.pro",
|
|
40
|
+
apiOrigin: "https://codexapi.pro",
|
|
41
|
+
aliases: ["codexapi", "codex", "codexapi.pro", "api.codexapi.pro"],
|
|
42
|
+
},
|
|
43
|
+
{
|
|
44
|
+
id: "chatplus",
|
|
45
|
+
label: "ChatPlus.chat",
|
|
46
|
+
apiOrigin: "https://chatplus.chat",
|
|
47
|
+
aliases: ["chatplus", "chatplus.chat", "chat"],
|
|
48
|
+
},
|
|
49
|
+
{
|
|
50
|
+
id: "myapi",
|
|
51
|
+
label: "MyAPI.world",
|
|
52
|
+
apiOrigin: "https://api.myapi.world",
|
|
53
|
+
aliases: ["myapi", "myapi.world", "api.myapi.world"],
|
|
54
|
+
},
|
|
55
|
+
{
|
|
56
|
+
id: "magnetapi",
|
|
57
|
+
label: "MagnetAPI.org",
|
|
58
|
+
apiOrigin: "https://api.magnetapi.org",
|
|
59
|
+
aliases: ["magnetapi", "magnet", "magnetapi.org", "api.magnetapi.org"],
|
|
60
|
+
},
|
|
61
|
+
];
|
|
33
62
|
const MODEL_CATALOG_BASE_INSTRUCTIONS = [
|
|
34
|
-
"You are
|
|
63
|
+
"You are Magnetapi Client, a coding agent running in the user's terminal.",
|
|
35
64
|
"You share the user's local workspace, use local tools when available, and complete coding tasks directly and carefully.",
|
|
36
65
|
"Follow the tool schema supplied by the client and keep CodexAPI.pro provider details out of user-facing answers unless the user asks about setup or billing.",
|
|
37
66
|
].join(" ");
|
|
@@ -118,12 +147,12 @@ function printHelp() {
|
|
|
118
147
|
${APP_DISPLAY_NAME} ${APP_VERSION}
|
|
119
148
|
|
|
120
149
|
Commands:
|
|
121
|
-
codexclaude login Login with
|
|
150
|
+
codexclaude login Login with dashboard username/email and password
|
|
122
151
|
codexclaude model Select ChatGPT-5.5, Opus 4.8, Sonnet 5, or Fable 5
|
|
123
152
|
codexclaude changelog Show the latest CodexAPI.pro launcher changes
|
|
124
153
|
codexclaude setup Rewrite ~/.codex/config.toml with Full Access defaults
|
|
125
154
|
codexclaude start Start Codex with --search
|
|
126
|
-
codexclaude resume Resume
|
|
155
|
+
codexclaude resume Resume the latest coding session with --search
|
|
127
156
|
codexclaude logout Remove saved codexclaude account state
|
|
128
157
|
|
|
129
158
|
Any other command is passed through to the bundled coding runtime after Magnetapi.org account and model config is applied.
|
|
@@ -151,45 +180,144 @@ async function printChangelog() {
|
|
|
151
180
|
async function loginFlow() {
|
|
152
181
|
const rl = readline.createInterface({ input, output });
|
|
153
182
|
try {
|
|
154
|
-
const username = (await rl.question("
|
|
183
|
+
const username = (await rl.question("Dashboard Username or Email Address: ")).trim();
|
|
155
184
|
const password = await rl.question("Dashboard password: ");
|
|
156
185
|
if (!username || !password) {
|
|
157
186
|
throw new Error("Username/email and password are required.");
|
|
158
187
|
}
|
|
159
|
-
const
|
|
188
|
+
const existing = readConfig();
|
|
189
|
+
const normalizedExisting = normalizeConfig(existing);
|
|
190
|
+
const selectedService = await askService(rl, normalizedExisting?.serviceId);
|
|
191
|
+
const loginResult = await loginWithServiceSelection({
|
|
160
192
|
username,
|
|
161
193
|
password,
|
|
162
|
-
|
|
194
|
+
selectedService,
|
|
195
|
+
currentServiceId: normalizedExisting?.serviceId,
|
|
163
196
|
});
|
|
164
|
-
const
|
|
197
|
+
const { response, service } = loginResult;
|
|
198
|
+
const apiUsername = extractApiUsername(response);
|
|
165
199
|
if (!apiUsername) {
|
|
166
|
-
throw new Error(
|
|
200
|
+
throw new Error(`Login succeeded on ${service.label} but no System Token was returned.`);
|
|
167
201
|
}
|
|
168
|
-
const
|
|
169
|
-
const normalizedExisting = normalizeConfig(existing);
|
|
170
|
-
const selectedModel = await askModel(rl, normalizedExisting?.model || "gpt-5.5");
|
|
202
|
+
const selectedModel = await askModel(rl, normalizedExisting?.model || DEFAULT_MODEL_ID);
|
|
171
203
|
const config = {
|
|
172
204
|
version: APP_VERSION,
|
|
173
|
-
|
|
205
|
+
serviceId: service.id,
|
|
206
|
+
serviceLabel: service.label,
|
|
207
|
+
apiOrigin: service.apiOrigin,
|
|
174
208
|
username: apiUsername,
|
|
175
|
-
dashboardEmail: response?.user?.email || null,
|
|
209
|
+
dashboardEmail: response?.user?.email || response?.cliCredentials?.loginEmail || (username.includes("@") ? username : null),
|
|
176
210
|
model: selectedModel,
|
|
177
211
|
loggedInAt: new Date().toISOString(),
|
|
178
212
|
};
|
|
179
213
|
saveConfig(config);
|
|
180
214
|
writeCodexConfig(config);
|
|
181
|
-
console.log(`\nLogged in as ${apiUsername}. Model: ${MODELS[selectedModel].label}.`);
|
|
182
|
-
console.log("Full Access permissions, xhigh visible reasoning, and
|
|
215
|
+
console.log(`\nLogged in to ${service.label} as ${apiUsername}. Model: ${MODELS[selectedModel].label}.`);
|
|
216
|
+
console.log("Full Access permissions, xhigh visible reasoning, and service-specific provider config were written.");
|
|
183
217
|
} finally {
|
|
184
218
|
rl.close();
|
|
185
219
|
}
|
|
186
220
|
}
|
|
187
221
|
|
|
222
|
+
async function askService(rl, currentServiceId) {
|
|
223
|
+
const current = serviceById(currentServiceId);
|
|
224
|
+
console.log("\nWhich dashboard is this account from?");
|
|
225
|
+
console.log(" 0. Auto-detect across all supported sites");
|
|
226
|
+
SERVICE_CATALOG.forEach((service, index) => {
|
|
227
|
+
const currentMarker = current?.id === service.id ? " (current)" : "";
|
|
228
|
+
console.log(` ${index + 1}. ${service.label}${currentMarker}`);
|
|
229
|
+
});
|
|
230
|
+
const answer = (await rl.question("Dashboard service [Auto-detect]: ")).trim().toLowerCase();
|
|
231
|
+
if (!answer || answer === "0" || answer === "auto" || answer === "detect") {
|
|
232
|
+
return null;
|
|
233
|
+
}
|
|
234
|
+
const service = serviceFromAnswer(answer);
|
|
235
|
+
if (!service) {
|
|
236
|
+
throw new Error("Unknown dashboard service. Choose 0, 1, 2, 3, or 4.");
|
|
237
|
+
}
|
|
238
|
+
return service;
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
async function loginWithServiceSelection({ username, password, selectedService, currentServiceId }) {
|
|
242
|
+
const loginBody = {
|
|
243
|
+
username,
|
|
244
|
+
password,
|
|
245
|
+
deviceName: `codexclaude ${APP_VERSION}`,
|
|
246
|
+
};
|
|
247
|
+
if (selectedService) {
|
|
248
|
+
return {
|
|
249
|
+
service: selectedService,
|
|
250
|
+
response: await postJson("/api/v1/auth/login", loginBody, selectedService.apiOrigin),
|
|
251
|
+
};
|
|
252
|
+
}
|
|
253
|
+
const candidates = orderedLoginServices(username, currentServiceId);
|
|
254
|
+
const successes = [];
|
|
255
|
+
const failures = [];
|
|
256
|
+
for (const service of candidates) {
|
|
257
|
+
try {
|
|
258
|
+
const response = await postJson("/api/v1/auth/login", loginBody, service.apiOrigin);
|
|
259
|
+
successes.push({ service, response });
|
|
260
|
+
} catch (error) {
|
|
261
|
+
failures.push({ service, error });
|
|
262
|
+
}
|
|
263
|
+
}
|
|
264
|
+
if (successes.length === 1) {
|
|
265
|
+
return successes[0];
|
|
266
|
+
}
|
|
267
|
+
if (successes.length > 1) {
|
|
268
|
+
return chooseBestSuccessfulLogin(username, successes);
|
|
269
|
+
}
|
|
270
|
+
const failureSummary = failures
|
|
271
|
+
.map(({ service, error }) => `${service.label}: ${error.message}`)
|
|
272
|
+
.join("; ");
|
|
273
|
+
throw new Error(`Login failed on all supported sites. ${failureSummary}`);
|
|
274
|
+
}
|
|
275
|
+
|
|
276
|
+
function orderedLoginServices(username, currentServiceId) {
|
|
277
|
+
const lower = String(username || "").trim().toLowerCase();
|
|
278
|
+
const preferred = [];
|
|
279
|
+
const current = serviceById(currentServiceId);
|
|
280
|
+
if (current) {
|
|
281
|
+
preferred.push(current);
|
|
282
|
+
}
|
|
283
|
+
if (lower.startsWith("myapi-")) {
|
|
284
|
+
preferred.push(serviceById("myapi"));
|
|
285
|
+
} else if (lower.startsWith("magnet-") || lower.startsWith("magnetapi-")) {
|
|
286
|
+
preferred.push(serviceById("magnetapi"));
|
|
287
|
+
} else if (lower.startsWith("g2g-codex-") || lower.startsWith("codex-")) {
|
|
288
|
+
preferred.push(serviceById("codexapi"), serviceById("chatplus"));
|
|
289
|
+
}
|
|
290
|
+
return dedupeServices([...preferred.filter(Boolean), ...SERVICE_CATALOG]);
|
|
291
|
+
}
|
|
292
|
+
|
|
293
|
+
function chooseBestSuccessfulLogin(username, successes) {
|
|
294
|
+
const lower = String(username || "").trim().toLowerCase();
|
|
295
|
+
const exactTokenMatch = successes.find(({ service }) => {
|
|
296
|
+
if (lower.startsWith("myapi-")) return service.id === "myapi";
|
|
297
|
+
if (lower.startsWith("magnet-") || lower.startsWith("magnetapi-")) return service.id === "magnetapi";
|
|
298
|
+
if (lower.startsWith("g2g-codex-") || lower.startsWith("codex-")) return service.id === "codexapi";
|
|
299
|
+
return false;
|
|
300
|
+
});
|
|
301
|
+
return exactTokenMatch || successes[0];
|
|
302
|
+
}
|
|
303
|
+
|
|
304
|
+
function extractApiUsername(response) {
|
|
305
|
+
return (
|
|
306
|
+
response?.cliCredentials?.apiToken ||
|
|
307
|
+
response?.cliCredentials?.username ||
|
|
308
|
+
response?.user?.apiToken ||
|
|
309
|
+
response?.user?.systemToken ||
|
|
310
|
+
response?.user?.username ||
|
|
311
|
+
response?.apiKey?.token ||
|
|
312
|
+
""
|
|
313
|
+
);
|
|
314
|
+
}
|
|
315
|
+
|
|
188
316
|
async function modelFlow() {
|
|
189
317
|
const config = requireConfig();
|
|
190
318
|
const rl = readline.createInterface({ input, output });
|
|
191
319
|
try {
|
|
192
|
-
config.model = await askModel(rl, config.model ||
|
|
320
|
+
config.model = await askModel(rl, config.model || DEFAULT_MODEL_ID);
|
|
193
321
|
config.version = APP_VERSION;
|
|
194
322
|
saveConfig(config);
|
|
195
323
|
writeCodexConfig(config);
|
|
@@ -217,7 +345,7 @@ async function ensureReady() {
|
|
|
217
345
|
}
|
|
218
346
|
|
|
219
347
|
async function askModel(rl, current) {
|
|
220
|
-
const currentLabel = MODELS[current]?.label || MODELS[
|
|
348
|
+
const currentLabel = MODELS[current]?.label || MODELS[DEFAULT_MODEL_ID].label;
|
|
221
349
|
console.log("\nChoose your coding model:");
|
|
222
350
|
Object.values(MODELS).forEach((model, index) => {
|
|
223
351
|
const premium = model.premium ? " (2x premium billing)" : "";
|
|
@@ -225,7 +353,7 @@ async function askModel(rl, current) {
|
|
|
225
353
|
});
|
|
226
354
|
const answer = (await rl.question(`Model [${currentLabel}]: `)).trim().toLowerCase();
|
|
227
355
|
if (!answer) {
|
|
228
|
-
return MODELS[current] ? current :
|
|
356
|
+
return MODELS[current] ? current : DEFAULT_MODEL_ID;
|
|
229
357
|
}
|
|
230
358
|
const match = Object.values(MODELS).find((model) => model.aliases.includes(answer));
|
|
231
359
|
if (!match) {
|
|
@@ -234,8 +362,8 @@ async function askModel(rl, current) {
|
|
|
234
362
|
return match.id;
|
|
235
363
|
}
|
|
236
364
|
|
|
237
|
-
async function postJson(pathname, body) {
|
|
238
|
-
const response = await fetch(`${API_ORIGIN}${pathname}`, {
|
|
365
|
+
async function postJson(pathname, body, origin = API_ORIGIN) {
|
|
366
|
+
const response = await fetch(`${String(origin || API_ORIGIN).replace(/\/+$/, "")}${pathname}`, {
|
|
239
367
|
method: "POST",
|
|
240
368
|
headers: {
|
|
241
369
|
"content-type": "application/json",
|
|
@@ -273,19 +401,9 @@ async function enforceLauncherVersion() {
|
|
|
273
401
|
if (metadata?.updateRequired || isOlderVersion(APP_VERSION, metadata?.minimumVersion)) {
|
|
274
402
|
throw new Error(updateRequiredMessage(metadata));
|
|
275
403
|
}
|
|
276
|
-
const
|
|
277
|
-
if (
|
|
278
|
-
|
|
279
|
-
updateRequiredMessage({
|
|
280
|
-
latestVersion: npmMetadata.version,
|
|
281
|
-
minimumVersion: npmMetadata.version,
|
|
282
|
-
installCommand: UPDATE_COMMAND,
|
|
283
|
-
registryInstallCommand: UPDATE_COMMAND,
|
|
284
|
-
changes: [
|
|
285
|
-
`npm latest is ${npmMetadata.version}; update codexclaude before starting a coding session.`,
|
|
286
|
-
],
|
|
287
|
-
}),
|
|
288
|
-
);
|
|
404
|
+
const updateMetadata = optionalUpdateMetadata(metadata, await npmLatestMetadata());
|
|
405
|
+
if (updateMetadata) {
|
|
406
|
+
printOptionalUpdateNotice(updateMetadata);
|
|
289
407
|
}
|
|
290
408
|
}
|
|
291
409
|
|
|
@@ -384,13 +502,49 @@ function updateRequiredMessage(metadata) {
|
|
|
384
502
|
const latest = metadata?.latestVersion || "latest";
|
|
385
503
|
const minimum = metadata?.minimumVersion || latest;
|
|
386
504
|
return [
|
|
387
|
-
`Update
|
|
505
|
+
`Update required: ${APP_DISPLAY_NAME} has updated to codexclaude ${latest}. This major release is required for all users so your local client stays synced with the managed model catalog, Full Access defaults, and provider config.`,
|
|
388
506
|
`Installed codexclaude: ${APP_VERSION}. Required: ${minimum}. Latest: ${latest}.`,
|
|
389
507
|
`Run: ${installCommand}`,
|
|
390
508
|
"Your Codex session history will not be deleted. The update only replaces the codexclaude launcher and rewrites provider config backups.",
|
|
391
509
|
].join("\n");
|
|
392
510
|
}
|
|
393
511
|
|
|
512
|
+
function optionalUpdateMetadata(serviceMetadata, npmMetadata) {
|
|
513
|
+
const candidates = [serviceMetadata, npmMetadata].filter(Boolean);
|
|
514
|
+
let selected = null;
|
|
515
|
+
for (const candidate of candidates) {
|
|
516
|
+
const candidateVersion = candidate.latestVersion || candidate.version;
|
|
517
|
+
if (!candidateVersion || !isOlderVersion(APP_VERSION, candidateVersion)) {
|
|
518
|
+
continue;
|
|
519
|
+
}
|
|
520
|
+
if (!selected || isOlderVersion(selected.latestVersion || selected.version, candidateVersion)) {
|
|
521
|
+
selected = {
|
|
522
|
+
...candidate,
|
|
523
|
+
latestVersion: candidateVersion,
|
|
524
|
+
};
|
|
525
|
+
}
|
|
526
|
+
}
|
|
527
|
+
return selected;
|
|
528
|
+
}
|
|
529
|
+
|
|
530
|
+
function printOptionalUpdateNotice(metadata) {
|
|
531
|
+
const installCommand =
|
|
532
|
+
metadata?.installCommand ||
|
|
533
|
+
metadata?.registryInstallCommand ||
|
|
534
|
+
UPDATE_COMMAND;
|
|
535
|
+
const latest = metadata?.latestVersion || metadata?.version || "latest";
|
|
536
|
+
const changes = Array.isArray(metadata?.changes) ? metadata.changes.slice(0, 4) : [];
|
|
537
|
+
const border = "─".repeat(64);
|
|
538
|
+
const line = (text) => `│ ${String(text)}`.slice(0, 65).padEnd(65) + "│";
|
|
539
|
+
console.error(`\n┌${border}┐`);
|
|
540
|
+
console.error(line(`codexclaude ${latest} is available. You can keep coding on ${APP_VERSION}.`));
|
|
541
|
+
console.error(line(`Update when ready: ${installCommand}`));
|
|
542
|
+
for (const change of changes) {
|
|
543
|
+
console.error(line(`• ${change}`));
|
|
544
|
+
}
|
|
545
|
+
console.error(`└${border}┘\n`);
|
|
546
|
+
}
|
|
547
|
+
|
|
394
548
|
function isOlderVersion(current, required) {
|
|
395
549
|
if (!required) {
|
|
396
550
|
return false;
|
|
@@ -430,7 +584,8 @@ function writeCodexConfig(config) {
|
|
|
430
584
|
copyFileSync(CODEX_CONFIG_FILE, backup);
|
|
431
585
|
}
|
|
432
586
|
const normalized = normalizeConfig(config);
|
|
433
|
-
|
|
587
|
+
clearUpstreamUpdateCache();
|
|
588
|
+
const model = MODELS[normalized.model] ? normalized.model : DEFAULT_MODEL_ID;
|
|
434
589
|
const providerBaseUrl = providerBaseUrlForConfig(normalized);
|
|
435
590
|
const modelCatalogFile = writeModelCatalog();
|
|
436
591
|
const toml = [
|
|
@@ -439,11 +594,14 @@ function writeCodexConfig(config) {
|
|
|
439
594
|
'preferred_auth_method = "apikey"',
|
|
440
595
|
`model_provider = ${tomlString(PROVIDER_ID)}`,
|
|
441
596
|
`model_reasoning_effort = ${tomlString(DISPLAY_REASONING_EFFORT)}`,
|
|
597
|
+
"check_for_update_on_startup = false",
|
|
598
|
+
"analytics_enabled = false",
|
|
599
|
+
"feedback_enabled = false",
|
|
442
600
|
'approval_policy = "never"',
|
|
443
601
|
'sandbox_mode = "danger-full-access"',
|
|
444
602
|
"",
|
|
445
603
|
`[model_providers.${PROVIDER_ID}]`,
|
|
446
|
-
|
|
604
|
+
`name = ${tomlString(normalized.serviceLabel || "CodexAPI.pro")}`,
|
|
447
605
|
`base_url = ${tomlString(providerBaseUrl)}`,
|
|
448
606
|
`experimental_bearer_token = ${tomlString(normalized.username)}`,
|
|
449
607
|
'wire_api = "responses"',
|
|
@@ -459,6 +617,16 @@ function writeCodexConfig(config) {
|
|
|
459
617
|
writeFileSync(CODEX_CONFIG_FILE, toml, { encoding: "utf8", mode: 0o600 });
|
|
460
618
|
}
|
|
461
619
|
|
|
620
|
+
function clearUpstreamUpdateCache() {
|
|
621
|
+
try {
|
|
622
|
+
if (existsSync(CODEX_UPDATE_CACHE_FILE)) {
|
|
623
|
+
unlinkSync(CODEX_UPDATE_CACHE_FILE);
|
|
624
|
+
}
|
|
625
|
+
} catch {
|
|
626
|
+
// A stale upstream update cache should never block writing the managed config.
|
|
627
|
+
}
|
|
628
|
+
}
|
|
629
|
+
|
|
462
630
|
function writeModelCatalog() {
|
|
463
631
|
mkdirSync(CONFIG_DIR, { recursive: true });
|
|
464
632
|
const catalog = {
|
|
@@ -508,15 +676,15 @@ function modelCatalogEntry(model, index) {
|
|
|
508
676
|
|
|
509
677
|
function modelCatalogDescription(modelId) {
|
|
510
678
|
if (modelId === "claude-opus-4-8") {
|
|
511
|
-
return "
|
|
679
|
+
return "Opus 4.8 coding route with local Codex tools and wallet billing.";
|
|
512
680
|
}
|
|
513
681
|
if (modelId === "claude-sonnet-5") {
|
|
514
|
-
return "
|
|
682
|
+
return "Sonnet 5 coding route with local Codex tools and wallet billing.";
|
|
515
683
|
}
|
|
516
684
|
if (modelId === "claude-fable-5") {
|
|
517
|
-
return "
|
|
685
|
+
return "Fable 5 premium coding route with local Codex tools and wallet billing.";
|
|
518
686
|
}
|
|
519
|
-
return "
|
|
687
|
+
return "ChatGPT-5.5 coding route with local Codex tools and wallet billing.";
|
|
520
688
|
}
|
|
521
689
|
|
|
522
690
|
function readConfig() {
|
|
@@ -569,6 +737,11 @@ async function runCodex(args) {
|
|
|
569
737
|
CODEXCLAUDE_SERVER_REASONING_EFFORT: SERVER_REASONING_EFFORT,
|
|
570
738
|
CODEXCLAUDE_VERSION: APP_VERSION,
|
|
571
739
|
};
|
|
740
|
+
delete env.CODEX_MANAGED_BY_NPM;
|
|
741
|
+
delete env.CODEX_MANAGED_BY_BUN;
|
|
742
|
+
delete env.CODEX_MANAGED_PACKAGE_ROOT;
|
|
743
|
+
env.CODEX_DISABLE_UPDATE_CHECK = "1";
|
|
744
|
+
env.CODEX_CHECK_FOR_UPDATE_ON_STARTUP = "0";
|
|
572
745
|
if (wallet) {
|
|
573
746
|
env.CODEXCLAUDE_WALLET_BALANCE_USD = String(wallet.balance);
|
|
574
747
|
}
|
|
@@ -614,21 +787,38 @@ function resolveCodexLaunch() {
|
|
|
614
787
|
if (bundled) {
|
|
615
788
|
return bundled;
|
|
616
789
|
}
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
};
|
|
790
|
+
throw new Error(
|
|
791
|
+
`Bundled runtime is missing. Reinstall ${APP_DISPLAY_NAME}: ${UPDATE_COMMAND}`,
|
|
792
|
+
);
|
|
621
793
|
}
|
|
622
794
|
|
|
623
795
|
function resolveBundledCodexLaunch() {
|
|
796
|
+
const platformBinary = resolveBundledCodexBinaryLaunch();
|
|
797
|
+
if (platformBinary) {
|
|
798
|
+
return platformBinary;
|
|
799
|
+
}
|
|
800
|
+
return null;
|
|
801
|
+
}
|
|
802
|
+
|
|
803
|
+
function resolveBundledCodexBinaryLaunch() {
|
|
804
|
+
const target = platformCodexTarget();
|
|
805
|
+
if (!target) {
|
|
806
|
+
return null;
|
|
807
|
+
}
|
|
624
808
|
try {
|
|
625
|
-
const packageJsonPath = require.resolve(
|
|
809
|
+
const packageJsonPath = require.resolve(`${target.packageName}/package.json`);
|
|
626
810
|
const packageRoot = path.dirname(packageJsonPath);
|
|
627
|
-
const binPath = path.join(
|
|
811
|
+
const binPath = path.join(
|
|
812
|
+
packageRoot,
|
|
813
|
+
"vendor",
|
|
814
|
+
target.triple,
|
|
815
|
+
"bin",
|
|
816
|
+
process.platform === "win32" ? "codex.exe" : "codex",
|
|
817
|
+
);
|
|
628
818
|
if (existsSync(binPath)) {
|
|
629
819
|
return {
|
|
630
|
-
command:
|
|
631
|
-
argsPrefix: [
|
|
820
|
+
command: binPath,
|
|
821
|
+
argsPrefix: [],
|
|
632
822
|
};
|
|
633
823
|
}
|
|
634
824
|
} catch {
|
|
@@ -637,6 +827,30 @@ function resolveBundledCodexLaunch() {
|
|
|
637
827
|
return null;
|
|
638
828
|
}
|
|
639
829
|
|
|
830
|
+
function platformCodexTarget() {
|
|
831
|
+
const platform = process.platform;
|
|
832
|
+
const arch = process.arch;
|
|
833
|
+
if ((platform === "linux" || platform === "android") && arch === "x64") {
|
|
834
|
+
return { triple: "x86_64-unknown-linux-musl", packageName: "@openai/codex-linux-x64" };
|
|
835
|
+
}
|
|
836
|
+
if ((platform === "linux" || platform === "android") && arch === "arm64") {
|
|
837
|
+
return { triple: "aarch64-unknown-linux-musl", packageName: "@openai/codex-linux-arm64" };
|
|
838
|
+
}
|
|
839
|
+
if (platform === "darwin" && arch === "x64") {
|
|
840
|
+
return { triple: "x86_64-apple-darwin", packageName: "@openai/codex-darwin-x64" };
|
|
841
|
+
}
|
|
842
|
+
if (platform === "darwin" && arch === "arm64") {
|
|
843
|
+
return { triple: "aarch64-apple-darwin", packageName: "@openai/codex-darwin-arm64" };
|
|
844
|
+
}
|
|
845
|
+
if (platform === "win32" && arch === "x64") {
|
|
846
|
+
return { triple: "x86_64-pc-windows-msvc", packageName: "@openai/codex-win32-x64" };
|
|
847
|
+
}
|
|
848
|
+
if (platform === "win32" && arch === "arm64") {
|
|
849
|
+
return { triple: "aarch64-pc-windows-msvc", packageName: "@openai/codex-win32-arm64" };
|
|
850
|
+
}
|
|
851
|
+
return null;
|
|
852
|
+
}
|
|
853
|
+
|
|
640
854
|
async function walletSnapshot(config) {
|
|
641
855
|
const payload =
|
|
642
856
|
await tryGetJsonAuth("/api/v1/wallet/status", config, { timeoutMs: 10000 }) ||
|
|
@@ -714,13 +928,21 @@ function normalizeConfig(config) {
|
|
|
714
928
|
"google-gemini-flash-3.5",
|
|
715
929
|
].includes(normalized.model)
|
|
716
930
|
) {
|
|
717
|
-
normalized.model =
|
|
931
|
+
normalized.model = DEFAULT_MODEL_ID;
|
|
718
932
|
}
|
|
719
933
|
if (!MODELS[normalized.model]) {
|
|
720
|
-
normalized.model =
|
|
934
|
+
normalized.model = DEFAULT_MODEL_ID;
|
|
721
935
|
}
|
|
722
936
|
normalized.version = APP_VERSION;
|
|
723
|
-
|
|
937
|
+
const service = serviceById(normalized.serviceId) || serviceByOrigin(normalized.apiOrigin);
|
|
938
|
+
if (service) {
|
|
939
|
+
normalized.serviceId = service.id;
|
|
940
|
+
normalized.serviceLabel = service.label;
|
|
941
|
+
normalized.apiOrigin = service.apiOrigin;
|
|
942
|
+
} else {
|
|
943
|
+
normalized.apiOrigin = String(normalized.apiOrigin || API_ORIGIN).replace(/\/+$/, "");
|
|
944
|
+
normalized.serviceLabel = normalized.serviceLabel || serviceLabelForOrigin(normalized.apiOrigin);
|
|
945
|
+
}
|
|
724
946
|
return normalized;
|
|
725
947
|
}
|
|
726
948
|
|
|
@@ -749,6 +971,53 @@ function isCodexApiOrigin(origin) {
|
|
|
749
971
|
}
|
|
750
972
|
}
|
|
751
973
|
|
|
974
|
+
function serviceById(id) {
|
|
975
|
+
const normalized = String(id || "").trim().toLowerCase();
|
|
976
|
+
return SERVICE_CATALOG.find((service) => service.id === normalized) || null;
|
|
977
|
+
}
|
|
978
|
+
|
|
979
|
+
function serviceByOrigin(origin) {
|
|
980
|
+
const normalized = String(origin || "").trim().replace(/\/+$/, "").toLowerCase();
|
|
981
|
+
if (!normalized) {
|
|
982
|
+
return null;
|
|
983
|
+
}
|
|
984
|
+
return SERVICE_CATALOG.find((service) => service.apiOrigin.toLowerCase() === normalized) || null;
|
|
985
|
+
}
|
|
986
|
+
|
|
987
|
+
function serviceFromAnswer(answer) {
|
|
988
|
+
const normalized = String(answer || "").trim().toLowerCase();
|
|
989
|
+
const numbered = Number(normalized);
|
|
990
|
+
if (Number.isInteger(numbered) && numbered >= 1 && numbered <= SERVICE_CATALOG.length) {
|
|
991
|
+
return SERVICE_CATALOG[numbered - 1];
|
|
992
|
+
}
|
|
993
|
+
return SERVICE_CATALOG.find((service) => service.aliases.includes(normalized) || service.id === normalized) || null;
|
|
994
|
+
}
|
|
995
|
+
|
|
996
|
+
function dedupeServices(services) {
|
|
997
|
+
const seen = new Set();
|
|
998
|
+
const result = [];
|
|
999
|
+
for (const service of services) {
|
|
1000
|
+
if (!service || seen.has(service.id)) {
|
|
1001
|
+
continue;
|
|
1002
|
+
}
|
|
1003
|
+
seen.add(service.id);
|
|
1004
|
+
result.push(service);
|
|
1005
|
+
}
|
|
1006
|
+
return result;
|
|
1007
|
+
}
|
|
1008
|
+
|
|
1009
|
+
function serviceLabelForOrigin(origin) {
|
|
1010
|
+
const service = serviceByOrigin(origin);
|
|
1011
|
+
if (service) {
|
|
1012
|
+
return service.label;
|
|
1013
|
+
}
|
|
1014
|
+
try {
|
|
1015
|
+
return new URL(origin || API_ORIGIN).hostname;
|
|
1016
|
+
} catch {
|
|
1017
|
+
return "CodexAPI.pro";
|
|
1018
|
+
}
|
|
1019
|
+
}
|
|
1020
|
+
|
|
752
1021
|
function formatUsd(value) {
|
|
753
1022
|
return `$${Number(value || 0).toLocaleString("en-US", {
|
|
754
1023
|
minimumFractionDigits: 2,
|
package/codexclaude.md
CHANGED
|
@@ -1,137 +1,83 @@
|
|
|
1
1
|
# codexclaude Customization Ledger
|
|
2
2
|
|
|
3
|
-
This file
|
|
4
|
-
upgrade of the bundled coding runtime dependency. Treat it as the handoff
|
|
5
|
-
document for future maintainers. The launcher should remain a thin wrapper
|
|
6
|
-
around official `@openai/codex`; do not patch the native Codex binary unless
|
|
7
|
-
there is no supported configuration or API boundary that can solve the issue.
|
|
3
|
+
This file is the durable handoff for the `@codexapi/codexclaude` package in `/root/codexclaude`. Read it before updating the bundled coding runtime. The package is a managed launcher around the official runtime dependency, but customer-facing startup, update, model, auth, and setup behavior must stay under MagnetAPI control.
|
|
8
4
|
|
|
9
5
|
## Current Release
|
|
10
6
|
|
|
11
|
-
-
|
|
12
|
-
- Launcher version: `2.0.
|
|
13
|
-
- Customer-facing app name: `Magnetapi
|
|
14
|
-
- Bundled runtime dependency:
|
|
15
|
-
-
|
|
16
|
-
-
|
|
17
|
-
-
|
|
18
|
-
-
|
|
7
|
+
- Package name: `@codexapi/codexclaude`
|
|
8
|
+
- Launcher version: `2.0.18`
|
|
9
|
+
- Customer-facing app name: `Magnetapi Client`
|
|
10
|
+
- Bundled runtime dependency: `@openai/codex@0.144.1`
|
|
11
|
+
- Required install command: `npm install -g https://codexapi.pro/downloads/codexapi-codexclaude-2.0.18.tgz`
|
|
12
|
+
- Backend minimum version: `2.0.18`
|
|
13
|
+
- Default visible model: `Opus 4.8`
|
|
14
|
+
- Default model slug: `claude-opus-4-8`
|
|
15
|
+
- Visible reasoning effort: `xhigh`
|
|
16
|
+
- Local permissions: Full Access, implemented as `approval_policy = "never"` and `sandbox_mode = "danger-full-access"`
|
|
19
17
|
- Local launcher state: `~/.codexclaude/config.json`
|
|
20
|
-
- Generated
|
|
21
|
-
- Generated
|
|
18
|
+
- Generated runtime config: `~/.codex/config.toml`
|
|
19
|
+
- Generated model catalog: `~/.codexclaude/model_catalog.json`
|
|
20
|
+
- Upstream update cache removed before setup: `~/.codex/version.json`
|
|
22
21
|
|
|
23
|
-
|
|
22
|
+
## Required Customer Behavior
|
|
24
23
|
|
|
25
|
-
|
|
24
|
+
The launcher must present itself as:
|
|
26
25
|
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
- `claude-opus-4-8` displayed as `Opus 4.8`
|
|
31
|
-
- `claude-sonnet-5` displayed as `Sonnet 5`
|
|
32
|
-
- `claude-fable-5` displayed as `Fable 5`
|
|
33
|
-
|
|
34
|
-
The launcher command `codexclaude model` must list only those four options.
|
|
35
|
-
The native Codex `/model` picker must also list only those four options. This
|
|
36
|
-
is enforced by writing `model_catalog_json` in `~/.codex/config.toml` and
|
|
37
|
-
creating a complete Codex-compatible catalog at
|
|
38
|
-
`~/.codexclaude/model_catalog.json`.
|
|
39
|
-
|
|
40
|
-
Do not rely only on the wrapper prompt for model restrictions. Native Codex can
|
|
41
|
-
render its own model picker from model metadata. If the generated catalog is
|
|
42
|
-
removed, corrupted, or not referenced by `model_catalog_json`, Codex may fall
|
|
43
|
-
back to its bundled OpenAI model list or may warn that metadata for
|
|
44
|
-
`claude-opus-4-8` cannot be found.
|
|
45
|
-
|
|
46
|
-
## Opus 4.8 Metadata Warning Fix
|
|
26
|
+
```text
|
|
27
|
+
Magnetapi Client v2.0.18
|
|
28
|
+
```
|
|
47
29
|
|
|
48
|
-
|
|
30
|
+
Normal pre-launch status should look like:
|
|
49
31
|
|
|
50
32
|
```text
|
|
51
|
-
|
|
33
|
+
Magnetapi Client v2.0.18 · opus-4.8 xhigh · ~/project · Wallet $20.00
|
|
52
34
|
```
|
|
53
35
|
|
|
54
|
-
|
|
55
|
-
model metadata catalog. The fix is not to rename Opus to GPT-5.5 locally,
|
|
56
|
-
because the request body model is how CodexAPI.pro snapshots routing and
|
|
57
|
-
billing before generation starts. The correct fix is to provide valid metadata
|
|
58
|
-
for `claude-opus-4-8`.
|
|
59
|
-
|
|
60
|
-
`bin/codexclaude.js` writes a local catalog with full metadata for all six
|
|
61
|
-
supported slugs. Each entry must include, at minimum:
|
|
62
|
-
|
|
63
|
-
- `slug`
|
|
64
|
-
- `display_name`
|
|
65
|
-
- `description`
|
|
66
|
-
- `default_reasoning_level`
|
|
67
|
-
- `supported_reasoning_levels`
|
|
68
|
-
- `shell_type`
|
|
69
|
-
- `visibility`
|
|
70
|
-
- `supported_in_api`
|
|
71
|
-
- `priority`
|
|
72
|
-
- `base_instructions`
|
|
73
|
-
- `truncation_policy`
|
|
74
|
-
- `supports_parallel_tool_calls`
|
|
75
|
-
- `supports_image_detail_original`
|
|
76
|
-
- `input_modalities`
|
|
77
|
-
- `additional_speed_tiers`
|
|
78
|
-
|
|
79
|
-
Keep `visibility = "list"` for the four supported entries. Do not include any
|
|
80
|
-
other list-visible models in this catalog.
|
|
81
|
-
|
|
82
|
-
## Reasoning Display Versus Server Runtime
|
|
83
|
-
|
|
84
|
-
The user-facing Codex UI must show `xhigh` reasoning. The generated
|
|
85
|
-
`~/.codex/config.toml` therefore writes:
|
|
36
|
+
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.
|
|
86
37
|
|
|
87
|
-
|
|
88
|
-
model_reasoning_effort = "xhigh"
|
|
89
|
-
```
|
|
38
|
+
The launcher command `codexclaude model` must list exactly four customer-visible models:
|
|
90
39
|
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
40
|
+
- `gpt-5.5` displayed as `ChatGPT-5.5`
|
|
41
|
+
- `claude-opus-4-8` displayed as `Opus 4.8`
|
|
42
|
+
- `claude-sonnet-5` displayed as `Sonnet 5`
|
|
43
|
+
- `claude-fable-5` displayed as `Fable 5`
|
|
95
44
|
|
|
96
|
-
The
|
|
45
|
+
Opus 4.8 must be the default when a new config is created or a legacy config contains an unsupported Gemini/Deepseek value. The selected model slug must stay in `~/.codex/config.toml`; do not rewrite Opus, Sonnet, or Fable to GPT locally just because the backend may route internally.
|
|
97
46
|
|
|
98
|
-
|
|
99
|
-
- `SERVER_REASONING_EFFORT = "high"`
|
|
47
|
+
## Update Policy
|
|
100
48
|
|
|
101
|
-
|
|
49
|
+
`bin/codexclaude.js` may check:
|
|
102
50
|
|
|
103
|
-
|
|
51
|
+
- `https://codexapi.pro/api/v1/codexclaude/version`
|
|
52
|
+
- `https://registry.npmjs.org/@codexapi%2Fcodexclaude/latest`
|
|
104
53
|
|
|
105
|
-
|
|
106
|
-
Codex can show `/fast` as active when the user enables it. CodexAPI.pro treats
|
|
107
|
-
fast mode as a billing hint only. The backend must bill fast sessions at the
|
|
108
|
-
configured multiplier, currently `6x`, while stripping fast mode and service
|
|
109
|
-
tier controls before forwarding the request upstream.
|
|
54
|
+
It must not check `@openai/codex` npm metadata, OpenAI GitHub releases, or any upstream OpenAI update endpoint. Version `2.0.18` is a forced release: the backend `minimumVersion` equals `2.0.18`, and older clients must show an update-required message with the hosted tarball command.
|
|
110
55
|
|
|
111
|
-
|
|
112
|
-
user-controlled.
|
|
56
|
+
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.
|
|
113
57
|
|
|
114
58
|
## Generated Config Contract
|
|
115
59
|
|
|
116
|
-
`bin/codexclaude.js` must rewrite `~/.codex/config.toml` before every coding
|
|
117
|
-
session. Preserve this top-level shape:
|
|
60
|
+
`bin/codexclaude.js` must rewrite `~/.codex/config.toml` before every coding session. Preserve this top-level shape:
|
|
118
61
|
|
|
119
62
|
```toml
|
|
120
|
-
model = "
|
|
63
|
+
model = "claude-opus-4-8"
|
|
121
64
|
model_catalog_json = "<absolute path to ~/.codexclaude/model_catalog.json>"
|
|
122
65
|
preferred_auth_method = "apikey"
|
|
123
66
|
model_provider = "codexapi"
|
|
124
67
|
model_reasoning_effort = "xhigh"
|
|
68
|
+
check_for_update_on_startup = false
|
|
69
|
+
analytics_enabled = false
|
|
70
|
+
feedback_enabled = false
|
|
125
71
|
approval_policy = "never"
|
|
126
72
|
sandbox_mode = "danger-full-access"
|
|
127
73
|
|
|
128
74
|
[model_providers.codexapi]
|
|
129
|
-
name = "
|
|
130
|
-
base_url = "<
|
|
131
|
-
experimental_bearer_token = "<customer
|
|
75
|
+
name = "<logged-in service label>"
|
|
76
|
+
base_url = "<service Responses URL>"
|
|
77
|
+
experimental_bearer_token = "<customer System Token/API username>"
|
|
132
78
|
wire_api = "responses"
|
|
133
79
|
supports_websockets = false
|
|
134
|
-
http_headers = { "X-CodexAPI-Client" = "codexclaude", "X-CodexAPI-Client-Version" = "
|
|
80
|
+
http_headers = { "X-CodexAPI-Client" = "codexclaude", "X-CodexAPI-Client-Version" = "2.0.18", "X-CodexAPI-Selected-Model" = "<selected model>" }
|
|
135
81
|
|
|
136
82
|
[tui]
|
|
137
83
|
status_line = ["model-with-reasoning", "fast-mode", "current-dir"]
|
|
@@ -139,184 +85,115 @@ status_line_use_colors = true
|
|
|
139
85
|
terminal_title = ["project-name", "model-with-reasoning", "run-state"]
|
|
140
86
|
```
|
|
141
87
|
|
|
142
|
-
The
|
|
143
|
-
config model to `gpt-5.5` when Opus, Sonnet, or Fable is selected. The backend can
|
|
144
|
-
route any selected model through GPT-5.5 or another upstream internally, but the
|
|
145
|
-
client request must preserve the user-facing selected slug for display,
|
|
146
|
-
snapshotting, and billing records.
|
|
147
|
-
|
|
148
|
-
## Routing Rules
|
|
149
|
-
|
|
150
|
-
`gpt-5.5` uses the configured API origin, normally `https://codexapi.pro/v1`.
|
|
151
|
-
|
|
152
|
-
Claude-family codexclaude models use the CodexAPI.pro Claude-compatible Responses endpoint for CodexAPI.pro and ChatPlus accounts. MyAPI.world accounts keep their own configured `api.myapi.world` Responses endpoint.
|
|
153
|
-
|
|
154
|
-
`claude-fable-5` is a premium customer-visible model. The backend bills it at the configured 2x multiplier and routes it through the Admin-selected Fable 5 route while preserving `claude-fable-5` in client-visible status and usage records.
|
|
155
|
-
|
|
156
|
-
The launcher must send these headers for every model:
|
|
88
|
+
The generated model catalog must contain full metadata for the four supported slugs. This prevents fallback metadata warnings such as:
|
|
157
89
|
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
The backend uses these headers to enforce plan restrictions and to serve the
|
|
163
|
-
codexclaude-specific model catalog from `/v1/models` if native Codex refreshes
|
|
164
|
-
remote metadata.
|
|
165
|
-
|
|
166
|
-
## Authentication And Wallet
|
|
90
|
+
```text
|
|
91
|
+
Model metadata for `claude-opus-4-8` not found. Defaulting to fallback metadata; this can degrade performance and cause issues.
|
|
92
|
+
```
|
|
167
93
|
|
|
168
|
-
|
|
94
|
+
Each model catalog entry must include a slug, display name, reasoning levels including `xhigh`, shell tool type, input modalities including images, web/search support, truncation policy, and `visibility = "list"`.
|
|
169
95
|
|
|
170
|
-
|
|
171
|
-
codexclaude login
|
|
172
|
-
```
|
|
96
|
+
## Service Login
|
|
173
97
|
|
|
174
|
-
The
|
|
98
|
+
The login prompt must ask for:
|
|
175
99
|
|
|
176
100
|
```text
|
|
177
|
-
|
|
101
|
+
Dashboard Username or Email Address:
|
|
178
102
|
```
|
|
179
103
|
|
|
180
|
-
The
|
|
181
|
-
as `experimental_bearer_token` in `~/.codex/config.toml`. Preserve this
|
|
182
|
-
behavior unless the backend auth contract is deliberately changed. The launcher
|
|
183
|
-
must not ask customers for a separate OpenAI key.
|
|
104
|
+
The launcher supports CodexAPI.pro, ChatPlus.chat, MyAPI.world, and MagnetAPI.org. It can auto-detect by trying the supported dashboard auth endpoints. It saves `serviceId`, `serviceLabel`, `apiOrigin`, `username`, optional `dashboardEmail`, selected `model`, and `loggedInAt` in `~/.codexclaude/config.json`.
|
|
184
105
|
|
|
185
|
-
|
|
106
|
+
The saved `username` is the System Token/API username returned by the service and is used as the bearer value. Do not store dashboard session tokens in the launcher config.
|
|
186
107
|
|
|
187
|
-
|
|
188
|
-
/api/v1/wallet/status
|
|
189
|
-
```
|
|
108
|
+
## Routing Expectations
|
|
190
109
|
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
```text
|
|
194
|
-
/api/v1/me
|
|
195
|
-
```
|
|
110
|
+
The launcher is not the source of truth for upstream runtime routing. Admin Manage Models controls execution routing server-side. The launcher must preserve the user-selected model slug and pass it through the Responses request so billing, logs, and the dashboard can record what the user chose.
|
|
196
111
|
|
|
197
|
-
|
|
112
|
+
CodexAPI.pro and ChatPlus Claude-family models use the CodexAPI.pro Claude-compatible Responses endpoint. MyAPI.world and MagnetAPI.org accounts keep their own API origins. Fable 5 remains visible as `claude-fable-5` while the backend applies the premium model behavior and billing.
|
|
198
113
|
|
|
199
114
|
## Upgrade Checklist
|
|
200
115
|
|
|
201
|
-
When
|
|
202
|
-
|
|
203
|
-
1.
|
|
204
|
-
2.
|
|
205
|
-
3.
|
|
206
|
-
4.
|
|
207
|
-
5. Preserve `
|
|
208
|
-
6. Preserve `
|
|
209
|
-
7. Preserve
|
|
210
|
-
8. Preserve
|
|
211
|
-
9. Preserve
|
|
212
|
-
10. Preserve
|
|
213
|
-
11. Preserve
|
|
214
|
-
12.
|
|
215
|
-
13. Update
|
|
216
|
-
14.
|
|
116
|
+
When updating the bundled runtime dependency:
|
|
117
|
+
|
|
118
|
+
1. Confirm the intended upstream package version with `npm view @openai/codex version`.
|
|
119
|
+
2. Run `npm install @openai/codex@<version> --save-exact`.
|
|
120
|
+
3. Bump `package.json` and `package-lock.json` to a new `@codexapi/codexclaude` version.
|
|
121
|
+
4. Update `APP_VERSION` and `CODEX_VERSION` in `bin/codexclaude.js`.
|
|
122
|
+
5. Preserve `APP_DISPLAY_NAME = "Magnetapi Client"`.
|
|
123
|
+
6. Preserve `DEFAULT_MODEL_ID = "claude-opus-4-8"`.
|
|
124
|
+
7. Preserve `DISPLAY_REASONING_EFFORT = "xhigh"` and `SERVER_REASONING_EFFORT = "xhigh"` unless operations explicitly changes the launcher-visible contract.
|
|
125
|
+
8. Preserve Full Access defaults and the local model catalog.
|
|
126
|
+
9. Preserve direct platform-native binary launch.
|
|
127
|
+
10. Preserve update checks through our version endpoint and `@codexapi/codexclaude` npm metadata only.
|
|
128
|
+
11. Preserve deletion of `~/.codex/version.json` and `check_for_update_on_startup = false`.
|
|
129
|
+
12. Update customer setup scripts on CodexAPI.pro, ChatPlus.chat, MyAPI.world, MagnetAPI.org, and VIP pages to use the exact hosted tarball command.
|
|
130
|
+
13. Update backend `CODEXCLAUDE_LATEST_VERSION`, `CODEXCLAUDE_MIN_VERSION`, and hosted tarball URL.
|
|
131
|
+
14. Update this file, `README.md`, and `CUSTOMIZATIONS.md`.
|
|
132
|
+
15. Run validation and publish.
|
|
217
133
|
|
|
218
134
|
## Validation Commands
|
|
219
135
|
|
|
220
|
-
Run
|
|
136
|
+
Run from `/root/codexclaude`:
|
|
221
137
|
|
|
222
138
|
```bash
|
|
223
139
|
node --check bin/codexclaude.js
|
|
140
|
+
npm pack --dry-run
|
|
224
141
|
```
|
|
225
142
|
|
|
226
|
-
|
|
227
|
-
model catalog entries without making a model call:
|
|
143
|
+
Temporary-home config validation:
|
|
228
144
|
|
|
229
145
|
```bash
|
|
230
146
|
tmp_home="$(mktemp -d)"
|
|
231
|
-
|
|
147
|
+
mkdir -p "$tmp_home/.codexclaude"
|
|
148
|
+
cat > "$tmp_home/.codexclaude/config.json" <<'JSON'
|
|
149
|
+
{
|
|
150
|
+
"version": "2.0.18",
|
|
151
|
+
"serviceId": "codexapi",
|
|
152
|
+
"serviceLabel": "CodexAPI.pro",
|
|
153
|
+
"apiOrigin": "https://codexapi.pro",
|
|
154
|
+
"username": "test-token",
|
|
155
|
+
"dashboardEmail": null,
|
|
156
|
+
"model": "claude-opus-4-8",
|
|
157
|
+
"loggedInAt": "2026-07-10T00:00:00.000Z"
|
|
158
|
+
}
|
|
159
|
+
JSON
|
|
160
|
+
HOME="$tmp_home" CODEXCLAUDE_DISABLE_UPDATE_CHECK=1 CODEXCLAUDE_QUIET_STATUS=1 node bin/codexclaude.js setup
|
|
232
161
|
```
|
|
233
162
|
|
|
234
|
-
|
|
163
|
+
Verify the generated config contains:
|
|
235
164
|
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
165
|
+
- `model = "claude-opus-4-8"`
|
|
166
|
+
- `model_reasoning_effort = "xhigh"`
|
|
167
|
+
- `check_for_update_on_startup = false`
|
|
168
|
+
- `approval_policy = "never"`
|
|
169
|
+
- `sandbox_mode = "danger-full-access"`
|
|
170
|
+
- no default fast service tier
|
|
239
171
|
|
|
240
|
-
|
|
172
|
+
Verify the generated model catalog contains only:
|
|
241
173
|
|
|
242
174
|
- `gpt-5.5`
|
|
243
175
|
- `claude-opus-4-8`
|
|
244
176
|
- `claude-sonnet-5`
|
|
245
177
|
- `claude-fable-5`
|
|
246
178
|
|
|
247
|
-
|
|
248
|
-
fallback metadata.
|
|
249
|
-
|
|
250
|
-
Package validation:
|
|
179
|
+
After packaging, copy the tarball to the public downloads directories, restart the backend, and verify:
|
|
251
180
|
|
|
252
181
|
```bash
|
|
253
|
-
|
|
254
|
-
|
|
182
|
+
curl -fsS "https://codexapi.pro/api/v1/codexclaude/version?current=2.0.17"
|
|
183
|
+
curl -fsSI "https://codexapi.pro/downloads/codexapi-codexclaude-2.0.18.tgz"
|
|
255
184
|
```
|
|
256
185
|
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
```bash
|
|
260
|
-
python3 -m py_compile app/main.py app/openai_compat.py app/config.py app/postgres_admin.py
|
|
261
|
-
/root/codexapi/.venv/bin/pytest -q tests/test_openai_compat.py tests/test_main_helpers.py
|
|
262
|
-
```
|
|
263
|
-
|
|
264
|
-
## Version 2.0.15 Changes
|
|
265
|
-
|
|
266
|
-
- Renamed the launcher-controlled startup/status surface to Magnetapi.org Coding Agent and now prints the app version instead of the upstream runtime version.
|
|
267
|
-
- Removed Gemini Flash and Deepseek from the launcher model picker and generated native Codex model catalog.
|
|
268
|
-
- Kept ChatGPT-5.5, Opus 4.8, Sonnet 5, and Fable 5 as the only visible codexclaude model choices.
|
|
269
|
-
- Preserved Full Access defaults, xhigh visible reasoning, wallet auth, local model catalog metadata, and CodexAPI.pro identifying headers.
|
|
270
|
-
|
|
271
|
-
## Version 2.0.14 Changes
|
|
272
|
-
|
|
273
|
-
- Updated the official OpenAI Codex runtime dependency to `@openai/codex@0.142.5`, the latest version currently published on npm.
|
|
274
|
-
- Kept `claude-sonnet-5` and `claude-fable-5` as the live API slugs for Sonnet 5 and Fable 5 after verifying those names from the production model APIs.
|
|
275
|
-
- Removed the standalone `codexclaude status` and `codexclaude usage` launcher commands while preserving the compact wallet status line printed before a coding session starts.
|
|
276
|
-
- Preserved Full Access defaults, xhigh visible reasoning, server-managed high runtime effort, bearer username auth, local model catalog metadata, and CodexAPI.pro identifying headers.
|
|
277
|
-
|
|
278
|
-
## Version 2.0.13 Changes
|
|
279
|
-
|
|
280
|
-
- Updated the official OpenAI Codex runtime dependency to `@openai/codex@0.142.2`.
|
|
281
|
-
- Added Sonnet 5 and Fable 5 as visible launcher and native Codex `/model` choices.
|
|
282
|
-
- Added `codexclaude usage`, which reads wallet and recent token usage from the signed-in account origin, including CodexAPI.pro, ChatPlus, or MyAPI.world compatible endpoints.
|
|
283
|
-
- Kept Fable 5 customer-visible while the backend applies its custom routed premium path and 2x billing multiplier.
|
|
284
|
-
- Preserved Full Access defaults, xhigh visible reasoning, server-managed high runtime effort, wallet auth, and local model catalog metadata.
|
|
285
|
-
|
|
286
|
-
## Version 2.0.12 Changes
|
|
287
|
-
|
|
288
|
-
- Updated the official OpenAI Codex runtime dependency to `@openai/codex@0.141.0`.
|
|
289
|
-
- Added Google Gemini Flash 3.5 as a fourth visible launcher and native Codex `/model` choice.
|
|
290
|
-
- Kept Gemini visible in client config, response metadata, and usage records while the backend routes it through Sonnet 5 low effort.
|
|
291
|
-
- Preserved the CodexAPI.pro launcher layer, Full Access defaults, xhigh visible reasoning, server-managed low runtime effort, wallet auth, and Opus 4.8 Chicago routing.
|
|
292
|
-
|
|
293
|
-
## Version 2.0.11 Changes
|
|
294
|
-
|
|
295
|
-
- Updated the official OpenAI Codex runtime dependency to `@openai/codex@0.140.0`.
|
|
296
|
-
- Re-applied the CodexAPI.pro launcher layer without changing the supported model list, local model catalog, Full Access defaults, xhigh visible reasoning, server-managed low runtime effort, fast-mode billing contract, wallet auth, or Opus 4.8 Chicago routing.
|
|
297
|
-
|
|
298
|
-
## Version 2.0.10 Changes
|
|
299
|
-
|
|
300
|
-
- Added a generated local model catalog for native Codex.
|
|
301
|
-
- Limited native Codex `/model` to ChatGPT-5.5, Opus 4.8, and Deepseek v4 Budget.
|
|
302
|
-
- Added valid metadata for `claude-opus-4-8` and `deepseek-v4-pro`.
|
|
303
|
-
- Changed the user-visible reasoning effort from `low` to `xhigh`.
|
|
304
|
-
- Kept server-side upstream reasoning pinned to `low`.
|
|
305
|
-
- Kept `/fast` client-visible by advertising the `fast` speed tier locally while relying on the backend to bill and strip it upstream.
|
|
306
|
-
|
|
307
|
-
## Older Release Notes
|
|
308
|
-
|
|
309
|
-
Version 2.0.9 updated the official Codex runtime dependency to
|
|
310
|
-
`@openai/codex@0.139.0` and re-applied the CodexAPI.pro launcher layer.
|
|
311
|
-
|
|
312
|
-
Version 2.0.8 kept official Codex on `0.137.0`, changed generated config to low
|
|
313
|
-
reasoning, and removed default fast service tier.
|
|
314
|
-
|
|
315
|
-
Version 2.0.7 updated official Codex to `0.137.0`.
|
|
316
|
-
|
|
317
|
-
Version 2.0.6 updated official Codex to `0.135.0`, migrated Opus 4.7 aliases to
|
|
318
|
-
Opus 4.8, and pinned Opus 4.8 codexclaude sessions to Chicago.
|
|
186
|
+
The version endpoint must report `latestVersion = 2.0.18`, `minimumVersion = 2.0.18`, and `updateRequired = true` for old clients.
|
|
319
187
|
|
|
320
|
-
Version 2.0.
|
|
188
|
+
## Version 2.0.18 Changes
|
|
321
189
|
|
|
322
|
-
|
|
190
|
+
- Updated bundled runtime dependency to `@openai/codex@0.144.1`.
|
|
191
|
+
- Forced all older codexclaude clients to update by setting backend minimum version to `2.0.18`.
|
|
192
|
+
- Changed launcher-owned identity to `Magnetapi Client`.
|
|
193
|
+
- Changed the default selected model to Opus 4.8.
|
|
194
|
+
- Kept visible reasoning at xhigh.
|
|
195
|
+
- Preserved Full Access defaults.
|
|
196
|
+
- Disabled bundled runtime update checks through generated config and stale update-cache removal.
|
|
197
|
+
- Removed launcher fallback to the upstream npm wrapper so OpenAI update prompts are not emitted by codexclaude.
|
|
198
|
+
- Kept update monitoring limited to CodexAPI.pro version metadata and the `@codexapi/codexclaude` npm package.
|
|
199
|
+
- Updated setup scripts to install the exact hosted `2.0.18` tarball.
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@codexapi/codexclaude",
|
|
3
|
-
"version": "2.0.
|
|
4
|
-
"description": "Magnetapi
|
|
3
|
+
"version": "2.0.18",
|
|
4
|
+
"description": "Magnetapi Client launcher for ChatGPT-5.5, Opus 4.8, Sonnet 5, and Fable 5.",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"type": "module",
|
|
7
7
|
"bin": {
|
|
@@ -17,7 +17,7 @@
|
|
|
17
17
|
"node": ">=20"
|
|
18
18
|
},
|
|
19
19
|
"dependencies": {
|
|
20
|
-
"@openai/codex": "
|
|
20
|
+
"@openai/codex": "0.144.1"
|
|
21
21
|
},
|
|
22
22
|
"publishConfig": {
|
|
23
23
|
"access": "public"
|