Codex的定制皮肤在闲鱼上居然能卖99元,真是一个不错的生意。但“换一张背景图”和“做一套完整皮肤”是两回事。
前者只会改变右侧内容区;后者还要处理全屏背景、侧栏磨砂、输入框可读性、导航图标、页面切换后的自动恢复,以及 Codex 重启时的启动方式。
最终结果不是覆盖在窗口上的假截图。侧栏、任务、卡片、输入框和快捷键仍然是 Codex 原生控件。
本文以 macOS、Codex Desktop 26.707.x、Codex Dream Skin Studio 1.1.1 为例。第三方项目和 Codex 都可能更新,选择器或安装细节变动时,应以仓库最新 README 和实际 DOM 为准。
一、先理解它如何工作
Dream Skin 不修改 /Applications/ChatGPT.app、app.asar 或应用签名。它使用 Codex 自带且经过签名验证的 Node.js,通过只绑定 127.0.0.1 的 Chrome DevTools Protocol(CDP)端口,把 CSS 和少量 DOM 装饰注入 Codex 渲染页。
这带来三个直接结论:
- Codex 必须带调试端口启动。直接点击普通 Codex 图标重新打开,会绕过皮肤启动器。
仓库中的 macos/SKILL.md 是可选的 Codex 能力说明,不是皮肤本体。真正运行的是安装到 ~/.codex/codex-dream-skin-studio 的脚本、CSS 和注入器。
二、准备环境
开始前确认:
- 官方 Codex Desktop 已安装,并至少启动过一次;
- ~/.codex/config.toml 已存在;
- 能接受主题运行时开放一个仅限本机回环地址的调试端口。
先关闭不必要的 Codex 窗口,并为后续文件保留一个工作目录:
三、安装前检查
先跑真实环境检查:
正常结果应包含:
如果出现默认图片不存在
我们在 2026 年 7 月 16 日拉取 main 时,遇到过 macos/assets/theme.json 指向未提交 JPG 的情况,错误类似:
先检查 theme.json 的 image 字段对应文件是否真的存在。如果不存在,而仓库中有 portal-hero.png,可将它改为:
这只是修正演示主题的资源引用,不涉及官方 Codex 文件。
如果完整测试停在深色主题断言
该版本安装逻辑已经不再强制 appearanceTheme = "dark",而旧测试仍可能检查这个字段。应区分“测试断言过期”和“安装环境失败”:以 doctor-macos.sh、注入载荷检查和 live DOM 验证为准,不要为了让旧断言通过而强制改回深色。
四、安装 Dream Skin 引擎
先安装但不立即重启 Codex:
安装后主要路径如下:
| |
|---|
| ~/.codex/codex-dream-skin-studio |
| ~/Library/Application Support/CodexDreamSkinStudio |
| ~/Library/Application Support/CodexDreamSkinStudio/theme |
| ~/Library/Application Support/CodexDreamSkinStudio/theme-backup.json |
桌面会生成四个入口:
- Codex Dream Skin - Customize.command
- Codex Dream Skin - Verify.command
- Codex Dream Skin - Restore.command
五、把自己的图片做成主题
可以双击桌面的 Customize,也可以直接运行命令。
本次机器人花田主题采用深海蓝、天空蓝、草绿色和花朵橙红:
脚本会把原图转换为适合注入的 JPEG,限制最长边与文件大小,再生成 theme.json。原图不会被修改。
六、从“右侧背景”升级为全屏沉浸式
默认自定义模式把图片主要应用到 main.main-surface,所以侧栏不会铺同一张图。要做全屏效果,应把图片放到 body,再把侧栏、内容区和输入框改成玻璃层。
在 macos/assets/dream-skin.css 末尾增加一组独立覆盖规则。核心结构如下:
这里不要一味追求透明。侧栏承担高密度导航,输入框承载文字输入,它们都应该比背景更实。任务区可以更透明,但必须保证长文本仍可读。
七、制作一套机器人花田侧栏图标
单张背景不会自动生成图标。完整皮肤需要为每个导航入口制作 SVG,并建立 DOM 映射。
本次图标体系使用统一的视觉语法:
SVG 文件放在:
统一使用 24×24 viewBox、1.7 px 圆角描边。主线采用 #087F69,机械填充采用半透明 #2BA7D8,花朵点缀采用 #E65A32。
不要直接替换按钮 HTML
最危险的做法是覆盖按钮 innerHTML。这样可能破坏 React 事件、焦点、快捷键、路由和无障碍名称。
更稳的方式是在 renderer-inject.js 中:
- 只扫描 aside.app-shell-left-panel;
- 候选限制为 button、a、[role="button"]、[role="link"];
- 插入 aria-hidden="true" 的装饰 SVG;
- cleanup 时移除所有注入节点与 class。
映射表可以写成:
Codex 会把快捷键附在文字后,例如 新建任务⌘N 和 聊天⌥⌘N。匹配前应去掉快捷键尾缀:
不要使用 nth-child 或构建产物中的哈希 class。它们在 Codex 更新、语言切换或侧栏项目增减后很容易失效。
处理原生图标留下的空槽
只隐藏原 SVG 不够。Codex 的原图标通常位于固定宽度的 w-4 span 中;SVG 隐藏后,这个 span 仍会占位,造成图标和文字之间出现大缝隙。
正确做法是只在父容器确实仅包含原 SVG 时标记整个槽:
对应 CSS:
不要再给新图标设置 margin-right。Codex 按钮本身已有 gap-2,额外 margin 会把标准 8 px 间距叠加成 16 px。
八、把修改后的版本同步到安装目录
如果先在克隆仓库中修改,再重新运行安装器即可:
也可以在开发时只同步相关文件,但正式交付更推荐重新运行安装器,避免源目录和安装目录版本漂移。
主题图片保存在 Application Support 中,重新部署引擎不会要求你重新选择图片。
九、正确启动 Codex
这是整个流程最容易忽略的一步。
普通点击 Codex 图标启动时,进程参数中没有:
此时即使主题文件和 injector 仍存在,也无法注入,表现就是“重启后皮肤没了”。
正确方式是双击桌面的:
或在 Terminal 运行:
第一次应用需要关闭并重新拉起 Codex。应用启动较慢时,应等待脚本自己的 45 秒窗口,不要在端口刚启动前就判定失败。
十、验证完整皮肤
1. 检查运行状态
理想状态应接近:
2. 验证真实 DOM
不要只看“背景出现了”。完整验收至少包括:
- 每个图标 pointer-events: none;
本次最终 live DOM 验证为 6/6 图标可见,六项间距均为 8 px。
十一、常见故障
1. 重启后没有皮肤
先看 Codex 进程是否带 --remote-debugging-port=9341。没有就说明是普通方式启动。关闭后使用 Codex Dream Skin.command。
2. 状态显示 active,但 cdp=false
这是旧状态文件或 injector 进程还在,但实际 Codex 没有监听端口。不要只相信状态文件,应同时检查端口与真实进程参数。
3. 图标位置存在,但图形不显示
定时 ensure() 可能把新 SVG 误标成原生图标。寻找原生 SVG 时必须排除 .dream-sidebar-icon 内部节点:
4. 图标和文字之间空隙很大
隐藏 SVG 的同时折叠原生图标 span;不要给新图标重复添加 margin。最终应测量实际像素,而不是只凭肉眼判断。
5. 启动脚本偶发退出码 141
在 set -o pipefail环境中,类似 codex_main_pids | head -n 1 的管道可能因 SIGPIPE 返回 141。应区分脚本管道问题与皮肤资源问题;必要时检查真实进程和端口,再直接执行一次 injector 验证。
6. 展示图比实际效果更“完整”
仓库图库里部分图片是效果合成预览,不是纯背景素材。人物贴纸、定制文字、装饰卡片和专属图标不会从一张图片里自动生成。完整效果必须分别制作资产并写映射。
十二、恢复官方外观
最简单的方法是双击桌面的:
命令行恢复:
这会停止注入器、移除 live 皮肤,并恢复安装时保存的桌面外观配置。
结语
真正可用的 Codex 皮肤,不是把一张图铺到窗口上,而是在三个目标之间找平衡:
背景图负责氛围,磨砂层负责可读性,SVG 图标负责一致性,CDP 启动与 live DOM 验证则负责让这一切真正运行起来。
如果只记住一件事:不要只验证“看起来像成功”。检查端口、进程参数、真实 DOM、点击区域和回滚路径,才算完成了一套皮肤。