← Projects

Linux porting · Build systems · Electron internals

Codex Desktop for Linux

OpenAI's Codex Desktop ships for macOS. I made it a first-class Linux application — native-toolchain fixes, a full KDE desktop-shell integration, a Wayland and GPU compatibility layer, and a deterministic patch framework that survives upstream updates — then embedded my own GPU-accelerated browser runtime into it for computer-use workflows.

The problem

The app is a macOS-first Electron build with minified bundles and no Linux target. Making it a real Linux citizen is not one fix; it is a hundred small ones — native modules that won't compile, a missing system tray, no close-to-tray or explicit quit, single-instance locks, CLI binaries under different names, Wayland/GPU quirks, and a mac-specific "app sunset" gate that would disable the build outright. And because it is someone else's app that ships new versions constantly, every fix has to re-apply cleanly against next week's bundle — or the whole thing goes stale in a fortnight.

What I built

How it works

The pipeline treats the upstream app as an input, never a fork. It pulls the official build from the vendor's own distribution at build time, unpacks it, and runs the patch manifest — an ordered set of roughly 55 patches with declared inter-dependencies. Because the bundles are minified and change every release, the discipline is strict: no patch is allowed to grep-and-replace source text. Each one parses the bundle into a syntax tree, finds its seam by structure, and edits ranges the parser hands back, so a patch either finds its exact target or reports a clean miss.

Patch pipelineThe upstream app is an input, not a fork: downloaded fresh, patched through the AST only, and proven deterministic before it is ever repackaged.

Patch pipeline diagram viewer

100%

Scroll to zoom · drag to move

The browser embedding is where the systems work gets deepest. Skynet renders web pages off-screen in a separate CEF process, and rather than screenshot them, it hands the Electron app the actual GPU frame: dma-buf and fence file descriptors passed over a sequential-packet socket viaSCM_RIGHTS, imported into the renderer as a shared texture and drawn to a canvas with no CPU copy. A broker in the Electron main process speaks browser-use JSON-RPC to the runtime behind an epoch/nonce/token handshake, and pointer, wheel, and keyboard events route back to the live surface. It is the same runtime that backs my standalone browser shell — one runtime, two embedders.

Embedded browser surfaceThe browser lives in its own process and hands the app real GPU frames over a file-descriptor-passing socket — a genuine live surface with input routed back, not a picture of one.

Embedded browser surface diagram viewer

100%

Scroll to zoom · drag to move

How it achieves the goal

The measure of this project is not the first successful build; it is the twentieth, against an upstream that never stopped moving. That is what the AST discipline and the determinism gate buy — drift shows up as a precise conflict at the exact seam, and a patch is deleted the release upstream ships the fix itself. Roughly 80 test files hold that contract, covering first-apply, idempotency, and drift-error behavior for each patch.

It is worth being precise about what this is: interoperability and porting work. The tooling operates on a copy downloaded to my own machine, authenticated with my own account, and run on an operating system the vendor did not target — making an app I use work where it should, and fixing the rough edges along the way. The embedded browser is opt-in behind a feature flag and advanced-experimental; the Linux port is what I run every day.