Run OpenAI Codex Desktop on Linux.
The official Codex Desktop app is macOS-only. This project converts the upstream macOS Codex.dmg into a runnable Linux Electron app, packages it as .deb, .rpm, or pacman artifacts, and includes a local updater that rebuilds future Linux packages from newer upstream DMGs.
codex-update-manager current crate version: 0.3.1
SemVer policy for the crate:
majorfor incompatible CLI, persisted-state, or install-flow changesminorfor compatible feature additionspatchfor fixes, docs, and maintenance-only updates
This repo supports 2 primary workflows:
- Generate a local Linux app into
codex-app/and run it directly from the checkout. - Build and install a native package that installs the app under
/opt/codex-desktopand the updater service undersystemd --user.
The build pipeline is:
- Extract the macOS
.dmgwith7z - Extract and patch
app.asar - Rebuild native Node.js modules for Linux
- Download a Linux Electron runtime
- Write a Linux launcher into
codex-app/start.sh - Optionally package
codex-app/as a Debian, RPM, or pacman package - When installed from a native package, run
codex-update-manageras asystemd --userservice for local auto-updates
You need:
- Node.js 20+
npm,npxpython37zcurlunzipmakeg++- Rust and
cargoforcodex-update-manager
The easiest setup path is:
bash scripts/install-deps.sh
npm i -g @openai/codexThat helper detects apt, dnf5, dnf, or pacman, installs system packages, and bootstraps Rust through rustup if needed.
If your system does not allow global npm installs, a rootless alternative also works:
npm i -g --prefix ~/.local @openai/codexUbuntu-family p7zip-full can be too old to extract newer APFS DMGs. If extraction fails, install a newer 7zz:
curl -L -o /tmp/7z.tar.xz https://www.7-zip.org/a/7z2409-linux-x64.tar.xz
tar -C /tmp -xf /tmp/7z.tar.xz
sudo install -m 755 /tmp/7zz /usr/local/bin/7zzYou need Node.js 20+, npm, Python 3, 7z, curl, build tools (gcc/g++/make), and Rust (cargo) for the updater crate and local package rebuilds.
The easiest way to install the required system packages is:
bash scripts/install-deps.shThat helper detects apt, dnf5, dnf, or pacman, installs the system dependencies, and bootstraps Rust through rustup if needed.
bash scripts/install-deps.shOr manually:
sudo pacman -S --needed nodejs npm python p7zip curl unzip zstd base-develYou also need the Rust toolchain for the updater crate:
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | shA Nix flake is provided that handles dependencies and patches Electron for NixOS:
nix run github:ilysenko/codex-desktop-linuxThis installs the app into codex-app/ in the current directory. You can also enter a dev shell with the required tooling:
nix develop github:ilysenko/codex-desktop-linuxClone the repo, generate the local app, and run it:
git clone https://github.com/ilysenko/codex-desktop-linux.git
cd codex-desktop-linux
bash scripts/install-deps.sh
npm i -g @openai/codex
make build-app
make run-appIf npm i -g needs elevated privileges on your system, replace it with:
npm i -g --prefix ~/.local @openai/codexmake build-app DMG=/path/to/Codex.dmgThis creates codex-app/ from the upstream DMG and writes the Linux launcher to codex-app/start.sh.
make build-appRun the generated app directly from the repo:
make run-appEquivalent direct command:
./codex-app/start.shBuild the package that matches the current distro automatically:
make packageOr choose the format explicitly:
make deb
make rpm
make pacmanIf you prefer an alias:
echo 'alias codex-desktop="~/codex-desktop-linux/codex-app/start.sh"' >> ~/.bashrcThe repository can build a Debian, RPM, or pacman package from the generated codex-app/ directory.
./scripts/build-deb.shOptional version override:
PACKAGE_VERSION=2026.03.24.120000+deadbeef ./scripts/build-deb.shOutput:
dist/codex-desktop_YYYY.MM.DD.HHMMSS_amd64.deb./scripts/build-rpm.shOptional version override:
PACKAGE_VERSION=2026.03.24.120000+deadbeef ./scripts/build-rpm.shOutput:
dist/codex-desktop-YYYY.MM.DD.HHMMSS-<release>.x86_64.rpm./scripts/build-pacman.shOutput:
dist/codex-desktop-YYYY.MM.DD.HHMMSS-1-x86_64.pkg.tar.zstInstall it with:
sudo pacman -U dist/codex-desktop-*.pkg.tar.zstmake installThese commands make sense after the native package is installed, because the service unit and updater binary are installed by the package.
Enable and start the user service:
make service-enableInspect the service:
make service-status
codex-update-manager status --jsonNotes:
codex-update-manager.serviceis asystemd --userservice, not a system-wide root service.- The packaged launcher also starts the service in best-effort mode when you open the installed app.
make service-enableis not meant for an unpackaged repo-only run unless you already installed the package into the system.
make help
make check
make test
make build-updater
make build-app
make run-app
make deb
make rpm
make pacman
make package
make install
make service-enable
make service-status
make clean-dist
make clean-statemake package auto-detects the native package manager available on the host and builds the matching package type (Debian, RPM, or pacman). make install does the same for the latest built native package.
The build and update flow is:
install.shextractsCodex.dmgwith7z- it extracts and patches
app.asar - it rebuilds native Node modules for Linux
- it downloads a Linux Electron runtime
- it writes the Linux launcher into
codex-app/start.sh scripts/build-deb.shorscripts/build-rpm.shpackagescodex-app/- the installed package provides
codex-update-managerpluscodex-update-manager.service - the updater checks for newer upstream DMGs and rebuilds future Linux package updates locally
The package installs a companion service named codex-update-manager.
- It runs as a
systemd --userservice. - The launcher starts it in best-effort mode on first app launch.
- It checks the upstream
Codex.dmgon startup and every 6 hours. - When a new DMG is detected, it rebuilds a local native package using
/opt/codex-desktop/update-builder. - If the app is open, the update waits until Electron exits.
- When the app is closed, the updater uses
pkexeconly for the final native-package install step. - On Arch, that final install step is
pacman -U --noconfirmagainst the locally rebuilt.pkg.tar.zst, notgit pull. - If a privileged install fails or is dismissed, the updater stays in
failedinstead of re-prompting every 15 seconds. - If an
Installingstate is interrupted by a crash or restart, the updater now recovers that state automatically instead of getting stuck and skipping all future upstream checks. - Before Electron launches, the launcher asks the updater to verify the installed Codex CLI and update it if the npm package is newer.
- That CLI preflight is best-effort: it uses a 1-hour cooldown for registry checks, falls back to
npm install -g --prefix ~/.localif a global install fails, and warns instead of aborting app launch when the automatic refresh does not succeed.
Inspect the live service and runtime files with:
systemctl --user status codex-update-manager.service
codex-update-manager status --json
sed -n '1,160p' ~/.local/state/codex-update-manager/state.json
sed -n '1,160p' ~/.local/state/codex-update-manager/service.logRuntime files live in the standard XDG locations:
~/.config/codex-update-manager/config.toml
~/.local/state/codex-update-manager/state.json
~/.local/state/codex-update-manager/service.log
~/.cache/codex-update-manager/The Electron launcher also writes:
~/.cache/codex-desktop/launcher.log
~/.local/state/codex-desktop/app.pidThat PID file lets the updater know whether Electron is still running before it installs a pending package.
The macOS Codex app is an Electron application. The core code (app.asar) is platform-independent JavaScript, but it bundles macOS-native modules and a macOS Electron binary.
The installer replaces the macOS Electron with a Linux build and recompiles the native modules using @electron/rebuild. The sparkle module is removed because it is macOS-only.
The extracted app expects a local webview origin on localhost:5175, so the launcher starts python3 -m http.server 5175 from content/webview/, waits for the socket to become reachable, and only then launches Electron.
Native-package-only launcher behavior such as desktop-entry hints and codex-update-manager session bootstrapping lives in packaging/linux/codex-packaged-runtime.sh, which the generated launcher loads only when present inside a packaged install.
The current evaluation for a future Rust replacement for the local webview server lives in docs/webview-server-evaluation.md.
| Problem | Solution |
|---|---|
Error: write EPIPE |
Run start.sh directly instead of piping output |
| Blank window | Check whether port 5175 is already in use: ss -tlnp | grep 5175 |
ERR_CONNECTION_REFUSED on :5175 |
The webview HTTP server failed to start. Ensure python3 works and port 5175 is free |
CODEX_CLI_PATH error |
Install the CLI with npm i -g @openai/codex or npm i -g --prefix ~/.local @openai/codex |
| Electron hangs while the CLI is outdated | Re-run the launcher and check ~/.cache/codex-desktop/launcher.log plus ~/.local/state/codex-update-manager/service.log; the launcher now runs a best-effort CLI preflight and warns if the automatic refresh fails |
| GPU/Vulkan/Wayland errors | The launcher sets --ozone-platform-hint=auto, --disable-gpu-sandbox, --disable-gpu-compositing, and --enable-features=WaylandWindowDecorations by default. If you need X11 explicitly, try ./codex-app/start.sh --ozone-platform=x11 |
| Window flickering | GPU compositing is now disabled by default (--disable-gpu-compositing). If flickering persists, try ./codex-app/start.sh --disable-gpu to fully disable GPU acceleration |
| Sandbox errors | The launcher already sets --no-sandbox |
| Stale install / cached DMG | Run ./install.sh --fresh to remove the existing install dir and re-download the DMG |
| Usage help | Run ./install.sh --help or ./codex-app/start.sh --help |
codex-update-manager keeps running after package removal |
Run systemctl --user disable --now codex-update-manager.service once in the affected session, then confirm /opt/codex-desktop is gone |
After changing installer, packaging, or updater logic, validate at least:
bash -n install.sh scripts/build-deb.sh scripts/build-rpm.sh scripts/build-pacman.sh scripts/install-deps.sh
cargo check -p codex-update-manager
cargo test -p codex-update-manager
make packageIf you are validating a Debian package specifically, also run:
dpkg-deb -I dist/codex-desktop_*.deb
dpkg-deb -c dist/codex-desktop_*.deb | sed -n '1,40p'If rpmbuild is available, also run:
make rpmIf makepkg is available (Arch Linux), also run:
./scripts/build-pacman.sh
pacman -Qip dist/codex-desktop-*.pkg.tar.zst
pacman -Qlp dist/codex-desktop-*.pkg.tar.zst | sed -n '1,40p'If launcher behavior changed, inspect:
sed -n '1,140p' codex-app/start.shThis is an unofficial community project. Codex Desktop is a product of OpenAI. This tool does not redistribute any OpenAI software; it automates the conversion process that users perform on their own copies.
MIT