Skip to content

feat: add WSL wrapper runner and performance docs#10

Open
julianhelpertz wants to merge 2 commits intoaidanqm:mainfrom
julianhelpertz:codex/wsl
Open

feat: add WSL wrapper runner and performance docs#10
julianhelpertz wants to merge 2 commits intoaidanqm:mainfrom
julianhelpertz:codex/wsl

Conversation

@julianhelpertz
Copy link

@julianhelpertz julianhelpertz commented Feb 24, 2026

Summary

  • add a dedicated WSL/Linux wrapper script at scripts/run.sh to run Codex from a macOS Codex.dmg
  • document required setup clearly, including that users must download Codex.dmg themselves
  • document WSLg refresh-rate tuning (.wslgconfig) and recommended Wayland launch command for better UX

Changes

  • Added scripts/run.sh:
    • DMG extraction (app.asar + app.asar.unpacked) on WSL/Linux
    • preload patching and Electron metadata detection
    • native module preparation for better-sqlite3 and node-pty
    • launch configuration via environment flags (CODEX_OZONE_PLATFORM, cursor, window position/size, etc.)
  • Updated README.md:
    • positioned project as a wrapper (not binary distribution)
    • clarified requirement to provide your own official Codex.dmg
    • added recommended WSL run command
    • added WSLg refresh-rate configuration instructions (60/120/144 Hz)

Test Plan

  • run bash -n scripts/run.sh
  • run ./scripts/run.sh --dmg ./Codex.dmg --no-launch
  • run CODEX_OZONE_PLATFORM=wayland ./scripts/run.sh --dmg ./Codex.dmg --reuse

Closes #7

Summary by Sourcery

Add a WSL/Linux runner script for launching the Codex macOS DMG and expand documentation for using the wrapper on Windows and WSL with performance-related guidance.

New Features:

  • Introduce a Bash-based WSL/Linux wrapper script to extract and run the Codex macOS DMG using a compatible Electron runtime.

Documentation:

  • Clarify that the project is a wrapper requiring a user-supplied Codex.dmg and extend README with WSL/Linux usage instructions, configuration options, and WSLg refresh-rate tuning guidance.

@sourcery-ai
Copy link

sourcery-ai bot commented Feb 24, 2026

Reviewer's Guide

Adds a new WSL/Linux Bash runner that extracts and patches the Codex macOS DMG, prepares native modules against the correct Electron version, and launches Codex with tunable display/performance options, alongside README updates documenting WSL usage, required DMG provisioning, and WSLg refresh-rate tuning.

Sequence diagram for WSL user running Codex via scripts_run_sh

sequenceDiagram
  actor WSLUser
  participant Bash as scripts_run_sh
  participant OS as WSL_Linux_OS
  participant SevenZ as ensure_7z
  participant APT as apt_get_dpkg_deb
  participant Node as Node_npm_npx
  participant Electron as Electron_runtime
  participant CodexCLI as Codex_CLI

  WSLUser->>Bash: ./scripts/run.sh --dmg ./Codex.dmg --reuse

  Bash->>OS: need_cmd node, npm, npx
  OS-->>Bash: binaries available

  Bash->>Bash: resolve_dmg_path
  Bash->>SevenZ: ensure_7z
  alt 7z in PATH or system
    SevenZ-->>Bash: path to 7z
  else 7z not installed
    SevenZ->>APT: apt-get download 7zip
    APT-->>SevenZ: 7zip deb package
    SevenZ->>APT: dpkg-deb -x to local tools dir
    SevenZ-->>Bash: local 7z path under work/tools
  end

  opt REUSE == 0
    Bash->>SevenZ: extract app.asar and app.asar.unpacked
    Bash->>Node: npx @electron/asar extract app.asar -> APP_DIR
    Bash->>Bash: copy_dir_contents app.asar.unpacked -> APP_DIR
  end

  Bash->>Node: patch_preload via node script
  Node-->>Bash: preload.js patched (process bridge)

  Bash->>Node: read package.json
  Node-->>Bash: ELECTRON_VERSION, native module versions, metadata

  Bash->>Node: prepare native modules in NATIVE_DIR
  Node-->>Bash: better-sqlite3.node, pty.node built for Electron
  Bash->>Bash: copy native modules into APP_DIR

  alt NO_LAUNCH == 1
    Bash-->>WSLUser: exit after preparation only
  else launch Electron
    Bash->>CodexCLI: resolve_codex_cli_path (find codex)
    CodexCLI-->>Bash: path to codex

    Bash->>Electron: exec electron binary
    activate Electron
    Electron->>Electron: read APP_DIR
    Electron->>CodexCLI: spawn Codex CLI as needed
    CodexCLI-->>Electron: responses for app features

    Electron-->>WSLUser: Codex UI displayed via WSLg/Wayland/X11
  end
Loading

File-Level Changes

Change Details Files
Introduce a dedicated WSL/Linux Bash runner that handles DMG extraction, app unpacking, native module rebuilding, and Electron launch configuration with environment-based UX tuning.
  • Create scripts/run.sh with strict bash options, central error/usage helpers, and argument parsing for DMG path, work dir, Codex CLI path, reuse flag, and no-launch mode.
  • Resolve and validate DMG and Codex CLI paths, and ensure 7z availability by either using system binaries or bootstrapping a local 7zip from apt-get/dpkg-deb into the work directory.
  • Extract app.asar and app.asar.unpacked from the Codex DMG into a work area, unpack the asar with @electron/asar, and merge unpacked assets into the app directory when not reusing artifacts.
  • Patch the app preload.js via a Node script to expose a sanitized process object in the renderer, using a regex-based insertion at a known bridge registration point.
  • Read Electron, better-sqlite3, node-pty versions and Codex build metadata from package.json, with sensible defaults for build number/flavor when missing.
  • Prepare a separate native-build workspace, install matching versions of better-sqlite3, node-pty, electron, @electron/rebuild, and prebuild-install, and rebuild native modules for the detected Electron version with fallbacks to prebuild-install when rebuild fails.
  • Copy rebuilt better-sqlite3 and node-pty native artifacts into the unpacked app node_modules tree, handling both prebuilds and build/Release layouts and verifying that pty.node exists.
  • Configure and launch the Electron binary from the native-build workspace, wiring user-data/cache directories, renderer URL, Codex build/CLI env vars, and constructing feature flags based on CODEX_OZONE_PLATFORM, Wayland decorations, scale factor, cursor size, window geometry, start-maximized, and optional GPU disabling.
  • Gate extraction/rebuild work behind the --reuse and --no-launch flags so the script can be used for one-time preparation, incremental reuse, or headless build-only workflows.
scripts/run.sh
Clarify project positioning and document WSL/WSLg usage including recommended launch commands and performance tuning.
  • Rephrase the project description to emphasize that this repository is a wrapper around the official macOS Codex DMG for Windows and WSL/Linux, not a binary distribution or auto-downloader, and that users must supply Codex.dmg themselves.
  • Scope requirements and quick-start instructions explicitly for the Windows runner, preserving existing behavior while making the platform targeting clear.
  • Add a WSL/Linux quick-start section detailing how to obtain/reference Codex.dmg from Windows, install the Codex CLI, and run the new scripts/run.sh wrapper with recommended CODEX_OZONE_PLATFORM=wayland and reuse options.
  • Document environment variables and options for WSL/Linux that influence GUI behavior (Wayland/X11 selection, scale factor, cursor size, window position/size, GPU disabling) with example invocations for common issues like blurry UI, oversized cursor, and off-screen windows.
  • Introduce a WSLg refresh rate tuning section that shows how to configure WESTON_RDP_MONITOR_REFRESH_RATE via .wslgconfig in ProgramData using PowerShell, including recommended values per monitor refresh rate and shutdown/restart instructions for WSL.
  • Add a note explicitly stating that auto-downloading the macOS Codex DMG is intentionally not implemented, reinforcing licensing and distribution constraints.
README.md

Assessment against linked issues

Issue Objective Addressed Explanation
#7 Provide a way to run the Codex app/CLI via WSL/Linux instead of only the native Windows Codex CLI runner.
#7 Document how to set up and use the WSL/Linux-based runner, including any necessary configuration or performance tuning steps.

Possibly linked issues


Tips and commands

Interacting with Sourcery

  • Trigger a new review: Comment @sourcery-ai review on the pull request.
  • Continue discussions: Reply directly to Sourcery's review comments.
  • Generate a GitHub issue from a review comment: Ask Sourcery to create an
    issue from a review comment by replying to it. You can also reply to a
    review comment with @sourcery-ai issue to create an issue from it.
  • Generate a pull request title: Write @sourcery-ai anywhere in the pull
    request title to generate a title at any time. You can also comment
    @sourcery-ai title on the pull request to (re-)generate the title at any time.
  • Generate a pull request summary: Write @sourcery-ai summary anywhere in
    the pull request body to generate a PR summary at any time exactly where you
    want it. You can also comment @sourcery-ai summary on the pull request to
    (re-)generate the summary at any time.
  • Generate reviewer's guide: Comment @sourcery-ai guide on the pull
    request to (re-)generate the reviewer's guide at any time.
  • Resolve all Sourcery comments: Comment @sourcery-ai resolve on the
    pull request to resolve all Sourcery comments. Useful if you've already
    addressed all the comments and don't want to see them anymore.
  • Dismiss all Sourcery reviews: Comment @sourcery-ai dismiss on the pull
    request to dismiss all existing Sourcery reviews. Especially useful if you
    want to start fresh with a new review - don't forget to comment
    @sourcery-ai review to trigger a new review!

Customizing Your Experience

Access your dashboard to:

  • Enable or disable review features such as the Sourcery-generated pull request
    summary, the reviewer's guide, and others.
  • Change the review language.
  • Add, remove or edit custom review instructions.
  • Adjust other review settings.

Getting Help

Copy link

@sourcery-ai sourcery-ai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hey - I've found 2 issues, and left some high level feedback:

  • When reading dependency versions from package.json, consider explicitly checking that BETTER_VERSION and PTY_VERSION are non-empty before using them in npm install, and fail fast with a clear error message if they’re missing to avoid confusing install errors.
  • The 7z bootstrap logic currently assumes an apt-based distro and a package named 7zip; you might want to allow overriding the 7z binary via an environment variable (e.g., CODEX_7Z_PATH) or make the package name configurable to better support non-Debian WSL/Linux setups.
Prompt for AI Agents
Please address the comments from this code review:

## Overall Comments
- When reading dependency versions from package.json, consider explicitly checking that BETTER_VERSION and PTY_VERSION are non-empty before using them in npm install, and fail fast with a clear error message if they’re missing to avoid confusing install errors.
- The 7z bootstrap logic currently assumes an apt-based distro and a package named `7zip`; you might want to allow overriding the 7z binary via an environment variable (e.g., CODEX_7Z_PATH) or make the package name configurable to better support non-Debian WSL/Linux setups.

## Individual Comments

### Comment 1
<location path="scripts/run.sh" line_range="215" />
<code_context>
+BS_DST="$APP_DIR/node_modules/better-sqlite3/build/Release/better_sqlite3.node"
+PTY_DST_PRE="$APP_DIR/node_modules/node-pty/prebuilds/$NODE_PTY_ARCH"
+PTY_DST_REL="$APP_DIR/node_modules/node-pty/build/Release"
+if [[ "$NO_LAUNCH" -eq 1 && "$REUSE" -eq 1 && -f "$BS_DST" && ( -f "$PTY_DST_PRE/pty.node" || -f "$PTY_DST_REL/pty.node" ) ]]; then
+  echo "Native modules already present in app. Skipping rebuild."
+else
</code_context>
<issue_to_address>
**issue (bug_risk):** The reuse check for native modules is gated on NO_LAUNCH, which seems inverted and causes extra rebuilds when launching.

With the current condition, native modules are only skipped when NO_LAUNCH=1 and REUSE=1. When actually launching (NO_LAUNCH=0) with REUSE=1 and valid artifacts, we still rebuild, negating reuse on repeated launches. Recommend removing the NO_LAUNCH check and relying on REUSE plus the existing file checks for better-sqlite3 and node-pty.
</issue_to_address>

### Comment 2
<location path="scripts/run.sh" line_range="46-47" />
<code_context>
+    (
+      cd "$pkg_dir"
+      rm -f 7zip_*.deb
+      apt-get download 7zip >/dev/null
+      deb="$(ls -1t 7zip_*.deb | head -n 1)"
+      dpkg-deb -x "$deb" "$out_dir"
+    )
+  fi
</code_context>
<issue_to_address>
**suggestion (bug_risk):** 7zip bootstrap flow can fail in a non-obvious way if apt-get download fails or produces no .deb.

If `apt-get download 7zip` fails (network, missing package, repo misconfig, etc.), `ls -1t 7zip_*.deb` will fail and `deb` will be empty, causing a confusing `dpkg-deb` error later. Please add an explicit check that the download succeeded and that `deb` is non-empty, and fail early with a clear message about the package download problem before calling `dpkg-deb`.

```suggestion
      cd "$pkg_dir"
      rm -f 7zip_*.deb
      if ! apt-get download 7zip >/dev/null 2>&1; then
        die "Failed to download 7zip package via apt-get. Check network connectivity and APT configuration, then retry."
      fi
      deb="$(ls -1t 7zip_*.deb 2>/dev/null | head -n 1)"
      if [[ -z "$deb" ]]; then
        die "apt-get download 7zip did not produce a 7zip_*.deb package in $pkg_dir"
      fi
```
</issue_to_address>

Sourcery is free for open source - if you like our reviews please consider sharing them ✨
Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.

BS_DST="$APP_DIR/node_modules/better-sqlite3/build/Release/better_sqlite3.node"
PTY_DST_PRE="$APP_DIR/node_modules/node-pty/prebuilds/$NODE_PTY_ARCH"
PTY_DST_REL="$APP_DIR/node_modules/node-pty/build/Release"
if [[ "$NO_LAUNCH" -eq 1 && "$REUSE" -eq 1 && -f "$BS_DST" && ( -f "$PTY_DST_PRE/pty.node" || -f "$PTY_DST_REL/pty.node" ) ]]; then
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

issue (bug_risk): The reuse check for native modules is gated on NO_LAUNCH, which seems inverted and causes extra rebuilds when launching.

With the current condition, native modules are only skipped when NO_LAUNCH=1 and REUSE=1. When actually launching (NO_LAUNCH=0) with REUSE=1 and valid artifacts, we still rebuild, negating reuse on repeated launches. Recommend removing the NO_LAUNCH check and relying on REUSE plus the existing file checks for better-sqlite3 and node-pty.

Comment on lines +46 to +47
cd "$pkg_dir"
rm -f 7zip_*.deb
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

suggestion (bug_risk): 7zip bootstrap flow can fail in a non-obvious way if apt-get download fails or produces no .deb.

If apt-get download 7zip fails (network, missing package, repo misconfig, etc.), ls -1t 7zip_*.deb will fail and deb will be empty, causing a confusing dpkg-deb error later. Please add an explicit check that the download succeeded and that deb is non-empty, and fail early with a clear message about the package download problem before calling dpkg-deb.

Suggested change
cd "$pkg_dir"
rm -f 7zip_*.deb
cd "$pkg_dir"
rm -f 7zip_*.deb
if ! apt-get download 7zip >/dev/null 2>&1; then
die "Failed to download 7zip package via apt-get. Check network connectivity and APT configuration, then retry."
fi
deb="$(ls -1t 7zip_*.deb 2>/dev/null | head -n 1)"
if [[ -z "$deb" ]]; then
die "apt-get download 7zip did not produce a 7zip_*.deb package in $pkg_dir"
fi

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Codex CLI via WSL instead of native Windows

1 participant