#!/usr/bin/env bash set -euo pipefail PREFIX="${1:-$HOME/.local}" ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)" NODE_BIN="$(command -v node)" REAL_GIT_BIN="$(command -v git)" JJ_BIN="$(command -v jj 2>/dev/null || printf '%s' jj)" mkdir -p "$PREFIX/bin" rm -rf "$PREFIX/lib/omp-codex-bridge" mkdir -p "$PREFIX/lib/omp-codex-bridge" tar --exclude='.git' --exclude='node_modules' -cf - -C "$ROOT" . | tar -xf - -C "$PREFIX/lib/omp-codex-bridge/" chmod +x "$PREFIX/lib/omp-codex-bridge/bin/codex.mjs" ln -sfn "$PREFIX/lib/omp-codex-bridge/bin/codex.mjs" "$PREFIX/bin/codex" echo "Installed $PREFIX/bin/codex" WRAPPER_CONTENT='#!/bin/sh export PATH="/opt/homebrew/bin:$HOME/.local/bin:$HOME/.bun/bin:$HOME/.nix-profile/bin:/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin:$PATH" export HOME="${HOME:-/Users/dawn}" export USER="${USER:-dawn}" BRIDGE_COMMAND="" SKIP_NEXT=0 for ARG in "$@"; do if [ "$SKIP_NEXT" -eq 1 ]; then SKIP_NEXT=0 continue fi case "$ARG" in -c|--config|-p|--profile|-s|--sandbox|-a|--ask-for-approval|--enable|--disable) SKIP_NEXT=1 ;; --version|-V) BRIDGE_COMMAND="version" break ;; -*) ;; *) BRIDGE_COMMAND="$ARG" break ;; esac done case "$BRIDGE_COMMAND" in app-server|remote-control|doctor|logs|log|bridge-version|version) ;; *) if [ -x "$0.upstream-bak" ]; then exec "$0.upstream-bak" "$@" fi ;; esac if command -v node >/dev/null 2>&1; then NODE_BIN="$(command -v node)" elif [ -x "/opt/homebrew/bin/node" ]; then NODE_BIN="/opt/homebrew/bin/node" elif [ -x "/usr/local/bin/node" ]; then NODE_BIN="/usr/local/bin/node" elif [ -x "$HOME/.bun/bin/bun" ]; then NODE_BIN="$HOME/.bun/bin/bun" else NODE_BIN="node" fi exec "$NODE_BIN" "'"$PREFIX"'/lib/omp-codex-bridge/bin/codex.mjs" "$@" ' CHATGPT_APP="${OMP_CODEX_CHATGPT_APP:-/Applications/ChatGPT.app}" CHATGPT_APP_CODEX="$CHATGPT_APP/Contents/Resources/codex" if [ "${OMP_CODEX_PATCH_CHATGPT_APP:-0}" = "1" ] && [ -d "$CHATGPT_APP/Contents/Resources" ]; then CHATGPT_EXECUTABLE="$CHATGPT_APP/Contents/MacOS/ChatGPT" if pgrep -f "$CHATGPT_EXECUTABLE" >/dev/null 2>&1; then osascript -e 'tell application id "com.openai.codex" to quit' >/dev/null 2>&1 || true for _ in $(seq 1 50); do pgrep -f "$CHATGPT_EXECUTABLE" >/dev/null 2>&1 || break sleep 0.1 done if pgrep -f "$CHATGPT_EXECUTABLE" >/dev/null 2>&1; then echo "ChatGPT.app is still running; refusing to patch its bundle or live SQLite databases" >&2 exit 1 fi echo "Quit ChatGPT.app before patching its bundle and thread databases" fi if [ -f "$CHATGPT_APP_CODEX" ] && ! grep -q "omp-codex-bridge" "$CHATGPT_APP_CODEX" 2>/dev/null; then cp -f "$CHATGPT_APP_CODEX" "${CHATGPT_APP_CODEX}.upstream-bak" echo "Backed up original ChatGPT.app codex binary to ${CHATGPT_APP_CODEX}.upstream-bak" fi printf "%s" "$WRAPPER_CONTENT" > "$CHATGPT_APP_CODEX" chmod +x "$CHATGPT_APP_CODEX" echo "Refreshed ChatGPT.app bundled codex wrapper at $CHATGPT_APP_CODEX" CHATGPT_GIT_PROXY="$CHATGPT_APP/Contents/Resources/omp-codex-git" GIT_PROXY_CONTENT='#!/bin/sh export PATH="/opt/homebrew/bin:$HOME/.local/bin:$HOME/.bun/bin:$HOME/.nix-profile/bin:/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin:$PATH" export OMP_CODEX_REAL_GIT="'"$REAL_GIT_BIN"'" export OMP_CODEX_JJ="'"$JJ_BIN"'" case " $* " in *" worktree add "*|*" worktree remove "*) exec "'"$NODE_BIN"'" "'"$PREFIX"'/lib/omp-codex-bridge/bin/git-worktree-proxy.mjs" "$@" ;; *) exec "'"$REAL_GIT_BIN"'" "$@" ;; esac ' printf "%s" "$GIT_PROXY_CONTENT" > "$CHATGPT_GIT_PROXY" chmod +x "$CHATGPT_GIT_PROXY" echo "Refreshed ChatGPT.app Git worktree proxy at $CHATGPT_GIT_PROXY" if [ -f "$CHATGPT_APP/Contents/Resources/app.asar" ]; then "$NODE_BIN" "$PREFIX/lib/omp-codex-bridge/scripts/patch-chatgpt-git-worker.mjs" \ "$CHATGPT_APP" "$CHATGPT_GIT_PROXY" echo "Patched ChatGPT.app Git worker for creation-time Jujutsu workspace selection" fi # Any resource edit invalidates the Developer ID seal. Re-sign every nested # component and the top-level app consistently; preserving the old nested # requirements leaves the new top-level resource seal internally mismatched. codesign --force --deep --sign - "$CHATGPT_APP" codesign --verify --deep --strict "$CHATGPT_APP" CODEX_STATE_DB="${CODEX_STATE_DB:-$HOME/.codex/state_5.sqlite}" if command -v sqlite3 >/dev/null 2>&1 && [ -f "$CODEX_STATE_DB" ]; then CODEX_BACKUP_DIR="$HOME/.codex/backups" CODEX_BACKUP="$CODEX_BACKUP_DIR/state_5.sqlite.pre-omp-only-$(date -u +%Y%m%dT%H%M%SZ).bak" mkdir -p "$CODEX_BACKUP_DIR" sqlite3 "$CODEX_STATE_DB" ".backup '$CODEX_BACKUP'" NATIVE_THREAD_COUNT="$(sqlite3 "$CODEX_STATE_DB" "SELECT count(*) FROM threads WHERE archived = 0 AND COALESCE(source, '') <> 'appServer';")" sqlite3 "$CODEX_STATE_DB" "BEGIN IMMEDIATE; UPDATE threads SET archived = 1, archived_at = CAST(strftime('%s','now') AS INTEGER) WHERE archived = 0 AND COALESCE(source, '') <> 'appServer'; COMMIT;" echo "Archived $NATIVE_THREAD_COUNT native Codex thread rows (backup: $CODEX_BACKUP)" fi CODEX_CATALOG_DB="${CODEX_CATALOG_DB:-$HOME/.codex/sqlite/codex-dev.db}" if command -v sqlite3 >/dev/null 2>&1 && [ -f "$CODEX_CATALOG_DB" ]; then CODEX_BACKUP_DIR="$HOME/.codex/backups" CATALOG_BACKUP="$CODEX_BACKUP_DIR/codex-dev.db.pre-omp-only-$(date -u +%Y%m%dT%H%M%SZ).bak" mkdir -p "$CODEX_BACKUP_DIR" sqlite3 "$CODEX_CATALOG_DB" ".backup '$CATALOG_BACKUP'" CATALOG_NATIVE_COUNT="$(sqlite3 "$CODEX_CATALOG_DB" "SELECT count(*) FROM local_thread_catalog WHERE host_id = 'local' AND COALESCE(source_kind, '') <> 'appServer';")" sqlite3 "$CODEX_CATALOG_DB" "BEGIN IMMEDIATE; DELETE FROM local_thread_catalog WHERE host_id = 'local' AND COALESCE(source_kind, '') <> 'appServer'; COMMIT;" echo "Removed $CATALOG_NATIVE_COUNT native local rows from Desktop's materialized catalog (backup: $CATALOG_BACKUP)" fi echo "Ad-hoc signed patched ChatGPT.app at $CHATGPT_APP" elif [ -d "$CHATGPT_APP/Contents/Resources" ]; then echo "Skipped signed ChatGPT.app bundle patch (set OMP_CODEX_PATCH_CHATGPT_APP=1 for an explicit ad-hoc-signed patch)" fi STANDALONE_CODEX="$HOME/.codex/packages/standalone/current/bin/codex" if [ -d "$HOME/.codex/packages/standalone/current/bin" ]; then if [ -f "$STANDALONE_CODEX" ] && ! grep -q "omp-codex-bridge" "$STANDALONE_CODEX" 2>/dev/null; then cp -f "$STANDALONE_CODEX" "${STANDALONE_CODEX}.upstream-bak" echo "Backed up standalone codex binary to ${STANDALONE_CODEX}.upstream-bak" fi printf "%s" "$WRAPPER_CONTENT" > "$STANDALONE_CODEX" chmod +x "$STANDALONE_CODEX" echo "Refreshed standalone codex wrapper at $STANDALONE_CODEX" fi echo "Verify the SSH login shell sees it: ssh 'command -v codex && codex doctor'"