aidevops 2.52.1

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 (329) hide show
  1. package/.agent/AGENTS.md +614 -0
  2. package/.agent/accounts.md +65 -0
  3. package/.agent/aidevops/add-new-mcp-to-aidevops.md +456 -0
  4. package/.agent/aidevops/api-integrations.md +335 -0
  5. package/.agent/aidevops/architecture.md +510 -0
  6. package/.agent/aidevops/configs.md +274 -0
  7. package/.agent/aidevops/docs.md +244 -0
  8. package/.agent/aidevops/extension.md +311 -0
  9. package/.agent/aidevops/mcp-integrations.md +340 -0
  10. package/.agent/aidevops/mcp-troubleshooting.md +162 -0
  11. package/.agent/aidevops/memory-patterns.md +172 -0
  12. package/.agent/aidevops/providers.md +217 -0
  13. package/.agent/aidevops/recommendations.md +321 -0
  14. package/.agent/aidevops/requirements.md +301 -0
  15. package/.agent/aidevops/resources.md +214 -0
  16. package/.agent/aidevops/security-requirements.md +174 -0
  17. package/.agent/aidevops/security.md +350 -0
  18. package/.agent/aidevops/service-links.md +400 -0
  19. package/.agent/aidevops/services.md +357 -0
  20. package/.agent/aidevops/setup.md +153 -0
  21. package/.agent/aidevops/troubleshooting.md +389 -0
  22. package/.agent/aidevops.md +124 -0
  23. package/.agent/build-plus.md +244 -0
  24. package/.agent/content/guidelines.md +109 -0
  25. package/.agent/content.md +87 -0
  26. package/.agent/health.md +59 -0
  27. package/.agent/legal.md +59 -0
  28. package/.agent/loop-state/full-loop.local.md +16 -0
  29. package/.agent/loop-state/ralph-loop.local.md +10 -0
  30. package/.agent/marketing.md +440 -0
  31. package/.agent/memory/README.md +260 -0
  32. package/.agent/onboarding.md +796 -0
  33. package/.agent/plan-plus.md +245 -0
  34. package/.agent/research.md +100 -0
  35. package/.agent/sales.md +333 -0
  36. package/.agent/scripts/101domains-helper.sh +701 -0
  37. package/.agent/scripts/add-missing-returns.sh +140 -0
  38. package/.agent/scripts/agent-browser-helper.sh +311 -0
  39. package/.agent/scripts/agno-setup.sh +712 -0
  40. package/.agent/scripts/ahrefs-mcp-wrapper.js +168 -0
  41. package/.agent/scripts/aidevops-update-check.sh +71 -0
  42. package/.agent/scripts/ampcode-cli.sh +522 -0
  43. package/.agent/scripts/auto-version-bump.sh +156 -0
  44. package/.agent/scripts/autogen-helper.sh +512 -0
  45. package/.agent/scripts/beads-sync-helper.sh +596 -0
  46. package/.agent/scripts/closte-helper.sh +5 -0
  47. package/.agent/scripts/cloudron-helper.sh +321 -0
  48. package/.agent/scripts/codacy-cli-chunked.sh +581 -0
  49. package/.agent/scripts/codacy-cli.sh +442 -0
  50. package/.agent/scripts/code-audit-helper.sh +5 -0
  51. package/.agent/scripts/coderabbit-cli.sh +417 -0
  52. package/.agent/scripts/coderabbit-pro-analysis.sh +238 -0
  53. package/.agent/scripts/commands/code-simplifier.md +86 -0
  54. package/.agent/scripts/commands/full-loop.md +246 -0
  55. package/.agent/scripts/commands/postflight-loop.md +103 -0
  56. package/.agent/scripts/commands/recall.md +182 -0
  57. package/.agent/scripts/commands/remember.md +132 -0
  58. package/.agent/scripts/commands/save-todo.md +175 -0
  59. package/.agent/scripts/commands/session-review.md +154 -0
  60. package/.agent/scripts/comprehensive-quality-fix.sh +106 -0
  61. package/.agent/scripts/context-builder-helper.sh +522 -0
  62. package/.agent/scripts/coolify-cli-helper.sh +674 -0
  63. package/.agent/scripts/coolify-helper.sh +380 -0
  64. package/.agent/scripts/crawl4ai-examples.sh +401 -0
  65. package/.agent/scripts/crawl4ai-helper.sh +1078 -0
  66. package/.agent/scripts/crewai-helper.sh +681 -0
  67. package/.agent/scripts/dev-browser-helper.sh +513 -0
  68. package/.agent/scripts/dns-helper.sh +396 -0
  69. package/.agent/scripts/domain-research-helper.sh +917 -0
  70. package/.agent/scripts/dspy-helper.sh +285 -0
  71. package/.agent/scripts/dspyground-helper.sh +291 -0
  72. package/.agent/scripts/eeat-score-helper.sh +1242 -0
  73. package/.agent/scripts/efficient-return-fix.sh +92 -0
  74. package/.agent/scripts/extract-opencode-prompts.sh +128 -0
  75. package/.agent/scripts/find-missing-returns.sh +113 -0
  76. package/.agent/scripts/fix-auth-headers.sh +104 -0
  77. package/.agent/scripts/fix-common-strings.sh +254 -0
  78. package/.agent/scripts/fix-content-type.sh +100 -0
  79. package/.agent/scripts/fix-error-messages.sh +130 -0
  80. package/.agent/scripts/fix-misplaced-returns.sh +74 -0
  81. package/.agent/scripts/fix-remaining-literals.sh +152 -0
  82. package/.agent/scripts/fix-return-statements.sh +41 -0
  83. package/.agent/scripts/fix-s131-default-cases.sh +249 -0
  84. package/.agent/scripts/fix-sc2155-simple.sh +102 -0
  85. package/.agent/scripts/fix-shellcheck-critical.sh +187 -0
  86. package/.agent/scripts/fix-string-literals.sh +273 -0
  87. package/.agent/scripts/full-loop-helper.sh +773 -0
  88. package/.agent/scripts/generate-opencode-agents.sh +497 -0
  89. package/.agent/scripts/generate-opencode-commands.sh +1629 -0
  90. package/.agent/scripts/generate-skills.sh +366 -0
  91. package/.agent/scripts/git-platforms-helper.sh +640 -0
  92. package/.agent/scripts/gitea-cli-helper.sh +743 -0
  93. package/.agent/scripts/github-cli-helper.sh +702 -0
  94. package/.agent/scripts/gitlab-cli-helper.sh +682 -0
  95. package/.agent/scripts/gsc-add-user-helper.sh +325 -0
  96. package/.agent/scripts/gsc-sitemap-helper.sh +678 -0
  97. package/.agent/scripts/hetzner-helper.sh +485 -0
  98. package/.agent/scripts/hostinger-helper.sh +229 -0
  99. package/.agent/scripts/keyword-research-helper.sh +1815 -0
  100. package/.agent/scripts/langflow-helper.sh +544 -0
  101. package/.agent/scripts/linkedin-automation.py +241 -0
  102. package/.agent/scripts/linter-manager.sh +599 -0
  103. package/.agent/scripts/linters-local.sh +434 -0
  104. package/.agent/scripts/list-keys-helper.sh +488 -0
  105. package/.agent/scripts/local-browser-automation.py +339 -0
  106. package/.agent/scripts/localhost-helper.sh +744 -0
  107. package/.agent/scripts/loop-common.sh +806 -0
  108. package/.agent/scripts/mainwp-helper.sh +728 -0
  109. package/.agent/scripts/markdown-formatter.sh +338 -0
  110. package/.agent/scripts/markdown-lint-fix.sh +311 -0
  111. package/.agent/scripts/mass-fix-returns.sh +58 -0
  112. package/.agent/scripts/mcp-diagnose.sh +167 -0
  113. package/.agent/scripts/mcp-inspector-helper.sh +449 -0
  114. package/.agent/scripts/memory-helper.sh +650 -0
  115. package/.agent/scripts/monitor-code-review.sh +255 -0
  116. package/.agent/scripts/onboarding-helper.sh +706 -0
  117. package/.agent/scripts/opencode-github-setup-helper.sh +797 -0
  118. package/.agent/scripts/opencode-test-helper.sh +213 -0
  119. package/.agent/scripts/pagespeed-helper.sh +464 -0
  120. package/.agent/scripts/pandoc-helper.sh +362 -0
  121. package/.agent/scripts/postflight-check.sh +555 -0
  122. package/.agent/scripts/pre-commit-hook.sh +259 -0
  123. package/.agent/scripts/pre-edit-check.sh +169 -0
  124. package/.agent/scripts/qlty-cli.sh +356 -0
  125. package/.agent/scripts/quality-cli-manager.sh +525 -0
  126. package/.agent/scripts/quality-feedback-helper.sh +462 -0
  127. package/.agent/scripts/quality-fix.sh +263 -0
  128. package/.agent/scripts/quality-loop-helper.sh +1108 -0
  129. package/.agent/scripts/ralph-loop-helper.sh +836 -0
  130. package/.agent/scripts/ralph-upstream-check.sh +341 -0
  131. package/.agent/scripts/secretlint-helper.sh +847 -0
  132. package/.agent/scripts/servers-helper.sh +241 -0
  133. package/.agent/scripts/ses-helper.sh +619 -0
  134. package/.agent/scripts/session-review-helper.sh +404 -0
  135. package/.agent/scripts/setup-linters-wizard.sh +379 -0
  136. package/.agent/scripts/setup-local-api-keys.sh +330 -0
  137. package/.agent/scripts/setup-mcp-integrations.sh +472 -0
  138. package/.agent/scripts/shared-constants.sh +246 -0
  139. package/.agent/scripts/site-crawler-helper.sh +1487 -0
  140. package/.agent/scripts/snyk-helper.sh +940 -0
  141. package/.agent/scripts/sonarcloud-autofix.sh +193 -0
  142. package/.agent/scripts/sonarcloud-cli.sh +191 -0
  143. package/.agent/scripts/sonarscanner-cli.sh +455 -0
  144. package/.agent/scripts/spaceship-helper.sh +747 -0
  145. package/.agent/scripts/stagehand-helper.sh +321 -0
  146. package/.agent/scripts/stagehand-python-helper.sh +321 -0
  147. package/.agent/scripts/stagehand-python-setup.sh +441 -0
  148. package/.agent/scripts/stagehand-setup.sh +439 -0
  149. package/.agent/scripts/system-cleanup.sh +340 -0
  150. package/.agent/scripts/terminal-title-helper.sh +388 -0
  151. package/.agent/scripts/terminal-title-setup.sh +549 -0
  152. package/.agent/scripts/test-stagehand-both-integration.sh +317 -0
  153. package/.agent/scripts/test-stagehand-integration.sh +309 -0
  154. package/.agent/scripts/test-stagehand-python-integration.sh +341 -0
  155. package/.agent/scripts/todo-ready.sh +263 -0
  156. package/.agent/scripts/tool-version-check.sh +362 -0
  157. package/.agent/scripts/toon-helper.sh +469 -0
  158. package/.agent/scripts/twilio-helper.sh +917 -0
  159. package/.agent/scripts/updown-helper.sh +279 -0
  160. package/.agent/scripts/validate-mcp-integrations.sh +250 -0
  161. package/.agent/scripts/validate-version-consistency.sh +131 -0
  162. package/.agent/scripts/vaultwarden-helper.sh +597 -0
  163. package/.agent/scripts/vercel-cli-helper.sh +816 -0
  164. package/.agent/scripts/verify-mirrors.sh +169 -0
  165. package/.agent/scripts/version-manager.sh +831 -0
  166. package/.agent/scripts/webhosting-helper.sh +471 -0
  167. package/.agent/scripts/webhosting-verify.sh +238 -0
  168. package/.agent/scripts/wordpress-mcp-helper.sh +508 -0
  169. package/.agent/scripts/worktree-helper.sh +595 -0
  170. package/.agent/scripts/worktree-sessions.sh +577 -0
  171. package/.agent/seo/dataforseo.md +215 -0
  172. package/.agent/seo/domain-research.md +532 -0
  173. package/.agent/seo/eeat-score.md +659 -0
  174. package/.agent/seo/google-search-console.md +366 -0
  175. package/.agent/seo/gsc-sitemaps.md +282 -0
  176. package/.agent/seo/keyword-research.md +521 -0
  177. package/.agent/seo/serper.md +278 -0
  178. package/.agent/seo/site-crawler.md +387 -0
  179. package/.agent/seo.md +236 -0
  180. package/.agent/services/accounting/quickfile.md +159 -0
  181. package/.agent/services/communications/telfon.md +470 -0
  182. package/.agent/services/communications/twilio.md +569 -0
  183. package/.agent/services/crm/fluentcrm.md +449 -0
  184. package/.agent/services/email/ses.md +399 -0
  185. package/.agent/services/hosting/101domains.md +378 -0
  186. package/.agent/services/hosting/closte.md +177 -0
  187. package/.agent/services/hosting/cloudflare.md +251 -0
  188. package/.agent/services/hosting/cloudron.md +478 -0
  189. package/.agent/services/hosting/dns-providers.md +335 -0
  190. package/.agent/services/hosting/domain-purchasing.md +344 -0
  191. package/.agent/services/hosting/hetzner.md +327 -0
  192. package/.agent/services/hosting/hostinger.md +287 -0
  193. package/.agent/services/hosting/localhost.md +419 -0
  194. package/.agent/services/hosting/spaceship.md +353 -0
  195. package/.agent/services/hosting/webhosting.md +330 -0
  196. package/.agent/social-media.md +69 -0
  197. package/.agent/templates/plans-template.md +114 -0
  198. package/.agent/templates/prd-template.md +129 -0
  199. package/.agent/templates/tasks-template.md +108 -0
  200. package/.agent/templates/todo-template.md +89 -0
  201. package/.agent/tools/ai-assistants/agno.md +471 -0
  202. package/.agent/tools/ai-assistants/capsolver.md +326 -0
  203. package/.agent/tools/ai-assistants/configuration.md +221 -0
  204. package/.agent/tools/ai-assistants/overview.md +209 -0
  205. package/.agent/tools/ai-assistants/status.md +171 -0
  206. package/.agent/tools/ai-assistants/windsurf.md +193 -0
  207. package/.agent/tools/ai-orchestration/autogen.md +406 -0
  208. package/.agent/tools/ai-orchestration/crewai.md +445 -0
  209. package/.agent/tools/ai-orchestration/langflow.md +405 -0
  210. package/.agent/tools/ai-orchestration/openprose.md +487 -0
  211. package/.agent/tools/ai-orchestration/overview.md +362 -0
  212. package/.agent/tools/ai-orchestration/packaging.md +647 -0
  213. package/.agent/tools/browser/agent-browser.md +464 -0
  214. package/.agent/tools/browser/browser-automation.md +400 -0
  215. package/.agent/tools/browser/chrome-devtools.md +282 -0
  216. package/.agent/tools/browser/crawl4ai-integration.md +422 -0
  217. package/.agent/tools/browser/crawl4ai-resources.md +277 -0
  218. package/.agent/tools/browser/crawl4ai-usage.md +416 -0
  219. package/.agent/tools/browser/crawl4ai.md +585 -0
  220. package/.agent/tools/browser/dev-browser.md +341 -0
  221. package/.agent/tools/browser/pagespeed.md +260 -0
  222. package/.agent/tools/browser/playwright.md +266 -0
  223. package/.agent/tools/browser/playwriter.md +310 -0
  224. package/.agent/tools/browser/stagehand-examples.md +456 -0
  225. package/.agent/tools/browser/stagehand-python.md +483 -0
  226. package/.agent/tools/browser/stagehand.md +421 -0
  227. package/.agent/tools/build-agent/agent-review.md +224 -0
  228. package/.agent/tools/build-agent/build-agent.md +784 -0
  229. package/.agent/tools/build-mcp/aidevops-plugin.md +476 -0
  230. package/.agent/tools/build-mcp/api-wrapper.md +445 -0
  231. package/.agent/tools/build-mcp/build-mcp.md +240 -0
  232. package/.agent/tools/build-mcp/deployment.md +401 -0
  233. package/.agent/tools/build-mcp/server-patterns.md +632 -0
  234. package/.agent/tools/build-mcp/transports.md +366 -0
  235. package/.agent/tools/code-review/auditing.md +383 -0
  236. package/.agent/tools/code-review/automation.md +219 -0
  237. package/.agent/tools/code-review/best-practices.md +203 -0
  238. package/.agent/tools/code-review/codacy.md +151 -0
  239. package/.agent/tools/code-review/code-simplifier.md +174 -0
  240. package/.agent/tools/code-review/code-standards.md +309 -0
  241. package/.agent/tools/code-review/coderabbit.md +101 -0
  242. package/.agent/tools/code-review/management.md +155 -0
  243. package/.agent/tools/code-review/qlty.md +248 -0
  244. package/.agent/tools/code-review/secretlint.md +565 -0
  245. package/.agent/tools/code-review/setup.md +250 -0
  246. package/.agent/tools/code-review/snyk.md +563 -0
  247. package/.agent/tools/code-review/tools.md +230 -0
  248. package/.agent/tools/content/summarize.md +353 -0
  249. package/.agent/tools/context/augment-context-engine.md +468 -0
  250. package/.agent/tools/context/context-builder-agent.md +76 -0
  251. package/.agent/tools/context/context-builder.md +375 -0
  252. package/.agent/tools/context/context7.md +371 -0
  253. package/.agent/tools/context/dspy.md +302 -0
  254. package/.agent/tools/context/dspyground.md +374 -0
  255. package/.agent/tools/context/llm-tldr.md +219 -0
  256. package/.agent/tools/context/osgrep.md +488 -0
  257. package/.agent/tools/context/prompt-optimization.md +338 -0
  258. package/.agent/tools/context/toon.md +292 -0
  259. package/.agent/tools/conversion/pandoc.md +304 -0
  260. package/.agent/tools/credentials/api-key-management.md +154 -0
  261. package/.agent/tools/credentials/api-key-setup.md +224 -0
  262. package/.agent/tools/credentials/environment-variables.md +180 -0
  263. package/.agent/tools/credentials/vaultwarden.md +382 -0
  264. package/.agent/tools/data-extraction/outscraper.md +974 -0
  265. package/.agent/tools/deployment/coolify-cli.md +388 -0
  266. package/.agent/tools/deployment/coolify-setup.md +353 -0
  267. package/.agent/tools/deployment/coolify.md +345 -0
  268. package/.agent/tools/deployment/vercel.md +390 -0
  269. package/.agent/tools/git/authentication.md +132 -0
  270. package/.agent/tools/git/gitea-cli.md +193 -0
  271. package/.agent/tools/git/github-actions.md +207 -0
  272. package/.agent/tools/git/github-cli.md +223 -0
  273. package/.agent/tools/git/gitlab-cli.md +190 -0
  274. package/.agent/tools/git/opencode-github-security.md +350 -0
  275. package/.agent/tools/git/opencode-github.md +328 -0
  276. package/.agent/tools/git/opencode-gitlab.md +252 -0
  277. package/.agent/tools/git/security.md +196 -0
  278. package/.agent/tools/git.md +207 -0
  279. package/.agent/tools/opencode/oh-my-opencode.md +375 -0
  280. package/.agent/tools/opencode/opencode-anthropic-auth.md +446 -0
  281. package/.agent/tools/opencode/opencode.md +651 -0
  282. package/.agent/tools/social-media/bird.md +437 -0
  283. package/.agent/tools/task-management/beads.md +336 -0
  284. package/.agent/tools/terminal/terminal-title.md +251 -0
  285. package/.agent/tools/ui/shadcn.md +196 -0
  286. package/.agent/tools/ui/ui-skills.md +115 -0
  287. package/.agent/tools/wordpress/localwp.md +311 -0
  288. package/.agent/tools/wordpress/mainwp.md +391 -0
  289. package/.agent/tools/wordpress/scf.md +527 -0
  290. package/.agent/tools/wordpress/wp-admin.md +729 -0
  291. package/.agent/tools/wordpress/wp-dev.md +940 -0
  292. package/.agent/tools/wordpress/wp-preferred.md +398 -0
  293. package/.agent/tools/wordpress.md +95 -0
  294. package/.agent/workflows/branch/bugfix.md +63 -0
  295. package/.agent/workflows/branch/chore.md +95 -0
  296. package/.agent/workflows/branch/experiment.md +115 -0
  297. package/.agent/workflows/branch/feature.md +59 -0
  298. package/.agent/workflows/branch/hotfix.md +98 -0
  299. package/.agent/workflows/branch/refactor.md +92 -0
  300. package/.agent/workflows/branch/release.md +96 -0
  301. package/.agent/workflows/branch.md +347 -0
  302. package/.agent/workflows/bug-fixing.md +267 -0
  303. package/.agent/workflows/changelog.md +129 -0
  304. package/.agent/workflows/code-audit-remote.md +279 -0
  305. package/.agent/workflows/conversation-starter.md +69 -0
  306. package/.agent/workflows/error-feedback.md +578 -0
  307. package/.agent/workflows/feature-development.md +355 -0
  308. package/.agent/workflows/git-workflow.md +702 -0
  309. package/.agent/workflows/multi-repo-workspace.md +268 -0
  310. package/.agent/workflows/plans.md +709 -0
  311. package/.agent/workflows/postflight.md +604 -0
  312. package/.agent/workflows/pr.md +571 -0
  313. package/.agent/workflows/preflight.md +278 -0
  314. package/.agent/workflows/ralph-loop.md +773 -0
  315. package/.agent/workflows/release.md +498 -0
  316. package/.agent/workflows/session-manager.md +254 -0
  317. package/.agent/workflows/session-review.md +311 -0
  318. package/.agent/workflows/sql-migrations.md +631 -0
  319. package/.agent/workflows/version-bump.md +283 -0
  320. package/.agent/workflows/wiki-update.md +333 -0
  321. package/.agent/workflows/worktree.md +477 -0
  322. package/LICENSE +21 -0
  323. package/README.md +1446 -0
  324. package/VERSION +1 -0
  325. package/aidevops.sh +1746 -0
  326. package/bin/aidevops +21 -0
  327. package/package.json +75 -0
  328. package/scripts/npm-postinstall.js +60 -0
  329. package/setup.sh +2366 -0
package/setup.sh ADDED
@@ -0,0 +1,2366 @@
1
+ #!/bin/bash
2
+
3
+ # AI Assistant Server Access Framework Setup Script
4
+ # Helps developers set up the framework for their infrastructure
5
+ #
6
+ # Version: 2.52.1
7
+ #
8
+ # Quick Install (one-liner):
9
+ # bash <(curl -fsSL https://aidevops.dev/install)
10
+ # OR: bash <(curl -fsSL https://raw.githubusercontent.com/marcusquinn/aidevops/main/setup.sh)
11
+
12
+ # Colors for output
13
+ GREEN='\033[0;32m'
14
+ BLUE='\033[0;34m'
15
+ YELLOW='\033[1;33m'
16
+ RED='\033[0;31m'
17
+ NC='\033[0m' # No Color
18
+
19
+ # Global flags
20
+ CLEAN_MODE=false
21
+ INTERACTIVE_MODE=false
22
+ UPDATE_TOOLS_MODE=false
23
+ REPO_URL="https://github.com/marcusquinn/aidevops.git"
24
+ INSTALL_DIR="$HOME/Git/aidevops"
25
+
26
+ print_info() { echo -e "${BLUE}[INFO]${NC} $1"; }
27
+ print_success() { echo -e "${GREEN}[SUCCESS]${NC} $1"; }
28
+ print_warning() { echo -e "${YELLOW}[WARNING]${NC} $1"; }
29
+ print_error() { echo -e "${RED}[ERROR]${NC} $1"; }
30
+
31
+ # Confirm step in interactive mode
32
+ # Usage: confirm_step "Step description" && function_to_run
33
+ # Returns: 0 if confirmed or not interactive, 1 if skipped
34
+ confirm_step() {
35
+ local step_name="$1"
36
+
37
+ # Skip confirmation in non-interactive mode
38
+ if [[ "$INTERACTIVE_MODE" != "true" ]]; then
39
+ return 0
40
+ fi
41
+
42
+ echo ""
43
+ echo -e "${YELLOW}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}"
44
+ echo -e "${BLUE}Step:${NC} $step_name"
45
+ echo -e "${YELLOW}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}"
46
+
47
+ while true; do
48
+ echo -n -e "${GREEN}Run this step? [Y]es / [n]o / [q]uit: ${NC}"
49
+ read -r response
50
+ # Convert to lowercase (bash 3.2 compatible)
51
+ response=$(echo "$response" | tr '[:upper:]' '[:lower:]')
52
+ case "$response" in
53
+ y|yes|"")
54
+ return 0
55
+ ;;
56
+ n|no|s|skip)
57
+ print_warning "Skipped: $step_name"
58
+ return 1
59
+ ;;
60
+ q|quit|exit)
61
+ echo ""
62
+ print_info "Setup cancelled by user"
63
+ exit 0
64
+ ;;
65
+ *)
66
+ echo "Please answer: y (yes), n (no), or q (quit)"
67
+ ;;
68
+ esac
69
+ done
70
+ }
71
+
72
+ # Backup rotation settings
73
+ BACKUP_KEEP_COUNT=10
74
+
75
+ # Create a backup with rotation (keeps last N backups)
76
+ # Usage: create_backup_with_rotation <source_path> <backup_name>
77
+ # Example: create_backup_with_rotation "$target_dir" "agents"
78
+ # Creates: ~/.aidevops/agents-backups/20251221_123456/
79
+ create_backup_with_rotation() {
80
+ local source_path="$1"
81
+ local backup_name="$2"
82
+ local backup_base="$HOME/.aidevops/${backup_name}-backups"
83
+ local backup_dir
84
+ backup_dir="$backup_base/$(date +%Y%m%d_%H%M%S)"
85
+
86
+ # Create backup directory
87
+ mkdir -p "$backup_dir"
88
+
89
+ # Copy source to backup
90
+ if [[ -d "$source_path" ]]; then
91
+ cp -R "$source_path" "$backup_dir/"
92
+ elif [[ -f "$source_path" ]]; then
93
+ cp "$source_path" "$backup_dir/"
94
+ else
95
+ print_warning "Source path does not exist: $source_path"
96
+ return 1
97
+ fi
98
+
99
+ print_info "Backed up to $backup_dir"
100
+
101
+ # Rotate old backups (keep last N)
102
+ local backup_count
103
+ backup_count=$(find "$backup_base" -maxdepth 1 -type d -name "20*" 2>/dev/null | wc -l | tr -d ' ')
104
+
105
+ if [[ $backup_count -gt $BACKUP_KEEP_COUNT ]]; then
106
+ local to_delete=$((backup_count - BACKUP_KEEP_COUNT))
107
+ print_info "Rotating backups: removing $to_delete old backup(s), keeping last $BACKUP_KEEP_COUNT"
108
+
109
+ # Delete oldest backups (sorted by name = sorted by date)
110
+ find "$backup_base" -maxdepth 1 -type d -name "20*" 2>/dev/null | sort | head -n "$to_delete" | while read -r old_backup; do
111
+ rm -rf "$old_backup"
112
+ done
113
+ fi
114
+
115
+ return 0
116
+ }
117
+
118
+ # Remove deprecated agent paths that have been moved
119
+ # This ensures clean upgrades when agents are reorganized
120
+ cleanup_deprecated_paths() {
121
+ local agents_dir="$HOME/.aidevops/agents"
122
+ local cleaned=0
123
+
124
+ # List of deprecated paths (add new ones here when reorganizing)
125
+ local deprecated_paths=(
126
+ # v2.40.7: wordpress moved from root to tools/wordpress
127
+ "$agents_dir/wordpress.md"
128
+ "$agents_dir/wordpress"
129
+ # v2.41.0: build-agent and build-mcp moved from root to tools/
130
+ "$agents_dir/build-agent.md"
131
+ "$agents_dir/build-agent"
132
+ "$agents_dir/build-mcp.md"
133
+ "$agents_dir/build-mcp"
134
+ )
135
+
136
+ for path in "${deprecated_paths[@]}"; do
137
+ if [[ -e "$path" ]]; then
138
+ rm -rf "$path"
139
+ ((cleaned++))
140
+ fi
141
+ done
142
+
143
+ if [[ $cleaned -gt 0 ]]; then
144
+ print_info "Cleaned up $cleaned deprecated agent path(s)"
145
+ fi
146
+
147
+ return 0
148
+ }
149
+
150
+ # Migrate old config-backups to new per-type backup structure
151
+ # This runs once to clean up the legacy backup directory
152
+ migrate_old_backups() {
153
+ local old_backup_dir="$HOME/.aidevops/config-backups"
154
+
155
+ # Skip if old directory doesn't exist
156
+ if [[ ! -d "$old_backup_dir" ]]; then
157
+ return 0
158
+ fi
159
+
160
+ # Count old backups
161
+ local old_count
162
+ old_count=$(find "$old_backup_dir" -maxdepth 1 -type d -name "20*" 2>/dev/null | wc -l | tr -d ' ')
163
+
164
+ if [[ $old_count -eq 0 ]]; then
165
+ # Empty directory, just remove it
166
+ rm -rf "$old_backup_dir"
167
+ return 0
168
+ fi
169
+
170
+ print_info "Migrating $old_count old backups to new structure..."
171
+
172
+ # Create new backup directories
173
+ mkdir -p "$HOME/.aidevops/agents-backups"
174
+ mkdir -p "$HOME/.aidevops/opencode-backups"
175
+
176
+ # Move the most recent backups (up to BACKUP_KEEP_COUNT) to new locations
177
+ # Old backups contained mixed content, so we'll just keep the newest ones as agents backups
178
+ local migrated=0
179
+ for backup in $(find "$old_backup_dir" -maxdepth 1 -type d -name "20*" 2>/dev/null | sort -r | head -n "$BACKUP_KEEP_COUNT"); do
180
+ local backup_name
181
+ backup_name=$(basename "$backup")
182
+
183
+ # Check if it contains agents folder (most common)
184
+ if [[ -d "$backup/agents" ]]; then
185
+ mv "$backup" "$HOME/.aidevops/agents-backups/$backup_name"
186
+ ((migrated++))
187
+ # Check if it contains opencode.json
188
+ elif [[ -f "$backup/opencode.json" ]]; then
189
+ mv "$backup" "$HOME/.aidevops/opencode-backups/$backup_name"
190
+ ((migrated++))
191
+ fi
192
+ done
193
+
194
+ # Remove remaining old backups and the old directory
195
+ rm -rf "$old_backup_dir"
196
+
197
+ if [[ $migrated -gt 0 ]]; then
198
+ print_success "Migrated $migrated recent backups, removed $((old_count - migrated)) old backups"
199
+ else
200
+ print_info "Cleaned up $old_count old backups"
201
+ fi
202
+
203
+ return 0
204
+ }
205
+
206
+ # Migrate loop state from .claude/ to .agent/loop-state/ in user projects
207
+ # This handles the breaking change from v2.51.0 where loop state directory moved
208
+ # The migration is non-destructive: moves files, doesn't delete originals until confirmed
209
+ migrate_loop_state_directories() {
210
+ print_info "Checking for legacy loop state directories..."
211
+
212
+ local migrated=0
213
+ local git_dirs=()
214
+
215
+ # Find Git repositories in common locations
216
+ # Check ~/Git/ and current directory's parent
217
+ for search_dir in "$HOME/Git" "$(dirname "$(pwd)")"; do
218
+ if [[ -d "$search_dir" ]]; then
219
+ while IFS= read -r -d '' git_dir; do
220
+ git_dirs+=("$(dirname "$git_dir")")
221
+ done < <(find "$search_dir" -maxdepth 3 -type d -name ".git" -print0 2>/dev/null)
222
+ fi
223
+ done
224
+
225
+ for repo_dir in "${git_dirs[@]}"; do
226
+ local old_state_dir="$repo_dir/.claude"
227
+ local new_state_dir="$repo_dir/.agent/loop-state"
228
+
229
+ # Skip if no old state directory
230
+ [[ ! -d "$old_state_dir" ]] && continue
231
+
232
+ # Check for loop state files in old location
233
+ local has_loop_state=false
234
+ if [[ -f "$old_state_dir/ralph-loop.local.md" ]] || \
235
+ [[ -f "$old_state_dir/loop-state.json" ]] || \
236
+ [[ -d "$old_state_dir/receipts" ]]; then
237
+ has_loop_state=true
238
+ fi
239
+
240
+ [[ "$has_loop_state" != "true" ]] && continue
241
+
242
+ print_info "Found legacy loop state in: $repo_dir/.claude/"
243
+
244
+ # Create new directory
245
+ mkdir -p "$new_state_dir"
246
+
247
+ # Move loop-related files
248
+ for file in ralph-loop.local.md loop-state.json re-anchor.md guardrails.md; do
249
+ if [[ -f "$old_state_dir/$file" ]]; then
250
+ mv "$old_state_dir/$file" "$new_state_dir/"
251
+ print_info " Moved $file"
252
+ fi
253
+ done
254
+
255
+ # Move receipts directory
256
+ if [[ -d "$old_state_dir/receipts" ]]; then
257
+ mv "$old_state_dir/receipts" "$new_state_dir/"
258
+ print_info " Moved receipts/"
259
+ fi
260
+
261
+ # Check if .claude/ is now empty (only has hidden files or nothing)
262
+ local remaining
263
+ remaining=$(find "$old_state_dir" -mindepth 1 -maxdepth 1 2>/dev/null | wc -l | tr -d ' ')
264
+
265
+ if [[ "$remaining" -eq 0 ]]; then
266
+ rmdir "$old_state_dir" 2>/dev/null && print_info " Removed empty .claude/"
267
+ else
268
+ print_warning " .claude/ has other files, not removing"
269
+ fi
270
+
271
+ # Update .gitignore if needed
272
+ local gitignore="$repo_dir/.gitignore"
273
+ if [[ -f "$gitignore" ]]; then
274
+ if ! grep -q "^\.agent/loop-state/" "$gitignore" 2>/dev/null; then
275
+ echo ".agent/loop-state/" >> "$gitignore"
276
+ print_info " Added .agent/loop-state/ to .gitignore"
277
+ fi
278
+ fi
279
+
280
+ ((migrated++))
281
+ done
282
+
283
+ if [[ $migrated -gt 0 ]]; then
284
+ print_success "Migrated loop state in $migrated repositories"
285
+ else
286
+ print_info "No legacy loop state directories found"
287
+ fi
288
+
289
+ return 0
290
+ }
291
+
292
+ # Bootstrap: Clone or update repo if running remotely (via curl)
293
+ bootstrap_repo() {
294
+ # Detect if running from curl (no script directory context)
295
+ local script_path="${BASH_SOURCE[0]}"
296
+
297
+ # If script_path is empty or stdin, we're running from curl
298
+ if [[ -z "$script_path" || "$script_path" == "/dev/stdin" || "$script_path" == "bash" ]]; then
299
+ print_info "Remote install detected - bootstrapping repository..."
300
+
301
+ # Check for git
302
+ if ! command -v git >/dev/null 2>&1; then
303
+ print_error "git is required but not installed"
304
+ echo "Install git first: brew install git (macOS) or sudo apt install git (Linux)"
305
+ exit 1
306
+ fi
307
+
308
+ # Create parent directory
309
+ mkdir -p "$(dirname "$INSTALL_DIR")"
310
+
311
+ if [[ -d "$INSTALL_DIR/.git" ]]; then
312
+ print_info "Existing installation found - updating..."
313
+ cd "$INSTALL_DIR" || exit 1
314
+ git pull --ff-only
315
+ if [[ $? -ne 0 ]]; then
316
+ print_warning "Git pull failed - trying reset to origin/main"
317
+ git fetch origin
318
+ git reset --hard origin/main
319
+ fi
320
+ else
321
+ print_info "Cloning aidevops to $INSTALL_DIR..."
322
+ if [[ -d "$INSTALL_DIR" ]]; then
323
+ print_warning "Directory exists but is not a git repo - backing up"
324
+ mv "$INSTALL_DIR" "$INSTALL_DIR.backup.$(date +%Y%m%d_%H%M%S)"
325
+ fi
326
+ git clone "$REPO_URL" "$INSTALL_DIR"
327
+ if [[ $? -ne 0 ]]; then
328
+ print_error "Failed to clone repository"
329
+ exit 1
330
+ fi
331
+ fi
332
+
333
+ print_success "Repository ready at $INSTALL_DIR"
334
+
335
+ # Re-execute the local script
336
+ cd "$INSTALL_DIR" || exit 1
337
+ exec bash "./setup.sh" "$@"
338
+ fi
339
+ }
340
+
341
+ # Detect package manager
342
+ detect_package_manager() {
343
+ if command -v brew >/dev/null 2>&1; then
344
+ echo "brew"
345
+ elif command -v apt-get >/dev/null 2>&1; then
346
+ echo "apt"
347
+ elif command -v dnf >/dev/null 2>&1; then
348
+ echo "dnf"
349
+ elif command -v yum >/dev/null 2>&1; then
350
+ echo "yum"
351
+ elif command -v pacman >/dev/null 2>&1; then
352
+ echo "pacman"
353
+ elif command -v apk >/dev/null 2>&1; then
354
+ echo "apk"
355
+ else
356
+ echo "unknown"
357
+ fi
358
+ }
359
+
360
+ # Install packages using detected package manager
361
+ install_packages() {
362
+ local pkg_manager="$1"
363
+ shift
364
+ local packages=("$@")
365
+
366
+ case "$pkg_manager" in
367
+ brew)
368
+ brew install "${packages[@]}"
369
+ ;;
370
+ apt)
371
+ sudo apt-get update && sudo apt-get install -y "${packages[@]}"
372
+ ;;
373
+ dnf)
374
+ sudo dnf install -y "${packages[@]}"
375
+ ;;
376
+ yum)
377
+ sudo yum install -y "${packages[@]}"
378
+ ;;
379
+ pacman)
380
+ sudo pacman -S --noconfirm "${packages[@]}"
381
+ ;;
382
+ apk)
383
+ sudo apk add "${packages[@]}"
384
+ ;;
385
+ *)
386
+ return 1
387
+ ;;
388
+ esac
389
+ }
390
+
391
+ # Check system requirements
392
+ check_requirements() {
393
+ print_info "Checking system requirements..."
394
+
395
+ local missing_deps=()
396
+
397
+ # Check for required commands
398
+ command -v jq >/dev/null 2>&1 || missing_deps+=("jq")
399
+ command -v curl >/dev/null 2>&1 || missing_deps+=("curl")
400
+ command -v ssh >/dev/null 2>&1 || missing_deps+=("ssh")
401
+
402
+ if [[ ${#missing_deps[@]} -gt 0 ]]; then
403
+ print_warning "Missing required dependencies: ${missing_deps[*]}"
404
+
405
+ local pkg_manager
406
+ pkg_manager=$(detect_package_manager)
407
+
408
+ if [[ "$pkg_manager" == "unknown" ]]; then
409
+ print_error "Could not detect package manager"
410
+ echo ""
411
+ echo "Please install manually:"
412
+ echo " macOS: brew install ${missing_deps[*]}"
413
+ echo " Ubuntu/Debian: sudo apt-get install ${missing_deps[*]}"
414
+ echo " Fedora: sudo dnf install ${missing_deps[*]}"
415
+ echo " CentOS/RHEL: sudo yum install ${missing_deps[*]}"
416
+ echo " Arch: sudo pacman -S ${missing_deps[*]}"
417
+ echo " Alpine: sudo apk add ${missing_deps[*]}"
418
+ exit 1
419
+ fi
420
+
421
+ echo ""
422
+ read -r -p "Install missing dependencies using $pkg_manager? (y/n): " install_deps
423
+
424
+ if [[ "$install_deps" == "y" ]]; then
425
+ print_info "Installing ${missing_deps[*]}..."
426
+ if install_packages "$pkg_manager" "${missing_deps[@]}"; then
427
+ print_success "Dependencies installed successfully"
428
+ else
429
+ print_error "Failed to install dependencies"
430
+ exit 1
431
+ fi
432
+ else
433
+ print_error "Cannot continue without required dependencies"
434
+ exit 1
435
+ fi
436
+ fi
437
+
438
+ print_success "All required dependencies found"
439
+ }
440
+
441
+ # Check for optional dependencies
442
+ check_optional_deps() {
443
+ print_info "Checking optional dependencies..."
444
+
445
+ local missing_optional=()
446
+
447
+ if ! command -v sshpass >/dev/null 2>&1; then
448
+ missing_optional+=("sshpass")
449
+ else
450
+ print_success "sshpass found"
451
+ fi
452
+
453
+ if [[ ${#missing_optional[@]} -gt 0 ]]; then
454
+ print_warning "Missing optional dependencies: ${missing_optional[*]}"
455
+ echo " sshpass - needed for password-based SSH (like Hostinger)"
456
+
457
+ local pkg_manager
458
+ pkg_manager=$(detect_package_manager)
459
+
460
+ if [[ "$pkg_manager" != "unknown" ]]; then
461
+ read -r -p "Install optional dependencies using $pkg_manager? (y/n): " install_optional
462
+
463
+ if [[ "$install_optional" == "y" ]]; then
464
+ print_info "Installing ${missing_optional[*]}..."
465
+ if install_packages "$pkg_manager" "${missing_optional[@]}"; then
466
+ print_success "Optional dependencies installed"
467
+ else
468
+ print_warning "Failed to install optional dependencies (non-critical)"
469
+ fi
470
+ else
471
+ print_info "Skipped optional dependencies"
472
+ fi
473
+ fi
474
+ fi
475
+ return 0
476
+ }
477
+
478
+ # Setup Git CLI tools
479
+ setup_git_clis() {
480
+ print_info "Setting up Git CLI tools..."
481
+
482
+ local cli_tools=()
483
+ local missing_packages=()
484
+ local missing_names=()
485
+
486
+ # Check for GitHub CLI
487
+ if ! command -v gh >/dev/null 2>&1; then
488
+ missing_packages+=("gh")
489
+ missing_names+=("GitHub CLI")
490
+ else
491
+ cli_tools+=("GitHub CLI")
492
+ fi
493
+
494
+ # Check for GitLab CLI
495
+ if ! command -v glab >/dev/null 2>&1; then
496
+ missing_packages+=("glab")
497
+ missing_names+=("GitLab CLI")
498
+ else
499
+ cli_tools+=("GitLab CLI")
500
+ fi
501
+
502
+ # Report found tools
503
+ if [[ ${#cli_tools[@]} -gt 0 ]]; then
504
+ print_success "Found Git CLI tools: ${cli_tools[*]}"
505
+ fi
506
+
507
+ # Offer to install missing tools
508
+ if [[ ${#missing_packages[@]} -gt 0 ]]; then
509
+ print_warning "Missing Git CLI tools: ${missing_names[*]}"
510
+ echo " These provide enhanced Git platform integration (repos, PRs, issues)"
511
+
512
+ local pkg_manager
513
+ pkg_manager=$(detect_package_manager)
514
+
515
+ if [[ "$pkg_manager" != "unknown" ]]; then
516
+ echo ""
517
+ read -r -p "Install Git CLI tools (${missing_packages[*]}) using $pkg_manager? (y/n): " install_git_clis
518
+
519
+ if [[ "$install_git_clis" == "y" ]]; then
520
+ print_info "Installing ${missing_packages[*]}..."
521
+ if install_packages "$pkg_manager" "${missing_packages[@]}"; then
522
+ print_success "Git CLI tools installed"
523
+ echo ""
524
+ echo "📋 Next steps - authenticate each CLI:"
525
+ for pkg in "${missing_packages[@]}"; do
526
+ case "$pkg" in
527
+ gh) echo " • gh auth login" ;;
528
+ glab) echo " • glab auth login" ;;
529
+ esac
530
+ done
531
+ else
532
+ print_warning "Failed to install some Git CLI tools (non-critical)"
533
+ fi
534
+ else
535
+ print_info "Skipped Git CLI tools installation"
536
+ echo ""
537
+ echo "📋 Manual installation:"
538
+ echo " macOS: brew install ${missing_packages[*]}"
539
+ echo " Ubuntu: sudo apt install ${missing_packages[*]}"
540
+ echo " Fedora: sudo dnf install ${missing_packages[*]}"
541
+ fi
542
+ else
543
+ echo ""
544
+ echo "📋 Manual installation:"
545
+ echo " macOS: brew install ${missing_packages[*]}"
546
+ echo " Ubuntu: sudo apt install ${missing_packages[*]}"
547
+ echo " Fedora: sudo dnf install ${missing_packages[*]}"
548
+ fi
549
+ else
550
+ print_success "All Git CLI tools installed and ready!"
551
+ fi
552
+
553
+ # Check for Gitea CLI separately (not in standard package managers)
554
+ if ! command -v tea >/dev/null 2>&1; then
555
+ print_info "Gitea CLI (tea) not found - install manually if needed:"
556
+ echo " go install code.gitea.io/tea/cmd/tea@latest"
557
+ echo " Or download from: https://dl.gitea.io/tea/"
558
+ else
559
+ print_success "Gitea CLI (tea) found"
560
+ fi
561
+
562
+ return 0
563
+ }
564
+
565
+ # Setup recommended tools (Tabby terminal, Zed editor)
566
+ setup_recommended_tools() {
567
+ print_info "Checking recommended development tools..."
568
+
569
+ local missing_tools=()
570
+ local missing_names=()
571
+
572
+ # Check for Tabby terminal
573
+ if [[ "$(uname)" == "Darwin" ]]; then
574
+ # macOS - check Applications folder
575
+ if [[ ! -d "/Applications/Tabby.app" ]]; then
576
+ missing_tools+=("tabby")
577
+ missing_names+=("Tabby (modern terminal)")
578
+ else
579
+ print_success "Tabby terminal found"
580
+ fi
581
+ elif [[ "$(uname)" == "Linux" ]]; then
582
+ # Linux - check if tabby command exists
583
+ if ! command -v tabby >/dev/null 2>&1; then
584
+ missing_tools+=("tabby")
585
+ missing_names+=("Tabby (modern terminal)")
586
+ else
587
+ print_success "Tabby terminal found"
588
+ fi
589
+ fi
590
+
591
+ # Check for Zed editor
592
+ local zed_exists=false
593
+ if [[ "$(uname)" == "Darwin" ]]; then
594
+ # macOS - check Applications folder
595
+ if [[ ! -d "/Applications/Zed.app" ]]; then
596
+ missing_tools+=("zed")
597
+ missing_names+=("Zed (AI-native editor)")
598
+ else
599
+ print_success "Zed editor found"
600
+ zed_exists=true
601
+ fi
602
+ elif [[ "$(uname)" == "Linux" ]]; then
603
+ # Linux - check if zed command exists
604
+ if ! command -v zed >/dev/null 2>&1; then
605
+ missing_tools+=("zed")
606
+ missing_names+=("Zed (AI-native editor)")
607
+ else
608
+ print_success "Zed editor found"
609
+ zed_exists=true
610
+ fi
611
+ fi
612
+
613
+ # Check for OpenCode extension in existing Zed installation
614
+ if [[ "$zed_exists" == "true" ]]; then
615
+ local zed_extensions_dir=""
616
+ if [[ "$(uname)" == "Darwin" ]]; then
617
+ zed_extensions_dir="$HOME/Library/Application Support/Zed/extensions/installed"
618
+ elif [[ "$(uname)" == "Linux" ]]; then
619
+ zed_extensions_dir="$HOME/.local/share/zed/extensions/installed"
620
+ fi
621
+
622
+ if [[ -d "$zed_extensions_dir" ]]; then
623
+ if [[ ! -d "$zed_extensions_dir/opencode" ]]; then
624
+ read -r -p "Install OpenCode extension for Zed? (y/n): " install_opencode_ext
625
+ if [[ "$install_opencode_ext" == "y" ]]; then
626
+ print_info "Installing OpenCode extension..."
627
+ if [[ "$(uname)" == "Darwin" ]]; then
628
+ open "zed://extension/opencode" 2>/dev/null
629
+ print_success "OpenCode extension install triggered"
630
+ print_info "Zed will open and prompt to install the extension"
631
+ elif [[ "$(uname)" == "Linux" ]]; then
632
+ xdg-open "zed://extension/opencode" 2>/dev/null || \
633
+ print_info "Open Zed and install 'opencode' from Extensions"
634
+ fi
635
+ fi
636
+ else
637
+ print_success "OpenCode extension already installed in Zed"
638
+ fi
639
+ fi
640
+ fi
641
+
642
+ # Offer to install missing tools
643
+ if [[ ${#missing_tools[@]} -gt 0 ]]; then
644
+ print_warning "Missing recommended tools: ${missing_names[*]}"
645
+ echo " Tabby - Modern terminal with profiles, SSH manager, split panes"
646
+ echo " Zed - High-performance AI-native code editor"
647
+ echo ""
648
+
649
+ # Install Tabby if missing
650
+ if [[ " ${missing_tools[*]} " =~ " tabby " ]]; then
651
+ read -r -p "Install Tabby terminal? (y/n): " install_tabby
652
+
653
+ if [[ "$install_tabby" == "y" ]]; then
654
+ print_info "Installing Tabby..."
655
+ if [[ "$(uname)" == "Darwin" ]]; then
656
+ if command -v brew >/dev/null 2>&1; then
657
+ brew install --cask tabby
658
+ if [[ $? -eq 0 ]]; then
659
+ print_success "Tabby installed successfully"
660
+ else
661
+ print_warning "Failed to install Tabby via Homebrew"
662
+ echo " Download manually: https://github.com/Eugeny/tabby/releases/latest"
663
+ fi
664
+ else
665
+ print_warning "Homebrew not found"
666
+ echo " Download manually: https://github.com/Eugeny/tabby/releases/latest"
667
+ fi
668
+ elif [[ "$(uname)" == "Linux" ]]; then
669
+ local pkg_manager
670
+ pkg_manager=$(detect_package_manager)
671
+ case "$pkg_manager" in
672
+ apt)
673
+ # Add packagecloud repo for Tabby
674
+ print_info "Adding Tabby repository..."
675
+ curl -s https://packagecloud.io/install/repositories/eugeny/tabby/script.deb.sh | sudo bash
676
+ sudo apt-get install -y tabby-terminal
677
+ ;;
678
+ dnf|yum)
679
+ print_info "Adding Tabby repository..."
680
+ curl -s https://packagecloud.io/install/repositories/eugeny/tabby/script.rpm.sh | sudo bash
681
+ sudo "$pkg_manager" install -y tabby-terminal
682
+ ;;
683
+ pacman)
684
+ # AUR package
685
+ print_info "Tabby available in AUR as 'tabby-bin'"
686
+ echo " Install with: yay -S tabby-bin"
687
+ ;;
688
+ *)
689
+ echo " Download manually: https://github.com/Eugeny/tabby/releases/latest"
690
+ ;;
691
+ esac
692
+ fi
693
+ else
694
+ print_info "Skipped Tabby installation"
695
+ fi
696
+ fi
697
+
698
+ # Install Zed if missing
699
+ if [[ " ${missing_tools[*]} " =~ " zed " ]]; then
700
+ read -r -p "Install Zed editor? (y/n): " install_zed
701
+
702
+ if [[ "$install_zed" == "y" ]]; then
703
+ print_info "Installing Zed..."
704
+ local zed_installed=false
705
+ if [[ "$(uname)" == "Darwin" ]]; then
706
+ if command -v brew >/dev/null 2>&1; then
707
+ brew install --cask zed
708
+ if [[ $? -eq 0 ]]; then
709
+ print_success "Zed installed successfully"
710
+ zed_installed=true
711
+ else
712
+ print_warning "Failed to install Zed via Homebrew"
713
+ echo " Download manually: https://zed.dev/download"
714
+ fi
715
+ else
716
+ print_warning "Homebrew not found"
717
+ echo " Download manually: https://zed.dev/download"
718
+ fi
719
+ elif [[ "$(uname)" == "Linux" ]]; then
720
+ # Zed provides an install script for Linux
721
+ print_info "Running Zed install script..."
722
+ curl -f https://zed.dev/install.sh | sh
723
+ if [[ $? -eq 0 ]]; then
724
+ print_success "Zed installed successfully"
725
+ zed_installed=true
726
+ else
727
+ print_warning "Failed to install Zed"
728
+ echo " See: https://zed.dev/docs/linux"
729
+ fi
730
+ fi
731
+
732
+ # Install OpenCode extension for Zed
733
+ if [[ "$zed_installed" == "true" ]]; then
734
+ read -r -p "Install OpenCode extension for Zed? (y/n): " install_opencode_ext
735
+ if [[ "$install_opencode_ext" == "y" ]]; then
736
+ print_info "Installing OpenCode extension..."
737
+ if [[ "$(uname)" == "Darwin" ]]; then
738
+ open "zed://extension/opencode" 2>/dev/null
739
+ print_success "OpenCode extension install triggered"
740
+ print_info "Zed will open and prompt to install the extension"
741
+ elif [[ "$(uname)" == "Linux" ]]; then
742
+ xdg-open "zed://extension/opencode" 2>/dev/null || \
743
+ print_info "Open Zed and install 'opencode' from Extensions (Cmd+Shift+X)"
744
+ fi
745
+ fi
746
+ fi
747
+ else
748
+ print_info "Skipped Zed installation"
749
+ fi
750
+ fi
751
+ else
752
+ print_success "All recommended tools installed!"
753
+ fi
754
+
755
+ return 0
756
+ }
757
+
758
+ # Setup SSH key if needed
759
+ setup_ssh_key() {
760
+ print_info "Checking SSH key setup..."
761
+
762
+ if [[ ! -f ~/.ssh/id_ed25519 ]]; then
763
+ print_warning "Ed25519 SSH key not found"
764
+ read -r -p "Generate new Ed25519 SSH key? (y/n): " generate_key
765
+
766
+ if [[ "$generate_key" == "y" ]]; then
767
+ read -r -p "Enter your email address: " email
768
+ ssh-keygen -t ed25519 -C "$email"
769
+ print_success "SSH key generated"
770
+ else
771
+ print_info "Skipping SSH key generation"
772
+ fi
773
+ else
774
+ print_success "Ed25519 SSH key found"
775
+ fi
776
+ return 0
777
+ }
778
+
779
+ # Setup configuration files
780
+ setup_configs() {
781
+ print_info "Setting up configuration files..."
782
+
783
+ # Create configs directory if it doesn't exist
784
+ mkdir -p configs
785
+
786
+ # Copy template configs if they don't exist
787
+ for template in configs/*.txt; do
788
+ if [[ -f "$template" ]]; then
789
+ config_file="${template%.txt}"
790
+ if [[ ! -f "$config_file" ]]; then
791
+ cp "$template" "$config_file"
792
+ print_success "Created $(basename "$config_file")"
793
+ print_warning "Please edit $(basename "$config_file") with your actual credentials"
794
+ else
795
+ print_info "Found existing config: $(basename "$config_file") - Skipping"
796
+ fi
797
+ fi
798
+ done
799
+
800
+ return 0
801
+ }
802
+
803
+ # Set proper permissions
804
+ set_permissions() {
805
+ print_info "Setting proper file permissions..."
806
+
807
+ # Make scripts executable
808
+ chmod +x ./*.sh
809
+ chmod +x .agent/scripts/*.sh
810
+ chmod +x ssh/*.sh
811
+
812
+ # Secure configuration files
813
+ chmod 600 configs/*.json 2>/dev/null || true
814
+
815
+ print_success "File permissions set"
816
+ return 0
817
+ }
818
+
819
+ # Add ~/.local/bin to PATH in shell config
820
+ add_local_bin_to_path() {
821
+ local shell_rc=""
822
+ local path_line='export PATH="$HOME/.local/bin:$PATH"'
823
+
824
+ # Detect shell config file
825
+ if [[ "$SHELL" == *"zsh"* ]] || [[ -n "$ZSH_VERSION" ]]; then
826
+ shell_rc="$HOME/.zshrc"
827
+ elif [[ "$SHELL" == *"bash"* ]] || [[ -n "$BASH_VERSION" ]]; then
828
+ if [[ "$(uname)" == "Darwin" ]]; then
829
+ shell_rc="$HOME/.bash_profile"
830
+ else
831
+ shell_rc="$HOME/.bashrc"
832
+ fi
833
+ elif [[ -f "$HOME/.zshrc" ]]; then
834
+ shell_rc="$HOME/.zshrc"
835
+ elif [[ -f "$HOME/.bashrc" ]]; then
836
+ shell_rc="$HOME/.bashrc"
837
+ elif [[ -f "$HOME/.bash_profile" ]]; then
838
+ shell_rc="$HOME/.bash_profile"
839
+ fi
840
+
841
+ if [[ -z "$shell_rc" ]]; then
842
+ print_warning "Could not detect shell config file"
843
+ print_info "Add this to your shell config: $path_line"
844
+ return 0
845
+ fi
846
+
847
+ # Create the rc file if it doesn't exist
848
+ if [[ ! -f "$shell_rc" ]]; then
849
+ touch "$shell_rc"
850
+ fi
851
+
852
+ # Check if already added
853
+ if grep -q '\.local/bin' "$shell_rc" 2>/dev/null; then
854
+ print_info "~/.local/bin already in PATH (found in $shell_rc)"
855
+ return 0
856
+ fi
857
+
858
+ # Add to shell config
859
+ echo "" >> "$shell_rc"
860
+ echo "# Added by aidevops setup" >> "$shell_rc"
861
+ echo "$path_line" >> "$shell_rc"
862
+
863
+ print_success "Added ~/.local/bin to PATH in $shell_rc"
864
+ print_info "Run 'source $shell_rc' or restart your terminal to use 'aidevops' command"
865
+
866
+ # Also export for current session
867
+ export PATH="$HOME/.local/bin:$PATH"
868
+
869
+ return 0
870
+ }
871
+
872
+ # Install aidevops CLI command
873
+ install_aidevops_cli() {
874
+ print_info "Installing aidevops CLI command..."
875
+
876
+ local script_dir
877
+ script_dir="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
878
+ local cli_source="$script_dir/aidevops.sh"
879
+ local cli_target="/usr/local/bin/aidevops"
880
+
881
+ if [[ ! -f "$cli_source" ]]; then
882
+ print_warning "aidevops.sh not found - skipping CLI installation"
883
+ return 0
884
+ fi
885
+
886
+ # Check if we can write to /usr/local/bin
887
+ if [[ -w "/usr/local/bin" ]]; then
888
+ # Direct symlink
889
+ ln -sf "$cli_source" "$cli_target"
890
+ print_success "Installed aidevops command to $cli_target"
891
+ elif [[ -w "$HOME/.local/bin" ]] || mkdir -p "$HOME/.local/bin" 2>/dev/null; then
892
+ # Use ~/.local/bin instead
893
+ cli_target="$HOME/.local/bin/aidevops"
894
+ ln -sf "$cli_source" "$cli_target"
895
+ print_success "Installed aidevops command to $cli_target"
896
+
897
+ # Check if ~/.local/bin is in PATH and add it if not
898
+ if [[ ":$PATH:" != *":$HOME/.local/bin:"* ]]; then
899
+ add_local_bin_to_path
900
+ fi
901
+ else
902
+ # Need sudo
903
+ print_info "Installing aidevops command requires sudo..."
904
+ if sudo ln -sf "$cli_source" "$cli_target"; then
905
+ print_success "Installed aidevops command to $cli_target"
906
+ else
907
+ print_warning "Could not install aidevops command globally"
908
+ print_info "You can run it directly: $cli_source"
909
+ fi
910
+ fi
911
+
912
+ return 0
913
+ }
914
+
915
+ # Setup shell aliases
916
+ setup_aliases() {
917
+ print_info "Setting up shell aliases..."
918
+
919
+ local shell_rc=""
920
+ local shell_name=""
921
+
922
+ # Detect shell - check $SHELL first, then try to detect from process
923
+ if [[ "$SHELL" == *"zsh"* ]]; then
924
+ shell_rc="$HOME/.zshrc"
925
+ shell_name="zsh"
926
+ elif [[ "$SHELL" == *"bash"* ]]; then
927
+ # macOS: use .bash_profile (login shell), Linux: use .bashrc
928
+ if [[ "$(uname)" == "Darwin" ]]; then
929
+ shell_rc="$HOME/.bash_profile"
930
+ else
931
+ shell_rc="$HOME/.bashrc"
932
+ fi
933
+ shell_name="bash"
934
+ elif [[ "$SHELL" == *"fish"* ]]; then
935
+ shell_rc="$HOME/.config/fish/config.fish"
936
+ shell_name="fish"
937
+ elif [[ "$SHELL" == *"ksh"* ]]; then
938
+ shell_rc="$HOME/.kshrc"
939
+ shell_name="ksh"
940
+ elif [[ -n "$ZSH_VERSION" ]]; then
941
+ shell_rc="$HOME/.zshrc"
942
+ shell_name="zsh"
943
+ elif [[ -n "$BASH_VERSION" ]]; then
944
+ if [[ "$(uname)" == "Darwin" ]]; then
945
+ shell_rc="$HOME/.bash_profile"
946
+ else
947
+ shell_rc="$HOME/.bashrc"
948
+ fi
949
+ shell_name="bash"
950
+ else
951
+ # Fallback: check common rc files
952
+ if [[ -f "$HOME/.zshrc" ]]; then
953
+ shell_rc="$HOME/.zshrc"
954
+ shell_name="zsh"
955
+ elif [[ -f "$HOME/.bashrc" ]]; then
956
+ shell_rc="$HOME/.bashrc"
957
+ shell_name="bash"
958
+ elif [[ -f "$HOME/.bash_profile" ]]; then
959
+ shell_rc="$HOME/.bash_profile"
960
+ shell_name="bash"
961
+ else
962
+ print_warning "Could not detect shell configuration file"
963
+ print_info "Supported shells: bash, zsh, fish, ksh"
964
+ print_info "You can manually add aliases to your shell config"
965
+ return 0
966
+ fi
967
+ fi
968
+
969
+ # Create the rc file if it doesn't exist (common on fresh systems)
970
+ if [[ ! -f "$shell_rc" ]]; then
971
+ print_info "Creating $shell_rc (file did not exist)"
972
+ touch "$shell_rc"
973
+ fi
974
+
975
+ # Check if aliases already exist
976
+ if grep -q "# AI Assistant Server Access" "$shell_rc" 2>/dev/null; then
977
+ print_info "Server Access aliases already configured in $shell_rc - Skipping"
978
+ return 0
979
+ fi
980
+
981
+ print_info "Detected shell: $shell_name"
982
+ read -r -p "Add shell aliases to $shell_rc? (y/n): " add_aliases
983
+
984
+ if [[ "$add_aliases" == "y" ]]; then
985
+ # Fish shell uses different syntax
986
+ if [[ "$shell_name" == "fish" ]]; then
987
+ mkdir -p "$HOME/.config/fish"
988
+ cat >> "$shell_rc" << 'EOF'
989
+
990
+ # AI Assistant Server Access Framework
991
+ alias servers './.agent/scripts/servers-helper.sh'
992
+ alias servers-list './.agent/scripts/servers-helper.sh list'
993
+ alias hostinger './.agent/scripts/hostinger-helper.sh'
994
+ alias hetzner './.agent/scripts/hetzner-helper.sh'
995
+ alias aws-helper './.agent/scripts/aws-helper.sh'
996
+ EOF
997
+ else
998
+ # Bash, zsh, ksh use same syntax
999
+ cat >> "$shell_rc" << 'EOF'
1000
+
1001
+ # AI Assistant Server Access Framework
1002
+ alias servers='./.agent/scripts/servers-helper.sh'
1003
+ alias servers-list='./.agent/scripts/servers-helper.sh list'
1004
+ alias hostinger='./.agent/scripts/hostinger-helper.sh'
1005
+ alias hetzner='./.agent/scripts/hetzner-helper.sh'
1006
+ alias aws-helper='./.agent/scripts/aws-helper.sh'
1007
+ EOF
1008
+ fi
1009
+ print_success "Aliases added to $shell_rc"
1010
+ print_info "Run 'source $shell_rc' or restart your terminal to use aliases"
1011
+ else
1012
+ print_info "Skipped alias setup by user request"
1013
+ fi
1014
+ return 0
1015
+ }
1016
+
1017
+ # Setup terminal title integration (syncs tab title with git repo/branch)
1018
+ setup_terminal_title() {
1019
+ print_info "Setting up terminal title integration..."
1020
+
1021
+ local setup_script=".agent/scripts/terminal-title-setup.sh"
1022
+
1023
+ if [[ ! -f "$setup_script" ]]; then
1024
+ print_warning "Terminal title setup script not found - skipping"
1025
+ return 0
1026
+ fi
1027
+
1028
+ # Check if already installed
1029
+ local shell_name
1030
+ shell_name=$(basename "${SHELL:-/bin/bash}")
1031
+ local rc_file=""
1032
+
1033
+ case "$shell_name" in
1034
+ zsh) rc_file="$HOME/.zshrc" ;;
1035
+ bash) rc_file="$HOME/.bashrc" ;;
1036
+ fish) rc_file="$HOME/.config/fish/config.fish" ;;
1037
+ esac
1038
+
1039
+ if [[ -n "$rc_file" ]] && [[ -f "$rc_file" ]] && grep -q "aidevops terminal-title" "$rc_file" 2>/dev/null; then
1040
+ print_info "Terminal title integration already configured in $rc_file - Skipping"
1041
+ return 0
1042
+ fi
1043
+
1044
+ # Show current status before asking
1045
+ echo ""
1046
+ print_info "Terminal title integration syncs your terminal tab with git repo/branch"
1047
+ print_info "Example: Tab shows 'aidevops/feature/xyz' when in that branch"
1048
+ echo ""
1049
+ echo "Current status:"
1050
+
1051
+ # Shell info
1052
+ local shell_info="$shell_name"
1053
+ if [[ "$shell_name" == "zsh" ]] && [[ -d "$HOME/.oh-my-zsh" ]]; then
1054
+ shell_info="$shell_name (Oh-My-Zsh)"
1055
+ fi
1056
+ echo " Shell: $shell_info"
1057
+
1058
+ # Tabby info
1059
+ local tabby_config="$HOME/Library/Application Support/tabby/config.yaml"
1060
+ if [[ -f "$tabby_config" ]]; then
1061
+ local disabled_count
1062
+ disabled_count=$(grep -c "disableDynamicTitle: true" "$tabby_config" 2>/dev/null || echo "0")
1063
+ if [[ "$disabled_count" -gt 0 ]]; then
1064
+ echo " Tabby: detected, dynamic titles disabled in $disabled_count profile(s) (will fix)"
1065
+ else
1066
+ echo " Tabby: detected, dynamic titles enabled"
1067
+ fi
1068
+ fi
1069
+
1070
+ echo ""
1071
+ read -r -p "Install terminal title integration? (y/n): " install_title
1072
+
1073
+ if [[ "$install_title" == "y" ]]; then
1074
+ if bash "$setup_script" install; then
1075
+ print_success "Terminal title integration installed"
1076
+ else
1077
+ print_warning "Terminal title setup encountered issues (non-critical)"
1078
+ fi
1079
+ else
1080
+ print_info "Skipped terminal title setup by user request"
1081
+ print_info "You can install later with: ~/.aidevops/agents/scripts/terminal-title-setup.sh install"
1082
+ fi
1083
+
1084
+ return 0
1085
+ }
1086
+
1087
+ # Deploy AI assistant templates
1088
+ deploy_ai_templates() {
1089
+ print_info "Deploying AI assistant templates..."
1090
+
1091
+ if [[ -f "templates/deploy-templates.sh" ]]; then
1092
+ print_info "Running template deployment script..."
1093
+ bash templates/deploy-templates.sh
1094
+
1095
+ if [[ $? -eq 0 ]]; then
1096
+ print_success "AI assistant templates deployed successfully"
1097
+ else
1098
+ print_warning "Template deployment encountered issues (non-critical)"
1099
+ fi
1100
+ else
1101
+ print_warning "Template deployment script not found - skipping"
1102
+ fi
1103
+ return 0
1104
+ }
1105
+
1106
+ # Extract OpenCode prompts from binary (for Plan+ system-reminder)
1107
+ # Must run before deploy_aidevops_agents so the cache exists for injection
1108
+ extract_opencode_prompts() {
1109
+ local extract_script=".agent/scripts/extract-opencode-prompts.sh"
1110
+ if [[ -f "$extract_script" ]]; then
1111
+ if bash "$extract_script"; then
1112
+ print_success "OpenCode prompts extracted"
1113
+ else
1114
+ print_warning "OpenCode prompt extraction encountered issues (non-critical)"
1115
+ fi
1116
+ fi
1117
+ return 0
1118
+ }
1119
+
1120
+ # Deploy aidevops agents to user location
1121
+ deploy_aidevops_agents() {
1122
+ print_info "Deploying aidevops agents to ~/.aidevops/agents/..."
1123
+
1124
+ local script_dir
1125
+ script_dir="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
1126
+ local source_dir="$script_dir/.agent"
1127
+ local target_dir="$HOME/.aidevops/agents"
1128
+
1129
+ # Create backup if target exists (with rotation)
1130
+ if [[ -d "$target_dir" ]]; then
1131
+ create_backup_with_rotation "$target_dir" "agents"
1132
+ fi
1133
+
1134
+ # Create target directory and copy agents
1135
+ mkdir -p "$target_dir"
1136
+
1137
+ # If clean mode, remove stale files first
1138
+ if [[ "$CLEAN_MODE" == "true" ]]; then
1139
+ print_info "Clean mode: removing stale files from $target_dir"
1140
+ rm -rf "${target_dir:?}"/*
1141
+ fi
1142
+
1143
+ # Copy all agent files and folders (excluding scripts which are large)
1144
+ # We copy scripts separately to maintain structure
1145
+ cp -R "$source_dir"/* "$target_dir/"
1146
+
1147
+ if [[ $? -eq 0 ]]; then
1148
+ print_success "Deployed agents to $target_dir"
1149
+
1150
+ # Set permissions on scripts
1151
+ chmod +x "$target_dir/scripts/"*.sh 2>/dev/null || true
1152
+
1153
+ # Count what was deployed
1154
+ local agent_count
1155
+ agent_count=$(find "$target_dir" -name "*.md" -type f | wc -l | tr -d ' ')
1156
+ local script_count
1157
+ script_count=$(find "$target_dir/scripts" -name "*.sh" -type f 2>/dev/null | wc -l | tr -d ' ')
1158
+
1159
+ print_info "Deployed $agent_count agent files and $script_count scripts"
1160
+
1161
+ # Copy VERSION file from repo root to deployed agents
1162
+ if [[ -f "$script_dir/VERSION" ]]; then
1163
+ if cp "$script_dir/VERSION" "$target_dir/VERSION"; then
1164
+ print_info "Copied VERSION file to deployed agents"
1165
+ else
1166
+ print_warning "Failed to copy VERSION file (Plan+ may not read version correctly)"
1167
+ fi
1168
+ else
1169
+ print_warning "VERSION file not found in repo root"
1170
+ fi
1171
+
1172
+ # Inject extracted OpenCode plan-reminder into Plan+ if available
1173
+ local plan_reminder="$HOME/.aidevops/cache/opencode-prompts/plan-reminder.txt"
1174
+ local plan_plus="$target_dir/plan-plus.md"
1175
+ if [[ -f "$plan_reminder" && -f "$plan_plus" ]]; then
1176
+ # Check if plan-plus.md has the placeholder marker
1177
+ if grep -q "OPENCODE-PLAN-REMINDER-INJECT" "$plan_plus"; then
1178
+ # Replace placeholder with extracted content
1179
+ local reminder_content
1180
+ reminder_content=$(cat "$plan_reminder")
1181
+ # Use awk to replace the placeholder section
1182
+ awk -v content="$reminder_content" '
1183
+ /<!-- OPENCODE-PLAN-REMINDER-INJECT-START -->/ { print; print content; skip=1; next }
1184
+ /<!-- OPENCODE-PLAN-REMINDER-INJECT-END -->/ { skip=0 }
1185
+ !skip { print }
1186
+ ' "$plan_plus" > "$plan_plus.tmp" && mv "$plan_plus.tmp" "$plan_plus"
1187
+ print_info "Injected OpenCode plan-reminder into Plan+"
1188
+ fi
1189
+ fi
1190
+ else
1191
+ print_error "Failed to deploy agents"
1192
+ return 1
1193
+ fi
1194
+
1195
+ return 0
1196
+ }
1197
+
1198
+ # Generate Agent Skills SKILL.md files for cross-tool compatibility
1199
+ generate_agent_skills() {
1200
+ print_info "Generating Agent Skills SKILL.md files..."
1201
+
1202
+ local skills_script="$HOME/.aidevops/agents/scripts/generate-skills.sh"
1203
+
1204
+ if [[ -f "$skills_script" ]]; then
1205
+ if bash "$skills_script" 2>/dev/null; then
1206
+ print_success "Agent Skills SKILL.md files generated"
1207
+ print_info "Skills compatible with: Cursor, Claude Code, VS Code, GitHub Copilot"
1208
+ else
1209
+ print_warning "Agent Skills generation encountered issues (non-critical)"
1210
+ fi
1211
+ else
1212
+ print_warning "Agent Skills generator not found at $skills_script"
1213
+ fi
1214
+
1215
+ return 0
1216
+ }
1217
+
1218
+ # Inject aidevops reference into AI assistant AGENTS.md files
1219
+ inject_agents_reference() {
1220
+ print_info "Adding aidevops reference to AI assistant configurations..."
1221
+
1222
+ local reference_line='Add ~/.aidevops/agents/AGENTS.md to context for AI DevOps capabilities.'
1223
+
1224
+ # AI assistant agent directories - these get cleaned and receive AGENTS.md reference
1225
+ # Format: "config_dir:agents_subdir" where agents_subdir is the folder containing agent files
1226
+ local ai_agent_dirs=(
1227
+ "$HOME/.config/opencode:agent"
1228
+ "$HOME/.cursor:rules"
1229
+ "$HOME/.claude:commands"
1230
+ "$HOME/.continue:."
1231
+ "$HOME/.cody:."
1232
+ "$HOME/.opencode:."
1233
+ )
1234
+
1235
+ local updated_count=0
1236
+
1237
+ for entry in "${ai_agent_dirs[@]}"; do
1238
+ local config_dir="${entry%%:*}"
1239
+ local agents_subdir="${entry##*:}"
1240
+ local agents_dir="$config_dir/$agents_subdir"
1241
+ local agents_file="$agents_dir/AGENTS.md"
1242
+
1243
+ # Only process if the config directory exists (tool is installed)
1244
+ if [[ -d "$config_dir" ]]; then
1245
+ # Create agents subdirectory if needed
1246
+ mkdir -p "$agents_dir"
1247
+
1248
+ # Check if AGENTS.md exists and has our reference
1249
+ if [[ -f "$agents_file" ]]; then
1250
+ # Check first line for our reference
1251
+ local first_line
1252
+ first_line=$(head -1 "$agents_file" 2>/dev/null || echo "")
1253
+ if [[ "$first_line" != *"~/.aidevops/agents/AGENTS.md"* ]]; then
1254
+ # Prepend reference to existing file
1255
+ local temp_file
1256
+ temp_file=$(mktemp)
1257
+ echo "$reference_line" > "$temp_file"
1258
+ echo "" >> "$temp_file"
1259
+ cat "$agents_file" >> "$temp_file"
1260
+ mv "$temp_file" "$agents_file"
1261
+ print_success "Added reference to $agents_file"
1262
+ ((updated_count++))
1263
+ else
1264
+ print_info "Reference already exists in $agents_file"
1265
+ fi
1266
+ else
1267
+ # Create new file with just the reference
1268
+ echo "$reference_line" > "$agents_file"
1269
+ print_success "Created $agents_file with aidevops reference"
1270
+ ((updated_count++))
1271
+ fi
1272
+ fi
1273
+ done
1274
+
1275
+ if [[ $updated_count -eq 0 ]]; then
1276
+ print_info "No AI assistant configs found to update (tools may not be installed yet)"
1277
+ else
1278
+ print_success "Updated $updated_count AI assistant configuration(s)"
1279
+ fi
1280
+
1281
+ return 0
1282
+ }
1283
+
1284
+ # Update OpenCode configuration
1285
+ update_opencode_config() {
1286
+ print_info "Updating OpenCode configuration..."
1287
+
1288
+ local opencode_config="$HOME/.config/opencode/opencode.json"
1289
+
1290
+ if [[ ! -f "$opencode_config" ]]; then
1291
+ print_info "OpenCode config not found at $opencode_config - skipping"
1292
+ return 0
1293
+ fi
1294
+
1295
+ # Create backup (with rotation)
1296
+ create_backup_with_rotation "$opencode_config" "opencode"
1297
+
1298
+ # Generate OpenCode agent configuration
1299
+ # - Primary agents: Added to opencode.json (for Tab order & MCP control)
1300
+ # - Subagents: Generated as markdown in ~/.config/opencode/agent/
1301
+ local generator_script=".agent/scripts/generate-opencode-agents.sh"
1302
+ if [[ -f "$generator_script" ]]; then
1303
+ print_info "Generating OpenCode agent configuration..."
1304
+ if bash "$generator_script"; then
1305
+ print_success "OpenCode agents configured (11 primary in JSON, subagents as markdown)"
1306
+ else
1307
+ print_warning "OpenCode agent generation encountered issues"
1308
+ fi
1309
+ else
1310
+ print_warning "OpenCode agent generator not found at $generator_script"
1311
+ fi
1312
+
1313
+ # Generate OpenCode commands
1314
+ # - Commands from workflows and agents -> /command-name
1315
+ local commands_script=".agent/scripts/generate-opencode-commands.sh"
1316
+ if [[ -f "$commands_script" ]]; then
1317
+ print_info "Generating OpenCode commands..."
1318
+ if bash "$commands_script"; then
1319
+ print_success "OpenCode commands configured"
1320
+ else
1321
+ print_warning "OpenCode command generation encountered issues"
1322
+ fi
1323
+ else
1324
+ print_warning "OpenCode command generator not found at $commands_script"
1325
+ fi
1326
+
1327
+ return 0
1328
+ }
1329
+
1330
+ # Verify repository location
1331
+ verify_location() {
1332
+ local current_dir
1333
+ current_dir="$(pwd)"
1334
+ local expected_location="$HOME/Git/aidevops"
1335
+
1336
+ if [[ "$current_dir" != "$expected_location" ]]; then
1337
+ print_warning "Repository is not in the recommended location"
1338
+ print_info "Current location: $current_dir"
1339
+ print_info "Recommended location: $expected_location"
1340
+ echo ""
1341
+ echo "For optimal AI assistant integration, consider moving this repository to:"
1342
+ echo " mkdir -p ~/git"
1343
+ echo " mv '$current_dir' '$expected_location'"
1344
+ echo ""
1345
+ else
1346
+ print_success "Repository is in the recommended location: $expected_location"
1347
+ fi
1348
+ return 0
1349
+ }
1350
+
1351
+
1352
+
1353
+ # Setup Python environment for DSPy
1354
+ setup_python_env() {
1355
+ print_info "Setting up Python environment for DSPy..."
1356
+
1357
+ # Check if Python 3 is available
1358
+ if ! command -v python3 &> /dev/null; then
1359
+ print_warning "Python 3 not found - DSPy setup skipped"
1360
+ print_info "Install Python 3.8+ to enable DSPy integration"
1361
+ return
1362
+ fi
1363
+
1364
+ local python_version=$(python3 --version | cut -d' ' -f2 | cut -d'.' -f1-2)
1365
+ local version_check=$(python3 -c "import sys; print(1 if sys.version_info >= (3, 8) else 0)")
1366
+
1367
+ if [[ "$version_check" != "1" ]]; then
1368
+ print_warning "Python 3.8+ required for DSPy, found $python_version - DSPy setup skipped"
1369
+ return
1370
+ fi
1371
+
1372
+ # Create Python virtual environment
1373
+ if [[ ! -d "python-env/dspy-env" ]]; then
1374
+ print_info "Creating Python virtual environment for DSPy..."
1375
+ mkdir -p python-env
1376
+ python3 -m venv python-env/dspy-env
1377
+
1378
+ if [[ $? -eq 0 ]]; then
1379
+ print_success "Python virtual environment created"
1380
+ else
1381
+ print_warning "Failed to create Python virtual environment - DSPy setup skipped"
1382
+ return
1383
+ fi
1384
+ else
1385
+ print_info "Python virtual environment already exists"
1386
+ fi
1387
+
1388
+ # Install DSPy dependencies
1389
+ print_info "Installing DSPy dependencies..."
1390
+ source python-env/dspy-env/bin/activate
1391
+ pip install --upgrade pip > /dev/null 2>&1
1392
+ pip install -r requirements.txt > /dev/null 2>&1
1393
+
1394
+ if [[ $? -eq 0 ]]; then
1395
+ print_success "DSPy dependencies installed successfully"
1396
+ else
1397
+ print_warning "Failed to install DSPy dependencies - check requirements.txt"
1398
+ fi
1399
+ }
1400
+
1401
+ # Setup Node.js environment for DSPyGround
1402
+ setup_nodejs_env() {
1403
+ print_info "Setting up Node.js environment for DSPyGround..."
1404
+
1405
+ # Check if Node.js is available
1406
+ if ! command -v node &> /dev/null; then
1407
+ print_warning "Node.js not found - DSPyGround setup skipped"
1408
+ print_info "Install Node.js 18+ to enable DSPyGround integration"
1409
+ return
1410
+ fi
1411
+
1412
+ local node_version=$(node --version | cut -d'v' -f2 | cut -d'.' -f1)
1413
+ if [[ $node_version -lt 18 ]]; then
1414
+ print_warning "Node.js 18+ required for DSPyGround, found v$node_version - DSPyGround setup skipped"
1415
+ return
1416
+ fi
1417
+
1418
+ # Check if npm is available
1419
+ if ! command -v npm &> /dev/null; then
1420
+ print_warning "npm not found - DSPyGround setup skipped"
1421
+ return
1422
+ fi
1423
+
1424
+ # Install DSPyGround globally if not already installed
1425
+ if ! command -v dspyground &> /dev/null; then
1426
+ print_info "Installing DSPyGround globally..."
1427
+ npm install -g dspyground > /dev/null 2>&1
1428
+
1429
+ if [[ $? -eq 0 ]]; then
1430
+ print_success "DSPyGround installed successfully"
1431
+ else
1432
+ print_warning "Failed to install DSPyGround globally"
1433
+ fi
1434
+ else
1435
+ print_success "DSPyGround already installed"
1436
+ fi
1437
+ }
1438
+
1439
+ # Setup LocalWP MCP server for AI database access
1440
+ setup_localwp_mcp() {
1441
+ print_info "Setting up LocalWP MCP server..."
1442
+
1443
+ # Check if LocalWP is installed
1444
+ local localwp_found=false
1445
+ if [[ -d "/Applications/Local.app" ]] || [[ -d "$HOME/Applications/Local.app" ]]; then
1446
+ localwp_found=true
1447
+ fi
1448
+
1449
+ if [[ "$localwp_found" != "true" ]]; then
1450
+ print_info "LocalWP not found - skipping MCP server setup"
1451
+ print_info "Install LocalWP from: https://localwp.com/"
1452
+ return 0
1453
+ fi
1454
+
1455
+ print_success "LocalWP found"
1456
+
1457
+ # Check if npm is available
1458
+ if ! command -v npm &> /dev/null; then
1459
+ print_warning "npm not found - cannot install LocalWP MCP server"
1460
+ print_info "Install Node.js and npm first"
1461
+ return 0
1462
+ fi
1463
+
1464
+ # Check if mcp-local-wp is already installed
1465
+ if command -v mcp-local-wp &> /dev/null; then
1466
+ print_success "LocalWP MCP server already installed"
1467
+ return 0
1468
+ fi
1469
+
1470
+ # Offer to install mcp-local-wp
1471
+ print_info "LocalWP MCP server enables AI assistants to query WordPress databases"
1472
+ read -r -p "Install LocalWP MCP server (@verygoodplugins/mcp-local-wp)? (y/n): " install_mcp
1473
+
1474
+ if [[ "$install_mcp" == "y" ]]; then
1475
+ print_info "Installing LocalWP MCP server..."
1476
+ if npm install -g @verygoodplugins/mcp-local-wp > /dev/null 2>&1; then
1477
+ print_success "LocalWP MCP server installed successfully"
1478
+ print_info "Start with: ~/.aidevops/agents/scripts/localhost-helper.sh start-mcp"
1479
+ print_info "Or configure in OpenCode MCP settings for auto-start"
1480
+ else
1481
+ print_warning "Failed to install LocalWP MCP server"
1482
+ print_info "Try manually: npm install -g @verygoodplugins/mcp-local-wp"
1483
+ fi
1484
+ else
1485
+ print_info "Skipped LocalWP MCP server installation"
1486
+ print_info "Install later: npm install -g @verygoodplugins/mcp-local-wp"
1487
+ fi
1488
+
1489
+ return 0
1490
+ }
1491
+
1492
+ # Setup Augment Context Engine MCP
1493
+ setup_augment_context_engine() {
1494
+ print_info "Setting up Augment Context Engine MCP..."
1495
+
1496
+ # Check Node.js version (requires 22+)
1497
+ if ! command -v node &> /dev/null; then
1498
+ print_warning "Node.js not found - Augment Context Engine setup skipped"
1499
+ print_info "Install Node.js 22+ to enable Augment Context Engine"
1500
+ return
1501
+ fi
1502
+
1503
+ local node_version=$(node --version | cut -d'v' -f2 | cut -d'.' -f1)
1504
+ if [[ $node_version -lt 22 ]]; then
1505
+ print_warning "Node.js 22+ required for Augment Context Engine, found v$node_version"
1506
+ print_info "Install: brew install node@22 (macOS) or nvm install 22"
1507
+ return
1508
+ fi
1509
+
1510
+ # Check if auggie is installed
1511
+ if ! command -v auggie &> /dev/null; then
1512
+ print_warning "Auggie CLI not found"
1513
+ print_info "Install with: npm install -g @augmentcode/auggie@prerelease"
1514
+ print_info "Then run: auggie login"
1515
+ return
1516
+ fi
1517
+
1518
+ # Check if logged in
1519
+ if [[ ! -f "$HOME/.augment/session.json" ]]; then
1520
+ print_warning "Auggie not logged in"
1521
+ print_info "Run: auggie login"
1522
+ return
1523
+ fi
1524
+
1525
+ print_success "Auggie CLI found and authenticated"
1526
+
1527
+ # MCP configuration is handled by generate-opencode-agents.sh for OpenCode
1528
+ # Other tools (Cursor, Claude Code, etc.) discover skills via SKILL.md files
1529
+
1530
+ print_info "Augment Context Engine available for tools supporting Agent Skills"
1531
+ print_info "Supported tools: OpenCode, Cursor, Claude Code, VS Code, GitHub Copilot"
1532
+ print_info "Verification: 'What is this project? Please use codebase retrieval tool.'"
1533
+ }
1534
+
1535
+ # Setup osgrep - Local Semantic Search
1536
+ setup_osgrep() {
1537
+ print_info "Setting up osgrep (local semantic search)..."
1538
+
1539
+ # Check Node.js version (requires 18+)
1540
+ if ! command -v node &> /dev/null; then
1541
+ print_warning "Node.js not found - osgrep setup skipped"
1542
+ print_info "Install Node.js 18+ to enable osgrep"
1543
+ return
1544
+ fi
1545
+
1546
+ local node_version
1547
+ node_version=$(node --version | cut -d'v' -f2 | cut -d'.' -f1)
1548
+ if [[ $node_version -lt 18 ]]; then
1549
+ print_warning "Node.js 18+ required for osgrep, found v$node_version"
1550
+ print_info "Install: brew install node@18 (macOS) or nvm install 18"
1551
+ return
1552
+ fi
1553
+
1554
+ # Check if osgrep is installed
1555
+ if ! command -v osgrep &> /dev/null; then
1556
+ print_warning "osgrep CLI not found"
1557
+ print_info "Install with: npm install -g osgrep"
1558
+ print_info "Then run: osgrep setup (downloads ~150MB embedding models)"
1559
+ return
1560
+ fi
1561
+
1562
+ # Check if models are downloaded
1563
+ if [[ ! -d "$HOME/.osgrep" ]]; then
1564
+ print_warning "osgrep models not yet downloaded"
1565
+ print_info "Run: osgrep setup"
1566
+ print_info "This downloads ~150MB of embedding models for local semantic search"
1567
+ else
1568
+ print_success "osgrep CLI found and configured"
1569
+ fi
1570
+
1571
+ # Note about Claude Code integration
1572
+ print_info "osgrep provides 100% local semantic search (no cloud, no auth)"
1573
+ print_info "For Claude Code: osgrep install-claude-code"
1574
+ print_info "Supported tools: OpenCode, Cursor, Gemini CLI, Claude Code, Zed"
1575
+ print_info "Verification: 'Search for authentication handling in this codebase'"
1576
+ }
1577
+
1578
+ # Setup Beads - Task Graph Visualization
1579
+ setup_beads() {
1580
+ print_info "Setting up Beads (task graph visualization)..."
1581
+
1582
+ # Check if Beads CLI (bd) is already installed
1583
+ if command -v bd &> /dev/null; then
1584
+ local bd_version
1585
+ bd_version=$(bd --version 2>/dev/null | head -1 || echo "unknown")
1586
+ print_success "Beads CLI (bd) already installed: $bd_version"
1587
+ else
1588
+ # Try to install via Homebrew first (macOS/Linux with Homebrew)
1589
+ if command -v brew &> /dev/null; then
1590
+ print_info "Installing Beads via Homebrew..."
1591
+ if brew install steveyegge/beads/bd 2>/dev/null; then
1592
+ print_success "Beads CLI installed via Homebrew"
1593
+ else
1594
+ print_warning "Homebrew tap installation failed, trying alternative..."
1595
+ # Try Go install if Go is available
1596
+ if command -v go &> /dev/null; then
1597
+ print_info "Installing Beads via Go..."
1598
+ if go install github.com/steveyegge/beads/cmd/bd@latest 2>/dev/null; then
1599
+ print_success "Beads CLI installed via Go"
1600
+ print_info "Ensure \$GOPATH/bin is in your PATH"
1601
+ else
1602
+ print_warning "Go installation failed"
1603
+ fi
1604
+ fi
1605
+ fi
1606
+ elif command -v go &> /dev/null; then
1607
+ print_info "Installing Beads via Go..."
1608
+ if go install github.com/steveyegge/beads/cmd/bd@latest 2>/dev/null; then
1609
+ print_success "Beads CLI installed via Go"
1610
+ print_info "Ensure \$GOPATH/bin is in your PATH"
1611
+ else
1612
+ print_warning "Go installation failed"
1613
+ fi
1614
+ else
1615
+ # Provide manual installation instructions
1616
+ print_warning "Beads CLI (bd) not installed"
1617
+ echo ""
1618
+ echo " Install options:"
1619
+ echo " macOS/Linux (Homebrew): brew install steveyegge/beads/bd"
1620
+ echo " Go: go install github.com/steveyegge/beads/cmd/bd@latest"
1621
+ echo " Manual: https://github.com/steveyegge/beads/releases"
1622
+ echo ""
1623
+ fi
1624
+ fi
1625
+
1626
+ print_info "Beads provides task graph visualization for TODO.md and PLANS.md"
1627
+ print_info "After installation, run: aidevops init beads"
1628
+
1629
+ # Offer to install optional Beads UI tools
1630
+ setup_beads_ui
1631
+
1632
+ return 0
1633
+ }
1634
+
1635
+ # Setup Beads UI Tools (optional visualization tools)
1636
+ setup_beads_ui() {
1637
+ echo ""
1638
+ print_info "Beads UI tools provide enhanced visualization:"
1639
+ echo " • beads_viewer (Python) - PageRank, critical path, graph analytics"
1640
+ echo " • beads-ui (Node.js) - Web dashboard with live updates"
1641
+ echo " • bdui (Node.js) - React/Ink terminal UI"
1642
+ echo " • perles (Rust) - BQL query language TUI"
1643
+ echo ""
1644
+
1645
+ read -r -p "Install optional Beads UI tools? (y/n): " install_beads_ui
1646
+
1647
+ if [[ "$install_beads_ui" != "y" ]]; then
1648
+ print_info "Skipped Beads UI tools (can install later from beads.md docs)"
1649
+ return 0
1650
+ fi
1651
+
1652
+ local installed_count=0
1653
+
1654
+ # beads_viewer (Python)
1655
+ if command -v pip3 &> /dev/null || command -v pip &> /dev/null; then
1656
+ read -r -p " Install beads_viewer (Python TUI with graph analytics)? (y/n): " install_viewer
1657
+ if [[ "$install_viewer" == "y" ]]; then
1658
+ print_info "Installing beads_viewer..."
1659
+ if pip3 install beads-viewer 2>/dev/null || pip install beads-viewer 2>/dev/null; then
1660
+ print_success "beads_viewer installed"
1661
+ ((installed_count++))
1662
+ else
1663
+ print_warning "Failed to install beads_viewer"
1664
+ fi
1665
+ fi
1666
+ fi
1667
+
1668
+ # beads-ui (Node.js)
1669
+ if command -v npm &> /dev/null; then
1670
+ read -r -p " Install beads-ui (Web dashboard)? (y/n): " install_web
1671
+ if [[ "$install_web" == "y" ]]; then
1672
+ print_info "Installing beads-ui..."
1673
+ if npm install -g beads-ui 2>/dev/null; then
1674
+ print_success "beads-ui installed (run: beads-ui)"
1675
+ ((installed_count++))
1676
+ else
1677
+ print_warning "Failed to install beads-ui"
1678
+ fi
1679
+ fi
1680
+
1681
+ read -r -p " Install bdui (React/Ink TUI)? (y/n): " install_bdui
1682
+ if [[ "$install_bdui" == "y" ]]; then
1683
+ print_info "Installing bdui..."
1684
+ if npm install -g bdui 2>/dev/null; then
1685
+ print_success "bdui installed (run: bdui)"
1686
+ ((installed_count++))
1687
+ else
1688
+ print_warning "Failed to install bdui"
1689
+ fi
1690
+ fi
1691
+ fi
1692
+
1693
+ # perles (Rust)
1694
+ if command -v cargo &> /dev/null; then
1695
+ read -r -p " Install perles (BQL query language TUI)? (y/n): " install_perles
1696
+ if [[ "$install_perles" == "y" ]]; then
1697
+ print_info "Installing perles (this may take a few minutes)..."
1698
+ if cargo install perles 2>/dev/null; then
1699
+ print_success "perles installed (run: perles)"
1700
+ ((installed_count++))
1701
+ else
1702
+ print_warning "Failed to install perles"
1703
+ fi
1704
+ fi
1705
+ fi
1706
+
1707
+ if [[ $installed_count -gt 0 ]]; then
1708
+ print_success "Installed $installed_count Beads UI tool(s)"
1709
+ else
1710
+ print_info "No Beads UI tools installed"
1711
+ fi
1712
+
1713
+ echo ""
1714
+ print_info "Beads UI documentation: ~/.aidevops/agents/tools/task-management/beads.md"
1715
+
1716
+ return 0
1717
+ }
1718
+
1719
+ # Setup Browser Automation Tools (Bun, dev-browser, Playwriter)
1720
+ setup_browser_tools() {
1721
+ print_info "Setting up browser automation tools..."
1722
+
1723
+ local has_bun=false
1724
+ local has_node=false
1725
+
1726
+ # Check Bun
1727
+ if command -v bun &> /dev/null; then
1728
+ has_bun=true
1729
+ print_success "Bun $(bun --version) found"
1730
+ fi
1731
+
1732
+ # Check Node.js (for Playwriter)
1733
+ if command -v node &> /dev/null; then
1734
+ has_node=true
1735
+ fi
1736
+
1737
+ # Install Bun if not present (required for dev-browser)
1738
+ if [[ "$has_bun" == "false" ]]; then
1739
+ print_info "Installing Bun (required for dev-browser)..."
1740
+ if curl -fsSL https://bun.sh/install | bash 2>/dev/null; then
1741
+ # Source the updated PATH
1742
+ export BUN_INSTALL="$HOME/.bun"
1743
+ export PATH="$BUN_INSTALL/bin:$PATH"
1744
+ if command -v bun &> /dev/null; then
1745
+ has_bun=true
1746
+ print_success "Bun installed: $(bun --version)"
1747
+ fi
1748
+ else
1749
+ print_warning "Bun installation failed - dev-browser will need manual setup"
1750
+ fi
1751
+ fi
1752
+
1753
+ # Setup dev-browser if Bun is available
1754
+ if [[ "$has_bun" == "true" ]]; then
1755
+ local dev_browser_dir="$HOME/.aidevops/dev-browser"
1756
+
1757
+ if [[ -d "${dev_browser_dir}/skills/dev-browser" ]]; then
1758
+ print_success "dev-browser already installed"
1759
+ else
1760
+ print_info "Installing dev-browser (stateful browser automation)..."
1761
+ if bash "$AGENTS_DIR/scripts/dev-browser-helper.sh" setup 2>/dev/null; then
1762
+ print_success "dev-browser installed"
1763
+ print_info "Start server with: bash ~/.aidevops/agents/scripts/dev-browser-helper.sh start"
1764
+ else
1765
+ print_warning "dev-browser setup failed - run manually:"
1766
+ print_info " bash ~/.aidevops/agents/scripts/dev-browser-helper.sh setup"
1767
+ fi
1768
+ fi
1769
+ fi
1770
+
1771
+ # Playwriter MCP (Node.js based, runs via npx)
1772
+ if [[ "$has_node" == "true" ]]; then
1773
+ print_success "Playwriter MCP available (runs via npx playwriter@latest)"
1774
+ print_info "Install Chrome extension: https://chromewebstore.google.com/detail/playwriter-mcp/jfeammnjpkecdekppnclgkkffahnhfhe"
1775
+ else
1776
+ print_warning "Node.js not found - Playwriter MCP unavailable"
1777
+ fi
1778
+
1779
+ print_info "Browser tools: dev-browser (stateful), Playwriter (extension), Stagehand (AI)"
1780
+ }
1781
+
1782
+ # Setup AI Orchestration Frameworks (Langflow, CrewAI, AutoGen)
1783
+ setup_ai_orchestration() {
1784
+ print_info "Setting up AI orchestration frameworks..."
1785
+
1786
+ local has_python=false
1787
+
1788
+ # Check Python
1789
+ if command -v python3 &> /dev/null; then
1790
+ local python_version
1791
+ python_version=$(python3 --version 2>&1 | cut -d' ' -f2)
1792
+ local major minor
1793
+ major=$(echo "$python_version" | cut -d. -f1)
1794
+ minor=$(echo "$python_version" | cut -d. -f2)
1795
+
1796
+ if [[ $major -ge 3 ]] && [[ $minor -ge 10 ]]; then
1797
+ has_python=true
1798
+ print_success "Python $python_version found (3.10+ required)"
1799
+ else
1800
+ print_warning "Python 3.10+ required for AI orchestration, found $python_version"
1801
+ fi
1802
+ else
1803
+ print_warning "Python 3 not found - AI orchestration frameworks unavailable"
1804
+ return 0
1805
+ fi
1806
+
1807
+ if [[ "$has_python" == "false" ]]; then
1808
+ return 0
1809
+ fi
1810
+
1811
+ # Create orchestration directory
1812
+ mkdir -p "$HOME/.aidevops/orchestration"
1813
+
1814
+ # Info about available frameworks
1815
+ print_info "AI Orchestration Frameworks available:"
1816
+ echo " - Langflow: Visual flow builder (localhost:7860)"
1817
+ echo " - CrewAI: Multi-agent teams (localhost:8501)"
1818
+ echo " - AutoGen: Microsoft agentic AI (localhost:8081)"
1819
+ echo ""
1820
+ print_info "Setup individual frameworks with:"
1821
+ echo " bash .agent/scripts/langflow-helper.sh setup"
1822
+ echo " bash .agent/scripts/crewai-helper.sh setup"
1823
+ echo " bash .agent/scripts/autogen-helper.sh setup"
1824
+ echo ""
1825
+ print_info "See .agent/tools/ai-orchestration/overview.md for comparison"
1826
+
1827
+ return 0
1828
+ }
1829
+
1830
+ # Setup OpenCode Plugins (Antigravity OAuth)
1831
+ # Helper function to add/update a single plugin in OpenCode config
1832
+ add_opencode_plugin() {
1833
+ local plugin_name="$1"
1834
+ local plugin_spec="$2"
1835
+ local opencode_config="$3"
1836
+
1837
+ # Check if plugin array exists and if plugin is already configured
1838
+ local has_plugin_array
1839
+ has_plugin_array=$(jq -e '.plugin' "$opencode_config" 2>/dev/null && echo "true" || echo "false")
1840
+
1841
+ if [[ "$has_plugin_array" == "true" ]]; then
1842
+ # Check if plugin is already in the array
1843
+ local plugin_exists
1844
+ plugin_exists=$(jq -e --arg p "$plugin_name" '.plugin | map(select(startswith($p))) | length > 0' "$opencode_config" 2>/dev/null && echo "true" || echo "false")
1845
+
1846
+ if [[ "$plugin_exists" == "true" ]]; then
1847
+ # Update existing plugin to latest version
1848
+ local temp_file
1849
+ temp_file=$(mktemp)
1850
+ jq --arg old "$plugin_name" --arg new "$plugin_spec" \
1851
+ '.plugin = [.plugin[] | if startswith($old) then $new else . end]' \
1852
+ "$opencode_config" > "$temp_file" && mv "$temp_file" "$opencode_config"
1853
+ print_success "Updated $plugin_name to latest version"
1854
+ else
1855
+ # Add plugin to existing array
1856
+ local temp_file
1857
+ temp_file=$(mktemp)
1858
+ jq --arg p "$plugin_spec" '.plugin += [$p]' "$opencode_config" > "$temp_file" && mv "$temp_file" "$opencode_config"
1859
+ print_success "Added $plugin_name plugin to OpenCode config"
1860
+ fi
1861
+ else
1862
+ # Create plugin array with the plugin
1863
+ local temp_file
1864
+ temp_file=$(mktemp)
1865
+ jq --arg p "$plugin_spec" '. + {plugin: [$p]}' "$opencode_config" > "$temp_file" && mv "$temp_file" "$opencode_config"
1866
+ print_success "Created plugin array with $plugin_name"
1867
+ fi
1868
+ }
1869
+
1870
+ setup_opencode_plugins() {
1871
+ print_info "Setting up OpenCode plugins..."
1872
+
1873
+ local opencode_config="$HOME/.config/opencode/opencode.json"
1874
+
1875
+ # Check if OpenCode is installed
1876
+ if ! command -v opencode &> /dev/null; then
1877
+ print_warning "OpenCode not found - plugin setup skipped"
1878
+ print_info "Install OpenCode first: https://opencode.ai"
1879
+ return 0
1880
+ fi
1881
+
1882
+ # Check if config exists
1883
+ if [[ ! -f "$opencode_config" ]]; then
1884
+ print_warning "OpenCode config not found at $opencode_config - plugin setup skipped"
1885
+ return 0
1886
+ fi
1887
+
1888
+ # Check if jq is available
1889
+ if ! command -v jq &> /dev/null; then
1890
+ print_warning "jq not found - cannot update OpenCode config"
1891
+ return 0
1892
+ fi
1893
+
1894
+ # Setup Antigravity OAuth plugin (Google OAuth)
1895
+ print_info "Setting up Antigravity OAuth plugin..."
1896
+ add_opencode_plugin "opencode-antigravity-auth" "opencode-antigravity-auth@latest" "$opencode_config"
1897
+
1898
+ print_info "Antigravity OAuth plugin enables Google OAuth for OpenCode"
1899
+ print_info "Models available: gemini-3-pro-high, claude-opus-4-5-thinking, etc."
1900
+ print_info "See: https://github.com/NoeFabris/opencode-antigravity-auth"
1901
+ echo ""
1902
+
1903
+ # Setup Anthropic OAuth plugin (Claude OAuth)
1904
+ print_info "Setting up Anthropic OAuth plugin..."
1905
+ add_opencode_plugin "opencode-anthropic-auth" "opencode-anthropic-auth@latest" "$opencode_config"
1906
+
1907
+ print_info "Anthropic OAuth plugin enables Claude Pro/Max authentication"
1908
+ print_info "Zero cost for Claude subscribers, auto token refresh, beta features"
1909
+ print_info "See: https://github.com/anomalyco/opencode-anthropic-auth"
1910
+ echo ""
1911
+
1912
+ print_info "After setup, authenticate with: opencode auth login"
1913
+ print_info " • For Google OAuth: Select 'Google' → 'OAuth with Google (Antigravity)'"
1914
+ print_info " • For Claude OAuth: Select 'Anthropic' → 'Claude Pro/Max'"
1915
+
1916
+ return 0
1917
+ }
1918
+
1919
+ # Setup Oh-My-OpenCode Plugin (coding productivity features)
1920
+ setup_oh_my_opencode() {
1921
+ print_info "Setting up Oh-My-OpenCode plugin..."
1922
+
1923
+ local opencode_config="$HOME/.config/opencode/opencode.json"
1924
+
1925
+ # Check if OpenCode is installed
1926
+ if ! command -v opencode &> /dev/null; then
1927
+ print_warning "OpenCode not found - Oh-My-OpenCode setup skipped"
1928
+ return 0
1929
+ fi
1930
+
1931
+ # Check if config exists
1932
+ if [[ ! -f "$opencode_config" ]]; then
1933
+ print_warning "OpenCode config not found - Oh-My-OpenCode setup skipped"
1934
+ return 0
1935
+ fi
1936
+
1937
+ # Check if jq is available
1938
+ if ! command -v jq &> /dev/null; then
1939
+ print_warning "jq not found - cannot update OpenCode config"
1940
+ return 0
1941
+ fi
1942
+
1943
+ echo ""
1944
+ print_info "Oh-My-OpenCode adds coding productivity features:"
1945
+ echo " • Async background agents (parallel task execution)"
1946
+ echo " • LSP tools (11 tools: hover, goto, references, rename, etc.)"
1947
+ echo " • AST-Grep (semantic code search/replace)"
1948
+ echo " • Curated agents (OmO, Oracle, Librarian, Explore, Frontend)"
1949
+ echo " • Claude Code compatibility (hooks, commands, skills)"
1950
+ echo " • Context window monitoring and session recovery"
1951
+ echo ""
1952
+ echo " Note: aidevops provides DevOps infrastructure (hosting, DNS, WordPress, SEO)"
1953
+ echo " Oh-My-OpenCode provides coding productivity (LSP, AST, background agents)"
1954
+ echo " They are complementary and work well together."
1955
+ echo ""
1956
+
1957
+ read -r -p "Install Oh-My-OpenCode plugin? (y/n): " install_omo
1958
+
1959
+ if [[ "$install_omo" != "y" ]]; then
1960
+ print_info "Skipped Oh-My-OpenCode installation"
1961
+ return 0
1962
+ fi
1963
+
1964
+ local plugin_name="oh-my-opencode"
1965
+
1966
+ # Check if plugin array exists
1967
+ local has_plugin_array
1968
+ has_plugin_array=$(jq -e '.plugin' "$opencode_config" 2>/dev/null && echo "true" || echo "false")
1969
+
1970
+ if [[ "$has_plugin_array" == "true" ]]; then
1971
+ # Check if plugin is already in the array
1972
+ local plugin_exists
1973
+ plugin_exists=$(jq -e --arg p "$plugin_name" '.plugin | map(select(. == $p or startswith($p + "@"))) | length > 0' "$opencode_config" 2>/dev/null && echo "true" || echo "false")
1974
+
1975
+ if [[ "$plugin_exists" == "true" ]]; then
1976
+ print_info "Oh-My-OpenCode already configured"
1977
+ else
1978
+ # Add plugin to existing array
1979
+ local temp_file
1980
+ temp_file=$(mktemp)
1981
+ jq --arg p "$plugin_name" '.plugin += [$p]' "$opencode_config" > "$temp_file" && mv "$temp_file" "$opencode_config"
1982
+ print_success "Added Oh-My-OpenCode plugin to OpenCode config"
1983
+ fi
1984
+ else
1985
+ # Create plugin array with the plugin
1986
+ local temp_file
1987
+ temp_file=$(mktemp)
1988
+ jq --arg p "$plugin_name" '. + {plugin: [$p]}' "$opencode_config" > "$temp_file" && mv "$temp_file" "$opencode_config"
1989
+ print_success "Created plugin array with Oh-My-OpenCode"
1990
+ fi
1991
+
1992
+ # Create oh-my-opencode config if it doesn't exist
1993
+ local omo_config="$HOME/.config/opencode/oh-my-opencode.json"
1994
+ if [[ ! -f "$omo_config" ]]; then
1995
+ print_info "Creating Oh-My-OpenCode configuration..."
1996
+ cat > "$omo_config" << 'EOF'
1997
+ {
1998
+ "$schema": "https://raw.githubusercontent.com/code-yeongyu/oh-my-opencode/master/assets/oh-my-opencode.schema.json",
1999
+ "google_auth": false,
2000
+ "disabled_mcps": ["context7"],
2001
+ "agents": {}
2002
+ }
2003
+ EOF
2004
+ print_success "Created $omo_config"
2005
+ print_info "Note: context7 MCP disabled in OmO (aidevops configures it separately)"
2006
+ fi
2007
+
2008
+ print_success "Oh-My-OpenCode plugin configured"
2009
+ echo ""
2010
+ print_info "Oh-My-OpenCode features now available:"
2011
+ echo " • Type 'ultrawork' or 'ulw' for maximum performance mode"
2012
+ echo " • Background agents run in parallel"
2013
+ echo " • LSP tools: lsp_hover, lsp_goto_definition, lsp_rename, etc."
2014
+ echo " • AST-Grep: ast_grep_search, ast_grep_replace"
2015
+ echo ""
2016
+ print_info "Curated agents (use @agent-name):"
2017
+ echo " • @oracle - Architecture, code review (GPT 5.2)"
2018
+ echo " • @librarian - Docs lookup, GitHub examples (Sonnet 4.5)"
2019
+ echo " • @explore - Fast codebase exploration (Grok)"
2020
+ echo " • @frontend-ui-ux-engineer - UI development (Gemini 3 Pro)"
2021
+ echo ""
2022
+ print_info "Documentation: https://github.com/code-yeongyu/oh-my-opencode"
2023
+
2024
+ return 0
2025
+ }
2026
+
2027
+ setup_seo_mcps() {
2028
+ print_info "Setting up SEO MCP servers..."
2029
+
2030
+ local has_node=false
2031
+ local has_python=false
2032
+ local has_uv=false
2033
+
2034
+ # Check Node.js
2035
+ if command -v node &> /dev/null; then
2036
+ has_node=true
2037
+ fi
2038
+
2039
+ # Check Python
2040
+ if command -v python3 &> /dev/null; then
2041
+ has_python=true
2042
+ fi
2043
+
2044
+ # Check uv (Python package manager)
2045
+ if command -v uv &> /dev/null; then
2046
+ has_uv=true
2047
+ elif command -v uvx &> /dev/null; then
2048
+ has_uv=true
2049
+ fi
2050
+
2051
+ # DataForSEO MCP (Node.js based)
2052
+ if [[ "$has_node" == "true" ]]; then
2053
+ print_info "DataForSEO MCP available via: npx dataforseo-mcp-server"
2054
+ print_info "Configure credentials in ~/.config/aidevops/mcp-env.sh:"
2055
+ print_info " DATAFORSEO_USERNAME and DATAFORSEO_PASSWORD"
2056
+ else
2057
+ print_warning "Node.js not found - DataForSEO MCP requires Node.js"
2058
+ fi
2059
+
2060
+ # Serper MCP (Python based, uses uv/uvx)
2061
+ if [[ "$has_uv" == "true" ]]; then
2062
+ print_info "Serper MCP available via: uvx serper-mcp-server"
2063
+ print_info "Configure credentials in ~/.config/aidevops/mcp-env.sh:"
2064
+ print_info " SERPER_API_KEY"
2065
+ elif [[ "$has_python" == "true" ]]; then
2066
+ print_info "Serper MCP available via: pip install serper-mcp-server"
2067
+ print_info "Then run: python3 -m serper_mcp_server"
2068
+ print_info "Configure credentials in ~/.config/aidevops/mcp-env.sh:"
2069
+ print_info " SERPER_API_KEY"
2070
+
2071
+ # Offer to install uv for better experience
2072
+ read -r -p "Install uv (recommended Python package manager)? (y/n): " install_uv
2073
+ if [[ "$install_uv" == "y" ]]; then
2074
+ print_info "Installing uv..."
2075
+ curl -LsSf https://astral.sh/uv/install.sh | sh
2076
+ if [[ $? -eq 0 ]]; then
2077
+ print_success "uv installed successfully"
2078
+ print_info "Restart your terminal or run: source ~/.bashrc (or ~/.zshrc)"
2079
+ else
2080
+ print_warning "Failed to install uv"
2081
+ fi
2082
+ fi
2083
+ else
2084
+ print_warning "Python not found - Serper MCP requires Python 3.11+"
2085
+ fi
2086
+
2087
+ # Check if credentials are configured
2088
+ if [[ -f "$HOME/.config/aidevops/mcp-env.sh" ]]; then
2089
+ # shellcheck source=/dev/null
2090
+ source "$HOME/.config/aidevops/mcp-env.sh"
2091
+
2092
+ if [[ -n "$DATAFORSEO_USERNAME" && -n "$DATAFORSEO_PASSWORD" ]]; then
2093
+ print_success "DataForSEO credentials configured"
2094
+ else
2095
+ print_info "DataForSEO: Set credentials with:"
2096
+ print_info " bash ~/.aidevops/agents/scripts/setup-local-api-keys.sh set DATAFORSEO_USERNAME your_username"
2097
+ print_info " bash ~/.aidevops/agents/scripts/setup-local-api-keys.sh set DATAFORSEO_PASSWORD your_password"
2098
+ fi
2099
+
2100
+ if [[ -n "$SERPER_API_KEY" ]]; then
2101
+ print_success "Serper API key configured"
2102
+ else
2103
+ print_info "Serper: Set API key with:"
2104
+ print_info " bash ~/.aidevops/agents/scripts/setup-local-api-keys.sh set SERPER_API_KEY your_key"
2105
+ fi
2106
+ else
2107
+ print_info "Configure SEO API credentials:"
2108
+ print_info " bash ~/.aidevops/agents/scripts/setup-local-api-keys.sh setup"
2109
+ fi
2110
+
2111
+ print_info "SEO MCP documentation: ~/.aidevops/agents/seo/"
2112
+ return 0
2113
+ }
2114
+
2115
+ # Check for tool updates after setup
2116
+ check_tool_updates() {
2117
+ print_info "Checking for tool updates..."
2118
+
2119
+ local tool_check_script="$HOME/.aidevops/agents/scripts/tool-version-check.sh"
2120
+
2121
+ if [[ ! -f "$tool_check_script" ]]; then
2122
+ # Try local script if deployed version not available yet
2123
+ tool_check_script=".agent/scripts/tool-version-check.sh"
2124
+ fi
2125
+
2126
+ if [[ ! -f "$tool_check_script" ]]; then
2127
+ print_warning "Tool version check script not found - skipping update check"
2128
+ return 0
2129
+ fi
2130
+
2131
+ # Run the check in quiet mode first to see if there are updates
2132
+ # Capture both output and exit code
2133
+ local outdated_output
2134
+ local check_exit_code
2135
+ outdated_output=$(bash "$tool_check_script" --quiet 2>&1) || check_exit_code=$?
2136
+ check_exit_code=${check_exit_code:-0}
2137
+
2138
+ # If the script failed, warn and continue
2139
+ if [[ $check_exit_code -ne 0 ]]; then
2140
+ print_warning "Tool version check encountered an error (exit code: $check_exit_code)"
2141
+ print_info "Run 'aidevops update-tools' manually to check for updates"
2142
+ return 0
2143
+ fi
2144
+
2145
+ if [[ -z "$outdated_output" ]]; then
2146
+ print_success "All tools are up to date!"
2147
+ return 0
2148
+ fi
2149
+
2150
+ # Show what's outdated
2151
+ echo ""
2152
+ print_warning "Some tools have updates available:"
2153
+ echo ""
2154
+ bash "$tool_check_script" --quiet
2155
+ echo ""
2156
+
2157
+ read -r -p "Update all outdated tools now? (y/n): " do_update
2158
+
2159
+ if [[ "$do_update" == "y" || "$do_update" == "Y" ]]; then
2160
+ print_info "Updating tools..."
2161
+ bash "$tool_check_script" --update
2162
+ print_success "Tool updates complete!"
2163
+ else
2164
+ print_info "Skipped tool updates"
2165
+ print_info "Run 'aidevops update-tools' anytime to update tools"
2166
+ fi
2167
+
2168
+ return 0
2169
+ }
2170
+
2171
+ # Parse command line arguments
2172
+ parse_args() {
2173
+ while [[ $# -gt 0 ]]; do
2174
+ case "$1" in
2175
+ --clean)
2176
+ CLEAN_MODE=true
2177
+ shift
2178
+ ;;
2179
+ --interactive|-i)
2180
+ INTERACTIVE_MODE=true
2181
+ shift
2182
+ ;;
2183
+ --update|-u)
2184
+ UPDATE_TOOLS_MODE=true
2185
+ shift
2186
+ ;;
2187
+ --help|-h)
2188
+ echo "Usage: ./setup.sh [OPTIONS]"
2189
+ echo ""
2190
+ echo "Options:"
2191
+ echo " --clean Remove stale files before deploying (cleans ~/.aidevops/agents/)"
2192
+ echo " --interactive Ask confirmation before each step"
2193
+ echo " -i Short for --interactive"
2194
+ echo " --update Check for and offer to update outdated tools after setup"
2195
+ echo " -u Short for --update"
2196
+ echo " --help Show this help message"
2197
+ echo ""
2198
+ echo "Default behavior adds/overwrites files without removing deleted agents."
2199
+ echo "Use --clean after removing or renaming agents to sync deletions."
2200
+ echo "Use --interactive to control each step individually."
2201
+ echo "Use --update to check for tool updates after setup completes."
2202
+ exit 0
2203
+ ;;
2204
+ *)
2205
+ print_error "Unknown option: $1"
2206
+ echo "Use --help for usage information"
2207
+ exit 1
2208
+ ;;
2209
+ esac
2210
+ done
2211
+ }
2212
+
2213
+ # Main setup function
2214
+ main() {
2215
+ # Bootstrap first (handles curl install)
2216
+ bootstrap_repo "$@"
2217
+
2218
+ parse_args "$@"
2219
+
2220
+ echo "🤖 AI DevOps Framework Setup"
2221
+ echo "============================="
2222
+ if [[ "$CLEAN_MODE" == "true" ]]; then
2223
+ echo "Mode: Clean (removing stale files)"
2224
+ fi
2225
+ if [[ "$INTERACTIVE_MODE" == "true" ]]; then
2226
+ echo "Mode: Interactive (confirm each step)"
2227
+ echo ""
2228
+ echo "Controls: [Y]es (default) / [n]o skip / [q]uit"
2229
+ fi
2230
+ if [[ "$UPDATE_TOOLS_MODE" == "true" ]]; then
2231
+ echo "Mode: Update (will check for tool updates after setup)"
2232
+ fi
2233
+ echo ""
2234
+
2235
+ # Required steps (always run)
2236
+ verify_location
2237
+ check_requirements
2238
+
2239
+ # Optional steps with confirmation in interactive mode
2240
+ confirm_step "Check optional dependencies (bun, node, python)" && check_optional_deps
2241
+ confirm_step "Setup recommended tools (Tabby, Zed, etc.)" && setup_recommended_tools
2242
+ confirm_step "Setup Git CLIs (gh, glab, tea)" && setup_git_clis
2243
+ confirm_step "Setup SSH key" && setup_ssh_key
2244
+ confirm_step "Setup configuration files" && setup_configs
2245
+ confirm_step "Set secure permissions on config files" && set_permissions
2246
+ confirm_step "Install aidevops CLI command" && install_aidevops_cli
2247
+ confirm_step "Setup shell aliases" && setup_aliases
2248
+ confirm_step "Setup terminal title integration" && setup_terminal_title
2249
+ confirm_step "Deploy AI templates to home directories" && deploy_ai_templates
2250
+ confirm_step "Migrate old backups to new structure" && migrate_old_backups
2251
+ confirm_step "Migrate loop state from .claude/ to .agent/loop-state/" && migrate_loop_state_directories
2252
+ confirm_step "Cleanup deprecated agent paths" && cleanup_deprecated_paths
2253
+ confirm_step "Extract OpenCode prompts" && extract_opencode_prompts
2254
+ confirm_step "Deploy aidevops agents to ~/.aidevops/agents/" && deploy_aidevops_agents
2255
+ confirm_step "Generate agent skills (SKILL.md files)" && generate_agent_skills
2256
+ confirm_step "Inject agents reference into AI configs" && inject_agents_reference
2257
+ confirm_step "Update OpenCode configuration" && update_opencode_config
2258
+ confirm_step "Setup Python environment (DSPy, crawl4ai)" && setup_python_env
2259
+ confirm_step "Setup Node.js environment" && setup_nodejs_env
2260
+ confirm_step "Setup LocalWP MCP server" && setup_localwp_mcp
2261
+ confirm_step "Setup Augment Context Engine MCP" && setup_augment_context_engine
2262
+ confirm_step "Setup osgrep (local semantic search)" && setup_osgrep
2263
+ confirm_step "Setup Beads task management" && setup_beads
2264
+ confirm_step "Setup SEO MCP servers (DataForSEO, Serper)" && setup_seo_mcps
2265
+ confirm_step "Setup browser automation tools" && setup_browser_tools
2266
+ confirm_step "Setup AI orchestration frameworks info" && setup_ai_orchestration
2267
+ confirm_step "Setup OpenCode plugins" && setup_opencode_plugins
2268
+ confirm_step "Setup Oh-My-OpenCode" && setup_oh_my_opencode
2269
+
2270
+ echo ""
2271
+ print_success "🎉 Setup complete!"
2272
+ echo ""
2273
+ echo "CLI Command:"
2274
+ echo " aidevops init - Initialize aidevops in a project"
2275
+ echo " aidevops features - List available features"
2276
+ echo " aidevops status - Check installation status"
2277
+ echo " aidevops update - Update to latest version"
2278
+ echo " aidevops update-tools - Check for and update installed tools"
2279
+ echo " aidevops uninstall - Remove aidevops"
2280
+ echo ""
2281
+ echo "Deployed to:"
2282
+ echo " ~/.aidevops/agents/ - Agent files (main agents, subagents, scripts)"
2283
+ echo " ~/.aidevops/*-backups/ - Backups with rotation (keeps last $BACKUP_KEEP_COUNT)"
2284
+ echo ""
2285
+ echo "Next steps:"
2286
+ echo "1. Edit configuration files in configs/ with your actual credentials"
2287
+ echo "2. Setup Git CLI tools and authentication (shown during setup)"
2288
+ echo "3. Setup API keys: bash .agent/scripts/setup-local-api-keys.sh setup"
2289
+ echo "4. Test access: ./.agent/scripts/servers-helper.sh list"
2290
+ echo "5. Read documentation: ~/.aidevops/agents/AGENTS.md"
2291
+ echo ""
2292
+ echo "For development on aidevops framework itself:"
2293
+ echo " See ~/Git/aidevops/AGENTS.md"
2294
+ echo ""
2295
+ echo "OpenCode Primary Agents (12 total, Tab to switch):"
2296
+ echo "• Plan+ - Enhanced planning with context tools (read-only)"
2297
+ echo "• Build+ - Enhanced build with context tools (full access)"
2298
+ echo "• Accounts, AI-DevOps, Content, Health, Legal, Marketing,"
2299
+ echo " Research, Sales, SEO, WordPress"
2300
+ echo ""
2301
+ echo "Agent Skills (SKILL.md) - Cross-tool compatibility:"
2302
+ echo "• Cursor, Claude Code, VS Code, GitHub Copilot auto-discover skills"
2303
+ echo "• 21 SKILL.md files generated in ~/.aidevops/agents/"
2304
+ echo "• Skills include: wordpress, seo, aidevops, build-mcp, and more"
2305
+ echo ""
2306
+ echo "MCP Integrations (OpenCode):"
2307
+ echo "• Augment Context Engine - Cloud semantic codebase retrieval"
2308
+ echo "• Context7 - Real-time library documentation"
2309
+ echo "• osgrep - Local semantic search (100% private)"
2310
+ echo "• DataForSEO - Comprehensive SEO data APIs"
2311
+ echo "• Serper - Google Search API"
2312
+ echo ""
2313
+ echo "DSPy & DSPyGround Integration:"
2314
+ echo "• ./.agent/scripts/dspy-helper.sh - DSPy prompt optimization toolkit"
2315
+ echo "• ./.agent/scripts/dspyground-helper.sh - DSPyGround playground interface"
2316
+ echo "• python-env/dspy-env/ - Python virtual environment for DSPy"
2317
+ echo "• data/dspy/ - DSPy projects and datasets"
2318
+ echo "• data/dspyground/ - DSPyGround projects and configurations"
2319
+ echo ""
2320
+ echo "Task Management:"
2321
+ echo "• Beads CLI (bd) - Task graph visualization"
2322
+ echo "• beads-sync-helper.sh - Sync TODO.md/PLANS.md with Beads"
2323
+ echo "• todo-ready.sh - Show tasks with no open blockers"
2324
+ echo "• Run: aidevops init beads - Initialize Beads in a project"
2325
+ echo ""
2326
+ echo "Security reminders:"
2327
+ echo "- Never commit configuration files with real credentials"
2328
+ echo "- Use strong passwords and enable MFA on all accounts"
2329
+ echo "- Regularly rotate API tokens and SSH keys"
2330
+ echo ""
2331
+ echo "Happy server managing! 🚀"
2332
+ echo ""
2333
+
2334
+ # Check for tool updates if --update flag was passed
2335
+ if [[ "$UPDATE_TOOLS_MODE" == "true" ]]; then
2336
+ echo ""
2337
+ check_tool_updates
2338
+ fi
2339
+
2340
+ # Offer to launch onboarding for new users (only if not running inside OpenCode)
2341
+ if [[ -z "${OPENCODE_SESSION:-}" ]] && command -v opencode &>/dev/null; then
2342
+ echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
2343
+ echo ""
2344
+ echo "🎯 Ready to configure your services?"
2345
+ echo ""
2346
+ echo "Launch OpenCode with the onboarding wizard to:"
2347
+ echo " • See which services are already configured"
2348
+ echo " • Get personalized recommendations based on your work"
2349
+ echo " • Set up API keys and credentials interactively"
2350
+ echo ""
2351
+ read -r -p "Launch OpenCode with /onboarding now? (y/n): " launch_onboarding
2352
+ if [[ "$launch_onboarding" == "y" || "$launch_onboarding" == "Y" ]]; then
2353
+ echo ""
2354
+ echo "Starting OpenCode..."
2355
+ opencode --prompt "/onboarding"
2356
+ else
2357
+ echo ""
2358
+ echo "You can run /onboarding anytime in OpenCode to configure services."
2359
+ fi
2360
+ fi
2361
+
2362
+ return 0
2363
+ }
2364
+
2365
+ # Run setup
2366
+ main "$@"