AGENTS.md

July 10, 2026 ยท View on GitHub

Purpose

This repository adapts the official macOS ChatGPT Desktop DMG into a runnable Linux app, packages it as .deb, .rpm, pacman, and AppImage artifacts, and ships a local Rust update manager that can rebuild future Linux packages from newer upstream DMGs.

The build flow: install.sh downloads/extracts Codex.dmg, patches the extracted app through core and enabled Linux feature descriptors, rebuilds native modules, downloads Linux Electron, stages bundled resources, writes codex-app/start.sh, and lets package builders produce native artifacts or AppImage. Native packages also include codex-update-manager and an update-builder bundle.

Maintainer Rules

  • This project supports only the latest upstream CODEX.DMG. When fixing upstream drift, remove old drift workarounds in the same change. Do not keep legacy DMG shapes, fallback patch paths, or version-specific compatibility branches around.
  • Keep core behavior focused on the app launching and working for most Linux users. Experimental, workflow-specific, editor-specific, browser-specific, distro-specific, or minority-use integrations belong in linux-features/ and must be disabled by default.
  • If an optional feature needs a new core touchpoint, add the smallest generic extension point to core, then keep feature-specific logic inside that feature directory.
  • Do not enable optional features in committed config. linux-features/features.json is local and gitignored; features.example.json stays empty.
  • Each repository feature under linux-features/<id>/ and each local feature under linux-features/local/<id>/ must include a README.md next to feature.json.
  • Do not manually patch generated output such as codex-app/start.sh for a durable fix. Change the source template, build helper, feature, or patch descriptor and regenerate.
  • Treat updater, package builder, launcher, and feature framework changes as cross-format changes unless the code explicitly scopes them to one package format or desktop target.

Source Routing

Use source files, not generated artifacts. Main routing:

  • Launcher/webview: launcher/start.sh.template, launcher/webview-server.py.
  • Packaged runtimes: packaging/linux/codex-packaged-runtime.sh, packaging/appimage/codex-appimage-runtime.sh.
  • Build pipeline: scripts/lib/*.sh.
  • Core patches: descriptors in scripts/patches/core/**/patch.js, implementations in scripts/patches/impl/, helpers in scripts/patches/lib/.
  • Linux features: linux-features/<id>/.
  • Package builders: scripts/build-*.sh and scripts/lib/package-common.sh.
  • Updater: updater/src/.
  • Computer Use: computer-use-linux/; compositor backends under computer-use-linux/src/windowing/backends/.
  • Nix: flake.nix, flake.lock, and nix/.

Detailed agent docs: repository map, generated/runtime notes, and validation playbook.

Primary human docs: architecture, build and packaging, Linux features, updater, Linux Computer Use, Nix, and troubleshooting.

Patch And Feature Rules

  • scripts/patch-linux-window-ui.js is the build-facing ASAR patcher CLI only. Do not import internals from it; use runner/helper APIs.
  • Core patch descriptors are the source of truth for shipped Linux compatibility patches. Read scripts/patches/core/README.md before adding or moving descriptors.
  • ASAR patches are fail-soft unless intentionally marked required-upstream. Each patch should be idempotent and report warnings when current upstream drift prevents a needle from matching.
  • Patch reports are written for installs/rebuilds. Upstream-build CI fails only for required upstream patches that are missing or skipped.
  • Do not recreate deleted compatibility barrels such as scripts/patches/main-process.js, webview-assets.js, or shared.js.
  • Feature patching uses only entrypoints.patchDescriptors. Removed feature patch entrypoints such as mainBundlePatch and entrypoints.patches are not supported.
  • Declarative feature resources, runtimeHooks, and packageHooks are preferred over ad hoc staging whenever possible.
  • Feature resource targets must stay inside the app directory and cannot target the app root. Mode values must be quoted octal strings such as "0644" or "0755".

Important Runtime Behavior

  • DMG extraction can warn when 7z cannot materialize the /Applications symlink. This is acceptable if a .app bundle was extracted successfully.
  • The managed Node.js runtime is installed under codex-app/resources/node-runtime/. If CODEX_MANAGED_NODE_VERSION or CODEX_MANAGED_NODE_URL is overridden, CODEX_MANAGED_NODE_SHA256 must be set too.
  • GUI launchers often do not inherit shell PATH. The generated launcher searches common Codex CLI and nvm locations and respects CODEX_CLI_PATH.
  • CLI preflight is launcher-scoped and best-effort. It can prompt to install or update the Codex CLI, but failures should warn rather than block app launch.
  • The generated launcher starts the local webview server before Electron and verifies the expected startup markers. See webview server evaluation before changing the server model.
  • Warm-start handoff uses a Unix-domain socket under $XDG_RUNTIME_DIR so second launches can send actions to the running app.
  • Linux Computer Use plugin registration is default-on platform port glue, but Computer Use UI enablement remains opt-in and must not bypass upstream server-side rollouts unrelated to local Linux support.
  • The Linux Chrome integration patches staged bundled resources. Do not fix only the user cache.
  • Native package install/removal hooks start, stop, disable, and reload the systemd --user updater service on a best-effort basis.
  • Failed privileged updater installs stay failed until a newer rebuild or an explicit retry path; avoid auto-retrying every reconcile cycle.
  • Manual rollback uses the last-known-good package recorded in updater state and the same format-specific command layer as normal installs.

Generated Artifacts

Treat these as generated or local runtime state, not primary source: codex-app/, codex-app-next/, codex-*-app/, dist/, dist/appimage.AppDir/, dist-next/rebuild/, target/, Codex.dmg, linux-features/features.json, linux-features/local/, codex-app/.codex-linux/linux-features-staged.json, updater config/state/log files under ~/.config, ~/.local/state, and ~/.cache, launcher state under ~/.cache/codex-desktop and ~/.local/state/codex-desktop, and $XDG_RUNTIME_DIR/codex-desktop/launch-action.sock.

See generated and runtime notes for details.

Common Commands

Regenerate the Linux app: ./install.sh ./Codex.dmg or ./install.sh. Guided native setup/install/update: make setup-native, make bootstrap-native, make install-native, make update-native.

Build native packages:

./scripts/build-deb.sh
./scripts/build-rpm.sh
./scripts/build-pacman.sh
./scripts/build-appimage.sh

Side-by-side rebuild candidate: ./scripts/rebuild-candidate.sh or ./scripts/rebuild-candidate.sh --install.

Runtime Expectations

  • python3, 7z, curl, unzip, tar, make, and g++ are required for install.sh.
  • Native package builders require their format-specific tools: dpkg-deb, rpmbuild, makepkg/pacman tooling, or appimagetool.
  • scripts/install-deps.sh bootstraps common host dependencies. On apt-based systems, NODEJS_MAJOR=24 bash scripts/install-deps.sh selects Node.js 24.
  • The packaged app still needs the Codex CLI at runtime, but launcher preflight attempts a best-effort install/update when possible.

Validation Matrix

Run the subset that matches the change; see the validation playbook for expanded checks.

bash -n install.sh
bash -n scripts/lib/*.sh
bash -n launcher/start.sh.template
bash -n scripts/build-deb.sh scripts/build-rpm.sh scripts/build-pacman.sh scripts/build-appimage.sh
node --test scripts/patch-linux-window-ui.test.js
node --test linux-features/*/test.js
bash tests/scripts_smoke.sh
cargo check -p codex-update-manager
cargo test -p codex-update-manager

Build the affected package formats when package payloads or shared package logic changes. Run ./scripts/ci-local.sh pr or ./scripts/ci-local.sh all for broad cross-format confidence.

Editing Guidance

  • Keep native-package-only behavior in packaging/linux/ helpers and AppImage-only behavior in packaging/appimage/ helpers.
  • Keep all package builders aligned through scripts/lib/package-common.sh when adding or removing shared payload files.
  • Keep new core patch descriptors fail-soft and idempotent unless there is a deliberate required-upstream CI policy.
  • Keep optional feature patches optional in CI and disabled by default.
  • Add tests near the behavior being changed: patcher tests for ASAR needles, feature tests for Linux features, Rust tests for updater/MCP backends, and package smoke checks for payload/layout changes.
  • When refreshing Nix hashes, use scripts/ci/update-nix-hashes.sh; do not hand-edit SRI hashes in flake.nix.