拆解 ChatGPT Linux 桌面应用
拆解 ChatGPT Linux 桌面应用:扒开壳,里面是一个叫 Codex 的引擎
本文基于对 OpenAI 官方 deb 包(chatgpt 26.924.22138,Linux x64)的静态拆解,全程未逆向混淆代码,所有结论均来自包内明文元数据与可观测的进程/文件结构。
引子:一个叫 codex-launcher 的"ChatGPT"
一切从命令行开始。装完 OpenAI 官方的 ChatGPT deb 包后,/usr/bin/chatgpt 其实是个两行的 shell 脚本,而它的文件名有点露馅:
$ file /usr/bin/chatgpt
/usr/bin/chatgpt: symbolic link to ../lib/chatgpt/codex-launcher
启动器叫 codex-launcher。顺着这条线往下挖,会发现这个 1.5GB 的 "ChatGPT" 应用,内部身份完全是另一个人。app.asar 里的 package.json:
{
"name": "openai-codex-electron",
"productName": "Codex",
"description": "Codex",
"author": "OpenAI",
"main": ".vite/build/early-bootstrap.js"
}
更实锤的是元数据文件 owl-electron-app.json:
{
"packagedFrom": "/home/runner/work/openai/openai/codex/codex-apps/electron/out/ChatGPT-linux-x64",
"runtimeName": "owl"
}
构建路径指向 CI 上的 openai/codex 单仓库,目录是 codex/codex-apps/electron,产物名 ChatGPT-linux-x64。也就是说:Linux 版 ChatGPT 桌面应用与 Codex 桌面应用出自同一套代码库,"ChatGPT" 只是外层品牌。壳层代号 Owl(owl-app.ini 里 [Owl] UserDataDirectoryName=Codex,连 Chromium 用户数据目录都叫 ~/.config/Codex)。
三条独立的版本线先记下,后文会反复出现:应用 26.924.22138、Electron 42.3.0、内置引擎 codex-cli 0.158.0-alpha.2.1。
总体架构
┌──────────────────────────────────────────────────────────────┐
│ deb: chatgpt 26.924.22138 (/usr/lib/chatgpt) │
│ │
│ Electron 42.3.0 壳(代号 Owl) │
│ ┌──────────────────────────┐ ┌──────────────────────────┐│
│ │ 主进程 .vite/build/* │ │ 渲染窗口 + 内嵌浏览器侧栏 ││
│ │ main 4.1MB + 服务级 chunks│◄─►│ browser-page-preload ││
│ │ app-protocol / policy │IPC│ sandbox-preload ││
│ └────────┬─────────────────┘ └──────────────────────────┘│
│ │ spawn + 原生管道 账号 / 云流量 │
│ ┌────────▼─────────────────┐ auth.openai.com │
│ │ codex(272MB Rust 静态) │ wss://codex-cloud- │
│ │ app-server 守护进程 │ backend.chatgpt.com │
│ └────────┬─────────────────┘ │
│ │ 共享 ~/.codex │
│ ┌────────▼───────────────────────────────────────────────┐ │
│ │ 组件: cua_node · code-mode-host · tectonic · rg │ │
│ │ 插件: codex-app-tools · browser · chrome · latex · … │ │
│ └─────────────────────────────────────────────────────────┘ │
└──────────────────────────────────────────────────────────────┘
主进程经 Vite + rolldown 打包(main、app-protocol、policy、service、startup-requirements、shell-env 等按职责拆分的 chunk),构建链是 electron-forge,原生模块只有两个小文件:hid-topology-watcher.node(外设监控)和 remote-control-device-key.node(远程控制设备密钥)。
引擎:272MB 的 Rust 二进制
resources/codex 是一个静态链接的 ELF,即 Codex CLI 本体(codex-cli 0.158.0-alpha.2.1)。跑一下 --help,会发现一半子命令都是为"被宿主应用驱动"准备的:
app-server(experimental)——Run the app server or related tooling,下辖daemon/proxy/generate-ts;agents——"Browse all agent sessions on the shared local app-server daemon";remote-control、queue、resume、apply……
关键设计在这里:桌面应用不把 codex 当一次性子进程,而是作为常驻的 app-server 守护进程。主进程代码里 codexHome 出现 248 次,codexCliPath、codex-app-server、codex-renderer-window: 等协议前缀密集出现;~/.codex/ipc/ipc.sock 就是那个 Unix 控制 socket——app-server proxy 子命令的注释直接写着 "Proxy stdio bytes to the running app-server control socket"。
换句话说,CLI 和桌面应用是同一个 daemon 的两个客户端。终端里跑过的会话,桌面应用里都在;反过来也一样。
组件弹药库:resources/ 下约 600MB 的"挂件"
| 组件 | 体积 | 说明 |
|---|---|---|
codex |
272MB | Rust Agent 引擎,app-server 模式 |
codex-code-mode-host |
71MB | "code mode" 执行宿主(静态 ELF) |
cua_node/ |
209MB | 定制 Node 24.21.0-cua.1 + node_repl 二进制 |
tectonic/ |
26MB | LaTeX 引擎 |
rg |
— | ripgrep |
plugins/openai-bundled/ |
23MB | 七个内置插件 |
native/*.node |
— | HID 拓扑监听、远程控制设备密钥 |
cua_node 值得单独说。manifest.json 声明这是 OpenAI 自建的 Node 分支 24.21.0-cua.1,专为 CUA(Computer Use Agent) 提供代码执行环境:lib/node_modules 里带 playwright(浏览器控制)、sharp、@oai 模块,另附一个独立的 node_repl 静态二进制作为 agent 写代码、跑代码的 REPL。主进程里有对应的 computer-use-native-pipe-server,审批消息走 computer-use-approval: 前缀的原生管道,单条消息上限 8MB——鼠标点击屏幕之前,先过一道人肉闸门。
七个内置插件:codex-app-tools、browser、chrome(自带 extension-host 扩展宿主)、deep-research、visualize、unified-computer-use、latex。skills/.curated 里有两个内置技能:onboard-new-user 和 hatch-pet——后文有彩蛋。
可下载的"主运行时"
应用跑文档类能力时会按需拉取 codex-primary-runtime 到 ~/.cache/codex-runtimes/,runtime.json 写得明明白白:
{
"bundleVersion": "26.904.11930",
"artifactToolVersion": "2.8.59",
"libreOfficeVersion": "25.2-headless-codex.1",
"nativeDependencies": ["libheif", "jxrlib", "libreoffice-headless", "poppler", "git"],
"nodeVersion": "v24.19.0",
"pythonVersion": "3.12.14"
}
LibreOffice headless + poppler,这就是 documents/visualize 插件处理 docx/xlsx/slides/PDF 的底气——整套文档工具链独立于应用本体,按 bundle 版本化管理,坏了可以单独重装。
数据层:CLI 和 GUI 共用 ~/.codex
这是整个拆解里最能说明产品意图的证据。桌面应用没有发明私有数据格式,直接把 Codex CLI 的 home 当作唯一数据层:
~/.codex/
├── config.toml # CLI 配置 + [desktop] 段(GUI 设置写回这里)
├── auth.json # 登录凭据
├── ipc/ipc.sock # app-server Unix 控制 socket
├── sessions/ + session_index.jsonl
├── logs_2.sqlite goals_1.sqlite memories_1.sqlite queue_1.sqlite
├── skills/ plugins/ pets/ node_repl/ browser/ computer-use/
└── dictation-history/ shell_snapshots/
config.toml 的 [desktop] 段(followUpQueueMode、conversationDetailMode、open-in-target-preferences)就是 GUI 偏好设置的落点;[marketplaces] 段注册内置插件源;记忆、目标、跟进队列各自一张 SQLite 表。另一层 ~/.config/Codex 则是标准 Chromium profile(SingletonLock、Local State、browser-sidebar-page-states.json……)。
由此带来的用户体验是:你在终端用 codex,和桌面应用看到的是同一份会话、技能与插件,codex resume 随时接管桌面会话。
顺带一个安全观察:config.toml 支持给自定义 model provider 写 experimental_bearer_token,是明文落盘(0600 权限)。BYOK 用户注意别把 ~/.codex 扫进云备份或同步盘。
两条控制通道
整个应用的骨架,是两条方向相反的通道:
① GUI → Codex:Electron 主进程拉起 app-server daemon,线程/回合/审批走 Unix socket 上的 app-server 协议。协议是版本化的(如 codexAppsMcp20260728),而且提供 generate-ts 子命令直接生成协议的 TypeScript 绑定——官方鼓励第三方宿主接入。
② Codex → GUI:内置插件 codex-app-tools(v0.1.5,自述 "Exposes Codex desktop app tools through one local MCP server")把应用能力注册成 MCP 工具:
"tools": {
"automation_update": { "approval_mode": "prompt" },
"create_thread": { "approval_mode": "prompt" },
"send_message_to_thread": { "approval_mode": "prompt" },
"fork_thread": { "approval_mode": "prompt" },
"handoff_thread": { "approval_mode": "prompt" }
}
通过 CODEX_APP_TOOLS_PIPE_PATH 原生管道回连应用,全部默认人工审批。
两条通道合起来是个闭环:agent 干活干到一半,可以自己"开个新会话"、"把任务移交给另一个线程"、甚至驱动 GUI 自动化——桌面应用自己,也是 agent 的一个 MCP 工具。
云侧
wss://codex-cloud-backend.chatgpt.com/:WebSocket 同步线程状态;<codex_delegation>标签:本地与 chatgpt.com/codex 云端任务互相委托/移交;- 深链与装机引导:
chatgpt.com/codex、/codex/deeplink、/codex/desktop-session、/codex/install.sh|.ps1; - 账号与支付:
auth.openai.com、api.openai.com/{auth,mfa,profile}、pay.openai.com; - 实验与灰度:Statsig 全家桶(
ab.chatgpt.com、api.oaistatsig.com),状态缓存在~/.config/Codex/statsig-state.json。
权限与沙箱
- MCP 工具默认
default_tools_approval_mode: "approve",危险工具(如自动化)单列为prompt; - Computer Use 有独立审批流(
computer-use-approval:原生管道协议); - 引擎自带
sandbox子命令,命令执行在平台沙箱内进行; - 渲染层 preload 分沙箱化(
sandbox-preload.js/browser-page-preload.js),本地页面走自定义app-protocol协议。
结语:为什么这个设计值得琢磨
"把 Agent 引擎嵌进应用"是常见做法,OpenAI 选了另一条路:引擎做成系统级常驻服务,应用只是它的一个客户端。三个收益:
- CLI、桌面、未来的 IDE 插件天然共享会话与凭据,"在哪儿开始、在哪儿继续"不再重要;
- Rust 引擎与 Electron 壳彻底解耦——应用 26.924.x、引擎 0.158.x-alpha、运行时 bundle 26.904.x,三条版本线独立演进,互不拖累;
- 审批策略与安全模型收敛在 daemon 一层,桌面壳再怎么换皮,闸门不动。
代价也直白:组件膨胀(1.5GB,其中引擎、CUA、文档运行时合计约 600MB),以及桌面与 CLI 之间的兼容只能靠 bundle 协议与版本协商兜底。
最后留个彩蛋:翻 ~/.codex 时看到 pets/ 目录,对应内置技能 hatch-pet——这个 1.5GB 的应用里,还养着一只电子宠物。
浙公网安备 33010602011771号