ilysenko/codex-desktop-linux
GitHub: ilysenko/codex-desktop-linux
将仅支持 macOS 的 OpenAI Codex Desktop 自动转换为可在主流 Linux 发行版上运行的 Electron 应用,并提供原生打包、自动更新和桌面操控能力。
Stars: 480 | Forks: 80
# Codex Desktop Linux 版
[OpenAI Codex Desktop](https://openai.com/codex/) 的非官方 Linux 构建。官方的 Codex Desktop 应用仅支持 macOS —— 本项目将上游的 macOS `Codex.dmg` 转换为可运行的 Linux Electron 应用,提供原生的 `.deb` / `.rpm` / `.pkg.tar.zst` 包以及 Nix flake,并包含一个本地自动更新器,可从较新的上游 DMG 重建未来的 Linux 包。
## 支持的平台
| 发行版 / 家族 | 包管理器 | 生成的格式 | 备注 |
|---|---|---|---|
| Debian, Ubuntu, Pop!_OS, Mint, Elementary | `apt` | `.deb` | 当发行版仓库中的 Node 版本过旧时,会从 NodeSource 引导安装 Node 20+ |
| Fedora 41+ | `dnf5` | `.rpm` | |
| Fedora < 41 | `dnf` | `.rpm` | |
| openSUSE Tumbleweed / Leap | `zypper` | `.rpm` | 使用 `zypper --no-gpg-checks install` 进行本地重建 |
| Arch, Manjaro, EndeavourOS | `pacman` | `.pkg.tar.zst` | |
| NixOS / Nix | flake | 可直接运行 | `nix run github:ilysenko/codex-desktop-linux` |
任何基于 systemd 的系统都应该支持可选的自动更新器服务(`systemd --user`)。启动器优先在带有 `XWayland` 的 Wayland 环境下运行(以获得更好的 Electron 弹出窗口定位);纯 Wayland 会话则回退到 `--ozone-platform-hint=auto`。X11 也得到了完全支持。
## 功能特性
| 功能 | 状态 | 备注 |
|---|---|---|
| 标准 Codex Desktop UI | ✅ 始终支持 | 聊天、浏览器、文件、MCP 插件 |
| 自动更新器 (`codex-update-manager`) | ✅ 始终支持 | 检测较新的上游 DMG,在本地重建并安装 |
| 原生打包 (`.deb` / `.rpm` / `.pkg.tar.zst`) | ✅ 始终支持 | 一次性执行 `make package` 即可选择您的发行版 |
| Linux 托盘 + 热启动交接 | ✅ 始终支持 | 单实例锁定,第二个实例会聚焦窗口 |
| GUI 安装提示 (`kdialog` / `zenity`) | ✅ 若已安装 | 回退到交互式终端提示 |
| Linux 浏览器标注 | ✅ 始终支持 | 存储锚点截图,独立的标记渲染 |
| Linux Computer Use | ⚠️ 选择启用 / 受控 | 原生 Rust MCP 后端(AT-SPI + `ydotool` + GNOME Shell 或 XDG Desktop Portal)。**同时受 OpenAI 按账户进行的 Statsig 推送控制** —— 可以安装该包,但只有当 OpenAI 为您的账户启用该功能时,它才会出现在 UI 中。已在 Ubuntu/GNOME 上验证;KDE/wlroots 尚未验证。 |
| 服务器端控制的功能 (例如 `gpt-5.5`) | 🟡 服务器端 | OpenAI 按账户进行推送,非项目可控。构建新包不会解锁这些功能。 |
## 快速安装
最快途径:安装依赖,构建本地应用,构建原生包,然后安装。
```
git clone https://github.com/ilysenko/codex-desktop-linux.git
cd codex-desktop-linux
bash scripts/install-deps.sh
make build-app
make package # auto-detects deb / rpm / pacman
make install # installs the newest package from dist/
```
`make package` 会选择与您的发行版匹配的格式。随后 `make install` 将对新构建的产物执行相应的 `dpkg -i` / `dnf install` / `zypper install` / `pacman -U` 命令。
当 `npm` 可用时,首次启动可以自动为您安装 Codex CLI (`@openai/codex`);您也可以使用 `npm i -g @openai/codex`(如果您不希望全局安装到 root 目录,可使用 `npm i -g --prefix ~/.local @openai/codex`)提前安装。
### NixOS / Nix 一行命令
```
nix run github:ilysenko/codex-desktop-linux
```
flake 会处理依赖项并为 NixOS 打补丁 Electron。GitHub Actions 机器人每天在 `main` 分支上刷新一次上游 `Codex.dmg` 的 SRI 哈希值。如果您恰巧在上游 Codex 发布后立即尝试并遇到 `error: hash mismatch in fixed-output derivation`,请等待最多一天让机器人更新后重试。
`nix develop github:ilysenko/codex-desktop-linux` 可进入包含所需工具的开发环境 shell。
## Linux Computer Use
Linux Computer Use 是一个**选择启用**的插件,它允许 Codex 通过原生 Rust MCP 后端(`codex-computer-use-linux`)检查和控制 Linux 上的桌面应用程序。它支持:
- **应用列表与无障碍树** — 通过 AT-SPI 总线 (`org.a11y.Bus`)
- **屏幕截图捕获** — 主要通过 GNOME Shell DBus 进行,回退通过 XDG Desktop Portal (`org.freedesktop.portal.Screenshot`) 进行
- **输入模拟** — 按键、文本、点击、滚动、拖拽 — 通过带有 `ydotoold` 守护进程的 `ydotool` 进行
### 运行时依赖
```
# Debian / Ubuntu
sudo apt install ydotool
# Fedora
sudo dnf install ydotool
# Arch
sudo pacman -S ydotool
# openSUSE
sudo zypper install ydotool
```
`ydotool` 需要 `/dev/uinput` 访问权限。最简单的方法是以守护进程身份运行 `ydotoold` 并将您的用户添加到 `input` 组(然后重新登录):
```
sudo systemctl enable --now ydotoold
sudo usermod -a -G input "$USER"
```
如果您使用的不是 GNOME,则需要一个有效的 XDG Desktop Portal 实现 —— KDE Plasma 使用 `xdg-desktop-portal-kde`,sway / Hyprland 使用 `xdg-desktop-portal-wlr`。GNOME 默认附带可用的门户。
### 验证就绪状态
该插件提供了一个 `doctor` 工具。一旦 Computer Use 在 Codex UI 中可见,您可以向 LLM 发问:
返回的响应是一份结构化报告,涵盖 AT-SPI 总线可用性、GNOME Shell 版本、Desktop Portal 接口、`ydotool` / `ydotoold` / `/dev/uinput` 以及顶级就绪判定。您也可以直接调用后端二进制文件:
```
./codex-app/resources/plugins/openai-bundled/plugins/computer-use/bin/codex-computer-use-linux doctor
./codex-app/resources/plugins/openai-bundled/plugins/computer-use/bin/codex-computer-use-linux setup # enables GNOME accessibility
./codex-app/resources/plugins/openai-bundled/plugins/computer-use/bin/codex-computer-use-linux apps # lists running apps via AT-SPI
./codex-app/resources/plugins/openai-bundled/plugins/computer-use/bin/codex-computer-use-linux state Codex
./codex-app/resources/plugins/openai-bundled/plugins/computer-use/bin/codex-computer-use-linux screenshot
```
### 重要提示
**安装该软件包本身不会在 Codex UI 中启用 Computer Use。** 该功能除了本项目解锁的平台门控外,还受 OpenAI 按账户进行的 Statsig 推送(`computerUse` 功能标志)控制。如果您的账户尚未在 OpenAI 的推送群体中,该插件已暂存但不可见 —— 这与 `gpt-5.5` 模型推送的模式相同。目前没有不故意绕过 OpenAI 门控的项目端解决方案。
如果您想在不影响默认安装的情况下测试后端,并排开发变体会在不同的 ID 和 webview 端口下构建一个单独的应用:
```
make build-dev-app
make run-dev-app
```
如果需要,可以使用 `DEV_APP_ID`、`DEV_APP_NAME` 和 `CODEX_WEBVIEW_PORT` 覆盖开发标识。
## 自动更新管理器
该软件包安装了一个名为 `codex-update-manager` 的伴随服务。
- 它作为 `systemd --user` 服务运行,在应用启动时由启动器以最大努力模式启动。
- 每次应用启动也会触发一个后台 `check-now --if-stale`;当最后一次成功的上游检查仍然有效,或者另一个检查/重建/安装已经处于活动状态时,更新器会跳过该请求。并发检查通过内核支持的文件锁 (`flock(2)`) 进行序列化。
- 它在守护进程启动时以及每 6 小时检查一次上游的 `Codex.dmg`。
- 当检测到新的 DMG 时,它会使用 `/opt/codex-desktop/update-builder` 重建本地的原生包。
- 如果应用处于打开状态,更新会等待 Electron 退出。
- 当应用关闭时,更新器仅针对最终的原生包安装步骤使用 `pkexec`(带有 `--disable-internal-agent` 参数,因此桌面 polkit 代理会渲染认证对话框)。
- 在 Arch 上,最终的安装步骤是对本地重建的 `.pkg.tar.zst` 执行 `pacman -U --noconfirm`。
- 在 openSUSE 上,最终的安装步骤是对本地重建的 `.rpm` 执行 `zypper --non-interactive --no-gpg-checks install`(该包未签名,因为是在本地构建的)。
- 失败或被取消的 `pkexec` 提示(退出代码为 `126` / `127`)会将候选项保留为 `ReadyToInstall` 状态,并在下一次应用退出时重试,而不是转为永久的 `Failed` 状态。
- 被崩溃或重启中断的 `Installing` 状态会自动恢复。
- 在 Electron 启动前,启动器仅解析可用的 Codex CLI 路径。如果 CLI 缺失且启动器是从交互式终端启动的,它会在尝试自动安装之前进行提示。随后,更新器 CLI 预检默认在后台运行,以便 npm 注册表检查和后续更新不会阻塞第一个窗口。设置 `CODEX_SYNC_CLI_PREFLIGHT=1` 可恢复同步预检以进行调试。
- 该 CLI 预检为尽力而为:注册表检查有 1 小时的冷却时间,如果全局安装失败则回退到 `npm install -g --prefix ~/.local`,并在自动刷新不成功时让应用启动继续使用当前的 CLI。
使用以下命令检查实时服务和运行时文件:
```
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
```
运行时文件位于标准的 XDG 路径下:
```
~/.config/codex-update-manager/config.toml
~/.local/state/codex-update-manager/state.json
~/.local/state/codex-update-manager/service.log
~/.cache/codex-update-manager/
~/.cache/codex-desktop/launcher.log
~/.local/state/codex-desktop/app.pid
```
## 从源码构建 / 自定义 DMG
### 前置条件
您需要:
- **Node.js 20+** 以及 `npm` 和 `npx`
- `python3`, `7z` (或 `7zz`), `curl`, `unzip`, `make`, `g++`
- **Rust 工具链** (`cargo`),用于 `codex-update-manager` 和 `codex-computer-use-linux` crates
最简单的设置是使用捆绑的引导脚本:
```
bash scripts/install-deps.sh
```
它会自动检测 `apt`、`dnf5`、`dnf`、`pacman` 或 `zypper`,安装系统软件包,并在需要时通过 `rustup` 引导安装 Rust。
#### Apt 专用 (Debian / Ubuntu / Pop!_OS / Mint)
在 Ubuntu 22.04、24.04 和 Debian 12 上,原生的 `apt install nodejs` 会安装 Node.js 18,版本过旧。`install-deps.sh` 会首先尝试发行版的 `nodejs` 候选版本;如果低于 Node 20,它会从 NodeSource 引导安装 Node.js 22:
```
bash scripts/install-deps.sh # bootstraps Node 22 if needed
NODEJS_MAJOR=24 bash scripts/install-deps.sh # bootstrap a different maintained line
```
如果您在 Debian 或 Ubuntu 上手动安装依赖,请在运行 `./install.sh` 之前,通过 NodeSource、`nvm` 或其他兼容来源安装带有 `npm` 和 `npx` 的 Node.js 20+。除非您的软件仓库提供 Node.js 20 或更新版本,否则不要依赖普通的发行版 `apt install nodejs npm`。
Ubuntu 系列的 `p7zip-full` 可能对于较新的 APFS DMG 来说版本过旧。`install-deps.sh` 会将 `7zz` 引导安装到 `~/.local/bin`(设置 `SEVENZIP_SYSTEM_INSTALL=1` 可改为安装到 `/usr/local/bin`)。
#### 各发行版的手动依赖
```
# Fedora 41+
sudo dnf install nodejs npm python3 7zip curl unzip @development-tools
# Fedora < 41
sudo dnf install nodejs npm python3 p7zip p7zip-plugins curl unzip
sudo dnf groupinstall 'Development Tools'
# openSUSE
sudo zypper install nodejs-default npm-default python3 p7zip-full curl unzip
sudo zypper install -t pattern devel_basis
# Arch / Manjaro
sudo pacman -S --needed nodejs npm python p7zip curl unzip zstd base-devel
# Rust toolchain(任何发行版)
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
```
### 生成本地 Electron 应用
这将从上游 DMG 生成 `codex-app/` 目录,并将 Linux 启动器写入 `codex-app/start.sh`:
```
make build-app # downloads upstream DMG
make build-app DMG=/path/to/Codex.dmg # use a local copy
make run-app # launches the generated app
```
等效的直接命令:
```
./install.sh # default: download or reuse cached DMG
./install.sh /path/to/Codex.dmg # use a specific DMG
./install.sh --fresh # remove existing install dir + cached DMG
./codex-app/start.sh # run after build
```
如果您的系统上 `npm i -g` 需要提升权限:
```
npm i -g --prefix ~/.local @openai/codex
```
## 原生包格式
在执行 `make build-app` 之后,使用您需要的格式从 `codex-app/` 构建原生包:
| 格式 | 构建命令 | 输出 | 安装 |
|---|---|---|---|
| Debian | `make deb` 或 `./scripts/build-deb.sh` | `dist/codex-desktop_*.deb` | `sudo dpkg -i dist/codex-desktop_*.deb` |
| RPM (Fedora / openSUSE) | `make rpm` 或 `./scripts/build-rpm.sh` | `dist/codex-desktop-*.x86_64.rpm` | `sudo dnf install dist/codex-desktop-*.rpm` (Fedora) 或 `sudo zypper install dist/codex-desktop-*.rpm` (openSUSE) |
| Arch (pacman) | `make pacman` 或 `./scripts/build-pacman.sh` | `dist/codex-desktop-*.pkg.tar.zst` | `sudo pacman -U dist/codex-desktop-*.pkg.tar.zst` |
| 自动检测 | `make package && make install` | 匹配您的发行版 | 由 `make install` 处理 |
使用 `PACKAGE_VERSION=YYYY.MM.DD.HHMMSS+commitish ./scripts/build-*.sh` 覆盖包版本。
打包脚本仅重新打包 `codex-app/` 中已有的内容。它们不会自行下载或解压 DMG原生包声明了 `nodejs (>= 20)` 作为依赖,因为捆绑的更新管理器会在本地重建未来的包。它们还会拉取 `polkit`(或在较旧的 Debian/Ubuntu 上的 `policykit-1`)以及 `pkexec`,以便特权安装流程能够开箱即用。
### 更新器服务控制
安装原生包后:
```
make service-enable # enable + start the systemd --user service
make service-status # systemctl --user status
codex-update-manager status --json
```
除非您已将软件包安装到系统中,否则 `make service-enable` 不适用于未打包的纯仓库运行。
## Make 目标
```
make help
make check
make test
make build-updater
make build-app
make run-app
make build-dev-app
make run-dev-app
make deb
make rpm
make pacman
make package # auto-detect distro
make install # install latest dist/ artifact
make service-enable
make service-status
make clean-dist
make clean-state
```
## 故障排除
| 问题 | 解决方案 |
|---|---|
| `Error: write EPIPE` | 直接运行 `start.sh`,而不是通过管道传输输出 |
| 空白窗口 | 检查配置的 webview 端口是否已被占用:`ss -tlnp \| grep -E '5175\|5176'` |
| webview 端口出现 `ERR_CONNECTION_REFUSED` | webview HTTP 服务器启动失败。请确保 `python3` 可用且配置的端口空闲 |
| 卡在 Codex 启动画面 | 检查 `~/.cache/codex-desktop/launcher.log`。如果 webview 源验证失败,可能是另一个进程正在使用配置的 webview 端口,或者解压的 `content/webview/` 包不完整 |
| `CODEX_CLI_PATH` 错误 | 使用 `npm i -g @openai/codex` 或 `npm i -g --prefix ~/.local @openai/codex` 安装 |
| Electron 在 CLI 过期时挂起 | 重新运行启动器并检查 `~/.cache/codex-desktop/launcher.log` 和 `~/.local/state/codex-update-manager/service.log`。尽力而为的 CLI 预检会在自动刷新失败时发出警告 |
| GPU / Vulkan / Wayland 错误 | 在 Wayland 且 `DISPLAY` 可用的情况下,启动器会使用 `--ozone-platform=x11` 以兼容窗口定位。否则使用 `--ozone-platform-hint=auto`。GPU 沙箱/合成默认禁用 |
| 窗口闪烁 | GPU 合成默认禁用。如果闪烁持续,尝试 `./codex-app/start.sh --disable-gpu` 完全禁用 GPU 加速 |
| 沙箱错误 | 启动器已设置 `--no-sandbox` |
| 安装过期 / 缓存的 DMG | `./install.sh --fresh` 移除现有安装目录并重新下载 |
| Computer Use 插件在 UI 中不可见 | 最可能的原因是 OpenAI 按账户进行的 Statsig 推送(`computerUse` 功能标志)尚未为您的账户启用。构建/重新安装不会改变这一点 |
| Computer Use `doctor` 报告 `ydotool not running` | `sudo systemctl enable --now ydotoold` 并将您的用户加入 `input` 组 |
| Computer Use AT-SPI 树为空 | 运行 `codex-computer-use-linux setup` 开启 GNOME 无障碍功能,然后重启目标应用 |
| 移除包后 `codex-update-manager` 仍在运行 | 在受影响的会话中执行一次 `systemctl --user disable --now codex-update-manager.service`,然后确认 `/opt/codex-desktop` 已被移除 |
## 工作原理
1. `install.sh` 使用 `7z`/`7zz` 解压 `Codex.dmg`
2. 它从上游元数据中自动检测 Electron 版本,若失败则回退到固定常量
3. 它解压并修补 `app.asar`(Linux 文件管理器集成、托盘、单实例交接、浏览器注释修复、Computer Use 平台门控、Linux 不透明背景等)—— 每个补丁都采用软失败机制,使用正则表达式匹配
4. 它通过 `@electron/rebuild` 为 Linux 重建原生 Node 模块(`better-sqlite3`、`node-pty`)
5. 它下载匹配的 Linux Electron 运行时(缓存在 `~/.cache/codex-desktop/electron/` 下)
6. 它将 Linux 启动器写入 `codex-app/start.sh`
7. `scripts/build-{deb,rpm,pacman}.sh` 将 `codex-app/` 打包为原生产物
8. 安装后的包提供 `codex-update-manager` 以及一个 `systemd --user` 服务单元
9. 更新器监视较新的上游 DMG 并在本地重建未来的 Linux 包
macOS Codex 应用是一个 Electron 应用程序;`app.asar` 是与平台无关的 JavaScript,但捆绑了 macOS 原生模块和 macOS Electron 二进制文件。安装程序用 Linux 构建替换 macOS Electron 并重新编译原生模块。`sparkle` 模块被移除,因为它仅适用于 macOS。
解压后的应用需要一个本地 webview 源,因此启动器从 `content/webview/` 运行 `python3 -m http.server "$CODEX_LINUX_WEBVIEW_PORT" --bind 127.0.0.1`,导出 `ELECTRON_RENDERER_URL`,等待套接字,验证 `/index.html` 是否包含预期的 Codex 启动标记,然后才启动 Electron。默认应用使用端口 `5175`;开发版应用变体默认使用 `5176`。启动器在 XDG 状态目录下跟踪所属的 webview 服务器 PID,从相同的 `content/webview/` 目录重新发现孤立的服务器,并重用已验证的服务器,而不是杀死所有匹配该端口的进程。
如果检测到现有的 Electron 进程,启动器会使用热启动交接:它通过 Unix 域套接字发送启动动作参数(例如 `--new-chat`、`--prompt-chat`)然后退出,让正在运行的应用的单实例处理器聚焦到正确的窗口。
仅限原生包的启动器行为(桌面项提示、`codex-update-manager` 会话引导、启动时的更新检查)位于 `packaging/linux/codex-packaged-runtime.sh` 中,生成的启动器只有在打包安装中存在该文件时才会加载它。
关于未来用 Rust 替代本地 webview 服务器的当前评估位于 `docs/webview-server-evaluation.md`。
## 验证
在更改安装程序、打包或更新器逻辑后:
```
bash -n install.sh scripts/build-deb.sh scripts/build-rpm.sh scripts/build-pacman.sh scripts/install-deps.sh
node --check scripts/patch-linux-window-ui.js
node --test scripts/patch-linux-window-ui.test.js
bash tests/scripts_smoke.sh
cargo check -p codex-update-manager
cargo test -p codex-update-manager
cargo check -p codex-computer-use-linux
cargo test -p codex-computer-use-linux
make package
```
如果 `dpkg-deb` 可用:
```
dpkg-deb -I dist/codex-desktop_*.deb
dpkg-deb -c dist/codex-desktop_*.deb | sed -n '1,40p'
```
如果 `rpmbuild` 可用:
```
make rpm
```
如果 `makepkg` 可用 (Arch):
```
./scripts/build-pacman.sh
pacman -Qip dist/codex-desktop-*.pkg.tar.zst
pacman -Qlp dist/codex-desktop-*.pkg.tar.zst | sed -n '1,40p'
```
## 版本控制
`codex-update-manager` 当前的 crate 版本:`0.6.0`
SemVer 策略:
- **修订版** 用于修复、文档和仅维护更新
- **次版本** 用于兼容的功能添加
- **主版本** 用于不兼容的 CLI、持久化状态或安装流程的更改
详情请参见 [CHANGELOG.md](CHANGELOG.md)。
## 免责声明
这是一个非官方的社区项目。Codex Desktop 是 OpenAI 的产品。本工具不重新分发任何 OpenAI 软件;它自动化了用户对自己副本执行的转换过程。
## 许可证
MIT
标签:AI编程助手, Arch Linux, Codex, deb, dmg, DNS解析, Electron, Fedora, Linux桌面应用, MITM代理, Nix, NixOS, OpenAI, pkg.tar.zst, rpm, Wayland, X11, 云资产清单, 内存规避, 包管理, 可视化界面, 威胁情报, 开发者工具, 开源项目, 数据集, 桌面环境, 类型转换, 系统工具, 系统托盘, 网络信息收集, 自动化安装, 自动更新, 逆向工程, 通知系统