可以试一下下面的脚本

#!/bin/bash

set -euo pipefail

APP_PATH="${CODEX_APP_PATH:-/Applications/Codex.app}"

RESOURCES_DIR="$APP_PATH/Contents/Resources"

APP_ASAR="$RESOURCES_DIR/app.asar"

APP_ASAR_BACKUP="$RESOURCES_DIR/app.asar.fastmode.bak"

UNPACKED_DIR="$RESOURCES_DIR/app"

red() { printf '\033[31m%s\033[0m\n' "$*"; }

green() { printf '\033[32m%s\033[0m\n' "$*"; }

yellow() { printf '\033[33m%s\033[0m\n' "$*"; }

blue() { printf '\033[36m%s\033[0m\n' "$*"; }

require_cmd() {

if ! command -v "$1" >/dev/null 2>&1; then

red "缺少依赖命令: $1"

exit 1

fi

}

confirm() {

local prompt="${1:-确认继续?}"

local answer

read -r -p "$prompt [y/N]: " answer

[[ "$answer" =~ ^([yY][eE][sS]|[yY])$ ]]

}

is_codex_running() {

pgrep -x "Codex" >/dev/null 2>&1

}

restart_app() {

require_cmd open

require_cmd pgrep

require_cmd sleep

if [[ ! -d "$APP_PATH" ]]; then

red "未找到 Codex.app,请通过环境变量 CODEX_APP_PATH 指定路径"

exit 1

fi

if is_codex_running; then

blue "正在关闭 Codex.app"

osascript -e 'tell application "Codex" to quit' >/dev/null 2>&1 || true

local waited=0

while is_codex_running && [[ "$waited" -lt 15 ]]; do

sleep 1

waited=$((waited + 1))

done

if is_codex_running; then

yellow "Codex.app 未在预期时间内退出,将继续尝试重新打开"

fi

fi

blue "正在启动 Codex.app"

open "$APP_PATH"

green "已触发 Codex.app 重启"

}

find_target_js() {

find "$UNPACKED_DIR/webview/assets" -type f -name 'general-settings*.js' 2>/dev/null | head -n 1

}

is_patched_file() {

local target_file="${1:-}"

[[ -n "$target_file" ]] || return 1

grep -Eq ',true\}|if\(!1\)return null;|if\(false\)return null;' "$target_file" 2>/dev/null

}

print_paths() {

blue "应用路径: $APP_PATH"

blue "资源目录: $RESOURCES_DIR"

blue "备份路径: $APP_ASAR_BACKUP"

}

status() {

print_paths

if [[ ! -d "$APP_PATH" ]]; then

red "未找到 Codex.app"

return 1

fi

if [[ -f "$APP_ASAR_BACKUP" ]]; then

green "已检测到原始 app.asar 备份"

else

yellow "未检测到原始 app.asar 备份"

fi

if [[ -d "$UNPACKED_DIR" ]]; then

green "已检测到解包目录: $UNPACKED_DIR"

else

yellow "未检测到解包目录"

fi

local target_js

target_js="$(find_target_js || true)"

if [[ -n "$target_js" ]]; then

blue "配置文件: $target_js"

if is_patched_file "$target_js"; then

green "fast 模式补丁: 已应用"

else

yellow "fast 模式补丁: 未应用"

fi

else

yellow "未找到 general-settings*.js,可能尚未解包或版本结构已变化"

fi

}

patch_js_file() {

local target_file="$1"

if is_patched_file "$target_file"; then

yellow "目标文件已处于补丁状态,跳过 JS 修改"

return 0

fi

# 兼容旧版帖子中的布尔判断写法。

perl -0pi -e 's/:r=e\[2\],r\}/:r=e[2],true\}/g' "$target_file"

if is_patched_file "$target_file"; then

green "已命中旧版 fast 模式补丁规则"

return 0

fi

# 兼容当前版本的功能门控写法:直接去掉 Speed 设置项的提前返回。

perl -0pi -e 's/if\(!n\)return null;/if(!1)return null;/g' "$target_file"

if is_patched_file "$target_file"; then

green "已命中当前版本的 fast 模式补丁规则"

return 0

fi

red "JS 补丁未生效,当前版本的代码结构可能已变化"

exit 1

}

write_fuses() {

require_cmd npx

local fuse

for fuse in \

GrantFileProtocolExtraPrivileges=off \

EnableCookieEncryption=off \

OnlyLoadAppFromAsar=off \

EnableEmbeddedAsarIntegrityValidation=off

do

blue "写入 fuse: $fuse"

npx @electron/fuses write --app "$APP_PATH" "$fuse"

done

}

resign_app() {

require_cmd codesign

blue "重新签名 Codex.app"

codesign --force --deep --sign - "$APP_PATH"

}

apply_patch_flow() {

print_paths

require_cmd find

require_cmd perl

require_cmd mv

require_cmd rm

if [[ ! -d "$APP_PATH" ]]; then

red "未找到 Codex.app,请通过环境变量 CODEX_APP_PATH 指定路径"

exit 1

fi

if [[ ! -d "$RESOURCES_DIR" ]]; then

red "未找到资源目录: $RESOURCES_DIR"

exit 1

fi

if [[ ! -d "$UNPACKED_DIR" ]]; then

if [[ ! -f "$APP_ASAR" ]]; then

red "未找到 app.asar,无法自动解包"

exit 1

fi

require_cmd npx

blue "开始解包 app.asar"

npx @electron/asar extract "$APP_ASAR" "$UNPACKED_DIR"

fi

if [[ -f "$APP_ASAR" && ! -f "$APP_ASAR_BACKUP" ]]; then

blue "创建原始包备份"

mv "$APP_ASAR" "$APP_ASAR_BACKUP"

fi

local target_js

target_js="$(find_target_js || true)"

if [[ -z "$target_js" ]]; then

red "未找到 general-settings*.js,当前版本可能不兼容"

exit 1

fi

blue "应用 JS 补丁: $target_js"

patch_js_file "$target_js"

write_fuses

resign_app

green "补丁已完成。重新启动 Codex.app 后,可在设置页检查是否出现 fast 选项。"

}

restore() {

print_paths

require_cmd rm

require_cmd mv

if [[ ! -f "$APP_ASAR_BACKUP" ]]; then

red "未找到备份文件,无法恢复"

exit 1

fi

if [[ -d "$UNPACKED_DIR" ]]; then

blue "删除解包目录"

rm -rf "$UNPACKED_DIR"

fi

if [[ -f "$APP_ASAR" ]]; then

blue "删除当前 app.asar"

rm -f "$APP_ASAR"

fi

blue "恢复原始 app.asar"

mv "$APP_ASAR_BACKUP" "$APP_ASAR"

resign_app

green "已恢复原始包。"

}

interactive_menu() {

print_paths

printf '\n'

echo "请选择操作:"

echo " 1) 查看状态"

echo " 2) 应用 fast 模式补丁"

echo " 3) 恢复原始文件"

echo " 4) 立即重启 Codex.app"

echo " 5) 退出"

printf '\n'

local choice

read -r -p "输入序号: " choice

case "$choice" in

1) status ;;

2)

confirm "即将修改 Codex.app,并重签名,是否继续?" || exit 0

apply_patch_flow

confirm "补丁完成,是否立即自动重启 Codex.app?" && restart_app

;;

3)

confirm "即将恢复原始 app.asar,是否继续?" || exit 0

restore

confirm "恢复完成,是否立即自动重启 Codex.app?" && restart_app

;;

4) restart_app ;;

5) exit 0 ;;

*) red "无效选项"; exit 1 ;;

esac

}

main() {

case "${1:-interactive}" in

status) status ;;

apply) apply_patch_flow ;;

restore) restore ;;

restart) restart_app ;;

interactive) interactive_menu ;;

*)

echo "用法:"

echo " $0 # 交互模式"

echo " $0 status # 查看状态"

echo " $0 apply # 应用补丁"

echo " $0 restore # 恢复原始包"

echo " $0 restart # 重启 Codex.app"

echo

echo "可选环境变量:"

echo " CODEX_APP_PATH=/Applications/Codex.app"

exit 1

;;

esac

}

main "$@"