-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathprovision-devlab.sh
More file actions
executable file
·1980 lines (1621 loc) · 76.7 KB
/
provision-devlab.sh
File metadata and controls
executable file
·1980 lines (1621 loc) · 76.7 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
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
#!/bin/zsh
################################################################################
# Portable Replicatable Scalable Developer Laboratory Setup for macOS
#
# Author: Balamurugan Krishnamoorthy
# Documentation: See PROVISION-DEVLAB.md for complete details
#
# Quick Start:
# ./provision-devlab.sh # Interactive setup
# ./provision-devlab.sh --yes # Automated setup
# ./provision-devlab.sh --status # Check current status
# ./provision-devlab.sh --help # Show usage options
################################################################################
# Global variables - Default to skip optional GUI features
SKIP_CASK_APPS=true
SKIP_ITERM_SETUP=true
AUTO_YES=false
SCRIPT_NAME="provision-devlab.sh"
# Path to the Python brew helper utility module
BREW_UTIL_SCRIPT="$(dirname "${BASH_SOURCE[0]}")/scripts/util/brew_helper.py"
# Colors for output (Maven-style)
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[1;34m' # Changed to bright/bold blue for better visibility
CYAN='\033[0;36m'
MAGENTA='\033[0;35m'
BOLD='\033[1m'
DIM='\033[2m'
GREY='\033[37m' # Light grey color
NC='\033[0m' # No Color
# Maven-style logging functions
log_info() { printf "${GREY}[INFO]${NC} %s\n" "$1"; }
log_success() { printf "${GREEN}[SUCCESS]${NC} %s\n" "$1"; }
log_warning() { printf "${YELLOW}[WARNING]${NC} %s\n" "$1"; }
log_error() { printf "${RED}[ERROR]${NC} %s\n" "$1"; }
log_phase() {
# Check if message already contains [PHASE X/Y] pattern
if [[ "$1" =~ ^\[PHASE\ [0-9]+/[0-9]+\] ]]; then
# Extract phase number and description
local phase_part=$(echo "$1" | sed 's/\[PHASE \([0-9]*\/[0-9]*\)\] \(.*\)/\1/')
local description=$(echo "$1" | sed 's/\[PHASE \([0-9]*\/[0-9]*\)\] \(.*\)/\2/')
printf "${GREY}[INFO] ${GREEN}------------------------------< ${CYAN}$phase_part${GREEN} >-----------------------------------${NC}\n"
printf "${CYAN}[PHASE]${NC} ${description}\n"
printf "${GREY}[INFO] ${GREEN}------------------------------------------------------------------------${NC}\n"
else
printf "${GREY}[INFO] ${BOLD}${CYAN}[PHASE]${NC} %s\n" "$1"
fi
}
log_phase_summary() {
local phase_num="$1"
local phase_title="$2"
shift 2
local accomplishments=("$@")
printf "\n${BOLD}${GREEN}✅ PHASE ${phase_num} COMPLETED: ${phase_title}${NC}\n"
printf "${DIM}${GREEN}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}\n"
for accomplishment in "${accomplishments[@]}"; do
printf "${CYAN} ▶ ${accomplishment}${NC}\n"
done
printf "${DIM}${GREEN}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}\n"
}
log_goal() {
# Check if message already contains [X.Y/Z.W] pattern
if [[ "$1" =~ ^\[[0-9]+\.[0-9]+/[0-9]+\.[0-9]+\] ]]; then
# Extract goal number and description
local goal_part=$(echo "$1" | sed 's/\[\([0-9]*\.[0-9]*\/[0-9]*\.[0-9]*\)\] \(.*\)/\1/')
local description=$(echo "$1" | sed 's/\[\([0-9]*\.[0-9]*\/[0-9]*\.[0-9]*\)\] \(.*\)/\2/')
printf "${BLUE}[GOAL] ${GREEN}--- ${description} ${BLUE}(${goal_part})${GREEN} ---${NC}\n"
else
printf "${BLUE}[GOAL]${NC} %s\n" "$1"
fi
}
log_build_success() { printf "\n${BOLD}${GREEN}------------------------------------------------------------------------\n"; printf "BUILD SUCCESS\n"; printf "------------------------------------------------------------------------${NC}\n"; }
log_build_failure() { printf "\n${BOLD}${RED}------------------------------------------------------------------------\n"; printf "BUILD FAILURE\n"; printf "------------------------------------------------------------------------${NC}\n"; }
################################################################################
# Main execution flow
function main() {
# Opening sequence
printf "\n${BLUE}[INIT]${NC} 🧪 Initializing Developer Laboratory Setup Protocol...${NC}\n"
printf "${BLUE}[SCAN]${NC} 🔍 Analyzing system configuration and requirements...${NC}\n"
printf "${GREY}[INFO]${NC} ${GREEN}========================================================================${NC}\n"
printf "${GREY}[INFO]${NC} 🚀 Developer Laboratory Environment Construction Sequence v1.0${NC}\n"
printf "${GREY}[INFO]${NC} 🧬 Crafting Your Ultimate Development DNA (CLI-Focused Setup)${NC}\n"
printf "${GREY}[INFO]${NC} ${GREEN}========================================================================${NC}\n"
printf "${BLUE}[STATUS]${NC} System ready for enhancement. Commencing CLI-focused setup sequence...${NC}\n"
if [[ $SKIP_CASK_APPS == true || $SKIP_ITERM_SETUP == true ]]; then
printf "${DIM}[NOTE]${NC} For GUI apps and iTerm themes, use: $SCRIPT_NAME -c -i${NC}\n"
fi
# Prerequisites: Essential setup steps
confirm_and_run_step "Setup Prerequisites (Second Brain & Homebrew)" setup_prerequisites "0"
# Main setup phases (7 phases)
confirm_and_run_step "Setup Developer Laboratory Directory Structure" setup_dir_struct_hierarchy "1"
confirm_and_run_step "Setup Zsh Environment" setup_zsh_environment "2"
confirm_and_run_step "Install Essential CLI Tools" install_essential_cli_tools "3"
confirm_and_run_step "Install Development Tools" install_development_tools "4"
confirm_and_run_step "Install Programming Languages" install_programming_languages "5"
confirm_and_run_step "Install IDEs and GUI Productivity Tools" install_ides_and_gui_productivity_tools "6"
confirm_and_run_step "Setup AI Development Environment" setup_agentic_ai_development "7"
# Maven-style build success
log_build_success
printf "${DIM}[INFO]${NC} Total time: $(( SECONDS / 60 ))m $(( SECONDS % 60 ))s\n"
printf "${DIM}[INFO]${NC} Finished at: $(date)\n"
printf "${DIM}[INFO]${NC} Final Memory: $(vm_stat | grep "Pages free" | awk '{print $3}' | sed 's/\.//')K\n"
printf "${BOLD}${GREEN}[INFO]${NC} Developer Environment Setup completed successfully!\n"
# Final manual review reminder for Git user profile configuration
printf "\n${YELLOW}[ACTION REQUIRED]${NC} Review and update your Git user profile configuration files:\n"
printf " • %s\n" "$SBRN_HOME/sys/hrt/conf/git/config"
printf " • %s\n" "$SBRN_HOME/sys/hrt/conf/git/config-personal"
printf " • %s\n" "$SBRN_HOME/sys/hrt/conf/git/config-work"
printf "${DIM}[HINT]${NC} Ensure your name and email are correct in the appropriate contexts.\n\n"
}
function confirm_and_run_step() {
local step_description="$1"
local step_function="$2"
local phase_number="${3:-0}" # Default to 0 if not provided
# Map step functions to phase emojis and descriptions
local emoji
local phase_desc
case "$step_function" in
setup_prerequisites)
emoji="🏗️"
phase_desc="Foundation Phase"
;;
setup_dir_struct_hierarchy)
emoji="📁"
phase_desc="Directory Structure Phase"
;;
setup_zsh_environment)
emoji="🐚"
phase_desc="Shell Environment Phase"
;;
install_essential_cli_tools)
emoji="🛠️"
phase_desc="CLI Tools Phase"
;;
install_development_tools)
emoji="🔧"
phase_desc="Development Tools Phase"
;;
install_programming_languages)
emoji="💻"
phase_desc="Programming Languages Phase"
;;
install_ides_and_gui_productivity_tools)
emoji="📝"
phase_desc="IDEs & GUI Tools Phase"
;;
setup_agentic_ai_development)
emoji="🤖"
phase_desc="AI Development Phase"
;;
*)
emoji="⚡"
phase_desc="Setup Phase"
;;
esac
if [[ "$AUTO_YES" == "true" ]]; then
printf "${BOLD}${CYAN}[PHASE ${phase_number}/7]${NC} ${BOLD}${emoji} Initiating %s...${NC}\n" "${phase_desc}"
printf "[AUTO]${NC} Auto-executing: %s\n" "$step_description"
REPLY="y"
else
printf "${BOLD}${CYAN}[PHASE ${phase_number}/7]${NC} ${BOLD}${emoji} Prepare to enter %s${NC}\n" "${phase_desc}"
printf "${YELLOW}[CONFIRM]${NC} Ready to proceed with %s? [y/N]: " "$step_description"
read -r REPLY
fi
if [[ $REPLY =~ ^[Yy]$ ]]; then
$step_function
printf "${GREEN}[INFO]${NC} %s ${GREEN}SUCCESS${NC}\n" "$step_description"
else
printf "${BLUE}[INFO]${NC} %s ${YELLOW}SKIPPED${NC}\n" "$step_description"
fi
}
################################################################################
# Prerequisites: Setup Second Brain Directory Root with HRT Repository
################################################################################
function setup_prerequisites() {
log_phase "[PHASE 0/7] 🏗️ Setting up prerequisites (Second Brain directory & Homebrew package manager)..."
# Goal 1: Setup Second Brain Directory
log_goal "[0.1/0.2] Setting up Second Brain directory & HRT repository..."
# Prompt user for second brain directory name
local sbrn_name="sbrn"
# Set SBRN_HOME based on user input
export SBRN_HOME="$HOME/$sbrn_name"
log_info "Second Brain directory set to: $SBRN_HOME"
# Create the base Second Brain directory
mkdir -p "$SBRN_HOME"
# Create essential sys directory structure
mkdir -p "$SBRN_HOME/sys"
# Clone the HRT (Home Runtime Tools) repository if it doesn't exist
if [[ ! -d "$SBRN_HOME/sys/hrt" ]]; then
log_info "Cloning HRT repository to $SBRN_HOME/sys/hrt..."
git clone --depth=1 https://github.com/krishnam-eng/sbrn-sys-hrt.git "$SBRN_HOME/sys/hrt"
log_success "HRT repository cloned successfully"
else
log_success "HRT repository already exists at $SBRN_HOME/sys/hrt"
fi
# Goal 2: Install Homebrew Package Manager
log_goal "[0.2/0.2] Installing Homebrew package manager..."
if ! python3 "$BREW_UTIL_SCRIPT" --check-homebrew &>/dev/null; then
log_info "Installing Homebrew..."
/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"
log_info "Homebrew PATH configuration is managed by HRT .zprofile"
else
log_success "Homebrew already installed"
fi
python3 "$BREW_UTIL_SCRIPT" --update
generate_phase_summary "0" "Prerequisites Setup"
log_success "Prerequisites setup completed"
}
#################################################################################
# Step 1: Setup Developer Laboratory Directory Structure
#################################################################################
function setup_dir_struct_hierarchy() {
log_phase "[PHASE 1/7] 📁 Setting up SBRN (Second Brain) directory structure..."
# Hide standard user folders to reduce clutter before creating SBRN structure
chflags hidden ~/Movies
chflags hidden ~/Music
chflags hidden ~/Desktop
chflags hidden ~/Public
chflags hidden ~/Pictures
chflags hidden ~/Library
# Create primary PARA directories under sbrn home for Projects, Areas, Resources, Archives
mkdir -p "$SBRN_HOME"
mkdir -p "$SBRN_HOME/proj"/{corp,oss,learn,lab,exp}
mkdir -p "$SBRN_HOME/area"/{work,personal,community,academic}
mkdir -p "$SBRN_HOME/rsrc"/{notes,templates,refs}
mkdir -p "$SBRN_HOME/arch"/{proj,area}
# Create Cloud Drives directories for mounting cloud storage
mkdir -p "$HOME/Drives"
mkdir -p "$HOME/Drives"/{iCloud,GoogleDrive,OneDrive,Dropbox}
log_info "Please manually mount your cloud drives (iCloud, Google Drive, OneDrive, Dropbox) under $HOME/Drives"
# Setup XDG Base Directory Specification environment variables
export XDG_CONFIG_HOME="$SBRN_HOME/sys/config"
export XDG_DATA_HOME="$SBRN_HOME/sys/local/share"
export XDG_STATE_HOME="$SBRN_HOME/sys/local/state"
export XDG_CACHE_HOME="$SBRN_HOME/sys/cache"
# Create XDG-compliant directories
mkdir -p "$XDG_DATA_HOME" "$XDG_STATE_HOME" "$XDG_CACHE_HOME"
# Create FSH config structure under SBRN_HOME/sys
mkdir -p "$SBRN_HOME/sys"/{bin,etc}
generate_phase_summary "1" "Directory Structure"
log_success "SBRN directory structure setup completed"
}
################################################################################
# Step 2: Setup Zsh Environment
################################################################################
function setup_zsh_environment() {
log_phase "[PHASE 2/7] 🐚 Setting up Zsh environment with My Zsh..."
# Set Zsh configuration directory (must be set before Oh My Zsh installation)
export ZDOTDIR="$XDG_CONFIG_HOME/zsh"
# Goal 1: Create XDG-compliant directories for Zsh files
log_goal "[2.1/2.6] Creating XDG-compliant directories for Zsh files..."
create_zsh_xdg_directories
# Goal 2: Install Oh My Zsh
log_goal "[2.2/2.6] Installing Oh My Zsh to custom directory..."
install_oh_my_zsh
# Goal 3: Install Powerlevel10k theme
log_goal "[2.3/2.6] Installing Powerlevel10k theme..."
install_powerlevel10k_theme
# Goal 4: Install essential plugins
log_goal "[2.4/2.6] Installing essential Zsh plugins that are not part of Oh My Zsh repo..."
install_zsh_plugins
# Goal 5: Install Meslo Nerd Font
log_goal "[2.5/2.6] Installing Meslo Nerd Font..."
install_meslo_font
# Goal 6: Setup Zsh configuration links from HRT
log_goal "[2.6/2.6] Setting up Zsh configuration links from HRT..."
setup_zsh_configuration_links
generate_phase_summary "2" "Zsh Environment"
log_success "Zsh environment setup completed"
}
function create_zsh_xdg_directories() {
mkdir -p "$XDG_STATE_HOME/zsh/sessions"
mkdir -p "$XDG_CACHE_HOME/zsh"
log_success "Created Zsh XDG directories (state, cache, sessions)"
}
function install_oh_my_zsh() {
local zsh_dir="$SBRN_HOME/sys/etc/oh-my-zsh"
if [[ ! -d "$zsh_dir" ]]; then
export ZSH="$zsh_dir"
log_goal "[2.2/2.6] Installing Oh My Zsh to $zsh_dir..."
sh -c "$(curl -fsSL https://raw.githubusercontent.com/ohmyzsh/ohmyzsh/master/tools/install.sh)" "" --unattended
log_success "Oh My Zsh installed successfully"
# Restore original .zshrc file from Oh My Zsh backup
log_info "Restoring original .zshrc configuration..."
cp "$XDG_CONFIG_HOME/zsh/.zshrc" "$XDG_CONFIG_HOME/zsh/.zshrc.oh-my-zsh-generated"
cp "$XDG_CONFIG_HOME/zsh/.zshrc.pre-oh-my-zsh" "$XDG_CONFIG_HOME/zsh/.zshrc"
log_success "Original .zshrc configuration restored (Oh My Zsh version backed up as .zshrc.oh-my-zsh-generated)"
else
log_success "Oh My Zsh already installed"
export ZSH="$zsh_dir"
fi
}
function install_powerlevel10k_theme() {
local p10k_dir="${ZSH}/custom/themes/powerlevel10k"
if [[ ! -d "$p10k_dir" ]]; then
log_goal "[2.3/2.6] Installing Powerlevel10k theme..."
git clone --depth=1 https://github.com/romkatv/powerlevel10k.git "$p10k_dir"
ln -sfn "$SBRN_HOME/sys/hrt/conf/p10k" "$XDG_CONFIG_HOME/p10k"
log_success "Powerlevel10k theme installed"
else
log_success "Powerlevel10k already installed"
fi
}
function install_zsh_plugins() {
local custom_dir="${ZSH}/custom"
# zsh-autosuggestions
if [[ ! -d "$custom_dir/plugins/zsh-autosuggestions" ]]; then
git clone --depth=1 https://github.com/zsh-users/zsh-autosuggestions.git "$custom_dir/plugins/zsh-autosuggestions"
log_success "Autosuggestions plugin installed"
else
log_success "Autosuggestions plugin already installed"
fi
# zsh-syntax-highlighting
if [[ ! -d "$custom_dir/plugins/zsh-syntax-highlighting" ]]; then
git clone --depth=1 https://github.com/zsh-users/zsh-syntax-highlighting.git "$custom_dir/plugins/zsh-syntax-highlighting"
log_success "Syntax highlighting plugin installed"
else
log_success "Syntax highlighting plugin already installed"
fi
# history-substring-search
if [[ ! -d "$custom_dir/plugins/history-substring-search" ]]; then
git clone --depth=1 https://github.com/zsh-users/zsh-history-substring-search.git "$custom_dir/plugins/history-substring-search"
log_success "History substring search plugin installed"
else
log_success "History substring search plugin already installed"
fi
# zsh-autoswitch-virtualenv
if [[ ! -d "$custom_dir/plugins/zsh-autoswitch-virtualenv" ]]; then
git clone --depth=1 https://github.com/MichaelAquilina/zsh-autoswitch-virtualenv.git "$custom_dir/plugins/zsh-autoswitch-virtualenv"
log_success "Autoswitch virtualenv plugin installed"
else
log_success "Autoswitch virtualenv plugin already installed"
fi
log_success "Zsh plugins installed"
}
function install_meslo_font() {
local font_dir="$HOME/Library/Fonts"
local temp_dir="/tmp/meslo-font"
if [[ ! -f "$font_dir/MesloLGS NF Regular.ttf" ]]; then
mkdir -p "$temp_dir"
cd "$temp_dir"
curl -LO https://github.com/ryanoasis/nerd-fonts/releases/latest/download/Meslo.zip
unzip -q Meslo.zip
cp *.ttf "$font_dir/"
cd - > /dev/null
rm -rf "$temp_dir"
log_success "Meslo Nerd Font installed"
else
log_success "Meslo Nerd Font already installed"
fi
}
function setup_zsh_configuration_links() {
# Symlink .zshenv
ln -sfn "$SBRN_HOME/sys/hrt/conf/zsh/.zshenv" ~/.zshenv
log_success "Linked .zshenv configuration"
# Symlink zsh configuration directory
ln -sfn "$SBRN_HOME/sys/hrt/conf/zsh" "$XDG_CONFIG_HOME/zsh"
log_success "Linked Zsh configuration directory"
}
################################################################################
# Step 3: Install Essential CLI Tools
################################################################################
function install_essential_cli_tools() {
log_phase "[PHASE 3/7] 🛠️ Installing essential CLI tools..."
# Shell Enhancements & CLI Productivity
install_shell_productivity_tools
# Networking, Security, & Transfer Tools
install_networking_security_tools
# Text, Regex, JSON, Data Tools
install_text_data_tools
# AI Assistant Tools
install_ai_assistant_tools
# Generate phase summary using utility function
generate_phase_summary "3" "Essential CLI Tools"
log_success "Essential CLI tools installation completed"
}
function install_shell_productivity_tools() {
log_goal "[3.1/3.4] Installing shell enhancement & productivity tools..."
local shell_tools=(
"coreutils" "tree" "fzf" "tmux" "screen" "htop" "bat" "fd" "tldr"
"eza" "zoxide" "watch" "ncdu" "glances" "lsd" "autoenv"
"atuin" "direnv" "broot" "figlet" "lolcat" "ranger"
"as-tree" "agedu" "zsh-autosuggestions" "zsh-completions"
"bash-completion" "fish" "starship"
)
brew_install_batch "${shell_tools[@]}"
}
function install_networking_security_tools() {
log_goal "[3.2/3.4] Installing Networking, Security, & Transfer tools..."
local network_tools=(
"curl" "wget" "httpie" "netcat" "gnupg" "certbot" "telnet"
)
brew_install_batch "${network_tools[@]}"
}
function install_text_data_tools() {
log_goal "[3.3/3.4] Installing basic text processing tools..."
local text_tools=(
"emacs" "nano" "grep" "colordiff" "base64" "base91" "ccat" "pygments"
)
brew_install_batch "${text_tools[@]}"
# Create ripgrep config directory and link configuration
ln -sfn "$SBRN_HOME/sys/hrt/conf/ripgrep" "$XDG_CONFIG_HOME/ripgrep"
}
function install_ai_assistant_tools() {
log_goal "[3.4/3.4] Installing AI assistant tools..."
log_info "Installing Claude CLI from claude.ai..."
if command -v claude &> /dev/null; then
log_success "Claude CLI already installed"
else
curl -fsSL https://claude.ai/install.sh | bash
if command -v claude &> /dev/null; then
log_success "Claude CLI installed successfully"
else
log_warning "Claude CLI installation may have failed - please check manually"
fi
fi
}
################################################################################
# Step 4: Install Development Tools
################################################################################
function install_development_tools() {
log_phase "[PHASE 4/7] 🔧 Installing developer CLI tools..."
# Developer Tools (VCS, Repos, Git Helpers)
install_vcs_tools
# Cloud & Containers
install_cloud_container_tools
# Graphics, OCR, and UI Libraries
install_graphics_ocr_libraries
# Code Editors and Development Tools
install_code_editors_and_tools
# API Development Tools
install_api_development_tools
# Backend Services and Data Stores
install_backend_services
# Configure Git to use diff-so-fancy
if command -v diff-so-fancy &>/dev/null; then
git config --global core.pager "diff-so-fancy | less --tabs=4 -RFX" 2>/dev/null || true
fi
generate_phase_summary "4" "Development Tools"
log_success "Development tools installation completed"
}
function install_vcs_tools() {
log_goal "[4.1/4.4] Installing VCS tools..."
local git_tools=(
"git" "git-extras" "git-lfs" "gh" "ghq" "diff-so-fancy"
"delta" "tig" "lazygit" "git-gui" "gibo"
)
brew_install_batch "${git_tools[@]}"
ln -sfn "$SBRN_HOME/sys/hrt/conf/git" "$XDG_CONFIG_HOME/git"
}
function install_cloud_container_tools() {
log_goal "[4.2/4.4] Installing cloud & containers tools..."
local cloud_tools=(
"docker" "docker-compose" "colima" "kubernetes-cli" "helm"
"awscli" "dive" "dockviz" "k9s" "kubecolor" "kompose" "krew"
"kube-ps1" "kubebuilder" "kustomize" "istioctl" "minikube"
"terraform" "pulumi" "railway" "vercel-cli" "ctop" "hcl2json"
"docker-buildx"
)
brew_install_batch "${cloud_tools[@]}"
# Configure Docker settings
configure_docker_config
# Install Docker Compose v2 plugin after Docker is installed
configure_docker_compose_v2
}
function configure_docker_compose_v2() {
log_info "Configuring Docker Compose v2 plugin..."
# Check if Docker is installed
if ! command -v docker &>/dev/null; then
log_warning "Docker not found - skipping Docker Compose v2 plugin installation"
return 1
fi
# Determine Docker config directory (use DOCKER_CONFIG if set, otherwise default)
local docker_config="${DOCKER_CONFIG:-$HOME/.docker}"
local cli_plugins_dir="$docker_config/cli-plugins"
# Create cli-plugins directory if it doesn't exist
mkdir -p "$cli_plugins_dir"
# Check if Docker Compose v2 plugin already exists and is working
if [[ -f "$cli_plugins_dir/docker-compose" ]] && docker compose version &>/dev/null; then
local current_version=$(docker compose version 2>/dev/null | grep -o 'v[0-9.]*' | head -1)
log_success "Docker Compose v2 plugin already installed: $current_version"
return 0
fi
# Determine system architecture
local arch=$(uname -m)
local compose_arch=""
case "$arch" in
"arm64"|"aarch64")
compose_arch="darwin-aarch64"
;;
"x86_64")
compose_arch="darwin-x86_64"
;;
*)
log_warning "Unsupported architecture: $arch - skipping Docker Compose v2 plugin installation"
return 1
;;
esac
# Get latest version from GitHub API
log_info "Fetching latest Docker Compose version..."
local latest_version=$(curl -s https://api.github.com/repos/docker/compose/releases/latest | grep -o '"tag_name": "[^"]*"' | head -1 | cut -d'"' -f4)
if [[ -z "$latest_version" ]]; then
log_warning "Failed to fetch latest version - using fallback v2.40.3"
latest_version="v2.40.3"
else
log_info "Latest version: $latest_version"
fi
# Download Docker Compose v2 plugin
local compose_url="https://github.com/docker/compose/releases/download/${latest_version}/docker-compose-${compose_arch}"
local compose_binary="$cli_plugins_dir/docker-compose"
local temp_binary="$cli_plugins_dir/docker-compose.tmp"
log_info "Downloading Docker Compose v2 plugin ($latest_version) for $compose_arch..."
if curl -L -f -o "$temp_binary" "$compose_url" 2>/dev/null; then
# Verify the downloaded file is not empty and is a valid binary
if [[ -s "$temp_binary" ]] && file "$temp_binary" | grep -q "Mach-O"; then
mv "$temp_binary" "$compose_binary"
chmod +x "$compose_binary"
# Verify installation
if docker compose version &>/dev/null; then
local installed_version=$(docker compose version 2>/dev/null | grep -o 'v[0-9.]*' | head -1)
log_success "Docker Compose v2 plugin installed successfully: $installed_version"
log_info "Plugin location: $compose_binary"
else
log_warning "Docker Compose v2 plugin installed but verification failed"
log_info "You may need to restart your shell or Docker daemon"
fi
else
rm -f "$temp_binary"
log_warning "Downloaded file appears invalid - skipping installation"
return 1
fi
else
log_warning "Failed to download Docker Compose v2 plugin from: $compose_url"
log_info "You can manually install it later or use the standalone docker-compose command"
return 1
fi
}
function configure_docker_config() {
log_info "Configuring Docker settings..."
# Check if Docker is installed
if ! command -v docker &>/dev/null; then
log_warning "Docker not found - skipping Docker configuration"
return 1
fi
# Determine Docker config directory (use DOCKER_CONFIG if set, otherwise default)
local docker_config="${DOCKER_CONFIG:-$HOME/.docker}"
local config_file="$docker_config/config.json"
local source_config="$SBRN_HOME/sys/hrt/conf/docker/config.json"
# Check if source config exists
if [[ ! -f "$source_config" ]]; then
log_warning "Docker config template not found at $source_config - skipping"
return 1
fi
# Create .docker directory if it doesn't exist
mkdir -p "$docker_config"
# Backup existing config if it exists and is not already a symlink
if [[ -f "$config_file" ]] && [[ ! -L "$config_file" ]]; then
local backup_file="$config_file.backup.$(date +%Y%m%d_%H%M%S)"
log_info "Backing up existing Docker config to: $backup_file"
mv "$config_file" "$backup_file"
fi
# Remove existing symlink if present (to recreate it)
if [[ -L "$config_file" ]]; then
rm "$config_file"
fi
# Create symlink to our managed config
ln -sfn "$source_config" "$config_file"
log_success "Docker config symlinked: $config_file -> $source_config"
# Verify the configuration
if [[ -L "$config_file" ]] && [[ -f "$config_file" ]]; then
log_success "Docker configuration successfully linked"
# Check if buildx is available (for macOS with Homebrew Docker)
if command -v docker &>/dev/null; then
if docker buildx version &>/dev/null 2>&1; then
local buildx_version=$(docker buildx version 2>/dev/null | head -1)
log_success "Docker buildx is available: $buildx_version"
else
log_warning "Docker buildx not found. Install with: brew install docker-buildx"
log_info "Then restart your terminal for the config to take effect"
fi
fi
else
log_warning "Docker config link verification failed"
return 1
fi
}
function install_graphics_ocr_libraries() {
log_goal "[4.3/4.4] Installing graphics, images, and UI libraries..."
local graphics_tools=(
"librsvg" "gtk+3" "ghostscript" "graphviz" "guile"
"pcre" "xerces-c" "pygobject3"
)
brew_install_batch "${graphics_tools[@]}"
}
function install_code_editors_and_tools() {
log_goal "[4.4/4.6] Installing development editors and code tools..."
local dev_editors=(
"vim" "neovim" "ripgrep" "ack"
)
brew_install_batch "${dev_editors[@]}"
}
function install_api_development_tools() {
log_goal "[4.5/4.6] Installing API development and documentation tools..."
local api_tools=(
"jwt-cli" "newman" "openapi-generator" "hugo"
)
brew_install_batch "${api_tools[@]}"
}
function install_backend_services() {
log_goal "[4.6/4.6] Installing backend services and data stores..."
# Database and caching services
local data_services=(
"postgresql@15" "redis" "etcd"
)
log_info "Installing database and caching services..."
brew_install_batch "${data_services[@]}"
# Server and service tools
local server_tools=(
"nginx" "sftpgo" "operator-sdk"
"logrotate" "rtmpdump"
)
log_info "Installing server and service tools..."
brew_install_batch "${server_tools[@]}"
}
################################################################################
# Step 5: Install Core Programming Languages & Runtimes
################################################################################
function install_programming_languages() {
log_phase "[PHASE 5/7] 💻 Installing core programming languages, runtime environment managers, and build tools..."
# Core Programming Languages & Runtimes
install_core_programming_languages
# Runtime Environment Managers
install_runtime_environment_managers
# Build Automation Tools
install_build_automation_tools
generate_phase_summary "5" "Programming Languages & Runtimes"
log_success "Programming languages, runtime environment managers, and build tools installation completed"
}
function install_core_programming_languages() {
log_goal "[5.1/5.3] Installing core programming languages and runtimes..."
local languages=(
"openjdk@17" "openjdk@21" "python@3.13" "perl"
"node" "go" "rust"
)
brew_install_batch "${languages[@]}"
}
function install_runtime_environment_managers() {
log_goal "[5.2/5.3] Installing runtime environment managers..."
local runtime_managers=(
"jenv" "uv" "nvm" "pipx" "pandoc" "mactex-no-gui"
)
brew_install_batch "${runtime_managers[@]}"
# Configure runtime environment managers
configure_jenv
configure_uv
setup_uv_python_toolbox_venv
configure_nvm
configure_pipx
}
# Setup a dedicated uv Python venv in XDG_DATA_HOME/python-envs/toolbox
function setup_uv_python_toolbox_venv() {
log_info "Setting up dedicated Python venv for toolbox in $XDG_DATA_HOME/python-envs/toolbox ..."
local venv_dir="$XDG_DATA_HOME/python-envs/toolbox"
mkdir -p "$XDG_DATA_HOME/python-envs"
if [[ ! -d "$venv_dir" ]]; then
python3 -m venv "$venv_dir" && log_success "Created venv at $venv_dir" || log_error "Failed to create venv at $venv_dir"
else
log_success "Python venv already exists at $venv_dir"
fi
# shellcheck disable=SC1090
source "$venv_dir/bin/activate"
log_success "Activated Python venv: $venv_dir"
}
function configure_jenv() {
log_info "Configuring jenv with Java versions (XDG-compliant)..."
# Currently, jenv does not natively support using the XDG Base Directory Specification
# Move existing jenv configuration to XDG config directory if it exists
[[ -d ~/.jenv ]] && [[ ! -L ~/.jenv ]] && [[ ! -d "$XDG_CONFIG_HOME/jenv" ]] && {
mkdir -p "$XDG_CONFIG_HOME"
mv ~/.jenv "$XDG_CONFIG_HOME/jenv"
ln -s "$XDG_CONFIG_HOME/jenv" ~/.jenv
log_success "Moved jenv configuration to XDG-compliant location"
}
# Set jenv to use XDG data directory
export JENV_ROOT="$XDG_DATA_HOME/jenv"
mkdir -p "$JENV_ROOT"
# Initialize jenv with XDG path
eval "$(jenv init -)"
# Enable essential plugins
jenv enable-plugin export 2>/dev/null || true
jenv enable-plugin maven 2>/dev/null || true
jenv enable-plugin gradle 2>/dev/null || true
# Add Java versions if they exist
for java_version in 17 21; do
local java_path="/opt/homebrew/opt/openjdk@${java_version}"
[[ ! -d "$java_path" ]] && java_path="/usr/local/opt/openjdk@${java_version}"
if [[ -d "$java_path" ]] && ! jenv versions | grep -q "$java_version"; then
jenv add "$java_path" 2>/dev/null && log_success "Added Java $java_version to jenv"
fi
done
jenv global 21 2>/dev/null && log_success "Set global Java version to 21"
# Application-specific XDG compliance directories
export ANDROID_HOME="$XDG_DATA_HOME/android"
export GRADLE_USER_HOME="$XDG_DATA_HOME/gradle"
mkdir -p "$ANDROID_HOME" "$GRADLE_USER_HOME"
log_success "jenv configured with XDG-compliant path: $JENV_ROOT"
}
function configure_nvm() {
log_info "Configuring NVM (Node Version Manager)..."
# Set NVM_DIR to XDG-compliant location
export NVM_DIR="$XDG_DATA_HOME/nvm"
mkdir -p "$NVM_DIR"
# Source NVM from Homebrew installation
source "/opt/homebrew/opt/nvm/nvm.sh"
log_success "NVM loaded from Homebrew installation"
# Install latest LTS Node.js if no versions are installed
# Check if any Node.js versions exist by looking at the versions directory
if [[ ! -d "$NVM_DIR/versions/node" ]] || [[ -z "$(ls -A "$NVM_DIR/versions/node" 2>/dev/null)" ]]; then
log_info "Installing latest LTS Node.js version..."
nvm install --lts
nvm use --lts
nvm alias default lts/*
log_success "Installed and set latest LTS Node.js as default"
else
log_success "Node.js versions already installed via NVM"
fi
}
function configure_uv() {
log_info "Configuring uv with XDG compliance for modern Python package management..."
# Set uv configuration to use XDG-compliant locations
export UV_CONFIG_FILE="$XDG_CONFIG_HOME/uv/uv.toml"
export UV_CACHE_DIR="$XDG_CACHE_HOME/uv"
export UV_TOOL_DIR="$XDG_DATA_HOME/uv/tools"
export UV_TOOL_BIN_DIR="$XDG_DATA_HOME/uv/bin"
export UV_PYTHON_INSTALL_DIR="$XDG_DATA_HOME/uv/python"
# Create XDG-compliant directories for uv
mkdir -p "$UV_CACHE_DIR"
mkdir -p "$XDG_DATA_HOME/uv"/{tools,bin,python}
# Link uv configuration directory from HRT repository
if [[ -d "$SBRN_HOME/sys/hrt/conf/uv" ]]; then
ln -sfn "$SBRN_HOME/sys/hrt/conf/uv" "$XDG_CONFIG_HOME/uv"
log_success "Linked uv configuration directory from HRT: $XDG_CONFIG_HOME/uv"
else
log_warning "HRT uv configuration directory not found, using default uv settings"
mkdir -p "$XDG_CONFIG_HOME/uv"
fi
# Add uv tool bin directory to PATH for current session
if [[ ":$PATH:" != *":$UV_TOOL_BIN_DIR:"* ]]; then
export PATH="$UV_TOOL_BIN_DIR:$PATH"
log_success "Added uv tool bin directory to current PATH: $UV_TOOL_BIN_DIR"
else
log_success "uv tool bin directory already in PATH"
fi
# Install a modern Python version if not available
if command -v uv &>/dev/null; then
log_info "Installing Python 3.13 via uv for optimal AI/ML compatibility..."
uv python install 3.13 2>/dev/null || log_info "Python 3.13 installation skipped (already exist)"
log_success "uv Python management configured"
fi
log_success "uv configured with XDG-compliant directories:"
echo " • UV_CONFIG_FILE: $UV_CONFIG_FILE (linked from HRT)"
echo " • UV_CACHE_DIR: $UV_CACHE_DIR"
echo " • UV_TOOL_DIR: $UV_TOOL_DIR"
echo " • UV_TOOL_BIN_DIR: $UV_TOOL_BIN_DIR (added to PATH)"
echo " • UV_PYTHON_INSTALL_DIR: $UV_PYTHON_INSTALL_DIR"
echo " • Configuration: Managed via HRT repository"
}
function configure_pipx() {
log_info "Configuring pipx to use XDG Base Directory Specification..."
# Set XDG-compliant environment variables for pipx
export PIPX_HOME="$XDG_DATA_HOME/pipx"
export PIPX_BIN_DIR="$XDG_DATA_HOME/pipx/bin"
export PIPX_MAN_DIR="$XDG_DATA_HOME/pipx/man"
export PIPX_SHARED_LIBS="$XDG_DATA_HOME/pipx/pyvenv"
export PIPX_LOCAL_VENVS="$XDG_DATA_HOME/pipx/venvs"
export PIPX_LOG_DIR="$XDG_STATE_HOME/pipx/logs"
export PIPX_CACHE_DIR="$XDG_CACHE_HOME/pipx"
# Create XDG-compliant directories
local pipx_dirs=(
"$PIPX_HOME"
"$PIPX_BIN_DIR"
"$PIPX_MAN_DIR"
"$PIPX_SHARED_LIBS"
"$PIPX_LOCAL_VENVS"
"$PIPX_LOG_DIR"
"$PIPX_CACHE_DIR"
)
for dir in "${pipx_dirs[@]}"; do
mkdir -p "$dir"
done
# Add pipx bin directory to PATH for current session
if [[ ":$PATH:" != *":$PIPX_BIN_DIR:"* ]]; then
export PATH="$PIPX_BIN_DIR:$PATH"
log_success "Added XDG pipx bin directory to current PATH: $PIPX_BIN_DIR"
else
log_success "pipx XDG bin directory already in PATH"
fi
log_success "pipx configured with XDG-compliant directories:"
echo " • PIPX_HOME: $PIPX_HOME"
echo " • PIPX_BIN_DIR: $PIPX_BIN_DIR (added to PATH)"
echo " • PIPX_CACHE_DIR: $PIPX_CACHE_DIR"
echo " • PIPX_LOG_DIR: $PIPX_LOG_DIR"
echo " • Configuration: Defined in HRT .zshenv for persistence across sessions"
}
function create_ml_dev_environment() {
log_goal "[7.2/7.5] Creating ML development environment using uv..."
if ! command -v uv &>/dev/null; then
log_warning "uv not available - skipping ML environment creation"
return 1
fi
# Create ml-dev project with uv in XDG location
local env_name="ml-dev"
local project_path="$XDG_DATA_HOME/python-projects/$env_name"
if [[ ! -d "$project_path" ]]; then