Skip to content

Leay15/codex-desktop-linux

 
 

Repository files navigation

Codex Desktop for Linux

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:

  • major for incompatible CLI, persisted-state, or install-flow changes
  • minor for compatible feature additions
  • patch for fixes, docs, and maintenance-only updates

Supported Workflows

This repo supports 2 primary workflows:

  1. Generate a local Linux app into codex-app/ and run it directly from the checkout.
  2. Build and install a native package that installs the app under /opt/codex-desktop and the updater service under systemd --user.

The build pipeline is:

  1. Extract the macOS .dmg with 7z
  2. Extract and patch app.asar
  3. Rebuild native Node.js modules for Linux
  4. Download a Linux Electron runtime
  5. Write a Linux launcher into codex-app/start.sh
  6. Optionally package codex-app/ as a Debian, RPM, or pacman package
  7. When installed from a native package, run codex-update-manager as a systemd --user service for local auto-updates

Prerequisites

You need:

  • Node.js 20+
  • npm, npx
  • python3
  • 7z
  • curl
  • unzip
  • make
  • g++
  • Rust and cargo for codex-update-manager

The easiest setup path is:

bash scripts/install-deps.sh
npm i -g @openai/codex

That 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/codex

Ubuntu / Pop!_OS Note

Ubuntu-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/7zz

Fedora

You 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.sh

That helper detects apt, dnf5, dnf, or pacman, installs the system dependencies, and bootstraps Rust through rustup if needed.

Arch Linux

bash scripts/install-deps.sh

Or manually:

sudo pacman -S --needed nodejs npm python p7zip curl unzip zstd base-devel

You also need the Rust toolchain for the updater crate:

curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh

NixOS

A Nix flake is provided that handles dependencies and patches Electron for NixOS:

nix run github:ilysenko/codex-desktop-linux

This 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-linux

Quick Start

Clone 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-app

If npm i -g needs elevated privileges on your system, replace it with:

npm i -g --prefix ~/.local @openai/codex

Use your own DMG

make build-app DMG=/path/to/Codex.dmg

Usage

1. Generate the local Electron app

This creates codex-app/ from the upstream DMG and writes the Linux launcher to codex-app/start.sh.

make build-app

Run the generated app directly from the repo:

make run-app

Equivalent direct command:

./codex-app/start.sh

2. Build a native package

Build the package that matches the current distro automatically:

make package

Or choose the format explicitly:

make deb
make rpm
make pacman

If you prefer an alias:

echo 'alias codex-desktop="~/codex-desktop-linux/codex-app/start.sh"' >> ~/.bashrc

Native Packages

The repository can build a Debian, RPM, or pacman package from the generated codex-app/ directory.

Debian

./scripts/build-deb.sh

Optional version override:

PACKAGE_VERSION=2026.03.24.120000+deadbeef ./scripts/build-deb.sh

Output:

dist/codex-desktop_YYYY.MM.DD.HHMMSS_amd64.deb

RPM

./scripts/build-rpm.sh

Optional version override:

PACKAGE_VERSION=2026.03.24.120000+deadbeef ./scripts/build-rpm.sh

Output:

dist/codex-desktop-YYYY.MM.DD.HHMMSS-<release>.x86_64.rpm

Arch Linux (pacman)

./scripts/build-pacman.sh

Output:

dist/codex-desktop-YYYY.MM.DD.HHMMSS-1-x86_64.pkg.tar.zst

Install it with:

sudo pacman -U dist/codex-desktop-*.pkg.tar.zst

Install the newest package from dist/

make install

Start or inspect the updater service

These 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-enable

Inspect the service:

make service-status
codex-update-manager status --json

Makefile shortcuts

Notes:

  • codex-update-manager.service is a systemd --user service, 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-enable is not meant for an unpackaged repo-only run unless you already installed the package into the system.

Make Targets

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-state

make 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.

How It Works

The build and update flow is:

  1. install.sh extracts Codex.dmg with 7z
  2. it extracts and patches app.asar
  3. it rebuilds native Node modules for Linux
  4. it downloads a Linux Electron runtime
  5. it writes the Linux launcher into codex-app/start.sh
  6. scripts/build-deb.sh or scripts/build-rpm.sh packages codex-app/
  7. the installed package provides codex-update-manager plus codex-update-manager.service
  8. the updater checks for newer upstream DMGs and rebuilds future Linux package updates locally

Update Manager

The package installs a companion service named codex-update-manager.

  • It runs as a systemd --user service.
  • The launcher starts it in best-effort mode on first app launch.
  • It checks the upstream Codex.dmg on 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 pkexec only for the final native-package install step.
  • On Arch, that final install step is pacman -U --noconfirm against the locally rebuilt .pkg.tar.zst, not git pull.
  • If a privileged install fails or is dismissed, the updater stays in failed instead of re-prompting every 15 seconds.
  • If an Installing state 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 ~/.local if 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.log

Runtime 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.pid

That PID file lets the updater know whether Electron is still running before it installs a pending package.

Technical Notes

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.

Troubleshooting

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

Validation

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 package

If 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 rpm

If 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.sh

Disclaimer

This 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.

License

MIT

About

Run OpenAI Codex Desktop on Linux - automated installer

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors

Languages

  • Rust 59.9%
  • Shell 33.1%
  • Makefile 3.2%
  • Nix 2.1%
  • JavaScript 1.7%