aidevops 2.100.6 → 2.100.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (4) hide show
  1. package/VERSION +1 -1
  2. package/aidevops.sh +1 -1
  3. package/package.json +1 -1
  4. package/setup.sh +120 -134
package/VERSION CHANGED
@@ -1 +1 @@
1
- 2.100.6
1
+ 2.100.7
package/aidevops.sh CHANGED
@@ -3,7 +3,7 @@
3
3
  # AI DevOps Framework CLI
4
4
  # Usage: aidevops <command> [options]
5
5
  #
6
- # Version: 2.100.6
6
+ # Version: 2.100.7
7
7
 
8
8
  set -euo pipefail
9
9
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "aidevops",
3
- "version": "2.100.6",
3
+ "version": "2.100.7",
4
4
  "description": "AI DevOps Framework - AI-assisted development workflows, code quality, and deployment automation",
5
5
  "type": "module",
6
6
  "main": "index.js",
package/setup.sh CHANGED
@@ -3,7 +3,7 @@
3
3
  # AI Assistant Server Access Framework Setup Script
4
4
  # Helps developers set up the framework for their infrastructure
5
5
  #
6
- # Version: 2.100.6
6
+ # Version: 2.100.7
7
7
  #
8
8
  # Quick Install (one-liner):
9
9
  # bash <(curl -fsSL https://aidevops.dev/install)
@@ -28,6 +28,41 @@ print_success() { echo -e "${GREEN}[SUCCESS]${NC} $1"; }
28
28
  print_warning() { echo -e "${YELLOW}[WARNING]${NC} $1"; }
29
29
  print_error() { echo -e "${RED}[ERROR]${NC} $1"; }
30
30
 
31
+ # Spinner for long-running operations
32
+ # Usage: run_with_spinner "Installing package..." command arg1 arg2
33
+ run_with_spinner() {
34
+ local message="$1"
35
+ shift
36
+ local pid
37
+ local spin_chars='⠋⠙⠹⠸⠼⠴⠦⠧⠇⠏'
38
+ local i=0
39
+
40
+ # Start command in background
41
+ "$@" &>/dev/null &
42
+ pid=$!
43
+
44
+ # Show spinner while command runs
45
+ printf "${BLUE}[INFO]${NC} %s " "$message"
46
+ while kill -0 "$pid" 2>/dev/null; do
47
+ printf "\r${BLUE}[INFO]${NC} %s %s" "$message" "${spin_chars:i++%${#spin_chars}:1}"
48
+ sleep 0.1
49
+ done
50
+
51
+ # Check exit status
52
+ wait "$pid"
53
+ local exit_code=$?
54
+
55
+ # Clear spinner and show result
56
+ printf "\r"
57
+ if [[ $exit_code -eq 0 ]]; then
58
+ print_success "$message done"
59
+ else
60
+ print_error "$message failed"
61
+ fi
62
+
63
+ return $exit_code
64
+ }
65
+
31
66
  # Find OpenCode config file (checks multiple possible locations)
32
67
  # Returns: path to config file, or empty string if not found
33
68
  find_opencode_config() {
@@ -660,9 +695,9 @@ check_requirements() {
660
695
  fi
661
696
 
662
697
  echo ""
663
- read -r -p "Install missing dependencies using $pkg_manager? (y/n): " install_deps
698
+ read -r -p "Install missing dependencies using $pkg_manager? [Y/n]: " install_deps
664
699
 
665
- if [[ "$install_deps" == "y" ]]; then
700
+ if [[ "$install_deps" =~ ^[Yy]?$ ]]; then
666
701
  print_info "Installing ${missing_deps[*]}..."
667
702
  if install_packages "$pkg_manager" "${missing_deps[@]}"; then
668
703
  print_success "Dependencies installed successfully"
@@ -699,9 +734,9 @@ check_optional_deps() {
699
734
  pkg_manager=$(detect_package_manager)
700
735
 
701
736
  if [[ "$pkg_manager" != "unknown" ]]; then
702
- read -r -p "Install optional dependencies using $pkg_manager? (y/n): " install_optional
737
+ read -r -p "Install optional dependencies using $pkg_manager? [Y/n]: " install_optional
703
738
 
704
- if [[ "$install_optional" == "y" ]]; then
739
+ if [[ "$install_optional" =~ ^[Yy]?$ ]]; then
705
740
  print_info "Installing ${missing_optional[*]}..."
706
741
  if install_packages "$pkg_manager" "${missing_optional[@]}"; then
707
742
  print_success "Optional dependencies installed"
@@ -755,9 +790,9 @@ setup_git_clis() {
755
790
 
756
791
  if [[ "$pkg_manager" != "unknown" ]]; then
757
792
  echo ""
758
- read -r -p "Install Git CLI tools (${missing_packages[*]}) using $pkg_manager? (y/n): " install_git_clis
793
+ read -r -p "Install Git CLI tools (${missing_packages[*]}) using $pkg_manager? [Y/n]: " install_git_clis
759
794
 
760
- if [[ "$install_git_clis" == "y" ]]; then
795
+ if [[ "$install_git_clis" =~ ^[Yy]?$ ]]; then
761
796
  print_info "Installing ${missing_packages[*]}..."
762
797
  if install_packages "$pkg_manager" "${missing_packages[@]}"; then
763
798
  print_success "Git CLI tools installed"
@@ -853,10 +888,10 @@ setup_file_discovery_tools() {
853
888
  if [[ "$pkg_manager" != "unknown" ]]; then
854
889
  local install_fd_tools="y"
855
890
  if [[ "$INTERACTIVE_MODE" == "true" ]]; then
856
- read -r -p "Install file discovery tools (${missing_packages[*]}) using $pkg_manager? (y/n): " install_fd_tools
891
+ read -r -p "Install file discovery tools (${missing_packages[*]}) using $pkg_manager? [Y/n]: " install_fd_tools
857
892
  fi
858
893
 
859
- if [[ "$install_fd_tools" == "y" ]]; then
894
+ if [[ "$install_fd_tools" =~ ^[Yy]?$ ]]; then
860
895
  print_info "Installing ${missing_packages[*]}..."
861
896
 
862
897
  # Handle package name differences across package managers
@@ -959,8 +994,8 @@ setup_worktrunk() {
959
994
  if [[ -n "$shell_rc" ]] && [[ -f "$shell_rc" ]]; then
960
995
  if ! grep -q "worktrunk" "$shell_rc" 2>/dev/null; then
961
996
  print_info "Shell integration not detected"
962
- read -r -p "Install Worktrunk shell integration (enables 'wt switch' to change directories)? (y/n): " install_shell
963
- if [[ "$install_shell" == "y" ]]; then
997
+ read -r -p "Install Worktrunk shell integration (enables 'wt switch' to change directories)? [Y/n]: " install_shell
998
+ if [[ "$install_shell" =~ ^[Yy]?$ ]]; then
964
999
  if wt config shell install 2>/dev/null; then
965
1000
  print_success "Shell integration installed"
966
1001
  print_info "Restart your terminal or run: source $shell_rc"
@@ -989,25 +1024,15 @@ setup_worktrunk() {
989
1024
  pkg_manager=$(detect_package_manager)
990
1025
 
991
1026
  if [[ "$pkg_manager" == "brew" ]]; then
992
- read -r -p "Install Worktrunk via Homebrew? (y/n): " install_wt
1027
+ read -r -p "Install Worktrunk via Homebrew? [Y/n]: " install_wt
993
1028
 
994
- if [[ "$install_wt" == "y" ]]; then
995
- print_info "Installing Worktrunk..."
996
- if brew install max-sixty/worktrunk/wt 2>/dev/null; then
997
- print_success "Worktrunk installed"
998
-
1029
+ if [[ "$install_wt" =~ ^[Yy]?$ ]]; then
1030
+ if run_with_spinner "Installing Worktrunk via Homebrew" brew install max-sixty/worktrunk/wt; then
999
1031
  # Install shell integration
1000
- print_info "Installing shell integration..."
1001
- local wt_shell_output
1002
- if wt_shell_output=$(wt config shell install 2>&1); then
1003
- print_success "Shell integration installed"
1032
+ if run_with_spinner "Installing shell integration" wt config shell install; then
1004
1033
  print_info "Restart your terminal or source your shell config"
1005
1034
  else
1006
- # Show the actual error for debugging
1007
1035
  print_warning "Shell integration failed - run manually: wt config shell install"
1008
- if [[ -n "$wt_shell_output" ]]; then
1009
- echo "$wt_shell_output" | head -3 | sed 's/^/ /'
1010
- fi
1011
1036
  fi
1012
1037
 
1013
1038
  echo ""
@@ -1027,16 +1052,13 @@ setup_worktrunk() {
1027
1052
  print_info "Fallback available: ~/.aidevops/agents/scripts/worktree-helper.sh"
1028
1053
  fi
1029
1054
  elif command -v cargo >/dev/null 2>&1; then
1030
- read -r -p "Install Worktrunk via Cargo? (y/n): " install_wt
1055
+ read -r -p "Install Worktrunk via Cargo? [Y/n]: " install_wt
1031
1056
 
1032
- if [[ "$install_wt" == "y" ]]; then
1033
- print_info "Installing Worktrunk via Cargo..."
1034
- if cargo install worktrunk 2>/dev/null; then
1035
- print_success "Worktrunk installed"
1036
-
1057
+ if [[ "$install_wt" =~ ^[Yy]?$ ]]; then
1058
+ if run_with_spinner "Installing Worktrunk via Cargo" cargo install worktrunk; then
1037
1059
  # Install shell integration
1038
- if wt config shell install 2>/dev/null; then
1039
- print_success "Shell integration installed"
1060
+ if run_with_spinner "Installing shell integration" wt config shell install; then
1061
+ print_info "Restart your terminal or source your shell config"
1040
1062
  else
1041
1063
  print_warning "Shell integration failed - run manually: wt config shell install"
1042
1064
  fi
@@ -1121,8 +1143,8 @@ setup_recommended_tools() {
1121
1143
 
1122
1144
  if [[ -d "$zed_extensions_dir" ]]; then
1123
1145
  if [[ ! -d "$zed_extensions_dir/opencode" ]]; then
1124
- read -r -p "Install OpenCode extension for Zed? (y/n): " install_opencode_ext
1125
- if [[ "$install_opencode_ext" == "y" ]]; then
1146
+ read -r -p "Install OpenCode extension for Zed? [Y/n]: " install_opencode_ext
1147
+ if [[ "$install_opencode_ext" =~ ^[Yy]?$ ]]; then
1126
1148
  print_info "Installing OpenCode extension..."
1127
1149
  if [[ "$(uname)" == "Darwin" ]]; then
1128
1150
  open "zed://extension/opencode" 2>/dev/null
@@ -1148,15 +1170,13 @@ setup_recommended_tools() {
1148
1170
 
1149
1171
  # Install Tabby if missing
1150
1172
  if [[ " ${missing_tools[*]} " =~ " tabby " ]]; then
1151
- read -r -p "Install Tabby terminal? (y/n): " install_tabby
1173
+ read -r -p "Install Tabby terminal? [Y/n]: " install_tabby
1152
1174
 
1153
- if [[ "$install_tabby" == "y" ]]; then
1154
- print_info "Installing Tabby..."
1175
+ if [[ "$install_tabby" =~ ^[Yy]?$ ]]; then
1155
1176
  if [[ "$(uname)" == "Darwin" ]]; then
1156
1177
  if command -v brew >/dev/null 2>&1; then
1157
- brew install --cask tabby
1158
- if [[ $? -eq 0 ]]; then
1159
- print_success "Tabby installed successfully"
1178
+ if run_with_spinner "Installing Tabby" brew install --cask tabby; then
1179
+ : # Success message handled by spinner
1160
1180
  else
1161
1181
  print_warning "Failed to install Tabby via Homebrew"
1162
1182
  echo " Download manually: https://github.com/Eugeny/tabby/releases/latest"
@@ -1197,16 +1217,13 @@ setup_recommended_tools() {
1197
1217
 
1198
1218
  # Install Zed if missing
1199
1219
  if [[ " ${missing_tools[*]} " =~ " zed " ]]; then
1200
- read -r -p "Install Zed editor? (y/n): " install_zed
1220
+ read -r -p "Install Zed editor? [Y/n]: " install_zed
1201
1221
 
1202
- if [[ "$install_zed" == "y" ]]; then
1203
- print_info "Installing Zed..."
1222
+ if [[ "$install_zed" =~ ^[Yy]?$ ]]; then
1204
1223
  local zed_installed=false
1205
1224
  if [[ "$(uname)" == "Darwin" ]]; then
1206
1225
  if command -v brew >/dev/null 2>&1; then
1207
- brew install --cask zed
1208
- if [[ $? -eq 0 ]]; then
1209
- print_success "Zed installed successfully"
1226
+ if run_with_spinner "Installing Zed" brew install --cask zed; then
1210
1227
  zed_installed=true
1211
1228
  else
1212
1229
  print_warning "Failed to install Zed via Homebrew"
@@ -1217,10 +1234,9 @@ setup_recommended_tools() {
1217
1234
  echo " Download manually: https://zed.dev/download"
1218
1235
  fi
1219
1236
  elif [[ "$(uname)" == "Linux" ]]; then
1220
- # Zed provides an install script for Linux
1237
+ # Zed provides an install script for Linux (interactive, can't use spinner)
1221
1238
  print_info "Running Zed install script..."
1222
- curl -f https://zed.dev/install.sh | sh
1223
- if [[ $? -eq 0 ]]; then
1239
+ if curl -f https://zed.dev/install.sh | sh; then
1224
1240
  print_success "Zed installed successfully"
1225
1241
  zed_installed=true
1226
1242
  else
@@ -1231,8 +1247,8 @@ setup_recommended_tools() {
1231
1247
 
1232
1248
  # Install OpenCode extension for Zed
1233
1249
  if [[ "$zed_installed" == "true" ]]; then
1234
- read -r -p "Install OpenCode extension for Zed? (y/n): " install_opencode_ext
1235
- if [[ "$install_opencode_ext" == "y" ]]; then
1250
+ read -r -p "Install OpenCode extension for Zed? [Y/n]: " install_opencode_ext
1251
+ if [[ "$install_opencode_ext" =~ ^[Yy]?$ ]]; then
1236
1252
  print_info "Installing OpenCode extension..."
1237
1253
  if [[ "$(uname)" == "Darwin" ]]; then
1238
1254
  open "zed://extension/opencode" 2>/dev/null
@@ -1319,12 +1335,10 @@ setup_minisim() {
1319
1335
  fi
1320
1336
 
1321
1337
  local install_minisim
1322
- read -r -p "Install MiniSim? (y/n): " install_minisim
1338
+ read -r -p "Install MiniSim? [Y/n]: " install_minisim
1323
1339
 
1324
- if [[ "$install_minisim" == "y" ]]; then
1325
- print_info "Installing MiniSim..."
1326
- if brew install --cask minisim; then
1327
- print_success "MiniSim installed successfully"
1340
+ if [[ "$install_minisim" =~ ^[Yy]?$ ]]; then
1341
+ if run_with_spinner "Installing MiniSim" brew install --cask minisim; then
1328
1342
  print_info "Global shortcut: Option + Shift + E"
1329
1343
  print_info "Documentation: ~/.aidevops/agents/tools/mobile/minisim.md"
1330
1344
  else
@@ -1345,9 +1359,9 @@ setup_ssh_key() {
1345
1359
 
1346
1360
  if [[ ! -f ~/.ssh/id_ed25519 ]]; then
1347
1361
  print_warning "Ed25519 SSH key not found"
1348
- read -r -p "Generate new Ed25519 SSH key? (y/n): " generate_key
1362
+ read -r -p "Generate new Ed25519 SSH key? [Y/n]: " generate_key
1349
1363
 
1350
- if [[ "$generate_key" == "y" ]]; then
1364
+ if [[ "$generate_key" =~ ^[Yy]?$ ]]; then
1351
1365
  read -r -p "Enter your email address: " email
1352
1366
  ssh-keygen -t ed25519 -C "$email"
1353
1367
  print_success "SSH key generated"
@@ -1563,9 +1577,9 @@ setup_aliases() {
1563
1577
  fi
1564
1578
 
1565
1579
  print_info "Detected shell: $shell_name"
1566
- read -r -p "Add shell aliases to $shell_rc? (y/n): " add_aliases
1580
+ read -r -p "Add shell aliases to $shell_rc? [Y/n]: " add_aliases
1567
1581
 
1568
- if [[ "$add_aliases" == "y" ]]; then
1582
+ if [[ "$add_aliases" =~ ^[Yy]?$ ]]; then
1569
1583
  # Fish shell uses different syntax
1570
1584
  if [[ "$shell_name" == "fish" ]]; then
1571
1585
  mkdir -p "$HOME/.config/fish"
@@ -1652,9 +1666,9 @@ setup_terminal_title() {
1652
1666
  fi
1653
1667
 
1654
1668
  echo ""
1655
- read -r -p "Install terminal title integration? (y/n): " install_title
1669
+ read -r -p "Install terminal title integration? [Y/n]: " install_title
1656
1670
 
1657
- if [[ "$install_title" == "y" ]]; then
1671
+ if [[ "$install_title" =~ ^[Yy]?$ ]]; then
1658
1672
  if bash "$setup_script" install; then
1659
1673
  print_success "Terminal title integration installed"
1660
1674
  else
@@ -2182,14 +2196,9 @@ setup_python_env() {
2182
2196
  source python-env/dspy-env/bin/activate
2183
2197
  pip install --upgrade pip > /dev/null 2>&1
2184
2198
 
2185
- local pip_output
2186
- if pip_output=$(pip install -r requirements.txt 2>&1); then
2187
- print_success "DSPy dependencies installed successfully"
2199
+ if run_with_spinner "Installing DSPy dependencies" pip install -r requirements.txt; then
2200
+ : # Success message handled by spinner
2188
2201
  else
2189
- print_warning "Failed to install DSPy dependencies:"
2190
- # Show last few lines of error for debugging
2191
- echo "$pip_output" | tail -8 | sed 's/^/ /'
2192
- echo ""
2193
2202
  print_info "Check requirements.txt or run manually:"
2194
2203
  print_info " source python-env/dspy-env/bin/activate && pip install -r requirements.txt"
2195
2204
  fi
@@ -2220,13 +2229,10 @@ setup_nodejs_env() {
2220
2229
 
2221
2230
  # Install DSPyGround globally if not already installed
2222
2231
  if ! command -v dspyground &> /dev/null; then
2223
- print_info "Installing DSPyGround globally..."
2224
- npm install -g dspyground > /dev/null 2>&1
2225
-
2226
- if [[ $? -eq 0 ]]; then
2227
- print_success "DSPyGround installed successfully"
2232
+ if run_with_spinner "Installing DSPyGround" npm install -g dspyground; then
2233
+ : # Success message handled by spinner
2228
2234
  else
2229
- print_warning "Failed to install DSPyGround globally"
2235
+ print_warning "Try manually: npm install -g dspyground"
2230
2236
  fi
2231
2237
  else
2232
2238
  print_success "DSPyGround already installed"
@@ -2462,16 +2468,13 @@ setup_localwp_mcp() {
2462
2468
 
2463
2469
  # Offer to install mcp-local-wp
2464
2470
  print_info "LocalWP MCP server enables AI assistants to query WordPress databases"
2465
- read -r -p "Install LocalWP MCP server (@verygoodplugins/mcp-local-wp)? (y/n): " install_mcp
2471
+ read -r -p "Install LocalWP MCP server (@verygoodplugins/mcp-local-wp)? [Y/n]: " install_mcp
2466
2472
 
2467
- if [[ "$install_mcp" == "y" ]]; then
2468
- print_info "Installing LocalWP MCP server..."
2469
- if npm install -g @verygoodplugins/mcp-local-wp > /dev/null 2>&1; then
2470
- print_success "LocalWP MCP server installed successfully"
2473
+ if [[ "$install_mcp" =~ ^[Yy]?$ ]]; then
2474
+ if run_with_spinner "Installing LocalWP MCP server" npm install -g @verygoodplugins/mcp-local-wp; then
2471
2475
  print_info "Start with: ~/.aidevops/agents/scripts/localhost-helper.sh start-mcp"
2472
2476
  print_info "Or configure in OpenCode MCP settings for auto-start"
2473
2477
  else
2474
- print_warning "Failed to install LocalWP MCP server"
2475
2478
  print_info "Try manually: npm install -g @verygoodplugins/mcp-local-wp"
2476
2479
  fi
2477
2480
  else
@@ -2580,16 +2583,13 @@ setup_beads() {
2580
2583
  else
2581
2584
  # Try to install via Homebrew first (macOS/Linux with Homebrew)
2582
2585
  if command -v brew &> /dev/null; then
2583
- print_info "Installing Beads via Homebrew..."
2584
- if brew install steveyegge/beads/bd 2>/dev/null; then
2585
- print_success "Beads CLI installed via Homebrew"
2586
+ if run_with_spinner "Installing Beads via Homebrew" brew install steveyegge/beads/bd; then
2587
+ : # Success message handled by spinner
2586
2588
  else
2587
2589
  print_warning "Homebrew tap installation failed, trying alternative..."
2588
2590
  # Try Go install if Go is available
2589
2591
  if command -v go &> /dev/null; then
2590
- print_info "Installing Beads via Go..."
2591
- if go install github.com/steveyegge/beads/cmd/bd@latest 2>/dev/null; then
2592
- print_success "Beads CLI installed via Go"
2592
+ if run_with_spinner "Installing Beads via Go" go install github.com/steveyegge/beads/cmd/bd@latest; then
2593
2593
  print_info "Ensure \$GOPATH/bin is in your PATH"
2594
2594
  else
2595
2595
  print_warning "Go installation failed"
@@ -2597,9 +2597,7 @@ setup_beads() {
2597
2597
  fi
2598
2598
  fi
2599
2599
  elif command -v go &> /dev/null; then
2600
- print_info "Installing Beads via Go..."
2601
- if go install github.com/steveyegge/beads/cmd/bd@latest 2>/dev/null; then
2602
- print_success "Beads CLI installed via Go"
2600
+ if run_with_spinner "Installing Beads via Go" go install github.com/steveyegge/beads/cmd/bd@latest; then
2603
2601
  print_info "Ensure \$GOPATH/bin is in your PATH"
2604
2602
  else
2605
2603
  print_warning "Go installation failed"
@@ -2635,9 +2633,9 @@ setup_beads_ui() {
2635
2633
  echo " • perles (Rust) - BQL query language TUI"
2636
2634
  echo ""
2637
2635
 
2638
- read -r -p "Install optional Beads UI tools? (y/n): " install_beads_ui
2636
+ read -r -p "Install optional Beads UI tools? [Y/n]: " install_beads_ui
2639
2637
 
2640
- if [[ "$install_beads_ui" != "y" ]]; then
2638
+ if [[ ! "$install_beads_ui" =~ ^[Yy]?$ ]]; then
2641
2639
  print_info "Skipped Beads UI tools (can install later from beads.md docs)"
2642
2640
  return 0
2643
2641
  fi
@@ -2646,24 +2644,21 @@ setup_beads_ui() {
2646
2644
 
2647
2645
  # beads_viewer (Python) - use pipx for isolated install
2648
2646
  if command -v pipx &> /dev/null || command -v pip3 &> /dev/null || command -v pip &> /dev/null; then
2649
- read -r -p " Install beads_viewer (Python TUI with graph analytics)? (y/n): " install_viewer
2650
- if [[ "$install_viewer" == "y" ]]; then
2647
+ read -r -p " Install beads_viewer (Python TUI with graph analytics)? [Y/n]: " install_viewer
2648
+ if [[ "$install_viewer" =~ ^[Yy]?$ ]]; then
2651
2649
  if command -v pipx &> /dev/null; then
2652
- print_info "Installing beads_viewer via pipx..."
2653
- if pipx install beads-viewer 2>/dev/null; then
2654
- print_success "beads_viewer installed (run: beads-viewer)"
2650
+ if run_with_spinner "Installing beads_viewer via pipx" pipx install beads-viewer; then
2651
+ print_info "Run: beads-viewer"
2655
2652
  ((installed_count++))
2656
2653
  else
2657
- print_warning "Failed to install beads_viewer"
2658
2654
  print_info "Try manually: pipx install beads-viewer"
2659
2655
  fi
2660
2656
  else
2661
- print_info "Installing beads_viewer..."
2662
- if pip3 install --user beads-viewer 2>/dev/null || pip install --user beads-viewer 2>/dev/null; then
2663
- print_success "beads_viewer installed"
2657
+ if run_with_spinner "Installing beads_viewer" pip3 install --user beads-viewer; then
2658
+ ((installed_count++))
2659
+ elif run_with_spinner "Installing beads_viewer" pip install --user beads-viewer; then
2664
2660
  ((installed_count++))
2665
2661
  else
2666
- print_warning "Failed to install beads_viewer"
2667
2662
  print_info "On macOS, install pipx first: brew install pipx && pipx ensurepath"
2668
2663
  fi
2669
2664
  fi
@@ -2672,39 +2667,30 @@ setup_beads_ui() {
2672
2667
 
2673
2668
  # beads-ui (Node.js)
2674
2669
  if command -v npm &> /dev/null; then
2675
- read -r -p " Install beads-ui (Web dashboard)? (y/n): " install_web
2676
- if [[ "$install_web" == "y" ]]; then
2677
- print_info "Installing beads-ui..."
2678
- if npm install -g beads-ui 2>/dev/null; then
2679
- print_success "beads-ui installed (run: beads-ui)"
2670
+ read -r -p " Install beads-ui (Web dashboard)? [Y/n]: " install_web
2671
+ if [[ "$install_web" =~ ^[Yy]?$ ]]; then
2672
+ if run_with_spinner "Installing beads-ui" npm install -g beads-ui; then
2673
+ print_info "Run: beads-ui"
2680
2674
  ((installed_count++))
2681
- else
2682
- print_warning "Failed to install beads-ui"
2683
2675
  fi
2684
2676
  fi
2685
2677
 
2686
- read -r -p " Install bdui (React/Ink TUI)? (y/n): " install_bdui
2687
- if [[ "$install_bdui" == "y" ]]; then
2688
- print_info "Installing bdui..."
2689
- if npm install -g bdui 2>/dev/null; then
2690
- print_success "bdui installed (run: bdui)"
2678
+ read -r -p " Install bdui (React/Ink TUI)? [Y/n]: " install_bdui
2679
+ if [[ "$install_bdui" =~ ^[Yy]?$ ]]; then
2680
+ if run_with_spinner "Installing bdui" npm install -g bdui; then
2681
+ print_info "Run: bdui"
2691
2682
  ((installed_count++))
2692
- else
2693
- print_warning "Failed to install bdui"
2694
2683
  fi
2695
2684
  fi
2696
2685
  fi
2697
2686
 
2698
2687
  # perles (Rust)
2699
2688
  if command -v cargo &> /dev/null; then
2700
- read -r -p " Install perles (BQL query language TUI)? (y/n): " install_perles
2701
- if [[ "$install_perles" == "y" ]]; then
2702
- print_info "Installing perles (this may take a few minutes)..."
2703
- if cargo install perles 2>/dev/null; then
2704
- print_success "perles installed (run: perles)"
2689
+ read -r -p " Install perles (BQL query language TUI)? [Y/n]: " install_perles
2690
+ if [[ "$install_perles" =~ ^[Yy]?$ ]]; then
2691
+ if run_with_spinner "Installing perles (Rust compile)" cargo install perles; then
2692
+ print_info "Run: perles"
2705
2693
  ((installed_count++))
2706
- else
2707
- print_warning "Failed to install perles"
2708
2694
  fi
2709
2695
  fi
2710
2696
  fi
@@ -2795,9 +2781,9 @@ setup_browser_tools() {
2795
2781
  print_success "Playwright already installed"
2796
2782
  else
2797
2783
  local install_playwright
2798
- read -r -p "Install Playwright MCP with browsers (chromium, firefox, webkit)? (y/n): " install_playwright
2784
+ read -r -p "Install Playwright MCP with browsers (chromium, firefox, webkit)? [Y/n]: " install_playwright
2799
2785
 
2800
- if [[ "$install_playwright" == "y" ]]; then
2786
+ if [[ "$install_playwright" =~ ^[Yy]?$ ]]; then
2801
2787
  print_info "Installing Playwright browsers..."
2802
2788
  # Use -y to auto-confirm npx install, suppress the "install without dependencies" warning
2803
2789
  # Use PIPESTATUS to check npx exit code, not grep's exit code
@@ -3014,9 +3000,9 @@ setup_oh_my_opencode() {
3014
3000
  echo " They are complementary and work well together."
3015
3001
  echo ""
3016
3002
 
3017
- read -r -p "Install Oh-My-OpenCode plugin? (y/n): " install_omo
3003
+ read -r -p "Install Oh-My-OpenCode plugin? [Y/n]: " install_omo
3018
3004
 
3019
- if [[ "$install_omo" != "y" ]]; then
3005
+ if [[ ! "$install_omo" =~ ^[Yy]?$ ]]; then
3020
3006
  print_info "Skipped Oh-My-OpenCode installation"
3021
3007
  return 0
3022
3008
  fi
@@ -3267,10 +3253,10 @@ setup_multi_tenant_credentials() {
3267
3253
  print_info "Everything continues to work as before - this is non-breaking."
3268
3254
  echo ""
3269
3255
 
3270
- read -r -p "Enable multi-tenant credential storage? (y/n): " enable_mt
3256
+ read -r -p "Enable multi-tenant credential storage? [Y/n]: " enable_mt
3271
3257
  enable_mt=$(echo "$enable_mt" | tr '[:upper:]' '[:lower:]')
3272
3258
 
3273
- if [[ "$enable_mt" == "y" || "$enable_mt" == "yes" ]]; then
3259
+ if [[ "$enable_mt" =~ ^[Yy]?$ || "$enable_mt" == "yes" ]]; then
3274
3260
  bash "$credential_helper" init
3275
3261
  print_success "Multi-tenant credential storage enabled"
3276
3262
  echo ""
@@ -3332,9 +3318,9 @@ check_tool_updates() {
3332
3318
  bash "$tool_check_script" --quiet
3333
3319
  echo ""
3334
3320
 
3335
- read -r -p "Update all outdated tools now? (y/n): " do_update
3321
+ read -r -p "Update all outdated tools now? [Y/n]: " do_update
3336
3322
 
3337
- if [[ "$do_update" == "y" || "$do_update" == "Y" ]]; then
3323
+ if [[ "$do_update" =~ ^[Yy]?$ || "$do_update" == "Y" ]]; then
3338
3324
  print_info "Updating tools..."
3339
3325
  bash "$tool_check_script" --update
3340
3326
  print_success "Tool updates complete!"
@@ -3543,8 +3529,8 @@ echo " aidevops uninstall - Remove aidevops"
3543
3529
  echo " • Get personalized recommendations based on your work"
3544
3530
  echo " • Set up API keys and credentials interactively"
3545
3531
  echo ""
3546
- read -r -p "Launch OpenCode with /onboarding now? (y/n): " launch_onboarding
3547
- if [[ "$launch_onboarding" == "y" || "$launch_onboarding" == "Y" ]]; then
3532
+ read -r -p "Launch OpenCode with /onboarding now? [Y/n]: " launch_onboarding
3533
+ if [[ "$launch_onboarding" =~ ^[Yy]?$ || "$launch_onboarding" == "Y" ]]; then
3548
3534
  echo ""
3549
3535
  echo "Starting OpenCode..."
3550
3536
  opencode --prompt "/onboarding"