aidevops 3.5.896 → 3.8.3

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.
@@ -1,4 +1,6 @@
1
1
  #!/usr/bin/env bash
2
+ # SPDX-License-Identifier: MIT
3
+ # SPDX-FileCopyrightText: 2025-2026 Marcus Quinn
2
4
  # Shell environment setup functions: oh-my-zsh, shell-compat, aliases, terminal-title
3
5
  # Part of aidevops setup.sh modularization (t316.3)
4
6
 
@@ -21,9 +23,24 @@ detect_running_shell() {
21
23
  return 0
22
24
  }
23
25
 
24
- # Detect the user's default login shell from $SHELL
26
+ # Detect the user's default login shell from the system (not $SHELL env var,
27
+ # which reflects the current shell, not the system default).
25
28
  detect_default_shell() {
26
- basename "${SHELL:-/bin/bash}"
29
+ local user_name shell_path
30
+ user_name="$(id -un 2>/dev/null || whoami)"
31
+ shell_path=""
32
+
33
+ if [[ "$(uname)" == "Darwin" ]]; then
34
+ shell_path="$(dscl . -read "/Users/$user_name" UserShell 2>/dev/null | awk 'NR==1 {print $2}' || true)"
35
+ else
36
+ if command -v getent >/dev/null 2>&1; then
37
+ shell_path="$(getent passwd "$user_name" 2>/dev/null | cut -d: -f7 || true)"
38
+ fi
39
+ fi
40
+
41
+ # Fallback to $SHELL if system query returned empty
42
+ [[ -z "$shell_path" ]] && shell_path="${SHELL:-/bin/bash}"
43
+ basename "$shell_path"
27
44
  return 0
28
45
  }
29
46
 
@@ -1002,8 +1019,32 @@ _aliases_check_configured() {
1002
1019
  return 1
1003
1020
  }
1004
1021
 
1022
+ # Replace the aidevops alias block in a single rc file.
1023
+ # Removes the old block (marker line through the next blank line) and appends
1024
+ # the new block. Idempotent: safe to call on every setup run.
1025
+ _aliases_replace_in_file() {
1026
+ local rc_file="$1"
1027
+ local alias_block="$2"
1028
+ local marker="# AI Assistant Server Access"
1029
+ local tmp_file
1030
+ tmp_file=$(mktemp "${TMPDIR:-/tmp}/aidevops-aliases-XXXXXX") || return 1
1031
+
1032
+ # Strip existing block: from marker line to the next blank line (inclusive)
1033
+ awk -v marker="$marker" '
1034
+ $0 ~ marker { in_block=1; next }
1035
+ in_block && /^[[:space:]]*$/ { in_block=0; next }
1036
+ in_block { next }
1037
+ { print }
1038
+ ' "$rc_file" >"$tmp_file" && mv "$tmp_file" "$rc_file"
1039
+
1040
+ # Append updated block
1041
+ printf '%s\n' "$alias_block" >>"$rc_file"
1042
+ return 0
1043
+ }
1044
+
1005
1045
  # Write alias blocks to fish or bash/zsh rc files.
1006
- # Prints the list of files aliases were added to (comma-separated).
1046
+ # Always replaces an existing aidevops alias block so updates propagate.
1047
+ # Prints the list of files aliases were added/updated in (comma-separated).
1007
1048
  _aliases_write_to_rc_files() {
1008
1049
  local is_fish="$1"
1009
1050
  local alias_block_bash="$2"
@@ -1014,10 +1055,13 @@ _aliases_write_to_rc_files() {
1014
1055
  if [[ "$is_fish" == "true" ]]; then
1015
1056
  local fish_rc="$HOME/.config/fish/config.fish"
1016
1057
  mkdir -p "$HOME/.config/fish"
1017
- echo "$alias_block_fish" >>"$fish_rc"
1058
+ if [[ ! -f "$fish_rc" ]]; then
1059
+ touch "$fish_rc"
1060
+ fi
1061
+ _aliases_replace_in_file "$fish_rc" "$alias_block_fish"
1018
1062
  added_to="$fish_rc"
1019
1063
  else
1020
- # Add to all bash/zsh rc files
1064
+ # Add/update in all bash/zsh rc files
1021
1065
  local rc_file
1022
1066
  while IFS= read -r rc_file; do
1023
1067
  [[ -z "$rc_file" ]] && continue
@@ -1027,12 +1071,7 @@ _aliases_write_to_rc_files() {
1027
1071
  touch "$rc_file"
1028
1072
  fi
1029
1073
 
1030
- # Skip if already has aliases (file created above if it didn't exist)
1031
- if grep -q "# AI Assistant Server Access" "$rc_file"; then
1032
- continue
1033
- fi
1034
-
1035
- echo "$alias_block_bash" >>"$rc_file"
1074
+ _aliases_replace_in_file "$rc_file" "$alias_block_bash"
1036
1075
  added_to="${added_to:+$added_to, }$rc_file"
1037
1076
  done < <(get_all_shell_rcs)
1038
1077
  fi
@@ -1054,6 +1093,8 @@ alias servers-list='./.agents/scripts/servers-helper.sh list'
1054
1093
  alias hostinger='./.agents/scripts/hostinger-helper.sh'
1055
1094
  alias hetzner='./.agents/scripts/hetzner-helper.sh'
1056
1095
  alias aws-helper='./.agents/scripts/aws-helper.sh'
1096
+ # Claude Code: skip interactive permission prompts (safe for personal machines)
1097
+ command -v claude >/dev/null 2>&1 && alias claude='claude --dangerously-skip-permissions'
1057
1098
  ALIASES
1058
1099
  return 0
1059
1100
  }
@@ -1068,6 +1109,8 @@ alias servers-list './.agents/scripts/servers-helper.sh list'
1068
1109
  alias hostinger './.agents/scripts/hostinger-helper.sh'
1069
1110
  alias hetzner './.agents/scripts/hetzner-helper.sh'
1070
1111
  alias aws-helper './.agents/scripts/aws-helper.sh'
1112
+ # Claude Code: skip interactive permission prompts (safe for personal machines)
1113
+ if command -v claude >/dev/null 2>&1; alias claude 'claude --dangerously-skip-permissions'; end
1071
1114
  ALIASES
1072
1115
  return 0
1073
1116
  }
@@ -1089,11 +1132,6 @@ setup_aliases() {
1089
1132
  local alias_block_fish
1090
1133
  alias_block_fish=$(_aliases_build_fish_block)
1091
1134
 
1092
- if _aliases_check_configured; then
1093
- print_info "Server Access aliases already configured - Skipping"
1094
- return 0
1095
- fi
1096
-
1097
1135
  print_info "Detected default shell: $default_shell"
1098
1136
  setup_prompt add_aliases "Add shell aliases? [Y/n]: " "Y"
1099
1137
 
@@ -0,0 +1,324 @@
1
+ #!/usr/bin/env bash
2
+ # SPDX-License-Identifier: MIT
3
+ # SPDX-FileCopyrightText: 2025-2026 Marcus Quinn
4
+ # Beads task graph visualization setup and Claude Code safety hooks.
5
+ # Split from agent-deploy.sh (t1940)
6
+
7
+ # Shell safety baseline
8
+ set -Eeuo pipefail
9
+ IFS=$'\n\t'
10
+ # shellcheck disable=SC2154 # rc is assigned by $? in the trap string
11
+ trap 'rc=$?; echo "[ERROR] ${BASH_SOURCE[0]}:${LINENO} exit $rc" >&2' ERR
12
+ shopt -s inherit_errexit 2>/dev/null || true
13
+
14
+ install_beads_binary() {
15
+ local os arch tarball_name
16
+ os=$(uname -s | tr '[:upper:]' '[:lower:]')
17
+ arch=$(uname -m)
18
+
19
+ # Map architecture names to Beads release naming convention
20
+ case "$arch" in
21
+ x86_64 | amd64) arch="amd64" ;;
22
+ aarch64 | arm64) arch="arm64" ;;
23
+ *)
24
+ print_warning "Unsupported architecture for Beads binary download: $arch"
25
+ return 1
26
+ ;;
27
+ esac
28
+
29
+ # Get latest version tag from GitHub API
30
+ local latest_version
31
+ latest_version=$(curl -fsSL "https://api.github.com/repos/steveyegge/beads/releases/latest" 2>/dev/null |
32
+ grep '"tag_name"' | head -1 | sed 's/.*"tag_name": *"v\{0,1\}\([^"]*\)".*/\1/')
33
+
34
+ if [[ -z "$latest_version" ]]; then
35
+ print_warning "Could not determine latest Beads version from GitHub"
36
+ return 1
37
+ fi
38
+
39
+ tarball_name="beads_${latest_version}_${os}_${arch}.tar.gz"
40
+ local download_url="https://github.com/steveyegge/beads/releases/download/v${latest_version}/${tarball_name}"
41
+
42
+ print_info "Downloading Beads CLI v${latest_version} (${os}/${arch})..."
43
+
44
+ local tmp_dir
45
+ tmp_dir=$(mktemp -d)
46
+ # shellcheck disable=SC2064 # Intentional: $tmp_dir must expand at trap definition time, not execution time
47
+ trap "rm -rf '$tmp_dir'" RETURN
48
+
49
+ if ! curl -fsSL "$download_url" -o "$tmp_dir/$tarball_name" 2>/dev/null; then
50
+ print_warning "Failed to download Beads binary from $download_url"
51
+ return 1
52
+ fi
53
+
54
+ if ! tar -xzf "$tmp_dir/$tarball_name" -C "$tmp_dir" 2>/dev/null; then
55
+ print_warning "Failed to extract Beads binary"
56
+ return 1
57
+ fi
58
+
59
+ local bd_binary
60
+ bd_binary=$(find "$tmp_dir" -name "bd" -type f 2>/dev/null | head -1)
61
+ if [[ -z "$bd_binary" ]]; then
62
+ print_warning "bd binary not found in downloaded archive"
63
+ return 1
64
+ fi
65
+
66
+ # Install to a writable location
67
+ local install_dir="/usr/local/bin"
68
+ if [[ ! -w "$install_dir" ]]; then
69
+ if command -v sudo &>/dev/null; then
70
+ sudo install -m 755 "$bd_binary" "$install_dir/bd"
71
+ else
72
+ # Fallback to user-local bin
73
+ install_dir="$HOME/.local/bin"
74
+ mkdir -p "$install_dir"
75
+ install -m 755 "$bd_binary" "$install_dir/bd"
76
+ if [[ ":$PATH:" != *":$HOME/.local/bin:"* ]]; then
77
+ export PATH="$HOME/.local/bin:$PATH"
78
+ print_info "Added ~/.local/bin to PATH for this session"
79
+ fi
80
+ fi
81
+ else
82
+ install -m 755 "$bd_binary" "$install_dir/bd"
83
+ fi
84
+
85
+ if command -v bd &>/dev/null; then
86
+ print_success "Beads CLI installed via binary download (v${latest_version})"
87
+ return 0
88
+ else
89
+ print_warning "Beads binary installed to $install_dir/bd but not found in PATH"
90
+ return 1
91
+ fi
92
+ }
93
+
94
+ install_beads_go() {
95
+ if ! command -v go &>/dev/null; then
96
+ return 1
97
+ fi
98
+ if run_with_spinner "Installing Beads via Go" go install github.com/steveyegge/beads/cmd/bd@latest; then
99
+ print_info "Ensure \$GOPATH/bin is in your PATH"
100
+ return 0
101
+ fi
102
+ print_warning "Go installation failed"
103
+ return 1
104
+ }
105
+
106
+ setup_beads() {
107
+ print_info "Setting up Beads (task graph visualization)..."
108
+
109
+ if command -v bd &>/dev/null; then
110
+ local bd_version
111
+ bd_version=$(bd --version 2>/dev/null | head -1 || echo "unknown")
112
+ print_success "Beads CLI (bd) already installed: $bd_version"
113
+ else
114
+ # Try to install via Homebrew first (macOS/Linux with Homebrew)
115
+ if command -v brew &>/dev/null; then
116
+ if run_with_spinner "Installing Beads via Homebrew" brew install steveyegge/beads/bd; then
117
+ : # Success message handled by spinner
118
+ else
119
+ print_warning "Homebrew tap installation failed, trying alternative..."
120
+ install_beads_binary || install_beads_go
121
+ fi
122
+ elif command -v go &>/dev/null; then
123
+ if ! install_beads_go; then
124
+ print_warning "Go installation failed, trying binary download..."
125
+ install_beads_binary
126
+ fi
127
+ else
128
+ # No brew, no Go -- try binary download first, then offer Homebrew install
129
+ if ! install_beads_binary; then
130
+ # Binary download failed -- offer to install Homebrew (Linux only)
131
+ if ensure_homebrew; then
132
+ # Homebrew now available, retry via tap
133
+ if run_with_spinner "Installing Beads via Homebrew" brew install steveyegge/beads/bd; then
134
+ : # Success
135
+ else
136
+ print_warning "Homebrew tap installation failed"
137
+ fi
138
+ else
139
+ print_warning "Beads CLI (bd) not installed"
140
+ echo ""
141
+ echo " Install options:"
142
+ echo " Binary download: https://github.com/steveyegge/beads/releases"
143
+ echo " macOS/Linux (Homebrew): brew install steveyegge/beads/bd"
144
+ echo " Go: go install github.com/steveyegge/beads/cmd/bd@latest"
145
+ echo ""
146
+ fi
147
+ fi
148
+ fi
149
+ fi
150
+
151
+ print_info "Beads provides task graph visualization for TODO.md and PLANS.md"
152
+ print_info "After installation, run: aidevops init beads"
153
+
154
+ # Offer to install optional Beads UI tools
155
+ setup_beads_ui
156
+
157
+ return 0
158
+ }
159
+
160
+ # _install_bv_tool: install the bv (beads_viewer) TUI tool.
161
+ # Returns 0 if installed, 1 if skipped or failed.
162
+ _install_bv_tool() {
163
+ setup_prompt install_viewer " Install bv (TUI with PageRank, critical path, graph analytics)? [Y/n]: " "Y"
164
+ if [[ ! "$install_viewer" =~ ^[Yy]?$ ]]; then
165
+ print_info "Install later:"
166
+ print_info " Homebrew: brew tap dicklesworthstone/tap && brew install dicklesworthstone/tap/bv"
167
+ print_info " Go: go install github.com/Dicklesworthstone/beads_viewer/cmd/bv@latest"
168
+ return 1
169
+ fi
170
+ if command -v brew &>/dev/null; then
171
+ if run_with_spinner "Installing bv via Homebrew" brew install dicklesworthstone/tap/bv; then
172
+ print_info "Run: bv (in a beads-enabled project)"
173
+ return 0
174
+ else
175
+ print_warning "Homebrew install failed - try manually:"
176
+ print_info " brew install dicklesworthstone/tap/bv"
177
+ return 1
178
+ fi
179
+ elif command -v go &>/dev/null; then
180
+ if run_with_spinner "Installing bv via Go" go install github.com/Dicklesworthstone/beads_viewer/cmd/bv@latest; then
181
+ print_info "Run: bv (in a beads-enabled project)"
182
+ return 0
183
+ else
184
+ print_warning "Go install failed"
185
+ return 1
186
+ fi
187
+ else
188
+ # Offer verified install script (download-then-execute, not piped)
189
+ setup_prompt use_script " Install bv via install script? [Y/n]: " "Y"
190
+ if [[ "$use_script" =~ ^[Yy]?$ ]]; then
191
+ if verified_install "bv (beads viewer)" "https://raw.githubusercontent.com/Dicklesworthstone/beads_viewer/main/install.sh"; then
192
+ print_info "Run: bv (in a beads-enabled project)"
193
+ return 0
194
+ else
195
+ print_warning "Install script failed - try manually:"
196
+ print_info " Homebrew: brew tap dicklesworthstone/tap && brew install dicklesworthstone/tap/bv"
197
+ return 1
198
+ fi
199
+ else
200
+ print_info "Install later:"
201
+ print_info " Homebrew: brew tap dicklesworthstone/tap && brew install dicklesworthstone/tap/bv"
202
+ print_info " Go: go install github.com/Dicklesworthstone/beads_viewer/cmd/bv@latest"
203
+ return 1
204
+ fi
205
+ fi
206
+ }
207
+
208
+ # _install_beads_node_tools: install beads-ui and bdui via npm.
209
+ # Echoes the count of tools installed to stdout.
210
+ # All informational output (spinner, status) goes to stderr so that
211
+ # command-substitution callers receive only the numeric count.
212
+ _install_beads_node_tools() {
213
+ local count=0
214
+ if ! command -v npm &>/dev/null; then
215
+ echo "$count"
216
+ return 0
217
+ fi
218
+ setup_prompt install_web " Install beads-ui (Web dashboard)? [Y/n]: " "Y"
219
+ if [[ "$install_web" =~ ^[Yy]?$ ]]; then
220
+ if run_with_spinner "Installing beads-ui" npm_global_install beads-ui 1>&2; then
221
+ print_info "Run: beads-ui" >&2
222
+ count=$((count + 1))
223
+ fi
224
+ fi
225
+ setup_prompt install_bdui " Install bdui (React/Ink TUI)? [Y/n]: " "Y"
226
+ if [[ "$install_bdui" =~ ^[Yy]?$ ]]; then
227
+ if run_with_spinner "Installing bdui" npm_global_install bdui 1>&2; then
228
+ print_info "Run: bdui" >&2
229
+ count=$((count + 1))
230
+ fi
231
+ fi
232
+ echo "$count"
233
+ return 0
234
+ }
235
+
236
+ # _install_perles: install the perles BQL query language TUI via cargo.
237
+ # Returns 0 if installed, 1 if skipped or unavailable.
238
+ _install_perles() {
239
+ if ! command -v cargo &>/dev/null; then
240
+ return 1
241
+ fi
242
+ setup_prompt install_perles " Install perles (BQL query language TUI)? [Y/n]: " "Y"
243
+ if [[ ! "$install_perles" =~ ^[Yy]?$ ]]; then
244
+ return 1
245
+ fi
246
+ if run_with_spinner "Installing perles (Rust compile)" cargo install perles; then
247
+ print_info "Run: perles"
248
+ return 0
249
+ fi
250
+ return 1
251
+ }
252
+
253
+ setup_beads_ui() {
254
+ echo ""
255
+ print_info "Beads UI tools provide enhanced visualization:"
256
+ echo " • bv (Go) - PageRank, critical path, graph analytics TUI"
257
+ echo " • beads-ui (Node.js) - Web dashboard with live updates"
258
+ echo " • bdui (Node.js) - React/Ink terminal UI"
259
+ echo " • perles (Rust) - BQL query language TUI"
260
+ echo ""
261
+
262
+ setup_prompt install_beads_ui "Install optional Beads UI tools? [Y/n]: " "Y"
263
+
264
+ if [[ ! "$install_beads_ui" =~ ^[Yy]?$ ]]; then
265
+ print_info "Skipped Beads UI tools (can install later from beads.md docs)"
266
+ return 0
267
+ fi
268
+
269
+ local installed_count=0
270
+
271
+ # bv (beads_viewer) - Go TUI installed via Homebrew
272
+ # https://github.com/Dicklesworthstone/beads_viewer
273
+ if _install_bv_tool; then
274
+ installed_count=$((installed_count + 1))
275
+ fi
276
+
277
+ # beads-ui and bdui (Node.js)
278
+ local node_count
279
+ node_count=$(_install_beads_node_tools)
280
+ installed_count=$((installed_count + node_count))
281
+
282
+ # perles (Rust)
283
+ if _install_perles; then
284
+ installed_count=$((installed_count + 1))
285
+ fi
286
+
287
+ if [[ $installed_count -gt 0 ]]; then
288
+ print_success "Installed $installed_count Beads UI tool(s)"
289
+ else
290
+ print_info "No Beads UI tools installed"
291
+ fi
292
+
293
+ echo ""
294
+ print_info "Beads UI documentation: ~/.aidevops/agents/tools/task-management/beads.md"
295
+
296
+ return 0
297
+ }
298
+
299
+ setup_safety_hooks() {
300
+ print_info "Setting up Claude Code safety hooks..."
301
+
302
+ if ! command -v python3 &>/dev/null; then
303
+ print_warning "Python 3 not found - safety hooks require Python 3"
304
+ return 0
305
+ fi
306
+
307
+ local helper_script="$HOME/.aidevops/agents/scripts/install-hooks-helper.sh"
308
+ if [[ ! -f "$helper_script" ]]; then
309
+ # Fall back to repo copy (INSTALL_DIR set by setup.sh)
310
+ helper_script="${INSTALL_DIR:-.}/.agents/scripts/install-hooks-helper.sh"
311
+ fi
312
+
313
+ if [[ ! -f "$helper_script" ]]; then
314
+ print_warning "install-hooks-helper.sh not found - skipping safety hooks"
315
+ return 0
316
+ fi
317
+
318
+ if bash "$helper_script" install; then
319
+ print_success "Claude Code safety hooks installed"
320
+ else
321
+ print_warning "Safety hook installation encountered issues (non-critical)"
322
+ fi
323
+ return 0
324
+ }
@@ -1,4 +1,6 @@
1
1
  #!/usr/bin/env bash
2
+ # SPDX-License-Identifier: MIT
3
+ # SPDX-FileCopyrightText: 2025-2026 Marcus Quinn
2
4
  # Tool installation functions: git-clis, fd, ripgrep, shellcheck, shfmt, rosetta, worktrunk, minisim, recommended-tools, nodejs, python, orbstack
3
5
  # Part of aidevops setup.sh modularization (t316.3)
4
6
 
@@ -1487,7 +1489,10 @@ setup_opencode_cli() {
1487
1489
 
1488
1490
  # Need either bun or npm to install
1489
1491
  local installer=""
1490
- local install_pkg="opencode-ai@latest"
1492
+ # Respect OPENCODE_PINNED_VERSION from shared-constants.sh if sourced,
1493
+ # otherwise fall back to latest.
1494
+ local pin_ver="${OPENCODE_PINNED_VERSION:-latest}"
1495
+ local install_pkg="opencode-ai@${pin_ver}"
1491
1496
 
1492
1497
  if command -v bun >/dev/null 2>&1; then
1493
1498
  installer="bun"