-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathsetup.sh
More file actions
executable file
·185 lines (158 loc) · 6.05 KB
/
setup.sh
File metadata and controls
executable file
·185 lines (158 loc) · 6.05 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
#!/bin/bash
set -euo pipefail
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
WORK_DIR="$SCRIPT_DIR/work"
DMG_PATH="${1:-$SCRIPT_DIR/Codex.dmg}"
# colors
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
NC='\033[0m'
info() { echo -e "${GREEN}[+]${NC} $1"; }
warn() { echo -e "${YELLOW}[!]${NC} $1"; }
fail() { echo -e "${RED}[✗]${NC} $1"; exit 1; }
# Remove environment variables that can force node-gyp/electron-rebuild to use
# the wrong runtime target or break /bin/sh in child processes.
sanitize_rebuild_env() {
unset npm_config_runtime npm_config_target npm_config_disturl npm_config_nodedir
while IFS= read -r var_name; do
unset "$var_name"
done < <(env | sed -n 's/^\(BASH_FUNC_[^=]*\)=.*/\1/p')
}
# check deps
command -v 7z >/dev/null 2>&1 || fail "7z not found. Install p7zip-full (apt) or p7zip (pacman)."
command -v bun >/dev/null 2>&1 || fail "bun not found. Install from https://bun.sh"
# check dmg
if [ ! -f "$DMG_PATH" ]; then
fail "Codex.dmg not found at $DMG_PATH\nDownload from https://openai.com/codex and place it in the repo root."
fi
info "Starting Lin-Codex setup..."
# extract dmg
EXTRACTED_DIR="$WORK_DIR/extracted"
if [ -d "$EXTRACTED_DIR/Codex Installer" ]; then
warn "Already extracted, skipping. Delete work/extracted/ to re-extract."
else
info "Extracting DMG..."
mkdir -p "$EXTRACTED_DIR"
7z x "$DMG_PATH" -o"$EXTRACTED_DIR" -y > /dev/null
info "DMG extracted."
fi
# locate the app bundle
APP_BUNDLE=$(find "$EXTRACTED_DIR" -name "Codex.app" -type d | head -1)
if [ -z "$APP_BUNDLE" ]; then
fail "Could not find Codex.app inside extracted DMG."
fi
info "Found app bundle: $APP_BUNDLE"
# extract app.asar
APP_DIR="$WORK_DIR/app"
ASAR_FILE="$APP_BUNDLE/Contents/Resources/app.asar"
ASAR_UNPACKED="$APP_BUNDLE/Contents/Resources/app.asar.unpacked"
if [ -d "$APP_DIR/.vite" ]; then
warn "App directory already set up, skipping. Delete work/app/ to redo."
else
if [ ! -f "$ASAR_FILE" ]; then
fail "app.asar not found in Codex.app bundle."
fi
# stub missing macOS-only native files so asar extract doesn't crash
if [ -d "$ASAR_UNPACKED" ]; then
find "$ASAR_UNPACKED" -name "*.node" -type l 2>/dev/null | while read -r broken; do
[ ! -e "$broken" ] && touch "$broken"
done
fi
mkdir -p "$ASAR_UNPACKED/native"
[ ! -f "$ASAR_UNPACKED/native/sparkle.node" ] && touch "$ASAR_UNPACKED/native/sparkle.node"
info "Extracting app.asar..."
bunx asar extract "$ASAR_FILE" "$APP_DIR"
# overlay unpacked native modules
if [ -d "$ASAR_UNPACKED" ]; then
info "Copying unpacked native modules..."
cp -r "$ASAR_UNPACKED/"* "$APP_DIR/"
fi
info "App extracted."
fi
# install electron + native deps
NATIVE_DIR="$WORK_DIR/native"
if [ -d "$NATIVE_DIR/node_modules/electron" ]; then
warn "Electron already installed, skipping. Delete work/native/ to reinstall."
else
info "Installing Electron and native dependencies..."
mkdir -p "$NATIVE_DIR"
# read electron version from app package.json
ELECTRON_VERSION=$(grep -o '"electron": "[^"]*"' "$APP_DIR/package.json" 2>/dev/null | head -1 | grep -o '[0-9][0-9.]*' || echo "40.0.0")
info "Using Electron $ELECTRON_VERSION"
cat > "$NATIVE_DIR/package.json" <<PKGJSON
{
"name": "lin-codex-native",
"version": "1.0.0",
"private": true,
"type": "commonjs"
}
PKGJSON
cd "$NATIVE_DIR"
bun install "electron@$ELECTRON_VERSION" better-sqlite3 node-pty
cd "$SCRIPT_DIR"
info "Electron and native modules installed."
fi
# rebuild native modules against electron's node headers
ELECTRON_PATH="$NATIVE_DIR/node_modules/electron/dist/electron"
if [ ! -f "$ELECTRON_PATH" ]; then
fail "Electron binary not found at $ELECTRON_PATH"
fi
ELECTRON_VERSION_RESOLVED=$(cd "$NATIVE_DIR" && node -e "console.log(require('electron/package.json').version)" 2>/dev/null || echo "40.0.0")
info "Rebuilding native modules for Electron $ELECTRON_VERSION_RESOLVED..."
# Clear previous build artifacts to avoid stale ABI binaries being reused.
for mod in better-sqlite3 node-pty; do
rm -rf "$NATIVE_DIR/node_modules/$mod/build"
done
(
cd "$NATIVE_DIR"
sanitize_rebuild_env
bunx @electron/rebuild --version "$ELECTRON_VERSION_RESOLVED" --module-dir "$NATIVE_DIR" --force
)
info "Native modules rebuilt for Electron."
info "Verifying native modules against Electron ABI..."
(
cd "$NATIVE_DIR"
ELECTRON_RUN_AS_NODE=1 "$ELECTRON_PATH" -e "require('./node_modules/better-sqlite3'); require('./node_modules/node-pty')"
) || fail "Native module verification failed in work/native. Delete work/native/ and rerun ./setup.sh."
info "Native modules verify in work/native."
# copy rebuilt native modules into app
info "Linking native modules into app..."
APP_MODULES="$APP_DIR/node_modules"
mkdir -p "$APP_MODULES"
for mod in better-sqlite3 node-pty bindings; do
if [ -d "$NATIVE_DIR/node_modules/$mod" ]; then
rm -rf "$APP_MODULES/$mod"
cp -r "$NATIVE_DIR/node_modules/$mod" "$APP_MODULES/$mod"
fi
done
info "Native modules linked."
info "Verifying linked native modules in app..."
(
cd "$APP_DIR"
ELECTRON_RUN_AS_NODE=1 "$ELECTRON_PATH" -e "require('./node_modules/better-sqlite3'); require('./node_modules/node-pty')"
) || fail "App native modules are ABI-incompatible. Delete work/app/ and work/native/, then rerun ./setup.sh."
info "App native modules verify."
# apply linux shim to main.js if not already patched
MAIN_JS="$APP_DIR/.vite/build/main.js"
if [ -f "$MAIN_JS" ] && ! grep -q "CODEX-LINUX-SHIM" "$MAIN_JS"; then
info "Applying Linux shim to main.js..."
SHIM='/* CODEX-LINUX-SHIM */
const path = require("path");
const appDir = path.resolve(__dirname, "../..");
process.env.ELECTRON_RENDERER_URL = process.env.ELECTRON_RENDERER_URL || "file://" + path.join(appDir, "webview", "index.html");
'
TEMP_MAIN=$(mktemp)
echo "$SHIM" > "$TEMP_MAIN"
cat "$MAIN_JS" >> "$TEMP_MAIN"
mv "$TEMP_MAIN" "$MAIN_JS"
info "Linux shim applied."
else
warn "Linux shim already present or main.js not found, skipping."
fi
echo ""
info "Setup complete! Run ./run.sh to launch Codex."
echo ""
echo " If you haven't already, install the Codex CLI:"
echo " bun install -g @openai/codex"
echo ""