codexapp 0.1.47 → 0.1.48

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/dist/index.html CHANGED
@@ -4,8 +4,8 @@
4
4
  <meta charset="UTF-8" />
5
5
  <meta name="viewport" content="width=device-width, initial-scale=1.0" />
6
6
  <title>Codex Web Local</title>
7
- <script type="module" crossorigin src="/assets/index-dkC99kKB.js"></script>
8
- <link rel="stylesheet" crossorigin href="/assets/index-DGYijDgu.css">
7
+ <script type="module" crossorigin src="/assets/index-DhcIXLYw.js"></script>
8
+ <link rel="stylesheet" crossorigin href="/assets/index-C55jtDWV.css">
9
9
  </head>
10
10
  <body class="bg-slate-950">
11
11
  <div id="app"></div>
package/dist-cli/index.js CHANGED
@@ -2,11 +2,11 @@
2
2
 
3
3
  // src/cli/index.ts
4
4
  import { createServer as createServer2 } from "http";
5
- import { chmodSync, createWriteStream, existsSync as existsSync4, mkdirSync } from "fs";
5
+ import { chmodSync, createWriteStream, existsSync as existsSync5, mkdirSync } from "fs";
6
6
  import { readFile as readFile4, stat as stat5, writeFile as writeFile4 } from "fs/promises";
7
- import { homedir as homedir3, networkInterfaces } from "os";
8
- import { isAbsolute as isAbsolute3, join as join5, resolve as resolve2 } from "path";
9
- import { spawn as spawn3, spawnSync } from "child_process";
7
+ import { homedir as homedir4, networkInterfaces } from "os";
8
+ import { isAbsolute as isAbsolute3, join as join6, resolve as resolve2 } from "path";
9
+ import { spawn as spawn3 } from "child_process";
10
10
  import { createInterface as createInterface2 } from "readline/promises";
11
11
  import { fileURLToPath as fileURLToPath2 } from "url";
12
12
  import { dirname as dirname3 } from "path";
@@ -16,8 +16,8 @@ import qrcode from "qrcode-terminal";
16
16
 
17
17
  // src/server/httpServer.ts
18
18
  import { fileURLToPath } from "url";
19
- import { dirname as dirname2, extname as extname2, isAbsolute as isAbsolute2, join as join4 } from "path";
20
- import { existsSync as existsSync3 } from "fs";
19
+ import { dirname as dirname2, extname as extname3, isAbsolute as isAbsolute2, join as join5 } from "path";
20
+ import { existsSync as existsSync4 } from "fs";
21
21
  import { writeFile as writeFile3, stat as stat4 } from "fs/promises";
22
22
  import express from "express";
23
23
 
@@ -28,9 +28,9 @@ import { mkdtemp as mkdtemp2, readFile as readFile2, mkdir as mkdir2, stat as st
28
28
  import { createReadStream } from "fs";
29
29
  import { request as httpRequest } from "http";
30
30
  import { request as httpsRequest } from "https";
31
- import { homedir as homedir2 } from "os";
31
+ import { homedir as homedir3 } from "os";
32
32
  import { tmpdir as tmpdir2 } from "os";
33
- import { basename, isAbsolute, join as join2, resolve } from "path";
33
+ import { basename as basename2, isAbsolute, join as join3, resolve } from "path";
34
34
  import { createInterface } from "readline";
35
35
  import { writeFile as writeFile2 } from "fs/promises";
36
36
 
@@ -1120,6 +1120,84 @@ async function handleSkillsRoutes(req, res, url, context) {
1120
1120
  return false;
1121
1121
  }
1122
1122
 
1123
+ // src/utils/commandInvocation.ts
1124
+ import { spawnSync } from "child_process";
1125
+ import { existsSync as existsSync2 } from "fs";
1126
+ import { homedir as homedir2 } from "os";
1127
+ import { basename, extname, join as join2 } from "path";
1128
+ var WINDOWS_CMD_NAMES = /* @__PURE__ */ new Set(["codex", "npm", "npx"]);
1129
+ function quoteCmdExeArg(value) {
1130
+ const normalized = value.replace(/"/g, '""');
1131
+ if (!/[\s"]/u.test(normalized)) {
1132
+ return normalized;
1133
+ }
1134
+ return `"${normalized}"`;
1135
+ }
1136
+ function needsCmdExeWrapper(command) {
1137
+ if (process.platform !== "win32") {
1138
+ return false;
1139
+ }
1140
+ const lowerCommand = command.toLowerCase();
1141
+ const baseName = basename(lowerCommand);
1142
+ if (/\.(cmd|bat)$/i.test(baseName)) {
1143
+ return true;
1144
+ }
1145
+ if (extname(baseName)) {
1146
+ return false;
1147
+ }
1148
+ return WINDOWS_CMD_NAMES.has(baseName);
1149
+ }
1150
+ function getSpawnInvocation(command, args = []) {
1151
+ if (needsCmdExeWrapper(command)) {
1152
+ return {
1153
+ command: "cmd.exe",
1154
+ args: ["/d", "/s", "/c", [quoteCmdExeArg(command), ...args.map((arg) => quoteCmdExeArg(arg))].join(" ")]
1155
+ };
1156
+ }
1157
+ return { command, args };
1158
+ }
1159
+ function spawnSyncCommand(command, args = [], options = {}) {
1160
+ const invocation = getSpawnInvocation(command, args);
1161
+ return spawnSync(invocation.command, invocation.args, options);
1162
+ }
1163
+ function canRunCommand(command, args = []) {
1164
+ const result = spawnSyncCommand(command, args, { stdio: "ignore" });
1165
+ return result.status === 0;
1166
+ }
1167
+ function getUserNpmPrefix() {
1168
+ return join2(homedir2(), ".npm-global");
1169
+ }
1170
+ function resolveCodexCommand() {
1171
+ if (canRunCommand("codex", ["--version"])) {
1172
+ return "codex";
1173
+ }
1174
+ if (process.platform === "win32") {
1175
+ const windowsCandidates = [
1176
+ process.env.APPDATA ? join2(process.env.APPDATA, "npm", "codex.cmd") : "",
1177
+ join2(homedir2(), ".local", "bin", "codex.cmd"),
1178
+ join2(getUserNpmPrefix(), "bin", "codex.cmd")
1179
+ ].filter(Boolean);
1180
+ for (const candidate2 of windowsCandidates) {
1181
+ if (existsSync2(candidate2) && canRunCommand(candidate2, ["--version"])) {
1182
+ return candidate2;
1183
+ }
1184
+ }
1185
+ }
1186
+ const userCandidate = join2(getUserNpmPrefix(), "bin", "codex");
1187
+ if (existsSync2(userCandidate) && canRunCommand(userCandidate, ["--version"])) {
1188
+ return userCandidate;
1189
+ }
1190
+ const prefix = process.env.PREFIX?.trim();
1191
+ if (!prefix) {
1192
+ return null;
1193
+ }
1194
+ const candidate = join2(prefix, "bin", "codex");
1195
+ if (existsSync2(candidate) && canRunCommand(candidate, ["--version"])) {
1196
+ return candidate;
1197
+ }
1198
+ return null;
1199
+ }
1200
+
1123
1201
  // src/server/codexAppServerBridge.ts
1124
1202
  function asRecord2(value) {
1125
1203
  return value !== null && typeof value === "object" && !Array.isArray(value) ? value : null;
@@ -1224,7 +1302,7 @@ async function listFilesWithRipgrep(cwd) {
1224
1302
  }
1225
1303
  function getCodexHomeDir2() {
1226
1304
  const codexHome = process.env.CODEX_HOME?.trim();
1227
- return codexHome && codexHome.length > 0 ? codexHome : join2(homedir2(), ".codex");
1305
+ return codexHome && codexHome.length > 0 ? codexHome : join3(homedir3(), ".codex");
1228
1306
  }
1229
1307
  async function runCommand2(command, args, options = {}) {
1230
1308
  await new Promise((resolve3, reject) => {
@@ -1262,7 +1340,7 @@ function isNotGitRepositoryError(error) {
1262
1340
  return message.includes("not a git repository") || message.includes("fatal: not a git repository");
1263
1341
  }
1264
1342
  async function ensureRepoHasInitialCommit(repoRoot) {
1265
- const agentsPath = join2(repoRoot, "AGENTS.md");
1343
+ const agentsPath = join3(repoRoot, "AGENTS.md");
1266
1344
  try {
1267
1345
  await stat2(agentsPath);
1268
1346
  } catch {
@@ -1323,7 +1401,7 @@ function normalizeStringRecord(value) {
1323
1401
  return next;
1324
1402
  }
1325
1403
  function getCodexAuthPath() {
1326
- return join2(getCodexHomeDir2(), "auth.json");
1404
+ return join3(getCodexHomeDir2(), "auth.json");
1327
1405
  }
1328
1406
  async function readCodexAuth() {
1329
1407
  try {
@@ -1337,10 +1415,10 @@ async function readCodexAuth() {
1337
1415
  }
1338
1416
  }
1339
1417
  function getCodexGlobalStatePath() {
1340
- return join2(getCodexHomeDir2(), ".codex-global-state.json");
1418
+ return join3(getCodexHomeDir2(), ".codex-global-state.json");
1341
1419
  }
1342
1420
  function getCodexSessionIndexPath() {
1343
- return join2(getCodexHomeDir2(), "session_index.jsonl");
1421
+ return join3(getCodexHomeDir2(), "session_index.jsonl");
1344
1422
  }
1345
1423
  var MAX_THREAD_TITLES = 500;
1346
1424
  var EMPTY_THREAD_TITLE_CACHE = { titles: {}, order: [] };
@@ -1599,10 +1677,10 @@ function handleFileUpload(req, res) {
1599
1677
  setJson2(res, 400, { error: "No file in request" });
1600
1678
  return;
1601
1679
  }
1602
- const uploadDir = join2(tmpdir2(), "codex-web-uploads");
1680
+ const uploadDir = join3(tmpdir2(), "codex-web-uploads");
1603
1681
  await mkdir2(uploadDir, { recursive: true });
1604
- const destDir = await mkdtemp2(join2(uploadDir, "f-"));
1605
- const destPath = join2(destDir, fileName);
1682
+ const destDir = await mkdtemp2(join3(uploadDir, "f-"));
1683
+ const destPath = join3(destDir, fileName);
1606
1684
  await writeFile2(destPath, fileData);
1607
1685
  setJson2(res, 200, { path: destPath });
1608
1686
  } catch (err) {
@@ -1709,7 +1787,8 @@ var AppServerProcess = class {
1709
1787
  start() {
1710
1788
  if (this.process) return;
1711
1789
  this.stopping = false;
1712
- const proc = spawn2("codex", this.appServerArgs, { stdio: ["pipe", "pipe", "pipe"] });
1790
+ const invocation = getSpawnInvocation(resolveCodexCommand() ?? "codex", this.appServerArgs);
1791
+ const proc = spawn2(invocation.command, invocation.args, { stdio: ["pipe", "pipe", "pipe"] });
1713
1792
  this.process = proc;
1714
1793
  proc.stdout.setEncoding("utf8");
1715
1794
  proc.stdout.on("data", (chunk) => {
@@ -1935,7 +2014,8 @@ var MethodCatalog = class {
1935
2014
  }
1936
2015
  async runGenerateSchemaCommand(outDir) {
1937
2016
  await new Promise((resolve3, reject) => {
1938
- const process2 = spawn2("codex", ["app-server", "generate-json-schema", "--out", outDir], {
2017
+ const invocation = getSpawnInvocation(resolveCodexCommand() ?? "codex", ["app-server", "generate-json-schema", "--out", outDir]);
2018
+ const process2 = spawn2(invocation.command, invocation.args, {
1939
2019
  stdio: ["ignore", "ignore", "pipe"]
1940
2020
  });
1941
2021
  let stderr = "";
@@ -1991,9 +2071,9 @@ var MethodCatalog = class {
1991
2071
  if (this.methodCache) {
1992
2072
  return this.methodCache;
1993
2073
  }
1994
- const outDir = await mkdtemp2(join2(tmpdir2(), "codex-web-local-schema-"));
2074
+ const outDir = await mkdtemp2(join3(tmpdir2(), "codex-web-local-schema-"));
1995
2075
  await this.runGenerateSchemaCommand(outDir);
1996
- const clientRequestPath = join2(outDir, "ClientRequest.json");
2076
+ const clientRequestPath = join3(outDir, "ClientRequest.json");
1997
2077
  const raw = await readFile2(clientRequestPath, "utf8");
1998
2078
  const parsed = JSON.parse(raw);
1999
2079
  const methods = this.extractMethodsFromClientRequest(parsed);
@@ -2004,9 +2084,9 @@ var MethodCatalog = class {
2004
2084
  if (this.notificationCache) {
2005
2085
  return this.notificationCache;
2006
2086
  }
2007
- const outDir = await mkdtemp2(join2(tmpdir2(), "codex-web-local-schema-"));
2087
+ const outDir = await mkdtemp2(join3(tmpdir2(), "codex-web-local-schema-"));
2008
2088
  await this.runGenerateSchemaCommand(outDir);
2009
- const serverNotificationPath = join2(outDir, "ServerNotification.json");
2089
+ const serverNotificationPath = join3(outDir, "ServerNotification.json");
2010
2090
  const raw = await readFile2(serverNotificationPath, "utf8");
2011
2091
  const parsed = JSON.parse(raw);
2012
2092
  const methods = this.extractMethodsFromServerNotification(parsed);
@@ -2168,7 +2248,7 @@ function createCodexBridgeMiddleware() {
2168
2248
  return;
2169
2249
  }
2170
2250
  if (req.method === "GET" && url.pathname === "/codex-api/home-directory") {
2171
- setJson2(res, 200, { data: { path: homedir2() } });
2251
+ setJson2(res, 200, { data: { path: homedir3() } });
2172
2252
  return;
2173
2253
  }
2174
2254
  if (req.method === "POST" && url.pathname === "/codex-api/worktree/create") {
@@ -2198,22 +2278,22 @@ function createCodexBridgeMiddleware() {
2198
2278
  await runCommand2("git", ["init"], { cwd: sourceCwd });
2199
2279
  gitRoot = await runCommandCapture("git", ["rev-parse", "--show-toplevel"], { cwd: sourceCwd });
2200
2280
  }
2201
- const repoName = basename(gitRoot) || "repo";
2202
- const worktreesRoot = join2(getCodexHomeDir2(), "worktrees");
2281
+ const repoName = basename2(gitRoot) || "repo";
2282
+ const worktreesRoot = join3(getCodexHomeDir2(), "worktrees");
2203
2283
  await mkdir2(worktreesRoot, { recursive: true });
2204
2284
  let worktreeId = "";
2205
2285
  let worktreeParent = "";
2206
2286
  let worktreeCwd = "";
2207
2287
  for (let attempt = 0; attempt < 12; attempt += 1) {
2208
2288
  const candidate = randomBytes(2).toString("hex");
2209
- const parent = join2(worktreesRoot, candidate);
2289
+ const parent = join3(worktreesRoot, candidate);
2210
2290
  try {
2211
2291
  await stat2(parent);
2212
2292
  continue;
2213
2293
  } catch {
2214
2294
  worktreeId = candidate;
2215
2295
  worktreeParent = parent;
2216
- worktreeCwd = join2(parent, repoName);
2296
+ worktreeCwd = join3(parent, repoName);
2217
2297
  break;
2218
2298
  }
2219
2299
  }
@@ -2318,7 +2398,7 @@ function createCodexBridgeMiddleware() {
2318
2398
  let index = 1;
2319
2399
  while (index < 1e5) {
2320
2400
  const candidateName = `New Project (${String(index)})`;
2321
- const candidatePath = join2(normalizedBasePath, candidateName);
2401
+ const candidatePath = join3(normalizedBasePath, candidateName);
2322
2402
  try {
2323
2403
  await stat2(candidatePath);
2324
2404
  index += 1;
@@ -2564,7 +2644,7 @@ function createAuthSession(password) {
2564
2644
  }
2565
2645
 
2566
2646
  // src/server/localBrowseUi.ts
2567
- import { dirname, extname, join as join3 } from "path";
2647
+ import { dirname, extname as extname2, join as join4 } from "path";
2568
2648
  import { open, readFile as readFile3, readdir as readdir3, stat as stat3 } from "fs/promises";
2569
2649
  var TEXT_EDITABLE_EXTENSIONS = /* @__PURE__ */ new Set([
2570
2650
  ".txt",
@@ -2595,7 +2675,7 @@ var TEXT_EDITABLE_EXTENSIONS = /* @__PURE__ */ new Set([
2595
2675
  ".ps1"
2596
2676
  ]);
2597
2677
  function languageForPath(pathValue) {
2598
- const extension = extname(pathValue).toLowerCase();
2678
+ const extension = extname2(pathValue).toLowerCase();
2599
2679
  switch (extension) {
2600
2680
  case ".js":
2601
2681
  return "javascript";
@@ -2656,7 +2736,7 @@ function decodeBrowsePath(rawPath) {
2656
2736
  }
2657
2737
  }
2658
2738
  function isTextEditablePath(pathValue) {
2659
- return TEXT_EDITABLE_EXTENSIONS.has(extname(pathValue).toLowerCase());
2739
+ return TEXT_EDITABLE_EXTENSIONS.has(extname2(pathValue).toLowerCase());
2660
2740
  }
2661
2741
  function looksLikeTextBuffer(buffer) {
2662
2742
  if (buffer.length === 0) return true;
@@ -2702,7 +2782,7 @@ function escapeForInlineScriptString(value) {
2702
2782
  async function getDirectoryItems(localPath) {
2703
2783
  const entries = await readdir3(localPath, { withFileTypes: true });
2704
2784
  const withMeta = await Promise.all(entries.map(async (entry) => {
2705
- const entryPath = join3(localPath, entry.name);
2785
+ const entryPath = join4(localPath, entry.name);
2706
2786
  const entryStat = await stat3(entryPath);
2707
2787
  const editable = !entry.isDirectory() && await isTextEditableFile(entryPath);
2708
2788
  return {
@@ -2889,8 +2969,8 @@ async function createTextEditorHtml(localPath) {
2889
2969
  // src/server/httpServer.ts
2890
2970
  import { WebSocketServer } from "ws";
2891
2971
  var __dirname = dirname2(fileURLToPath(import.meta.url));
2892
- var distDir = join4(__dirname, "..", "dist");
2893
- var spaEntryFile = join4(distDir, "index.html");
2972
+ var distDir = join5(__dirname, "..", "dist");
2973
+ var spaEntryFile = join5(distDir, "index.html");
2894
2974
  var IMAGE_CONTENT_TYPES = {
2895
2975
  ".avif": "image/avif",
2896
2976
  ".bmp": "image/bmp",
@@ -2947,7 +3027,7 @@ function createServer(options = {}) {
2947
3027
  res.status(400).json({ error: "Expected absolute local file path." });
2948
3028
  return;
2949
3029
  }
2950
- const contentType = IMAGE_CONTENT_TYPES[extname2(localPath).toLowerCase()];
3030
+ const contentType = IMAGE_CONTENT_TYPES[extname3(localPath).toLowerCase()];
2951
3031
  if (!contentType) {
2952
3032
  res.status(415).json({ error: "Unsupported image type." });
2953
3033
  return;
@@ -3034,7 +3114,7 @@ function createServer(options = {}) {
3034
3114
  res.status(404).json({ error: "File not found." });
3035
3115
  }
3036
3116
  });
3037
- const hasFrontendAssets = existsSync3(spaEntryFile);
3117
+ const hasFrontendAssets = existsSync4(spaEntryFile);
3038
3118
  if (hasFrontendAssets) {
3039
3119
  app.use(express.static(distDir));
3040
3120
  }
@@ -3107,7 +3187,7 @@ var program = new Command().name("codexui").description("Web interface for Codex
3107
3187
  var __dirname2 = dirname3(fileURLToPath2(import.meta.url));
3108
3188
  async function readCliVersion() {
3109
3189
  try {
3110
- const packageJsonPath = join5(__dirname2, "..", "package.json");
3190
+ const packageJsonPath = join6(__dirname2, "..", "package.json");
3111
3191
  const raw = await readFile4(packageJsonPath, "utf8");
3112
3192
  const parsed = JSON.parse(raw);
3113
3193
  return typeof parsed.version === "string" ? parsed.version : "unknown";
@@ -3119,46 +3199,25 @@ function isTermuxRuntime() {
3119
3199
  return Boolean(process.env.TERMUX_VERSION || process.env.PREFIX?.includes("/com.termux/"));
3120
3200
  }
3121
3201
  function canRun(command, args = []) {
3122
- const result = spawnSync(command, args, { stdio: "ignore" });
3123
- return result.status === 0;
3202
+ const result = canRunCommand(command, args);
3203
+ return result;
3124
3204
  }
3125
3205
  function runOrFail(command, args, label) {
3126
- const result = spawnSync(command, args, { stdio: "inherit" });
3206
+ const result = spawnSyncCommand(command, args, { stdio: "inherit" });
3127
3207
  if (result.status !== 0) {
3128
3208
  throw new Error(`${label} failed with exit code ${String(result.status ?? -1)}`);
3129
3209
  }
3130
3210
  }
3131
3211
  function runWithStatus(command, args) {
3132
- const result = spawnSync(command, args, { stdio: "inherit" });
3212
+ const result = spawnSyncCommand(command, args, { stdio: "inherit" });
3133
3213
  return result.status ?? -1;
3134
3214
  }
3135
- function getUserNpmPrefix() {
3136
- return join5(homedir3(), ".npm-global");
3137
- }
3138
- function resolveCodexCommand() {
3139
- if (canRun("codex", ["--version"])) {
3140
- return "codex";
3141
- }
3142
- const userCandidate = join5(getUserNpmPrefix(), "bin", "codex");
3143
- if (existsSync4(userCandidate) && canRun(userCandidate, ["--version"])) {
3144
- return userCandidate;
3145
- }
3146
- const prefix = process.env.PREFIX?.trim();
3147
- if (!prefix) {
3148
- return null;
3149
- }
3150
- const candidate = join5(prefix, "bin", "codex");
3151
- if (existsSync4(candidate) && canRun(candidate, ["--version"])) {
3152
- return candidate;
3153
- }
3154
- return null;
3155
- }
3156
3215
  function resolveCloudflaredCommand() {
3157
3216
  if (canRun("cloudflared", ["--version"])) {
3158
3217
  return "cloudflared";
3159
3218
  }
3160
- const localCandidate = join5(homedir3(), ".local", "bin", "cloudflared");
3161
- if (existsSync4(localCandidate) && canRun(localCandidate, ["--version"])) {
3219
+ const localCandidate = join6(homedir4(), ".local", "bin", "cloudflared");
3220
+ if (existsSync5(localCandidate) && canRun(localCandidate, ["--version"])) {
3162
3221
  return localCandidate;
3163
3222
  }
3164
3223
  return null;
@@ -3211,9 +3270,9 @@ async function ensureCloudflaredInstalledLinux() {
3211
3270
  if (!mappedArch) {
3212
3271
  throw new Error(`cloudflared auto-install is not supported for Linux architecture: ${process.arch}`);
3213
3272
  }
3214
- const userBinDir = join5(homedir3(), ".local", "bin");
3273
+ const userBinDir = join6(homedir4(), ".local", "bin");
3215
3274
  mkdirSync(userBinDir, { recursive: true });
3216
- const destination = join5(userBinDir, "cloudflared");
3275
+ const destination = join6(userBinDir, "cloudflared");
3217
3276
  const downloadUrl = `https://github.com/cloudflare/cloudflared/releases/latest/download/cloudflared-linux-${mappedArch}`;
3218
3277
  console.log("\ncloudflared not found. Installing to ~/.local/bin...\n");
3219
3278
  await downloadFile(downloadUrl, destination);
@@ -3252,8 +3311,8 @@ async function resolveCloudflaredForTunnel() {
3252
3311
  return ensureCloudflaredInstalledLinux();
3253
3312
  }
3254
3313
  function hasCodexAuth() {
3255
- const codexHome = process.env.CODEX_HOME?.trim() || join5(homedir3(), ".codex");
3256
- return existsSync4(join5(codexHome, "auth.json"));
3314
+ const codexHome = process.env.CODEX_HOME?.trim() || join6(homedir4(), ".codex");
3315
+ return existsSync5(join6(codexHome, "auth.json"));
3257
3316
  }
3258
3317
  function ensureCodexInstalled() {
3259
3318
  let codexCommand = resolveCodexCommand();
@@ -3271,7 +3330,7 @@ function ensureCodexInstalled() {
3271
3330
  Global npm install requires elevated permissions. Retrying with --prefix ${userPrefix}...
3272
3331
  `);
3273
3332
  runOrFail("npm", ["install", "-g", "--prefix", userPrefix, pkg], `${label} (user prefix)`);
3274
- process.env.PATH = `${join5(userPrefix, "bin")}:${process.env.PATH ?? ""}`;
3333
+ process.env.PATH = `${join6(userPrefix, "bin")}:${process.env.PATH ?? ""}`;
3275
3334
  };
3276
3335
  if (isTermuxRuntime()) {
3277
3336
  console.log("\nCodex CLI not found. Installing Termux-compatible Codex CLI from npm...\n");
@@ -3412,8 +3471,8 @@ function listenWithFallback(server, startPort) {
3412
3471
  });
3413
3472
  }
3414
3473
  function getCodexGlobalStatePath2() {
3415
- const codexHome = process.env.CODEX_HOME?.trim() || join5(homedir3(), ".codex");
3416
- return join5(codexHome, ".codex-global-state.json");
3474
+ const codexHome = process.env.CODEX_HOME?.trim() || join6(homedir4(), ".codex");
3475
+ return join6(codexHome, ".codex-global-state.json");
3417
3476
  }
3418
3477
  function normalizeUniqueStrings(value) {
3419
3478
  if (!Array.isArray(value)) return [];