-
Notifications
You must be signed in to change notification settings - Fork 2
Expand file tree
/
Copy pathinstall_my_programs_mac
More file actions
executable file
·467 lines (392 loc) · 14.8 KB
/
Copy pathinstall_my_programs_mac
File metadata and controls
executable file
·467 lines (392 loc) · 14.8 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
#!/usr/bin/env bash
set -euo pipefail
timestamp=$(date +"%Y%m%d%H%M%S")
ARCH=$(uname -m)
DRY_RUN=false
INSTALL_DESKTOP_EXTRAS=false
BEADS_INSTALL_REF="dd01a655b9602ba20d0c666515467e064a815609"
BR_INSTALL_FAILED=false
export PATH="$HOME/.local/bin:$PATH"
usage() {
cat <<'EOF'
Usage: install_my_programs_mac [options]
Options:
--dry-run Print planned actions without changing the system
--desktop-extras Install optional macOS desktop apps and services
-h, --help Show this help message
EOF
}
parse_args() {
while [[ $# -gt 0 ]]; do
case "$1" in
--dry-run)
DRY_RUN=true
;;
--desktop-extras)
INSTALL_DESKTOP_EXTRAS=true
;;
-h | --help)
usage
exit 0
;;
*)
echo "Unknown option: $1" >&2
usage >&2
exit 1
;;
esac
shift
done
}
run_cmd() {
if [[ "$DRY_RUN" == "true" ]]; then
printf '[dry-run] %s\n' "$*"
return 0
fi
"$@"
}
backup_copy() {
local source="$1"
local target="$2"
local target_dir
[[ -f "$source" ]] || return 0
target_dir="$(dirname "$target")"
run_cmd mkdir -p "$target_dir"
if [[ -f "$target" ]]; then
run_cmd cp "$target" "$target.${timestamp}.bak"
fi
run_cmd cp -f "$source" "$target"
echo "✅ Installed ${target#"$HOME"/}"
}
install_local_bin_script() {
local source="$1"
local name
name="$(basename "$source")"
[[ -f "$source" ]] || return 0
run_cmd mkdir -p "$HOME/.local/bin"
run_cmd cp -f "$source" "$HOME/.local/bin/$name"
run_cmd chmod +x "$HOME/.local/bin/$name"
}
install_iterm2_profile() {
local source="./run_commands/my_iterm2_profile.json"
local target="$HOME/Library/Application Support/iTerm2/DynamicProfiles/utils-scripts.json"
[[ -f "$source" ]] || return 0
backup_copy "$source" "$target"
}
install_optional_brew_formula() {
local formula="$1"
local label="${2:-$1}"
if [[ "$DRY_RUN" == "true" ]]; then
run_cmd brew install "$formula"
return
fi
if ! brew info "$formula" >/dev/null 2>&1; then
echo "ℹ️ ${label} unavailable in current Homebrew taps; skipping"
return
fi
if brew list "$formula" &>/dev/null; then
echo "✅ ${label} already installed"
return
fi
brew install "$formula"
echo "✅ Installed ${label}"
}
install_brew_tap() {
local tap="$1"
if [[ "$DRY_RUN" == "true" ]]; then
run_cmd brew tap "$tap"
return
fi
if brew tap | grep -qx "$tap"; then
echo "✅ Homebrew tap ${tap} already available"
return
fi
brew tap "$tap"
echo "✅ Added Homebrew tap ${tap}"
}
install_optional_brew_cask() {
local cask="$1"
local label="${2:-$1}"
if [[ "$DRY_RUN" == "true" ]]; then
run_cmd brew install --cask "$cask"
return
fi
if ! brew info --cask "$cask" >/dev/null 2>&1; then
echo "ℹ️ ${label} unavailable in current Homebrew taps; skipping"
return
fi
if brew list --cask "$cask" &>/dev/null; then
echo "✅ ${label} already installed"
return
fi
if brew install --cask "$cask"; then
echo "✅ Installed ${label}"
else
echo "⚠️ Failed to install ${label}; continuing." >&2
fi
}
install_macos_desktop_extras() {
echo "Installing optional macOS desktop extras..."
install_optional_brew_cask stats "Stats"
install_optional_brew_cask raycast "Raycast"
install_optional_brew_cask rectangle "Rectangle"
install_optional_brew_cask alt-tab "AltTab"
install_optional_brew_cask dockdoor "DockDoor"
install_optional_brew_cask maccy "Maccy"
install_optional_brew_cask espanso "Espanso"
install_optional_brew_cask tailscale-app "Tailscale"
install_optional_brew_cask appcleaner "AppCleaner"
install_brew_tap FelixKratz/formulae
install_optional_brew_formula borders "JankyBorders (borders)"
install_brew_tap koekeishiya/formulae
install_optional_brew_formula koekeishiya/formulae/yabai "yabai"
install_optional_brew_formula koekeishiya/formulae/skhd "skhd"
cat <<'EOF'
Next steps for macOS desktop extras:
- Stats: launch once if you want menu bar system metrics and choose the modules you want visible.
- Raycast: launch once, complete onboarding, and decide whether it should replace Spotlight shortcuts.
- Rectangle: launch once, grant Accessibility access, and let it load the synced `~/Library/Application Support/Rectangle/RectangleConfig.json` layout.
- AltTab: launch once and grant Accessibility access if you want app switching to replace macOS Cmd-Tab.
- DockDoor: launch once and grant Accessibility access.
- Maccy: launch once; grant Accessibility if you want auto-paste/global shortcut reliability.
- Espanso: launch once, confirm the menu bar app appears, and review Secure Input guidance if expansion stops.
- Tailscale: the app installer may prompt for admin approval; sign in after launch and approve the system extension if macOS asks.
- AppCleaner: optional manual app; SmartDelete is personal preference.
- JankyBorders: the installer now syncs `~/.config/borders/bordersrc`; start it with `brew services start borders` if you want always-on borders.
- yabai: advanced window manager; grant Accessibility, run `yabai --start-service`, and review upstream docs before enabling scripting addition or SIP-related features.
- skhd: start manually with `skhd --start-service` after you have a keybinding config you want to keep.
EOF
}
install_monitoring_stack() {
echo "Installing terminal monitoring tools..."
install_optional_brew_formula bottom "bottom (btm)"
if [[ "$ARCH" == "arm64" ]]; then
install_optional_brew_formula asitop "asitop"
fi
echo "ℹ️ nvtop is skipped on macOS; use 'bottom' (btm) and Activity Monitor alternatives"
}
install_productivity_cli_stack() {
echo "Installing advanced productivity CLI tools..."
install_optional_brew_formula lazygit
install_optional_brew_formula glow
install_optional_brew_formula hyperfine
install_optional_brew_formula yq
install_optional_brew_formula shellcheck
install_optional_brew_formula shfmt
install_optional_brew_formula git-delta "git-delta (delta)"
install_optional_brew_formula tealdeer "tealdeer (tldr)"
install_optional_brew_formula gawk
install_optional_brew_formula entr
install_optional_brew_formula parallel "gnu parallel"
install_optional_brew_formula dua-cli "dua-cli (dua)"
install_optional_brew_formula dust
install_optional_brew_formula procs
install_optional_brew_formula xh
install_optional_brew_formula doggo
install_optional_brew_formula watchexec
install_optional_brew_formula kubectl
install_optional_brew_formula k9s
install_optional_brew_formula trivy
install_optional_brew_formula zellij
}
install_br_tracker() {
echo "📿 Installing Beads tracker (br)..."
if command -v br &>/dev/null; then
echo "✅ br already installed. Skipping."
return
fi
if command -v bd &>/dev/null; then
if [[ ! -e "$HOME/.local/bin/br" ]]; then
ln -sf "$(command -v bd)" "$HOME/.local/bin/br"
fi
echo "✅ bd already installed; linked br -> bd"
return
fi
local install_url="https://raw.githubusercontent.com/steveyegge/beads/${BEADS_INSTALL_REF}/scripts/install.sh"
if [[ "$DRY_RUN" == "true" ]]; then
printf "[dry-run] %s\n" "curl -fsSL ${install_url} -o /tmp/beads-install.sh && bash /tmp/beads-install.sh"
return
fi
local install_script
install_script="$(mktemp)"
if ! curl -fsSL "$install_url" -o "$install_script"; then
echo "⚠️ Failed to download br installer from pinned source. Continuing setup." >&2
BR_INSTALL_FAILED=true
rm -f "$install_script"
return
fi
if ! bash "$install_script"; then
echo "⚠️ br installer failed. Continuing setup." >&2
BR_INSTALL_FAILED=true
rm -f "$install_script"
return
fi
rm -f "$install_script"
if [[ -x "$HOME/.local/bin/bd" ]] && [[ ! -e "$HOME/.local/bin/br" ]]; then
ln -sf "$HOME/.local/bin/bd" "$HOME/.local/bin/br"
fi
export PATH="$HOME/.local/bin:$PATH"
if command -v br >/dev/null 2>&1; then
echo "✅ br available on PATH"
else
echo "⚠️ br installed under ~/.local/bin but is not yet on PATH for this shell." >&2
BR_INSTALL_FAILED=true
fi
}
install_repo_configs() {
echo "Syncing shell and terminal configs..."
backup_copy "./run_commands/my_bashrc" "$HOME/.bashrc"
backup_copy "./run_commands/my_zshrc" "$HOME/.zshrc"
backup_copy "./run_commands/my_tmux.conf" "$HOME/.tmux.conf"
backup_copy "./run_commands/my_vimrc" "$HOME/.vimrc"
backup_copy "./run_commands/my_startship.toml" "$HOME/.config/starship.toml"
backup_copy "./run_commands/my_ghostty_config" "$HOME/.config/ghostty/config"
backup_copy "./run_commands/bordersrc" "$HOME/.config/borders/bordersrc"
run_cmd chmod +x "$HOME/.config/borders/bordersrc"
backup_copy "./run_commands/RectangleConfig.json" "$HOME/Library/Application Support/Rectangle/RectangleConfig.json"
backup_copy "./run_commands/my_wezterm.lua" "$HOME/.wezterm.lua"
backup_copy "./run_commands/my_skhdrc" "$HOME/.skhdrc"
backup_copy "./run_commands/codex_config.toml" "$HOME/.codex/config.template.toml"
if [[ -f "./run_commands/my_nvim_init.lua" ]]; then
backup_copy "./run_commands/my_nvim_init.lua" "$HOME/.config/nvim/init.lua"
fi
for module in plugins options keymaps lsp ui; do
backup_copy "./run_commands/nvim/lua/utils_scripts/${module}.lua" "$HOME/.config/nvim/lua/utils_scripts/${module}.lua"
done
if [[ -f "./run_commands/secrets_shell.env.example" ]]; then
run_cmd mkdir -p "$HOME/.config/secrets"
if [[ ! -f "$HOME/.config/secrets/shell.env" ]]; then
run_cmd cp -f "./run_commands/secrets_shell.env.example" "$HOME/.config/secrets/shell.env"
run_cmd chmod 600 "$HOME/.config/secrets/shell.env"
echo "✅ Installed $HOME/.config/secrets/shell.env (edit with your local secrets)"
fi
fi
install_iterm2_profile
}
install_local_helpers() {
echo "Installing local helper scripts..."
install_local_bin_script "./bootstrap_shell_secrets"
install_local_bin_script "./br_init_project"
install_local_bin_script "./codex_apply_config"
install_local_bin_script "./repomix_generate"
install_local_bin_script "./run_commands/tmux_network_bandwidth_safe"
}
install_tmux_plugins() {
if [[ "$DRY_RUN" == "true" ]]; then
printf '[dry-run] %s\n' 'sync tmux plugins from ~/.tmux.conf'
return 0
fi
run_cmd mkdir -p "$HOME/.tmux/plugins"
if [[ ! -d "$HOME/.tmux/plugins/tpm" ]]; then
run_cmd git clone https://github.com/tmux-plugins/tpm "$HOME/.tmux/plugins/tpm"
fi
if command -v tmux >/dev/null 2>&1 && [[ -x "$HOME/.tmux/plugins/tpm/bin/install_plugins" ]]; then
echo "Installing tmux plugins from ~/.tmux.conf..."
tmux start-server >/dev/null 2>&1 || true
tmux has-session -t installer-bootstrap >/dev/null 2>&1 || tmux new-session -d -s installer-bootstrap >/dev/null 2>&1 || true
if ! tmux source-file "$HOME/.tmux.conf"; then
echo "⚠️ tmux source-file failed; continuing without tmux plugin bootstrap"
elif ! "$HOME/.tmux/plugins/tpm/bin/install_plugins"; then
echo "⚠️ tmux plugin install failed; continuing"
fi
tmux kill-session -t installer-bootstrap >/dev/null 2>&1 || true
fi
}
install_window_manager_examples() {
if [[ "$DRY_RUN" == "true" ]]; then
printf '[dry-run] %s\n' 'install yabai/skhd example configs when missing'
return 0
fi
if [[ -x "/opt/homebrew/opt/yabai/bin/yabai" ]] && [[ ! -f "$HOME/.yabairc" ]]; then
cp "/opt/homebrew/opt/yabai/share/yabai/examples/yabairc" "$HOME/.yabairc"
chmod +x "$HOME/.yabairc"
echo "✅ Installed ~/.yabairc from yabai example"
fi
if [[ -x "/opt/homebrew/opt/skhd/bin/skhd" ]] && [[ ! -f "$HOME/.skhdrc" ]]; then
cp "/opt/homebrew/opt/skhd/share/skhd/examples/skhdrc" "$HOME/.skhdrc"
echo "✅ Installed ~/.skhdrc from skhd example"
fi
}
parse_args "$@"
if ! command -v brew &>/dev/null; then
if [[ -x "/opt/homebrew/bin/brew" ]]; then
eval "$(/opt/homebrew/bin/brew shellenv)"
elif [[ -x "/usr/local/bin/brew" ]]; then
eval "$(/usr/local/bin/brew shellenv)"
fi
fi
# 🧩 Install Homebrew if not already installed
if ! command -v brew &>/dev/null; then
echo "Installing Homebrew..."
if [[ "$DRY_RUN" == "true" ]]; then
printf "[dry-run] /bin/bash -c \"\$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)\"\n"
else
/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"
fi
fi
if [[ "$DRY_RUN" != "true" ]] && ! command -v brew &>/dev/null; then
if [[ -x "/opt/homebrew/bin/brew" ]]; then
eval "$(/opt/homebrew/bin/brew shellenv)"
elif [[ -x "/usr/local/bin/brew" ]]; then
eval "$(/usr/local/bin/brew shellenv)"
fi
fi
if [[ "$DRY_RUN" != "true" ]] && ! command -v brew &>/dev/null; then
echo "❌ Homebrew is not available on PATH after install. Reopen your shell and retry." >&2
exit 1
fi
echo "Updating Homebrew..."
run_cmd brew update
run_cmd brew upgrade
# 🧰 Core developer tools
run_cmd brew install \
wget htop btop tmux neovim curl git jq tree \
fzf zoxide ripgrep bat fd gh \
direnv atuin pre-commit glow yq shellcheck shfmt git-delta tealdeer gawk entr parallel \
python uv
install_monitoring_stack
install_productivity_cli_stack
install_br_tracker
for terminal_cask in ghostty wezterm iterm2; do
if [[ "$DRY_RUN" == "true" ]]; then
run_cmd brew install --cask "$terminal_cask"
elif brew list --cask "$terminal_cask" &>/dev/null; then
:
elif [[ "$terminal_cask" == "ghostty" && -d "/Applications/Ghostty.app" ]]; then
echo "✅ Ghostty app already present at /Applications/Ghostty.app"
elif [[ "$terminal_cask" == "wezterm" && -d "/Applications/WezTerm.app" ]]; then
echo "✅ WezTerm app already present at /Applications/WezTerm.app"
elif [[ "$terminal_cask" == "iterm2" && -d "/Applications/iTerm.app" ]]; then
echo "✅ iTerm app already present at /Applications/iTerm.app"
else
run_cmd brew install --cask "$terminal_cask"
fi
done
if [[ "$INSTALL_DESKTOP_EXTRAS" == "true" ]]; then
install_macos_desktop_extras
fi
# 🧠 AI/ML environment (optional)
run_cmd brew install \
cmake openblas lapack \
protobuf rust
install_optional_brew_formula gcc
# 🐚 Zsh terminal enhancements
run_cmd brew install starship zsh zsh-autosuggestions zsh-syntax-highlighting
# 🧩 Fonts (optional)
run_cmd brew install --cask font-fira-code-nerd-font
install_repo_configs
install_local_helpers
install_tmux_plugins
install_window_manager_examples
if [[ -x "$HOME/.local/bin/codex_apply_config" ]]; then
"$HOME/.local/bin/codex_apply_config"
fi
# 🧮 Lua / auxiliary tools (optional)
run_cmd brew install luarocks
echo "✅ Setup complete! Recommended next steps:"
echo "- Run: 'chsh -s $(which zsh)' to make Zsh your default shell"
echo "- Run: 'eval \"\$(starship init zsh)\"' to enable Starship prompt"
echo "- Optional: start window services manually with 'yabai --start-service' and 'skhd --start-service'"
if [[ "$BR_INSTALL_FAILED" == "true" ]]; then
echo "⚠️ Setup completed with warnings: br could not be installed automatically."
fi