-
Notifications
You must be signed in to change notification settings - Fork 10
Expand file tree
/
Copy pathinstall.sh
More file actions
executable file
·619 lines (548 loc) · 20.9 KB
/
install.sh
File metadata and controls
executable file
·619 lines (548 loc) · 20.9 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
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
#!/usr/bin/env bash
#
# settings-opencode installer
#
# Default: interactive, prompts each step.
# Flags:
# --yes, -y Non-interactive, accept all defaults
# --no-claude Skip ~/.claude mirror install
# --uninstall Remove env-var block and symlinks (does not delete the repo)
# --help, -h Show usage
#
set -euo pipefail
# ------------------------------ constants ------------------------------------
MARKER_START="# >>> settings-opencode >>>"
MARKER_END="# <<< settings-opencode <<<"
TARGET_OPENCODE="$HOME/.config/opencode"
TARGET_CLAUDE="$HOME/.claude"
REPO_DIR="$( cd "$( dirname "${BASH_SOURCE[0]:-$0}" )" && pwd )"
ASSUME_YES=0
SKIP_CLAUDE=0
DO_UNINSTALL=0
WSL_MODE=0
WSL_WIN_HOME=""
# ------------------------------ presentation ---------------------------------
if [ -t 1 ]; then
BOLD=$'\033[1m'; DIM=$'\033[2m'
RED=$'\033[31m'; GREEN=$'\033[32m'; YELLOW=$'\033[33m'; BLUE=$'\033[34m'
RESET=$'\033[0m'
else
BOLD=""; DIM=""; RED=""; GREEN=""; YELLOW=""; BLUE=""; RESET=""
fi
step() { printf "\n${BOLD}${BLUE}==>${RESET} ${BOLD}%s${RESET}\n" "$*"; }
info() { printf " %s\n" "$*"; }
ok() { printf " ${GREEN}OK${RESET} %s\n" "$*"; }
warn() { printf " ${YELLOW}WARN${RESET} %s\n" "$*"; }
err() { printf " ${RED}ERR${RESET} %s\n" "$*" >&2; }
# Ask yes/no with default. $1 = prompt, $2 = default (Y or N)
ask() {
local prompt="$1" default="${2:-Y}" hint reply
if [ "$ASSUME_YES" = "1" ]; then
[ "$default" = "Y" ] && return 0 || return 1
fi
if [ "$default" = "Y" ]; then hint="[Y/n]"; else hint="[y/N]"; fi
while :; do
printf " ${BOLD}?${RESET} %s %s " "$prompt" "$hint"
read -r reply || reply=""
reply="${reply:-$default}"
case "$reply" in
Y|y|Yes|yes) return 0 ;;
N|n|No|no) return 1 ;;
*) printf " please answer y or n\n" ;;
esac
done
}
# ------------------------------ usage ----------------------------------------
print_help() {
cat <<EOF
${BOLD}settings-opencode installer${RESET}
Usage: ./install.sh [flags]
Flags:
--yes, -y Non-interactive (accept all defaults)
--no-claude Skip the ~/.claude mirror install
--uninstall Remove the env-var block and symlinks created by this script
(does not delete the cloned repo or your data)
--help, -h Show this message
What it does (interactive by default):
1. Verifies prerequisites (git, bun or npm).
2. Links this repo into ~/.config/opencode (or uses it in place).
3. Installs JS deps with bun (if available) or npm.
4. Adds OPENCODE_MODEL_* and OPENCODE_REASONING_* defaults to your shell rc,
fenced with markers so re-runs and uninstalls are idempotent.
5. Optionally symlinks the .claude/ mirror into ~/.claude.
6. Prints next steps for MCP servers and a smoke test.
EOF
}
# ------------------------------ helpers --------------------------------------
detect_shell_rc() {
case "${SHELL:-}" in
*/zsh) printf "%s\n" "$HOME/.zshrc" ;;
*/bash) [ -f "$HOME/.bashrc" ] && printf "%s\n" "$HOME/.bashrc" || printf "%s\n" "$HOME/.bash_profile" ;;
*/fish) printf "%s\n" "$HOME/.config/fish/config.fish" ;;
*) printf "" ;;
esac
}
backup_path() {
local target="$1" backup
backup="${target}.bak.$(date +%Y%m%d-%H%M%S)"
info "moving existing $target -> $backup"
mv "$target" "$backup"
ok "backed up to $backup"
}
# Copy src/ contents into dst/ (used on WSL where symlinks across /mnt/c don't work).
# Excludes node_modules, .git, and lockfile artifacts so user runs npm install on the Windows side.
rsync_to_windows_target() {
local src="$1" dst="$2"
if ! command -v rsync >/dev/null 2>&1; then
err "rsync is required for the WSL -> Windows copy install"
err " sudo apt install -y rsync"
exit 1
fi
mkdir -p "$dst"
rsync -a --delete \
--exclude='node_modules' \
--exclude='.git' \
--exclude='*.log' \
--exclude='.DS_Store' \
"$src/" "$dst/"
}
# ------------------------------ env-var block --------------------------------
env_block_content() {
cat <<'EOF'
# Added by settings-opencode installer. Edit values to match your provider.
# To remove this block, run: ~/.config/opencode/install.sh --uninstall
export OPENCODE_MODEL_PRIMARY="anthropic/claude-sonnet-4-6"
export OPENCODE_MODEL_SUBAGENT_PLANNER="anthropic/claude-opus-4-7"
export OPENCODE_MODEL_SUBAGENT_WORKER="anthropic/claude-sonnet-4-6"
export OPENCODE_MODEL_SUBAGENT_MINI="anthropic/claude-haiku-4-5"
export OPENCODE_REASONING_PRIMARY="high"
export OPENCODE_REASONING_SECONDARY="medium"
export OPENCODE_REASONING_TERTIARY="low"
EOF
}
# Insert or replace the marker-fenced block in $1 (rc file).
write_env_block() {
local rc="$1"
[ -f "$rc" ] || : >"$rc"
if grep -qF "$MARKER_START" "$rc" 2>/dev/null; then
info "updating existing settings-opencode block in $rc"
# Strip old block (portable awk: skip lines between markers, inclusive)
local tmp
tmp="$(mktemp)"
awk -v s="$MARKER_START" -v e="$MARKER_END" '
$0 == s { skip = 1; next }
$0 == e { skip = 0; next }
!skip { print }
' "$rc" > "$tmp"
mv "$tmp" "$rc"
else
info "adding settings-opencode block to $rc"
fi
{
printf "\n%s\n" "$MARKER_START"
env_block_content
printf "%s\n" "$MARKER_END"
} >> "$rc"
ok "wrote env block to $rc"
}
remove_env_block() {
local rc="$1"
[ -f "$rc" ] || { info "$rc not found, skipping"; return 0; }
if ! grep -qF "$MARKER_START" "$rc" 2>/dev/null; then
info "no settings-opencode block in $rc, skipping"
return 0
fi
local tmp
tmp="$(mktemp)"
awk -v s="$MARKER_START" -v e="$MARKER_END" '
$0 == s { skip = 1; next }
$0 == e { skip = 0; next }
!skip { print }
' "$rc" > "$tmp"
mv "$tmp" "$rc"
ok "removed env block from $rc"
}
# ------------------------------ steps ----------------------------------------
is_wsl() {
grep -qiE "(microsoft|wsl)" /proc/version 2>/dev/null
}
detect_wsl_windows_user() {
local u=""
if command -v cmd.exe >/dev/null 2>&1; then
u="$(cmd.exe /c 'echo %USERNAME%' 2>/dev/null | tr -d '\r\n' || true)"
fi
if [ -z "$u" ] && command -v wslvar >/dev/null 2>&1; then
u="$(wslvar USERNAME 2>/dev/null | tr -d '\r\n' || true)"
fi
if [ -z "$u" ] && command -v powershell.exe >/dev/null 2>&1; then
u="$(powershell.exe -NoProfile -Command '[Environment]::UserName' 2>/dev/null | tr -d '\r\n' || true)"
fi
printf "%s" "$u"
}
configure_wsl_targets() {
is_wsl || return 0
info "WSL detected — opencode config lives on the Windows side"
local winuser
winuser="$(detect_wsl_windows_user)"
if [ -z "$winuser" ] || [ ! -d "/mnt/c/Users/$winuser" ]; then
warn "could not auto-detect your Windows username under /mnt/c/Users"
if [ "$ASSUME_YES" = "1" ]; then
err "non-interactive run cannot prompt — aborting. Pass --windows-user=<name> or run interactively."
exit 1
fi
printf " ${BOLD}?${RESET} Enter your Windows username (folder under /mnt/c/Users): "
read -r winuser || winuser=""
winuser="$(printf "%s" "$winuser" | tr -d '\r\n')"
if [ -z "$winuser" ] || [ ! -d "/mnt/c/Users/$winuser" ]; then
err "invalid Windows user — /mnt/c/Users/$winuser does not exist"
exit 1
fi
fi
WSL_WIN_HOME="/mnt/c/Users/$winuser"
TARGET_OPENCODE="$WSL_WIN_HOME/.config/opencode"
TARGET_CLAUDE="$WSL_WIN_HOME/.claude"
WSL_MODE=1
ok "Windows home: $WSL_WIN_HOME"
ok "opencode target: $TARGET_OPENCODE"
ok "claude target: $TARGET_CLAUDE"
}
check_prereqs() {
step "Checking prerequisites"
local missing=0
if ! command -v git >/dev/null 2>&1; then
err "git not found"; missing=1
else
ok "git $(git --version | awk '{print $3}')"
fi
local pm=""
if [ "$WSL_MODE" = "1" ]; then
info "WSL mode — bun/npm not required on Linux side (Windows handles deps)"
if ! command -v rsync >/dev/null 2>&1; then
err "rsync not found — required for WSL -> Windows copy"
err " sudo apt install -y rsync"
missing=1
else
ok "rsync $(rsync --version | head -1 | awk '{print $3}')"
fi
else
if command -v bun >/dev/null 2>&1; then
pm="bun"
ok "bun $(bun --version)"
elif command -v npm >/dev/null 2>&1; then
pm="npm"
ok "npm $(npm --version) (bun not found, will use npm)"
else
err "neither bun nor npm found — install one before continuing"
missing=1
fi
fi
PKG_MANAGER="$pm"
[ "$missing" = "0" ] || { err "missing required tools"; exit 1; }
}
check_environment() {
step "Checking environment"
# 1. Detect Windows Node leaking into WSL (only matters for Linux-side install).
if is_wsl && [ "$WSL_MODE" != "1" ]; then
local node_path node_platform
node_path="$(command -v node 2>/dev/null || true)"
if [ -n "$node_path" ]; then
case "$node_path" in
/mnt/c/*|/mnt/[a-z]/*)
err "node resolves to a Windows path: $node_path"
err "Windows Node cannot build native modules (better-sqlite3) from a WSL path."
err "Install Linux Node inside WSL:"
err " sudo apt update && sudo apt install -y build-essential python3 curl"
err " curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.40.1/install.sh | bash"
err " source ~/.bashrc && nvm install --lts && nvm use --lts"
err "Then re-run this installer."
exit 1
;;
esac
node_platform="$("$node_path" -p "process.platform" 2>/dev/null || true)"
if [ -n "$node_platform" ] && [ "$node_platform" != "linux" ]; then
err "node platform is '$node_platform', expected 'linux' inside WSL"
err "You are running a non-Linux Node binary. Install Linux Node via nvm."
exit 1
fi
ok "Linux Node at $node_path"
fi
fi
# 2. Repo dir writable by current user.
if [ ! -w "$REPO_DIR" ]; then
err "$REPO_DIR is not writable by user '$USER'"
err "Fix ownership: sudo chown -R \"$USER:$USER\" \"$REPO_DIR\""
exit 1
fi
# 3. Stale node_modules owned by another user (classic 'sudo npm install' aftermath).
if [ -d "$REPO_DIR/node_modules" ]; then
local nm_owner
nm_owner="$(stat -c '%U' "$REPO_DIR/node_modules" 2>/dev/null || stat -f '%Su' "$REPO_DIR/node_modules" 2>/dev/null || echo "")"
if [ -n "$nm_owner" ] && [ "$nm_owner" != "$USER" ]; then
err "$REPO_DIR/node_modules is owned by '$nm_owner', not '$USER'"
err "Likely a previous 'sudo npm install' or a failed Windows-Node attempt."
err "Clean it up:"
err " sudo rm -rf \"$REPO_DIR/node_modules\" \"$REPO_DIR/package-lock.json\""
err " sudo chown -R \"$USER:$USER\" \"$REPO_DIR\""
err "Then re-run this installer (without sudo)."
exit 1
fi
if [ ! -w "$REPO_DIR/node_modules" ]; then
err "$REPO_DIR/node_modules exists but is not writable by '$USER'"
err "Clean it up:"
err " sudo rm -rf \"$REPO_DIR/node_modules\" \"$REPO_DIR/package-lock.json\""
err "Then re-run this installer (without sudo)."
exit 1
fi
fi
# 4. Refuse to run the installer itself as root.
if [ "${EUID:-$(id -u)}" = "0" ]; then
err "Do not run install.sh as root/sudo."
err "It will create root-owned node_modules that you can't modify later."
err "Run as your normal user."
exit 1
fi
ok "environment looks sane"
}
install_repo_link() {
if [ "$WSL_MODE" = "1" ]; then
step "Copying repo into $TARGET_OPENCODE (WSL -> Windows)"
if [ -e "$TARGET_OPENCODE" ] && [ ! -L "$TARGET_OPENCODE" ]; then
info "$TARGET_OPENCODE exists"
if ask "back it up and replace with a fresh copy of $REPO_DIR?" Y; then
backup_path "$TARGET_OPENCODE"
else
warn "skipping copy — Windows opencode will keep using whatever is already there"
return 0
fi
elif [ -L "$TARGET_OPENCODE" ]; then
info "$TARGET_OPENCODE is a symlink — removing (Windows can't follow WSL symlinks)"
rm "$TARGET_OPENCODE"
fi
rsync_to_windows_target "$REPO_DIR" "$TARGET_OPENCODE"
ok "copied $REPO_DIR -> $TARGET_OPENCODE (node_modules excluded)"
return 0
fi
step "Linking repo into $TARGET_OPENCODE"
if [ "$REPO_DIR" = "$TARGET_OPENCODE" ]; then
ok "repo already lives at $TARGET_OPENCODE"
return 0
fi
if [ -L "$TARGET_OPENCODE" ] && [ "$(readlink "$TARGET_OPENCODE")" = "$REPO_DIR" ]; then
ok "$TARGET_OPENCODE already symlinks to this repo"
return 0
fi
if [ -e "$TARGET_OPENCODE" ] || [ -L "$TARGET_OPENCODE" ]; then
info "$TARGET_OPENCODE exists"
if ask "back it up and replace with a symlink to $REPO_DIR?" Y; then
backup_path "$TARGET_OPENCODE"
else
warn "skipping link step — you'll need to point OpenCode at this repo manually"
return 0
fi
fi
mkdir -p "$(dirname "$TARGET_OPENCODE")"
ln -s "$REPO_DIR" "$TARGET_OPENCODE"
ok "symlinked $TARGET_OPENCODE -> $REPO_DIR"
}
install_deps() {
if [ "$WSL_MODE" = "1" ]; then
step "Skipping Linux-side npm install (WSL mode)"
warn "Windows opencode needs node_modules built with Windows Node.js."
warn "Linux Node would produce binaries Windows cannot load (better-sqlite3, etc.)."
info "From PowerShell or cmd.exe on Windows, run:"
info " cd \"%USERPROFILE%\\.config\\opencode\""
info " npm install (or: bun install)"
return 0
fi
step "Installing JS dependencies ($PKG_MANAGER)"
cd "$REPO_DIR"
if [ "$PKG_MANAGER" = "bun" ]; then
bun install
else
npm ci || npm install
fi
ok "deps installed"
}
install_env_vars() {
step "Configuring shell environment variables"
local rc
rc="$(detect_shell_rc)"
if [ -z "$rc" ]; then
warn "couldn't detect a known shell rc for SHELL=${SHELL:-unset}"
info "add the following to your shell profile manually:"
printf "\n"
env_block_content | sed 's/^/ /'
printf "\n"
return 0
fi
info "target rc file: $rc"
if ask "write the OPENCODE_MODEL_* and OPENCODE_REASONING_* defaults there?" Y; then
write_env_block "$rc"
info "open a new shell or run: source \"$rc\""
else
info "skipped. Here's the block to paste manually:"
printf "\n"
env_block_content | sed 's/^/ /'
printf "\n"
fi
}
install_claude_mirror() {
if [ "$SKIP_CLAUDE" = "1" ]; then
step "Claude Code mirror — skipped (--no-claude)"
return 0
fi
step "Claude Code mirror"
if ! ask "install the .claude mirror into $TARGET_CLAUDE?" Y; then
info "skipped"
return 0
fi
local source_claude="$REPO_DIR/.claude"
if [ ! -d "$source_claude" ]; then
warn ".claude/ not found in repo, skipping"
return 0
fi
if [ "$WSL_MODE" = "1" ]; then
info "WSL mode — copying instead of symlinking"
if [ -e "$TARGET_CLAUDE" ] && [ ! -L "$TARGET_CLAUDE" ]; then
if ask "back up existing $TARGET_CLAUDE and replace with fresh copy?" Y; then
backup_path "$TARGET_CLAUDE"
else
warn "skipping"
return 0
fi
elif [ -L "$TARGET_CLAUDE" ]; then
rm "$TARGET_CLAUDE"
fi
rsync_to_windows_target "$source_claude" "$TARGET_CLAUDE"
ok "copied $source_claude -> $TARGET_CLAUDE"
return 0
fi
if [ -L "$TARGET_CLAUDE" ] && [ "$(readlink "$TARGET_CLAUDE")" = "$source_claude" ]; then
ok "$TARGET_CLAUDE already symlinks here"
return 0
fi
if [ -e "$TARGET_CLAUDE" ] || [ -L "$TARGET_CLAUDE" ]; then
info "$TARGET_CLAUDE exists"
if ask "back it up before linking?" Y; then
backup_path "$TARGET_CLAUDE"
else
warn "skipping (would clobber existing $TARGET_CLAUDE)"
return 0
fi
fi
ln -s "$source_claude" "$TARGET_CLAUDE"
ok "symlinked $TARGET_CLAUDE -> $source_claude"
}
print_next_steps() {
step "Next steps"
if [ "$WSL_MODE" = "1" ]; then
cat <<EOF
WSL -> Windows install. Finish setup from a Windows shell (PowerShell or cmd.exe):
cd "%USERPROFILE%\\.config\\opencode"
npm install (or: bun install)
Then in WSL:
1. Reload your shell (or: source "$(detect_shell_rc)")
2. Re-run this script to push fresh changes from the repo to the Windows target.
Adjust env-var values for your provider in $(detect_shell_rc)
Re-run anytime: $REPO_DIR/install.sh
Uninstall: $REPO_DIR/install.sh --uninstall
EOF
return 0
fi
cat <<EOF
1. Reload your shell (or: source "$(detect_shell_rc)")
2. Optional: install Wallaby.js + run \`wallaby update-mcp\` if you want runtime-test introspection
3. Smoke test:
opencode
/plan add a TODO list to my homepage
Adjust env-var values for your provider in $(detect_shell_rc)
Re-run anytime: $REPO_DIR/install.sh
Uninstall: $REPO_DIR/install.sh --uninstall
EOF
}
# ------------------------------ uninstall ------------------------------------
run_uninstall() {
configure_wsl_targets
step "Uninstall"
info "this will:"
info " - remove the marker-fenced env block from your shell rc"
if [ "$WSL_MODE" = "1" ]; then
info " - remove the copied directory at $TARGET_OPENCODE (after confirm)"
info " - remove the copied directory at $TARGET_CLAUDE (after confirm)"
else
info " - remove $TARGET_OPENCODE if it symlinks to this repo"
info " - remove $TARGET_CLAUDE if it symlinks to this repo"
fi
info "the cloned repo at $REPO_DIR is left intact."
if ! ask "proceed?" N; then
info "aborted"
exit 0
fi
local rc
rc="$(detect_shell_rc)"
[ -n "$rc" ] && remove_env_block "$rc" || warn "no known shell rc detected, skipping env block"
if [ "$WSL_MODE" = "1" ]; then
if [ -d "$TARGET_OPENCODE" ] && [ ! -L "$TARGET_OPENCODE" ]; then
if ask "delete copied directory $TARGET_OPENCODE ?" N; then
rm -rf "$TARGET_OPENCODE"
ok "removed $TARGET_OPENCODE"
else
info "left $TARGET_OPENCODE in place"
fi
else
info "$TARGET_OPENCODE not found or not a directory, skipping"
fi
if [ -d "$TARGET_CLAUDE" ] && [ ! -L "$TARGET_CLAUDE" ]; then
if ask "delete copied directory $TARGET_CLAUDE ?" N; then
rm -rf "$TARGET_CLAUDE"
ok "removed $TARGET_CLAUDE"
else
info "left $TARGET_CLAUDE in place"
fi
else
info "$TARGET_CLAUDE not found or not a directory, skipping"
fi
else
if [ -L "$TARGET_OPENCODE" ] && [ "$(readlink "$TARGET_OPENCODE")" = "$REPO_DIR" ]; then
rm "$TARGET_OPENCODE"
ok "removed symlink $TARGET_OPENCODE"
else
info "$TARGET_OPENCODE is not a symlink to this repo, leaving it alone"
fi
if [ -L "$TARGET_CLAUDE" ] && [ "$(readlink "$TARGET_CLAUDE")" = "$REPO_DIR/.claude" ]; then
rm "$TARGET_CLAUDE"
ok "removed symlink $TARGET_CLAUDE"
else
info "$TARGET_CLAUDE is not a symlink to this repo, leaving it alone"
fi
fi
step "Done. Backups (if any) are at *.bak.YYYYMMDD-HHMMSS — restore manually if you want them back."
}
# ------------------------------ main -----------------------------------------
while [ $# -gt 0 ]; do
case "$1" in
--yes|-y) ASSUME_YES=1 ;;
--no-claude) SKIP_CLAUDE=1 ;;
--uninstall) DO_UNINSTALL=1 ;;
-h|--help) print_help; exit 0 ;;
*) err "unknown flag: $1"; print_help; exit 1 ;;
esac
shift
done
if [ "$DO_UNINSTALL" = "1" ]; then
run_uninstall
exit 0
fi
step "settings-opencode installer"
info "repo: $REPO_DIR"
info "mode: $([ "$ASSUME_YES" = "1" ] && echo "non-interactive" || echo "interactive")"
configure_wsl_targets
check_prereqs
check_environment
info "target: $TARGET_OPENCODE"
info "claude: $([ "$SKIP_CLAUDE" = "1" ] && echo "skipped" || echo "$TARGET_CLAUDE")"
install_repo_link
install_deps
install_env_vars
install_claude_mirror
print_next_steps