Add OpenCode and Tidewave CLI support

- OpenCode: Open-source AI coding assistant (npm install -g opencode-ai)
  Supports multiple LLM providers including OpenAI, Anthropic, Gemini

- Tidewave: Elixir/Phoenix MCP server for AI-powered development
  Downloads binary from GitHub releases with ELF validation
  Enables runtime introspection, SQL queries, and code evaluation

Both tools are optional components in the interactive installer.
Tidewave is automatically skipped if Erlang is not selected.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
guessthepw 2026-01-25 12:16:06 -05:00
parent 63bcc0aea3
commit 2861664a03
3 changed files with 91 additions and 10 deletions

View file

@ -5,6 +5,13 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
## [0.10.0] - 2025-01-25
### Added
- OpenCode: Open-source AI coding assistant with multi-provider support
- Tidewave CLI: Elixir/Phoenix MCP server for AI-powered development
- New component selection options for OpenCode and Tidewave
## [0.9.1] - 2025-01-25 ## [0.9.1] - 2025-01-25
### Fixed ### Fixed

View file

@ -70,7 +70,9 @@ All components are optional — deselect what you don't need in the interactive
| Playwright | latest | Browser testing framework | | Playwright | latest | Browser testing framework |
| PostgreSQL | system default | Database | | PostgreSQL | system default | Database |
| Ollama | latest | Local LLM inference | | Ollama | latest | Local LLM inference |
| Claude Code | latest | AI coding assistant | | Claude Code | latest | AI coding assistant (Anthropic) |
| OpenCode | latest | Open-source AI coding assistant (multi-provider) |
| Tidewave | latest | Elixir/Phoenix MCP server for AI tools |
| yq | latest | YAML processor | | yq | latest | YAML processor |
| watchexec | latest | File watcher (via cargo) | | watchexec | latest | File watcher (via cargo) |
| TigerVNC + XFCE | system | VNC access for browser login flows | | TigerVNC + XFCE | system | VNC access for browser login flows |

View file

@ -284,7 +284,7 @@ if [[ "$(uname -s)" == "Darwin" ]]; then
# ---- Interactive component selection ---- # ---- Interactive component selection ----
# Component IDs and descriptions # Component IDs and descriptions
COMP_IDS=(postgresql mise node erlang chromium vnc ollama claude playwright plugins) COMP_IDS=(postgresql mise node erlang chromium vnc ollama claude opencode playwright plugins)
COMP_NAMES=( COMP_NAMES=(
"PostgreSQL" "PostgreSQL"
"mise" "mise"
@ -294,20 +294,22 @@ if [[ "$(uname -s)" == "Darwin" ]]; then
"VNC + XFCE" "VNC + XFCE"
"Ollama" "Ollama"
"Claude Code" "Claude Code"
"OpenCode"
"Playwright" "Playwright"
"Claude Plugins" "Claude Plugins + Tidewave"
) )
COMP_DESCS=( COMP_DESCS=(
"Database server for local development" "Database server for local development"
"Version manager for Node.js, Erlang, Elixir" "Version manager for Node.js, Erlang, Elixir"
"JavaScript runtime (required for Claude Code)" "JavaScript runtime (required for Claude/OpenCode)"
"BEAM VM + Elixir functional language" "BEAM VM + Elixir functional language"
"Browser for automation and testing" "Browser for automation and testing"
"Remote desktop for browser-based login flows" "Remote desktop for browser-based login flows"
"Local LLM runner for offline inference" "Local LLM runner for offline inference"
"AI coding assistant CLI from Anthropic" "AI coding assistant CLI from Anthropic"
"Open-source AI coding assistant (multi-provider)"
"Browser testing and automation framework" "Browser testing and automation framework"
"Code review, feature dev, browser automation plugins" "Code review, Tidewave MCP, browser automation"
) )
# All selected by default # All selected by default
@ -1077,6 +1079,54 @@ install_playwright() {
fi fi
} }
install_opencode() {
export PATH="$HOME/.local/share/mise/shims:$HOME/.local/bin:$PATH"
if command_exists opencode; then
echo "OpenCode already installed"
return 0
fi
npm install -g opencode-ai
}
install_tidewave() {
if command_exists tidewave; then
echo "Tidewave already installed"
return 0
fi
# Download Tidewave CLI binary
local arch
arch=$(detect_architecture)
local tidewave_arch=""
case "$arch" in
amd64) tidewave_arch="x86_64-unknown-linux-gnu" ;;
arm64) tidewave_arch="aarch64-unknown-linux-gnu" ;;
esac
# Get latest release URL from GitHub
local release_url="https://github.com/tidewave-ai/tidewave/releases/latest/download/tidewave-${tidewave_arch}"
# Security: Download to temp file first, validate, then install
local temp_file
temp_file=$(mktemp)
if curl -fsSL "$release_url" -o "$temp_file"; then
# Verify it's an executable (ELF binary)
if file "$temp_file" | grep -q "ELF"; then
sudo mv "$temp_file" /usr/local/bin/tidewave
sudo chmod +x /usr/local/bin/tidewave
echo "Tidewave CLI installed"
else
log_error "Downloaded tidewave is not a valid binary"
rm -f "$temp_file"
return 1
fi
else
log_error "Failed to download Tidewave CLI"
rm -f "$temp_file"
return 1
fi
}
install_plugins() { install_plugins() {
export PATH="$HOME/.local/share/mise/shims:$HOME/.local/bin:$PATH" export PATH="$HOME/.local/share/mise/shims:$HOME/.local/bin:$PATH"
mkdir -p ~/.config/claude mkdir -p ~/.config/claude
@ -1096,6 +1146,12 @@ install_plugins() {
echo "Adding MCP servers..." echo "Adding MCP servers..."
claude mcp add playwright --scope user -- npx @anthropic-ai/mcp-server-playwright 2>/dev/null || true claude mcp add playwright --scope user -- npx @anthropic-ai/mcp-server-playwright 2>/dev/null || true
claude mcp add superpowers-chrome --scope user -- npx github:obra/superpowers-chrome --headless 2>/dev/null || true claude mcp add superpowers-chrome --scope user -- npx github:obra/superpowers-chrome --headless 2>/dev/null || true
# Note: Tidewave MCP is configured per-project when running a Phoenix app
# Use: claude mcp add --transport http tidewave http://localhost:4000/tidewave/mcp
echo ""
echo "Tidewave MCP: Add per-project with your Phoenix app running:"
echo " claude mcp add --transport http tidewave http://localhost:PORT/tidewave/mcp"
} }
install_base_deps() { install_base_deps() {
@ -1246,6 +1302,8 @@ register_step "chromium" "Chromium browser"
register_step "vnc" "VNC server + XFCE desktop" register_step "vnc" "VNC server + XFCE desktop"
register_step "ollama" "Ollama local LLM runner" register_step "ollama" "Ollama local LLM runner"
register_step "claude" "Claude Code CLI" register_step "claude" "Claude Code CLI"
register_step "opencode" "OpenCode CLI"
register_step "tidewave" "Tidewave CLI (Elixir MCP)"
register_step "playwright" "Playwright browser automation" register_step "playwright" "Playwright browser automation"
register_step "plugins" "Claude Code plugins" register_step "plugins" "Claude Code plugins"
@ -1258,16 +1316,21 @@ should_skip "chromium" && skip_step "chromium"
should_skip "vnc" && skip_step "vnc" should_skip "vnc" && skip_step "vnc"
should_skip "ollama" && skip_step "ollama" should_skip "ollama" && skip_step "ollama"
should_skip "claude" && skip_step "claude" should_skip "claude" && skip_step "claude"
should_skip "opencode" && skip_step "opencode"
should_skip "playwright" && skip_step "playwright" should_skip "playwright" && skip_step "playwright"
should_skip "plugins" && skip_step "plugins" should_skip "plugins" && skip_step "plugins"
# Elixir skipped if Erlang skipped # Elixir skipped if Erlang skipped
[ "${STEP_STATUS[erlang]}" = "skipped" ] && skip_step "elixir" [ "${STEP_STATUS[erlang]}" = "skipped" ] && skip_step "elixir"
# Claude/Playwright skipped if Node skipped # Tidewave skipped if Erlang skipped (it's for Phoenix/Elixir projects)
[ "${STEP_STATUS[erlang]}" = "skipped" ] && skip_step "tidewave"
# Claude/OpenCode/Playwright skipped if Node skipped
if [ "${STEP_STATUS[node]}" = "skipped" ]; then if [ "${STEP_STATUS[node]}" = "skipped" ]; then
[ "${STEP_STATUS[mise]}" = "skipped" ] || true # mise can still install [ "${STEP_STATUS[mise]}" = "skipped" ] || true # mise can still install
skip_step "claude" skip_step "claude"
skip_step "opencode"
skip_step "playwright" skip_step "playwright"
skip_step "plugins" skip_step "plugins"
fi fi
@ -1315,11 +1378,14 @@ if [ "${STEP_STATUS[mise]}" = "done" ]; then
fi fi
# ============================================================================ # ============================================================================
# Phase 4: Elixir + Claude + Playwright (Elixir needs Erlang, others need Node) # Phase 4: Elixir + Claude + OpenCode + Playwright + Tidewave
# (Elixir/Tidewave need Erlang, others need Node)
# ============================================================================ # ============================================================================
[ "${STEP_STATUS[erlang]}" = "done" ] && [ "${STEP_STATUS[elixir]}" != "skipped" ] && start_step "elixir" install_elixir [ "${STEP_STATUS[erlang]}" = "done" ] && [ "${STEP_STATUS[elixir]}" != "skipped" ] && start_step "elixir" install_elixir
[ "${STEP_STATUS[node]}" = "done" ] && [ "${STEP_STATUS[claude]}" != "skipped" ] && start_step "claude" install_claude [ "${STEP_STATUS[erlang]}" = "done" ] && [ "${STEP_STATUS[tidewave]}" != "skipped" ] && start_step "tidewave" install_tidewave
[ "${STEP_STATUS[node]}" = "done" ] && [ "${STEP_STATUS[playwright]}" != "skipped" ] && start_step "playwright" install_playwright [ "${STEP_STATUS[node]}" = "done" ] && [ "${STEP_STATUS[claude]}" != "skipped" ] && start_step "claude" install_claude
[ "${STEP_STATUS[node]}" = "done" ] && [ "${STEP_STATUS[opencode]}" != "skipped" ] && start_step "opencode" install_opencode
[ "${STEP_STATUS[node]}" = "done" ] && [ "${STEP_STATUS[playwright]}" != "skipped" ] && start_step "playwright" install_playwright
wait_for_running_steps wait_for_running_steps
@ -1393,6 +1459,12 @@ fi
if [ "${STEP_STATUS[claude]}" = "done" ]; then if [ "${STEP_STATUS[claude]}" = "done" ]; then
echo -e "${CYAN}Claude:${NC} claude" echo -e "${CYAN}Claude:${NC} claude"
fi fi
if [ "${STEP_STATUS[opencode]}" = "done" ]; then
echo -e "${CYAN}OpenCode:${NC} opencode"
fi
if [ "${STEP_STATUS[tidewave]}" = "done" ]; then
echo -e "${CYAN}Tidewave:${NC} tidewave (run in Phoenix project dir)"
fi
if [ "${STEP_STATUS[ollama]}" = "done" ]; then if [ "${STEP_STATUS[ollama]}" = "done" ]; then
echo -e "${CYAN}Ollama:${NC} ollama run llama3.2" echo -e "${CYAN}Ollama:${NC} ollama run llama3.2"
fi fi