aidevops 2.107.0 → 2.109.0

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.
package/README.md CHANGED
@@ -257,26 +257,6 @@ See `.agents/tools/task-management/beads.md` for complete documentation and inst
257
257
 
258
258
  **Your AI assistant now has agentic access to 30+ service integrations.**
259
259
 
260
- ### OpenCode Antigravity OAuth Plugin
261
-
262
- The setup automatically installs the [opencode-antigravity-auth](https://github.com/NoeFabris/opencode-antigravity-auth) plugin, enabling Google OAuth authentication for OpenCode. This gives you access to Antigravity rate limits and premium models.
263
-
264
- **After setup, authenticate:**
265
-
266
- ```bash
267
- opencode auth login
268
- # Select: Google → OAuth with Google (Antigravity)
269
- # Press Enter to skip Project ID prompt
270
- ```
271
-
272
- **Available models via Antigravity:**
273
-
274
- - `gemini-3-pro-high` / `gemini-3-pro-low` / `gemini-3-flash`
275
- - `claude-sonnet-4-5` / `claude-sonnet-4-5-thinking` / `claude-opus-4-5-thinking`
276
- - `gpt-oss-120b-medium`
277
-
278
- **Multi-account load balancing:** Add multiple Google accounts for automatic rate limit distribution and failover. See the [plugin documentation](https://github.com/NoeFabris/opencode-antigravity-auth) for model configuration.
279
-
280
260
  ### OpenCode Anthropic OAuth (Built-in)
281
261
 
282
262
  OpenCode v1.1.36+ includes Anthropic OAuth authentication natively. No external plugin is needed.
@@ -888,7 +868,7 @@ See `.agents/tools/ocr/glm-ocr.md` for batch processing, PDF workflows, and Peek
888
868
 
889
869
  ## **MCP Integrations**
890
870
 
891
- **Model Context Protocol servers for real-time AI assistant integration.** The framework configures these MCPs for **[OpenCode](https://opencode.ai/)** (TUI, Desktop, and Extension for Zed/VSCode/AntiGravity).
871
+ **Model Context Protocol servers for real-time AI assistant integration.** The framework configures these MCPs for **[OpenCode](https://opencode.ai/)** (TUI, Desktop, and Extension for Zed/VSCode).
892
872
 
893
873
  ### **All Supported MCPs (19 available)**
894
874
 
package/VERSION CHANGED
@@ -1 +1 @@
1
- 2.107.0
1
+ 2.109.0
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.107.0
6
+ # Version: 2.109.0
7
7
 
8
8
  set -euo pipefail
9
9
 
@@ -597,6 +597,7 @@ cmd_update() {
597
597
  print_error "Failed to create temp file for setup script"
598
598
  return 1
599
599
  }
600
+ trap 'rm -f "${tmp_setup:-}"' RETURN
600
601
  if curl -fsSL "https://raw.githubusercontent.com/marcusquinn/aidevops/main/setup.sh" -o "$tmp_setup" 2>/dev/null && [[ -s "$tmp_setup" ]]; then
601
602
  chmod +x "$tmp_setup"
602
603
  bash "$tmp_setup"
@@ -1484,6 +1485,7 @@ cmd_upgrade_planning() {
1484
1485
  local temp_file="${todo_file}.merge"
1485
1486
  local tasks_file
1486
1487
  tasks_file=$(mktemp)
1488
+ trap 'rm -f "${tasks_file:-}"' RETURN
1487
1489
  printf '%s\n' "$existing_tasks" > "$tasks_file"
1488
1490
  # Use while-read to avoid BSD awk "newline in string" warning with -v
1489
1491
  local in_backlog=false
@@ -1548,6 +1550,7 @@ cmd_upgrade_planning() {
1548
1550
  local temp_file="${plans_file}.merge"
1549
1551
  local plans_content_file
1550
1552
  plans_content_file=$(mktemp)
1553
+ trap 'rm -f "${plans_content_file:-}"' RETURN
1551
1554
  printf '%s\n' "$existing_plans" > "$plans_content_file"
1552
1555
  # Use while-read to avoid BSD awk "newline in string" warning with -v
1553
1556
  local in_active=false
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "aidevops",
3
- "version": "2.107.0",
3
+ "version": "2.109.0",
4
4
  "description": "AI DevOps Framework - AI-assisted development workflows, code quality, and deployment automation",
5
5
  "type": "module",
6
6
  "bin": {
package/setup.sh CHANGED
@@ -4,7 +4,7 @@ set -euo pipefail
4
4
  # AI Assistant Server Access Framework Setup Script
5
5
  # Helps developers set up the framework for their infrastructure
6
6
  #
7
- # Version: 2.107.0
7
+ # Version: 2.109.0
8
8
  #
9
9
  # Quick Install:
10
10
  # npm install -g aidevops && aidevops update (recommended)
@@ -334,6 +334,7 @@ cleanup_deprecated_paths() {
334
334
  if jq -e '.plugin | index("oh-my-opencode")' "$opencode_config" >/dev/null 2>&1; then
335
335
  local tmp_file
336
336
  tmp_file=$(mktemp)
337
+ trap 'rm -f "${tmp_file:-}"' RETURN
337
338
  jq '.plugin = [.plugin[] | select(. != "oh-my-opencode")]' "$opencode_config" > "$tmp_file" && mv "$tmp_file" "$opencode_config"
338
339
  print_info "Removed oh-my-opencode from OpenCode plugin list"
339
340
  fi
@@ -514,6 +515,7 @@ cleanup_deprecated_mcps() {
514
515
  local cleaned=0
515
516
  local tmp_config
516
517
  tmp_config=$(mktemp)
518
+ trap 'rm -f "${tmp_config:-}"' RETURN
517
519
 
518
520
  cp "$opencode_config" "$tmp_config"
519
521
 
@@ -637,6 +639,7 @@ disable_ondemand_mcps() {
637
639
  local disabled=0
638
640
  local tmp_config
639
641
  tmp_config=$(mktemp)
642
+ trap 'rm -f "${tmp_config:-}"' RETURN
640
643
 
641
644
  cp "$opencode_config" "$tmp_config"
642
645
 
@@ -714,6 +717,7 @@ validate_opencode_config() {
714
717
  if jq -e ".[\"$key\"]" "$opencode_config" > /dev/null 2>&1; then
715
718
  local tmp_fix
716
719
  tmp_fix=$(mktemp)
720
+ trap 'rm -f "${tmp_fix:-}"' RETURN
717
721
  if jq "del(.[\"$key\"])" "$opencode_config" > "$tmp_fix" 2>/dev/null; then
718
722
  create_backup_with_rotation "$opencode_config" "opencode"
719
723
  mv "$tmp_fix" "$opencode_config"
@@ -1489,6 +1493,229 @@ setup_oh_my_zsh() {
1489
1493
  return 0
1490
1494
  }
1491
1495
 
1496
+ # Ensure shell compatibility when switching between bash and zsh
1497
+ # Best practice: create a shared profile sourced by both shells, so users
1498
+ # don't lose PATH entries, aliases, exports, or tool integrations when
1499
+ # switching their default shell. This is especially important on macOS
1500
+ # where the system default changed from bash to zsh in Catalina, and many
1501
+ # users have years of bash customizations they don't want to lose.
1502
+ setup_shell_compatibility() {
1503
+ print_info "Setting up cross-shell compatibility..."
1504
+
1505
+ local shared_profile="$HOME/.shell_common"
1506
+ local zsh_rc="$HOME/.zshrc"
1507
+
1508
+ # If shared profile already exists, we've already set this up
1509
+ if [[ -f "$shared_profile" ]]; then
1510
+ print_success "Cross-shell compatibility already configured ($shared_profile)"
1511
+ return 0
1512
+ fi
1513
+
1514
+ # Need both bash and zsh to be relevant
1515
+ if ! command -v zsh >/dev/null 2>&1; then
1516
+ print_info "zsh not installed - cross-shell setup not needed"
1517
+ return 0
1518
+ fi
1519
+ if ! command -v bash >/dev/null 2>&1; then
1520
+ print_info "bash not installed - cross-shell setup not needed"
1521
+ return 0
1522
+ fi
1523
+
1524
+ # Collect all bash config files that exist
1525
+ # macOS: .bash_profile (login) + .bashrc (interactive, often sourced by .bash_profile)
1526
+ # Linux: .bashrc (primary) + .bash_profile (login, often sources .bashrc)
1527
+ # We check all of them on both platforms since tools write to either
1528
+ local -a bash_files=()
1529
+ [[ -f "$HOME/.bash_profile" ]] && bash_files+=("$HOME/.bash_profile")
1530
+ [[ -f "$HOME/.bashrc" ]] && bash_files+=("$HOME/.bashrc")
1531
+ [[ -f "$HOME/.profile" ]] && bash_files+=("$HOME/.profile")
1532
+
1533
+ if [[ ${#bash_files[@]} -eq 0 ]]; then
1534
+ print_info "No bash config files found - skipping cross-shell setup"
1535
+ return 0
1536
+ fi
1537
+
1538
+ if [[ ! -f "$zsh_rc" ]]; then
1539
+ print_info "No .zshrc found - skipping cross-shell setup"
1540
+ return 0
1541
+ fi
1542
+
1543
+ # Count customizations across all bash config files
1544
+ local total_exports=0
1545
+ local total_aliases=0
1546
+ local total_paths=0
1547
+
1548
+ for src_file in "${bash_files[@]}"; do
1549
+ local n
1550
+ n=$(grep -cE '^\s*export\s+[A-Z]' "$src_file" 2>/dev/null || echo "0")
1551
+ total_exports=$((total_exports + n))
1552
+ n=$(grep -cE '^\s*alias\s+' "$src_file" 2>/dev/null || echo "0")
1553
+ total_aliases=$((total_aliases + n))
1554
+ n=$(grep -cE 'PATH.*=' "$src_file" 2>/dev/null || echo "0")
1555
+ total_paths=$((total_paths + n))
1556
+ done
1557
+
1558
+ if [[ $total_exports -eq 0 && $total_aliases -eq 0 && $total_paths -eq 0 ]]; then
1559
+ print_info "No bash customizations detected - skipping cross-shell setup"
1560
+ return 0
1561
+ fi
1562
+
1563
+ print_info "Detected bash customizations across ${#bash_files[@]} file(s):"
1564
+ echo " Exports: $total_exports, Aliases: $total_aliases, PATH entries: $total_paths"
1565
+ echo ""
1566
+ print_info "Best practice: create a shared profile (~/.shell_common) sourced by"
1567
+ print_info "both bash and zsh, so your customizations work in either shell."
1568
+ echo ""
1569
+
1570
+ local setup_compat="Y"
1571
+ if [[ "$NON_INTERACTIVE" != "true" ]]; then
1572
+ read -r -p "Create shared shell profile for cross-shell compatibility? [Y/n]: " setup_compat
1573
+ fi
1574
+
1575
+ if [[ ! "$setup_compat" =~ ^[Yy]?$ ]]; then
1576
+ print_info "Skipped cross-shell compatibility setup"
1577
+ print_info "Set up later by creating ~/.shell_common and sourcing it from both shells"
1578
+ return 0
1579
+ fi
1580
+
1581
+ # Extract portable customizations from bash config into shared profile
1582
+ # We extract: exports, PATH modifications, aliases, eval statements, source commands
1583
+ # We skip: bash-specific syntax (shopt, PROMPT_COMMAND, PS1, completion, bind, etc.)
1584
+ # We deduplicate lines that appear in multiple files (e.g. .bash_profile sources .bashrc)
1585
+ print_info "Creating shared profile: $shared_profile"
1586
+
1587
+ {
1588
+ echo "# Shared shell profile - sourced by both bash and zsh"
1589
+ echo "# Created by aidevops setup to preserve customizations across shell switches"
1590
+ echo "# Edit this file for settings you want in BOTH bash and zsh"
1591
+ echo "# Shell-specific settings go in ~/.bashrc or ~/.zshrc"
1592
+ echo ""
1593
+ } > "$shared_profile"
1594
+
1595
+ # Track lines we've already written to avoid duplicates
1596
+ # (common on Linux where .bash_profile sources .bashrc)
1597
+ local -a seen_lines=()
1598
+ local extracted=0
1599
+
1600
+ for src_file in "${bash_files[@]}"; do
1601
+ local src_basename
1602
+ src_basename=$(basename "$src_file")
1603
+ local added_header=false
1604
+
1605
+ while IFS= read -r line || [[ -n "$line" ]]; do
1606
+ # Skip empty lines
1607
+ [[ -z "$line" ]] && continue
1608
+ # Skip pure comment lines
1609
+ [[ "$line" =~ ^[[:space:]]*# ]] && continue
1610
+
1611
+ # Skip bash-specific settings that don't work in zsh
1612
+ case "$line" in
1613
+ *shopt*) continue ;;
1614
+ *PROMPT_COMMAND*) continue ;;
1615
+ *PS1=*) continue ;;
1616
+ *PS2=*) continue ;;
1617
+ *bash_completion*) continue ;;
1618
+ *"complete "*) continue ;;
1619
+ *"bind "*) continue ;;
1620
+ *HISTCONTROL*) continue ;;
1621
+ *HISTFILESIZE*) continue ;;
1622
+ *HISTSIZE*) continue ;;
1623
+ *"source /etc/bash"*) continue ;;
1624
+ *". /etc/bash"*) continue ;;
1625
+ *"source /etc/profile"*) continue ;;
1626
+ *". /etc/profile"*) continue ;;
1627
+ # Skip lines that source .bashrc from .bash_profile (circular)
1628
+ *".bashrc"*) continue ;;
1629
+ # Skip lines that source .shell_common (we'll add this ourselves)
1630
+ *"shell_common"*) continue ;;
1631
+ esac
1632
+
1633
+ # Match portable lines: exports, aliases, PATH, eval, source/dot-source
1634
+ local is_portable=false
1635
+ case "$line" in
1636
+ export\ [A-Z]*|export\ PATH*) is_portable=true ;;
1637
+ alias\ *) is_portable=true ;;
1638
+ eval\ *) is_portable=true ;;
1639
+ *PATH=*) is_portable=true ;;
1640
+ esac
1641
+ # Also match 'source' and '. ' commands (tool integrations like nvm, rvm, pyenv)
1642
+ if [[ "$is_portable" == "false" ]]; then
1643
+ case "$line" in
1644
+ source\ *|.\ /*|.\ \$*|.\ \~*) is_portable=true ;;
1645
+ esac
1646
+ fi
1647
+
1648
+ if [[ "$is_portable" == "true" ]]; then
1649
+ # Deduplicate: skip if we've already seen this exact line
1650
+ local is_dup=false
1651
+ local seen
1652
+ for seen in "${seen_lines[@]}"; do
1653
+ if [[ "$seen" == "$line" ]]; then
1654
+ is_dup=true
1655
+ break
1656
+ fi
1657
+ done
1658
+ if [[ "$is_dup" == "true" ]]; then
1659
+ continue
1660
+ fi
1661
+
1662
+ if [[ "$added_header" == "false" ]]; then
1663
+ echo "" >> "$shared_profile"
1664
+ echo "# From $src_basename" >> "$shared_profile"
1665
+ added_header=true
1666
+ fi
1667
+ echo "$line" >> "$shared_profile"
1668
+ seen_lines+=("$line")
1669
+ ((extracted++)) || true
1670
+ fi
1671
+ done < "$src_file"
1672
+ done
1673
+
1674
+ if [[ $extracted -eq 0 ]]; then
1675
+ rm -f "$shared_profile"
1676
+ print_info "No portable customizations found to extract"
1677
+ return 0
1678
+ fi
1679
+
1680
+ chmod 644 "$shared_profile"
1681
+ print_success "Extracted $extracted unique customization(s) to $shared_profile"
1682
+
1683
+ # Add sourcing to .zshrc if not already present
1684
+ if ! grep -q 'shell_common' "$zsh_rc" 2>/dev/null; then
1685
+ {
1686
+ echo ""
1687
+ echo "# Cross-shell compatibility (added by aidevops setup)"
1688
+ echo "# Sources shared profile so bash customizations work in zsh too"
1689
+ # shellcheck disable=SC2016
1690
+ echo '[ -f "$HOME/.shell_common" ] && . "$HOME/.shell_common"'
1691
+ } >> "$zsh_rc"
1692
+ print_success "Added shared profile sourcing to .zshrc"
1693
+ fi
1694
+
1695
+ # Add sourcing to bash config files if not already present
1696
+ for src_file in "${bash_files[@]}"; do
1697
+ if ! grep -q 'shell_common' "$src_file" 2>/dev/null; then
1698
+ {
1699
+ echo ""
1700
+ echo "# Cross-shell compatibility (added by aidevops setup)"
1701
+ echo "# Shared profile - edit ~/.shell_common for settings in both shells"
1702
+ # shellcheck disable=SC2016
1703
+ echo '[ -f "$HOME/.shell_common" ] && . "$HOME/.shell_common"'
1704
+ } >> "$src_file"
1705
+ print_success "Added shared profile sourcing to $(basename "$src_file")"
1706
+ fi
1707
+ done
1708
+
1709
+ echo ""
1710
+ print_success "Cross-shell compatibility configured"
1711
+ print_info "Your customizations are now in: $shared_profile"
1712
+ print_info "Both bash and zsh will source this file automatically."
1713
+ print_info "Edit ~/.shell_common for settings you want in both shells."
1714
+ print_info "Use ~/.bashrc or ~/.zshrc for shell-specific settings only."
1715
+
1716
+ return 0
1717
+ }
1718
+
1492
1719
  # Check for optional dependencies
1493
1720
  check_optional_deps() {
1494
1721
  print_info "Checking optional dependencies..."
@@ -2583,6 +2810,7 @@ deploy_aidevops_agents() {
2583
2810
  print_info "Clean mode: removing stale files from $target_dir (preserving ${preserved_dirs[*]})"
2584
2811
  local tmp_preserve
2585
2812
  tmp_preserve="$(mktemp -d)"
2813
+ trap 'rm -rf "${tmp_preserve:-}"' RETURN
2586
2814
  if [[ -z "$tmp_preserve" || ! -d "$tmp_preserve" ]]; then
2587
2815
  print_error "Failed to create temp dir for preserving agents"
2588
2816
  return 1
@@ -2675,6 +2903,7 @@ deploy_aidevops_agents() {
2675
2903
  # (awk -v doesn't handle multi-line content with special chars well)
2676
2904
  local tmp_file
2677
2905
  tmp_file=$(mktemp)
2906
+ trap 'rm -f "${tmp_file:-}"' RETURN
2678
2907
  local in_placeholder=false
2679
2908
  while IFS= read -r line || [[ -n "$line" ]]; do
2680
2909
  if [[ "$line" == *"OPENCODE-PLAN-REMINDER-INJECT-START"* ]]; then
@@ -3105,6 +3334,7 @@ inject_agents_reference() {
3105
3334
  # Prepend reference to existing file
3106
3335
  local temp_file
3107
3336
  temp_file=$(mktemp)
3337
+ trap 'rm -f "${temp_file:-}"' RETURN
3108
3338
  echo "$reference_line" > "$temp_file"
3109
3339
  echo "" >> "$temp_file"
3110
3340
  cat "$agents_file" >> "$temp_file"
@@ -3434,6 +3664,7 @@ update_mcp_paths_in_opencode() {
3434
3664
 
3435
3665
  local tmp_config
3436
3666
  tmp_config=$(mktemp)
3667
+ trap 'rm -f "${tmp_config:-}"' RETURN
3437
3668
  cp "$opencode_config" "$tmp_config"
3438
3669
 
3439
3670
  local updated=0
@@ -4257,7 +4488,7 @@ setup_safety_hooks() {
4257
4488
  return 0
4258
4489
  }
4259
4490
 
4260
- # Setup OpenCode Plugins (Antigravity OAuth)
4491
+ # Setup OpenCode Plugins
4261
4492
  # Helper function to add/update a single plugin in OpenCode config
4262
4493
  add_opencode_plugin() {
4263
4494
  local plugin_name="$1"
@@ -4277,6 +4508,7 @@ add_opencode_plugin() {
4277
4508
  # Update existing plugin to latest version
4278
4509
  local temp_file
4279
4510
  temp_file=$(mktemp)
4511
+ trap 'rm -f "${temp_file:-}"' RETURN
4280
4512
  jq --arg old "$plugin_name" --arg new "$plugin_spec" \
4281
4513
  '.plugin = [.plugin[] | if startswith($old) then $new else . end]' \
4282
4514
  "$opencode_config" > "$temp_file" && mv "$temp_file" "$opencode_config"
@@ -4285,6 +4517,7 @@ add_opencode_plugin() {
4285
4517
  # Add plugin to existing array
4286
4518
  local temp_file
4287
4519
  temp_file=$(mktemp)
4520
+ trap 'rm -f "${temp_file:-}"' RETURN
4288
4521
  jq --arg p "$plugin_spec" '.plugin += [$p]' "$opencode_config" > "$temp_file" && mv "$temp_file" "$opencode_config"
4289
4522
  print_success "Added $plugin_name plugin to OpenCode config"
4290
4523
  fi
@@ -4292,6 +4525,7 @@ add_opencode_plugin() {
4292
4525
  # Create plugin array with the plugin
4293
4526
  local temp_file
4294
4527
  temp_file=$(mktemp)
4528
+ trap 'rm -f "${temp_file:-}"' RETURN
4295
4529
  jq --arg p "$plugin_spec" '. + {plugin: [$p]}' "$opencode_config" > "$temp_file" && mv "$temp_file" "$opencode_config"
4296
4530
  print_success "Created plugin array with $plugin_name"
4297
4531
  fi
@@ -4328,21 +4562,11 @@ setup_opencode_plugins() {
4328
4562
  print_success "aidevops compaction plugin registered (preserves context across compaction)"
4329
4563
  fi
4330
4564
 
4331
- # Setup Antigravity OAuth plugin (Google OAuth)
4332
- print_info "Setting up Antigravity OAuth plugin..."
4333
- add_opencode_plugin "opencode-antigravity-auth" "opencode-antigravity-auth@latest" "$opencode_config"
4334
-
4335
- print_info "Antigravity OAuth plugin enables Google OAuth for OpenCode"
4336
- print_info "Models available: gemini-3-pro-high, claude-opus-4-5-thinking, etc."
4337
- print_info "See: https://github.com/NoeFabris/opencode-antigravity-auth"
4338
- echo ""
4339
-
4340
4565
  # Note: opencode-anthropic-auth is built into OpenCode v1.1.36+
4341
4566
  # Adding it as an external plugin causes TypeError due to double-loading.
4342
4567
  # Removed in v2.90.0 - see PR #230.
4343
4568
 
4344
4569
  print_info "After setup, authenticate with: opencode auth login"
4345
- print_info " • For Google OAuth: Select 'Google' → 'OAuth with Google (Antigravity)'"
4346
4570
  print_info " • For Claude OAuth: Select 'Anthropic' → 'Claude Pro/Max' (built-in)"
4347
4571
 
4348
4572
  return 0
@@ -4434,6 +4658,7 @@ setup_google_analytics_mcp() {
4434
4658
  if [[ "$enable_mcp" == "true" ]]; then
4435
4659
  local tmp_config
4436
4660
  tmp_config=$(mktemp)
4661
+ trap 'rm -f "${tmp_config:-}"' RETURN
4437
4662
  if jq --arg creds "$creds_path" --arg proj "$project_id" \
4438
4663
  '.mcp["google-analytics-mcp"].environment.GOOGLE_APPLICATION_CREDENTIALS = $creds |
4439
4664
  .mcp["google-analytics-mcp"].environment.GOOGLE_PROJECT_ID = $proj |
@@ -4454,6 +4679,7 @@ setup_google_analytics_mcp() {
4454
4679
  # Add google-analytics-mcp to opencode.json
4455
4680
  local tmp_config
4456
4681
  tmp_config=$(mktemp)
4682
+ trap 'rm -f "${tmp_config:-}"' RETURN
4457
4683
 
4458
4684
  if jq --arg creds "$creds_path" --arg proj "$project_id" --argjson enabled "$enable_mcp" \
4459
4685
  '.mcp["google-analytics-mcp"] = {
@@ -4566,7 +4792,7 @@ setup_quickfile_mcp() {
4566
4792
 
4567
4793
  local tmp_config
4568
4794
  tmp_config=$(mktemp)
4569
- trap 'rm -f "$tmp_config"' RETURN
4795
+ trap 'rm -f "${tmp_config:-}"' RETURN
4570
4796
 
4571
4797
  if jq --arg np "$node_path" --arg dp "$quickfile_dir/dist/index.js" \
4572
4798
  '.mcp.quickfile = {"type": "local", "command": [$np, $dp], "enabled": true}' \
@@ -4815,6 +5041,7 @@ main() {
4815
5041
 
4816
5042
  # Shell environment setup (early, so later tools benefit from zsh/Oh My Zsh)
4817
5043
  confirm_step "Setup Oh My Zsh (optional, enhances zsh)" && setup_oh_my_zsh
5044
+ confirm_step "Setup cross-shell compatibility (preserve bash config in zsh)" && setup_shell_compatibility
4818
5045
 
4819
5046
  # OrbStack (macOS only - offer VM option early)
4820
5047
  confirm_step "Setup OrbStack (lightweight Linux VMs on macOS)" && setup_orbstack_vm