/** * @file Centralized Codex home directory path management. Resolves the Codex * home directory, project-level Codex surfaces, and project roots. Supports a * custom root via the CODEX_HOME environment variable so the dashboard can * track non-standard Codex installations, and changes it at runtime * (`setCodexHome`, persisted to the settings file). * @author Nguyễn Ngọc Trí Vĩ */ const fs = require("node:fs"); const path = require("node:path"); const os = require("node:os"); /** * The Codex home directory. Resolves to $CODEX_HOME if set, else * ~/.codex. Always reads process.env at call time so tests can inject. * * @returns {string} Absolute path to the Codex home directory. */ function getCodexHome() { return process.env.CODEX_HOME || path.join(os.homedir(), ".codex"); } /** * CODEX_HOME as given and, when a symlink makes it differ, as resolved — so a * path Codex reports (it may canonicalize) matches either. * * @returns {string[]} one or two absolute paths. */ function codexHomes() { const raw = path.resolve(getCodexHome()); try { const real = fs.realpathSync(raw); return real === raw ? [raw] : [raw, real]; } catch { return [raw]; } } /** * The directory where Codex stores per-project surfaces (rollout journals, * SQLite mirrors, etc.) for a project at the given working directory. * * @param {string} cwd Absolute path to a project root. * @returns {string} Absolute path to /.codex. */ function getProjectCodexDir(cwd) { return path.join(cwd, ".codex"); } /** * The project root. For now, this is just an identity function — cwd is * the project root. Exists as a contract for consistency with claude-home.js * and to anchor the path-resolution hierarchy. * * @param {string} cwd Absolute path to a project root (where AGENTS.md lives). * @returns {string} The same cwd. */ function getProjectRoot(cwd) { return cwd; } /** * Update CODEX_HOME at runtime: `process.env` changes at once and the value * persists to the settings file (see `settings-env.js`). The path passes the * shared guard that refuses anything that is or contains the user's home * (`EBADHOME`). A codex pane gets this value through tmux `-e` at its next * start; one already running keeps the home it started with. * * @param {string} newPath absolute path, `~/` expanded. * @returns {string} the resolved absolute path. */ function setCodexHome(newPath) { const { validateHomeDir, applySetting } = require("./settings-env"); const resolved = validateHomeDir("CODEX_HOME", newPath); applySetting("CODEX_HOME", resolved); return resolved; } module.exports = { codexHomes, getCodexHome, setCodexHome, getProjectCodexDir, getProjectRoot, };