codex-plusplus-tweak-system

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

codex-plusplus Tweak System

codex-plusplus 调整系统

Skill by ara.so — Daily 2026 Skills collection.
codex-plusplus
is a tweak injection system for the Codex desktop app (Electron-based). It patches
app.asar
, injects a loader stub, and runs a hot-reloadable runtime from the user directory. Tweaks are small ESM modules with a manifest and
start/stop
lifecycle — no app rebuild required.

技能来自 ara.so — 2026日常技能合集。
codex-plusplus
是一款针对Codex桌面应用(基于Electron)的调整项注入系统。它会修补
app.asar
,注入加载器存根,并从用户目录运行支持热重载的运行时。调整项是带有清单和
start/stop
生命周期的小型ESM模块——无需重新构建应用。

Installation

安装

Homebrew (macOS, recommended)

Homebrew(macOS,推荐)

sh
brew install b-nnett/codex-plusplus/codexplusplus
codexplusplus install
sh
brew install b-nnett/codex-plusplus/codexplusplus
codexplusplus install

Bun (global)

Bun(全局安装)

sh
bun install -g github:b-nnett/codex-plusplus
codexplusplus install
sh
bun install -g github:b-nnett/codex-plusplus
codexplusplus install

Source bootstrap (macOS / Linux)

源码引导安装(macOS / Linux)

sh
curl -fsSL https://raw.githubusercontent.com/b-nnett/codex-plusplus/main/install.sh | bash
sh
curl -fsSL https://raw.githubusercontent.com/b-nnett/codex-plusplus/main/install.sh | bash

Windows PowerShell

Windows PowerShell

powershell
irm https://raw.githubusercontent.com/b-nnett/codex-plusplus/main/install.ps1 | iex
The installer:
  1. Locates
    Codex.app
    (or Windows equivalent)
  2. Backs up the original to
    ~/.codex-plusplus/backup/
  3. Patches
    app.asar
    to require the loader
  4. Recomputes asar header SHA-256, writes it into
    Info.plist
  5. Flips
    EnableEmbeddedAsarIntegrityValidation
    in the Electron Framework binary
  6. Re-signs ad-hoc on macOS (
    codesign --force --deep --sign -
    )
  7. Installs a launch agent / login item for auto-repair on Codex updates
  8. Installs default tweaks unless
    --no-default-tweaks
    is passed

powershell
irm https://raw.githubusercontent.com/b-nnett/codex-plusplus/main/install.ps1 | iex
安装程序会执行以下操作:
  1. 定位
    Codex.app
    (或Windows对应版本)
  2. 将原始文件备份到
    ~/.codex-plusplus/backup/
  3. 修补
    app.asar
    以引入加载器
  4. 重新计算asar头的SHA-256,并写入
    Info.plist
  5. 在Electron Framework二进制文件中开启
    EnableEmbeddedAsarIntegrityValidation
  6. 在macOS上进行临时签名(
    codesign --force --deep --sign -
  7. 安装启动代理/登录项,以便在Codex更新时自动修复
  8. 安装默认调整项,除非传入
    --no-default-tweaks
    参数

Key CLI Commands

核心CLI命令

sh
codexplusplus install              # Patch Codex and install runtime
codexplusplus install --no-default-tweaks  # Skip default tweak set

codexplusplus status               # Show patch status and runtime version
codexplusplus doctor               # Diagnose issues (integrity, signing, etc.)
codexplusplus repair               # Re-apply patch (e.g. after Codex update)
codexplusplus repair --quiet       # Silent repair (used by watcher/launch agent)

codexplusplus update               # Pull latest codex-plusplus source, rebuild, repair
codexplusplus update-codex         # Restore official-signed Codex for Sparkle updater

codexplusplus uninstall            # Revert all patches, restore backup

codexplusplus tweaks list          # List installed tweaks and enabled state
codexplusplus tweaks open          # Open user tweaks directory in Finder/Explorer

sh
codexplusplus install              # 修补Codex并安装运行时
codexplusplus install --no-default-tweaks  # 跳过默认调整项集合

codexplusplus status               # 显示补丁状态和运行时版本
codexplusplus doctor               # 诊断问题(完整性、签名等)
codexplusplus repair               # 重新应用补丁(例如Codex更新后)
codexplusplus repair --quiet       # 静默修复(由监视器/启动代理使用)

codexplusplus update               # 拉取最新codex-plusplus源码、重建并修复
codexplusplus update-codex         # 恢复官方签名的Codex版本以适配Sparkle更新器

codexplusplus uninstall            # 还原所有补丁,恢复备份

codexplusplus tweaks list          # 列出已安装的调整项及其启用状态
codexplusplus tweaks open          # 在Finder/资源管理器中打开用户调整项目录

File Locations

文件位置

ArtifactPath
Loader stub
Codex.app/Contents/Resources/app.asar
Runtime
<user-data-dir>/runtime/
Tweaks
<user-data-dir>/tweaks/
Config
<user-data-dir>/config.json
Backup
<user-data-dir>/backup/
<user-data-dir>
per OS:
  • macOS:
    ~/Library/Application Support/codex-plusplus/
  • Linux:
    $XDG_DATA_HOME/codex-plusplus/
    (default
    ~/.local/share/codex-plusplus/
    )
  • Windows:
    %APPDATA%/codex-plusplus/

产物路径
加载器存根
Codex.app/Contents/Resources/app.asar
运行时
<user-data-dir>/runtime/
调整项
<user-data-dir>/tweaks/
配置文件
<user-data-dir>/config.json
备份文件
<user-data-dir>/backup/
各系统的
<user-data-dir>
路径:
  • macOS:
    ~/Library/Application Support/codex-plusplus/
  • Linux:
    $XDG_DATA_HOME/codex-plusplus/
    (默认
    ~/.local/share/codex-plusplus/
  • Windows:
    %APPDATA%/codex-plusplus/

Writing a Tweak

编写调整项

Folder Structure

文件夹结构

<user-data-dir>/tweaks/my-tweak/
├── manifest.json
└── index.ts        # or .js / .mjs
<user-data-dir>/tweaks/my-tweak/
├── manifest.json
└── index.ts        # 或 .js / .mjs

manifest.json

manifest.json

json
{
  "id": "com.yourname.my-tweak",
  "name": "My Tweak",
  "version": "0.1.0",
  "githubRepo": "yourname/my-tweak",
  "author": "yourname",
  "description": "Short description of what this tweak does.",
  "minRuntime": "0.1.0"
}
Required fields:
id
(reverse-domain),
name
,
version
,
githubRepo
(for update checks),
author
,
description
,
minRuntime
.
json
{
  "id": "com.yourname.my-tweak",
  "name": "My Tweak",
  "version": "0.1.0",
  "githubRepo": "yourname/my-tweak",
  "author": "yourname",
  "description": "Short description of what this tweak does.",
  "minRuntime": "0.1.0"
}
必填字段:
id
(反向域名格式)、
name
version
githubRepo
(用于更新检查)、
author
description
minRuntime

index.ts — Minimal Tweak

最简调整项(index.ts)

ts
import type { Tweak } from "@codex-plusplus/sdk";

export default {
  start(api) {
    api.log.info("My tweak started");
  },
  stop() {
    // Cleanup: remove event listeners, DOM nodes, etc.
  },
} satisfies Tweak;
ts
import type { Tweak } from "@codex-plusplus/sdk";

export default {
  start(api) {
    api.log.info("My tweak started");
  },
  stop() {
    // 清理操作:移除事件监听器、DOM节点等
  },
} satisfies Tweak;

index.ts — Settings Panel

设置面板(index.ts)

ts
import type { Tweak } from "@codex-plusplus/sdk";

export default {
  start(api) {
    api.settings.register({
      id: "my-tweak",
      title: "My Tweak",
      render(root) {
        root.innerHTML = `
          <div style="padding: 16px;">
            <h2>My Tweak Settings</h2>
            <label>
              <input type="checkbox" id="my-tweak-toggle" />
              Enable feature
            </label>
          </div>
        `;

        const toggle = root.querySelector<HTMLInputElement>("#my-tweak-toggle")!;
        toggle.checked = api.storage.get("enabled") ?? false;
        toggle.addEventListener("change", () => {
          api.storage.set("enabled", toggle.checked);
        });
      },
    });
  },
  stop() {},
} satisfies Tweak;
ts
import type { Tweak } from "@codex-plusplus/sdk";

export default {
  start(api) {
    api.settings.register({
      id: "my-tweak",
      title: "My Tweak",
      render(root) {
        root.innerHTML = `
          <div style="padding: 16px;">
            <h2>My Tweak Settings</h2>
            <label>
              <input type="checkbox" id="my-tweak-toggle" />
              Enable feature
            </label>
          </div>
        `;

        const toggle = root.querySelector<HTMLInputElement>("#my-tweak-toggle")!;
        toggle.checked = api.storage.get("enabled") ?? false;
        toggle.addEventListener("change", () => {
          api.storage.set("enabled", toggle.checked);
        });
      },
    });
  },
  stop() {},
} satisfies Tweak;

index.ts — DOM Injection with Cleanup

带清理的DOM注入(index.ts)

ts
import type { Tweak } from "@codex-plusplus/sdk";

let cleanup: (() => void) | null = null;

export default {
  start(api) {
    // Wait for DOM element to appear
    const unobserve = api.dom.waitFor(".codex-toolbar", (toolbar) => {
      const btn = document.createElement("button");
      btn.textContent = "My Action";
      btn.className = "codex-plusplus-btn";
      btn.addEventListener("click", () => {
        api.log.info("Button clicked");
      });
      toolbar.appendChild(btn);

      cleanup = () => btn.remove();
    });

    api.onStop(() => {
      unobserve();
      cleanup?.();
    });
  },
  stop() {},
} satisfies Tweak;
ts
import type { Tweak } from "@codex-plusplus/sdk";

let cleanup: (() => void) | null = null;

export default {
  start(api) {
    // 等待DOM元素出现
    const unobserve = api.dom.waitFor(".codex-toolbar", (toolbar) => {
      const btn = document.createElement("button");
      btn.textContent = "My Action";
      btn.className = "codex-plusplus-btn";
      btn.addEventListener("click", () => {
        api.log.info("Button clicked");
      });
      toolbar.appendChild(btn);

      cleanup = () => btn.remove();
    });

    api.onStop(() => {
      unobserve();
      cleanup?.();
    });
  },
  stop() {},
} satisfies Tweak;

index.ts — Keyboard Shortcut

键盘快捷键(index.ts)

ts
import type { Tweak } from "@codex-plusplus/sdk";

export default {
  start(api) {
    const handler = (e: KeyboardEvent) => {
      if ((e.metaKey || e.ctrlKey) && e.shiftKey && e.key === "k") {
        e.preventDefault();
        api.log.info("Shortcut triggered: Cmd/Ctrl+Shift+K");
        // your action here
      }
    };

    document.addEventListener("keydown", handler);
    api.onStop(() => document.removeEventListener("keydown", handler));
  },
  stop() {},
} satisfies Tweak;

ts
import type { Tweak } from "@codex-plusplus/sdk";

export default {
  start(api) {
    const handler = (e: KeyboardEvent) => {
      if ((e.metaKey || e.ctrlKey) && e.shiftKey && e.key === "k") {
        e.preventDefault();
        api.log.info("Shortcut triggered: Cmd/Ctrl+Shift+K");
        // 此处添加你的操作
      }
    };

    document.addEventListener("keydown", handler);
    api.onStop(() => document.removeEventListener("keydown", handler));
  },
  stop() {},
} satisfies Tweak;

Tweak API Reference (
api
object in
start
)

调整项API参考(
start
中的
api
对象)

APIDescription
api.log.info(msg)
Log to Codex++ console
api.log.warn(msg)
Warning log
api.log.error(msg)
Error log
api.settings.register({ id, title, render })
Add a panel under Settings → Tweaks
api.storage.get(key)
Read persisted value for this tweak
api.storage.set(key, value)
Persist value (JSON-serializable)
api.dom.waitFor(selector, cb)
Watch for a DOM element; returns unobserve fn
api.onStop(fn)
Register a cleanup callback called on
stop()

API描述
api.log.info(msg)
输出日志到Codex++控制台
api.log.warn(msg)
输出警告日志
api.log.error(msg)
输出错误日志
api.settings.register({ id, title, render })
在「设置」→「调整项」下添加面板
api.storage.get(key)
读取当前调整项的持久化值
api.storage.set(key, value)
持久化存储值(需支持JSON序列化)
api.dom.waitFor(selector, cb)
监听指定DOM元素;返回取消监听函数
api.onStop(fn)
注册在
stop()
时执行的清理回调

Config (
config.json
)

配置文件(
config.json

json
{
  "autoRepair": true,
  "autoUpdateRuntime": true,
  "tweaks": {
    "com.yourname.my-tweak": {
      "enabled": true
    }
  }
}
  • autoRepair
    — watcher re-patches after Codex updates (default
    true
    )
  • autoUpdateRuntime
    — daily runtime refresh from CLI (default
    true
    ); disable in Settings → Codex Plus Plus → Config

json
{
  "autoRepair": true,
  "autoUpdateRuntime": true,
  "tweaks": {
    "com.yourname.my-tweak": {
      "enabled": true
    }
  }
}
  • autoRepair
    — 监视器会在Codex更新后重新修补(默认
    true
  • autoUpdateRuntime
    — 每天从CLI刷新运行时(默认
    true
    );可在「设置」→「Codex Plus Plus」→「配置」中禁用

Tweak Update Checks

调整项更新检查

Every tweak with
githubRepo
set is checked against GitHub Releases once per day. Codex++ compares the latest release tag (semver) to the local
manifest.json
version.
  • No auto-update — users see "Update Available" in Settings → Tweaks with a link to the release.
  • To publish a tweak update: create a GitHub Release with a semver tag (e.g.
    v0.2.0
    ) and attach the tweak folder as a zip.

每个设置了
githubRepo
的调整项每天会与GitHub Releases进行一次版本检查。Codex++会将最新的发布标签(语义化版本)与本地
manifest.json
中的版本进行对比。
  • 无自动更新 — 用户会在「设置」→「调整项」中看到「有可用更新」提示,并附带发布链接。
  • 发布调整项更新:创建带有语义化版本标签(例如
    v0.2.0
    )的GitHub Release,并将调整项文件夹打包为zip附件。

Default Tweaks

默认调整项

Installed on first run (skip with
--no-default-tweaks
):
IDRepo
co.bennett.custom-keyboard-shortcuts
b-nnett/codex-plusplus-keyboard-shortcuts
co.bennett.ui-improvements
b-nnett/codex-plusplus-bennett-ui

首次运行时会安装(可通过
--no-default-tweaks
跳过):
ID仓库
co.bennett.custom-keyboard-shortcuts
b-nnett/codex-plusplus-keyboard-shortcuts
co.bennett.ui-improvements
b-nnett/codex-plusplus-bennett-ui

Updating Codex (macOS — Sparkle conflict)

更新Codex(macOS — Sparkle冲突)

Codex++ ad-hoc signs the app, breaking Sparkle's integrity check. Use:
sh
codexplusplus update-codex
This restores an official Developer ID–signed build for the updater. After Codex updates and restarts, the launch agent watcher re-applies Codex++ automatically.

Codex++的临时签名会破坏Sparkle的完整性校验。请使用:
sh
codexplusplus update-codex
该命令会恢复官方开发者ID签名的版本以适配更新器。Codex更新并重启后,启动代理监视器会自动重新应用Codex++补丁。

Uninstall

卸载

sh
codexplusplus uninstall
Restores the backed-up original
app.asar
, removes the launch agent, and removes
<user-data-dir>
. Tweaks you wrote remain on disk unless you delete them manually.

sh
codexplusplus uninstall
还原备份的原始
app.asar
,移除启动代理,并删除
<user-data-dir>
。你编写的调整项会保留在磁盘上,除非手动删除。

Troubleshooting

故障排除

"App is damaged and can't be opened" (macOS)

"应用已损坏,无法打开"(macOS)

The ad-hoc signature isn't trusted on first launch. Run:
sh
xattr -cr /Applications/Codex.app
Then open the app again.
首次启动时临时签名不被信任。执行以下命令:
sh
xattr -cr /Applications/Codex.app
然后重新打开应用。

Patch not persisting after Codex update

Codex更新后补丁未保留

The launch agent should re-run
repair
automatically. Check status:
sh
codexplusplus status
codexplusplus doctor
If the launch agent isn't running, reinstall:
sh
codexplusplus uninstall && codexplusplus install
启动代理应自动重新执行
repair
命令。检查状态:
sh
codexplusplus status
codexplusplus doctor
如果启动代理未运行,请重新安装:
sh
codexplusplus uninstall && codexplusplus install

Tweak not loading

调整项未加载

  1. Check
    manifest.json
    has all required fields (
    id
    ,
    name
    ,
    version
    ,
    githubRepo
    ,
    author
    ,
    description
    ,
    minRuntime
    ).
  2. Ensure
    index.js
    /
    index.ts
    exports a default object with
    start
    and
    stop
    .
  3. Check logs:
    api.log.error
    output appears in Codex DevTools console.
  4. Run
    codexplusplus doctor
    for runtime integrity checks.
  1. 检查
    manifest.json
    包含所有必填字段(
    id
    name
    version
    githubRepo
    author
    description
    minRuntime
    )。
  2. 确保
    index.js
    /
    index.ts
    导出包含
    start
    stop
    的默认对象。
  3. 检查日志:
    api.log.error
    的输出会显示在Codex开发者工具控制台中。
  4. 执行
    codexplusplus doctor
    进行运行时完整性检查。

Runtime version mismatch

运行时版本不匹配

sh
codexplusplus repair   # refreshes runtime from CLI
sh
codexplusplus repair   # 从CLI刷新运行时

Tweaks directory location

调整项目录位置

sh
codexplusplus tweaks open   # opens in Finder/Explorer

sh
codexplusplus tweaks open   # 在Finder/资源管理器中打开

Security Model

安全模型

  • Tweaks run in the renderer process with the same privileges as Codex's own renderer code.
  • Codex++ does not auto-update tweak code — users must manually review and install updates.
  • githubRepo
    is only used for version checks via the GitHub Releases API, not for auto-downloading code.
  • See
    SECURITY.md
    for the full policy and vulnerability reporting process.

  • 调整项在渲染进程中运行,拥有与Codex自身渲染代码相同的权限。
  • Codex++不会自动更新调整项代码——用户必须手动审核并安装更新。
  • githubRepo
    仅用于通过GitHub Releases API进行版本检查,不会自动下载代码。
  • 完整的安全策略和漏洞上报流程请查看
    SECURITY.md

Community

社区