Codex++是如何工作的?asar补丁+预加载注入+运行时加载三层架构完整解析
【免费下载链接】codex-plusplusCodex++ tweak system for the Codex desktop app项目地址: https://gitcode.com/gh_mirrors/co/codex-plusplus
Codex++ 是一个为 Codex 桌面应用打造的tweak 系统(插件注入框架):只需一次性对本地Codex.app打补丁,就能注入自定义功能、修复 UI 问题,并内置一个应用内的插件管理器——全程无需重新编译 Codex。这篇文章带你完整走一遍「asar 补丁 → 预加载注入 → 运行时加载」三层架构的工作原理,看懂这个 Electron 应用是如何被"安全改造"的。
全局速览:Codex++ 的三层架构一览
先记住这张总表,后文逐层展开 🧭:
| 层级 | 所在位置 | 职责 | 核心文件 |
|---|---|---|---|
| ① asar 补丁 | Codex.app/Contents/Resources/app.asar内部 | 一次性把入口换成 loader 桩 | asar.ts |
| ② 预加载注入 | asar 内 loader + 用户目录runtime/ | 在主进程和渲染进程各挂一个钩子 | loader.cjs |
| ③ 运行时加载 | <用户目录>/runtime/+tweaks/ | 发现、启停、热重载插件 | main.ts |
其中「用户目录」即 macOS 上的~/Library/Application Support/codex-plusplus/、Windows 上的%APPDATA%/codex-plusplus/。补丁之外的一切(runtime、插件、配置、日志)都放在应用包外面,这是整个架构的精髓。
第一层:asar 补丁——一次性的"打孔"操作
Codex 桌面应用是典型的 Electron 应用:几乎所有代码都打包在app.asar这个压缩归档里,入口由归档内package.json的main字段决定。安装器做的事可以用一句话概括:把入口指针从 Codex 自己的启动脚本改写成 Codex++ 的 loader 桩。
具体流程有 5 步关键操作:
- 备份:先把原始
Codex.app完整备份到backup/目录,随时可回滚; - 改写入口:解包 asar,把
package.json的main指向codex-plusplus-loader.cjs,同时在__codexpp字段里记录原入口名和用户目录路径; - 重算校验和:把新 asar 头部 JSON 的 SHA-256 写回
Info.plist的ElectronAsarIntegrity字段——因为 Electron 启动时会校验这个哈希,不改就会拒绝启动; - 关闭安全熔断:顺手把 Electron Framework 二进制里的
EnableEmbeddedAsarIntegrityValidationfuse 关掉,作为双保险; - 重新签名:macOS 上用本机专属的 "Codex++ Local Signing" 身份重签应用,保证 Gatekeeper 放行。
这套"解包 → 修改 → 重打包"的核心实现在 patchAsar() 里,它还会精确保留原 asar 的 unpacked 文件清单,避免require找不到模块。
💡为什么只改入口而不换整个 asar?Codex 的 asar 约有 115 MB,每次安装/更新都整包复制太慢;而改入口只增加约 1 KB,轻量且幂等。详见 docs/ARCHITECTURE.md。
第二层:预加载注入——让运行时"抢跑"在 Codex 之前
启动 Codex 后,Electron 读取 asar 里的main字段,加载到的第一个脚本就是 loader 桩。它的代码不到百行,但干了一件关键的事(见 loader.cjs):
- 从
package.json读回用户目录路径,写入CODEX_PLUSPLUS_USER_ROOT环境变量; - 先
require用户目录下的runtime/main.js(Codex++ 主进程入口); - 后
require被替换下来的 Codex 原始入口。
顺序很重要:runtime 会在 Codex 创建任何窗口之前钩住 Electron 的 session,通过session.registerPreloadScript()(旧版本回退到setPreloads(),见 registerPreload())把preload.js追加进每个渲染进程——注意是"追加"而非"替换",所以 Codex 自带的 preload 照常运行,互不干扰。
为什么选 preload 而不是直接改 React 源码?docs/ARCHITECTURE.md 里解释得很直白:Codex 是 Vite 打包的单 chunk 压缩产物,没有任何稳定的模块注册表可挂钩,字符串级改压缩代码每发一个新版就碎一次;而 preload + DOM 观察只依赖稳定的界面特征(如[role="dialog"]),所以大部分 Codex 更新都能直接兼容。
preload 进入渲染进程后(preload/index.ts)会按序做四件事:安装 React 全局钩子(供后续遍历组件树)→ 启动设置页注入器 → 向主进程 IPC 拉取插件清单并逐个start()→ 订阅"插件已变更"广播以支持热重载。
其中最有视觉存在感的是设置页注入:它监听设置页 DOM,动态添加 "Codex++" 分组,注入 ⚙️ Config、☰ Tweaks、◇ Tweak Store 三个入口(布局逻辑见 settings-injector.ts)。从此你可以在应用内直接开关、配置每一个 tweak。
第三层:运行时加载——插件的发现与热重载
真正"干活"的插件(tweak)全部住在用户目录的tweaks/下,每个插件就是一个小文件夹:
my-tweak/ ├── manifest.json # 名称、版本、作用域等元数据 └── index.js # 入口,暴露 start(api) / stop()主进程启动时用 discoverTweaks() 扫描该目录:读manifest.json、校验合法性(必须声明githubRepo等字段)、定位入口文件。随后按作用域分发——main插件在主进程立即启动,renderer插件由各窗口的 preload 启动。
这层的几个巧思值得新手特别注意:
- 🔄热重载:main.ts 用 chokidar 盯着
tweaks/目录,文件改动落定后防抖 250ms 就停止旧插件、清模块缓存、重新发现并广播codexpp:tweaks-changed——保存即生效,无需重启应用; - 📦沙盒存储:渲染进程插件没有 Node 文件系统权限,读写文件走 IPC 落到各自的
tweak-data/<id>/沙盒目录,互不越界; - 🛡️失败隔离:loader 里每个步骤都包在
safe()里,就算 Codex++ 自身崩了,也会"吞掉错误、放行原入口"——插件系统坏了可以,Codex 打不开不行; - 🏪应用内商店:设置页的 Tweak Store 会拉取经过人工审核的插件注册表,安装时锁定到审核通过的 commit,插件更新只提示、绝不自动替换。下图就是商店里 "Goal" 插件的图标:
想动手写一个插件?完整 API 和示例在 docs/WRITING-TWEAKS.md。
为什么这样设计?4 个关键取舍
| 设计选择 | 换来的好处 |
|---|---|
| 只改 asar 入口(+1 KB)而非整包替换 | 安装/更新极快,改动幂等可重放 |
| 运行时放在用户目录而非应用包内 | 迭代插件/运行时不用重跑安装器 |
| preload + DOM 观察而非改 React 源码 | 与 Codex 打包结构解耦,抗版本更新 |
setPreloads追加而非webPreferences.preload覆盖 | 不破坏 Codex 自带 preload,零冲突 |
更新与自愈:补丁被覆盖怎么办?
Codex 官方走 Sparkle 自动更新时,新包会直接盖掉补丁——应用照常启动,但插件暂时失效。别慌,watcher 机制会接管:系统级监视器(macOS 盯app.asar,Windows 登录时检查)发现哈希漂移后,自动执行codexplusplus repair --quiet。repair是幂等的:哈希没变就直接退出,变了就对新包重打补丁并刷新用户目录里的 runtime(不碰你的插件代码)。
常用命令速查:codexplusplus status(查看状态)、repair(手动修复)、safe-mode(临时停用全部插件排查问题)、uninstall(一键还原)。遇到问题先看 docs/TROUBLESHOOTING.md。
写在最后:一图记住整个启动链路
把三层串起来,Codex++ 的完整启动链路是这样的:
启动 Codex → asar 入口指向loader 桩→ loader 先加载用户目录的runtime/main.js→ runtime 给所有 session追加 preload.js并发现 tweaks → 再加载 Codex 原始入口 → 设置页被注入Tweaks 管理面板→ 插件保存即热重载
一句话总结:asar 补丁负责"开门",预加载注入负责"布线",运行时加载负责"通电"。门只在安装时开一次,电却可以随手开关——这就是 Codex++ 用最小侵入实现完整插件体系的秘密所在。
【免费下载链接】codex-plusplusCodex++ tweak system for the Codex desktop app项目地址: https://gitcode.com/gh_mirrors/co/codex-plusplus
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考