Files

240 lines
7.5 KiB
Bash

#!/usr/bin/env bash
set -euo pipefail
# Colors
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
CYAN='\033[0;36m'
DARKGRAY='\033[0;90m'
NC='\033[0m' # No Color
# Detect OS
OS="unknown"
case "$(uname -s)" in
Linux*) OS="linux";;
Darwin*) OS="macos";;
CYGWIN*|MINGW*|MSYS*) OS="windows";;
esac
# Config paths
if [ "$OS" = "windows" ]; then
CONFIG_DIR="$USERPROFILE/.config/opencode"
else
CONFIG_DIR="$HOME/.config/opencode"
fi
REPO_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
echo -e "${CYAN}========================================${NC}"
echo -e "${CYAN} Opencode Config Installer (Unix) ${NC}"
echo -e "${CYAN} OS: $OS ${NC}"
echo -e "${CYAN}========================================${NC}"
echo ""
# Check prerequisites
echo -e "${YELLOW}[*] Checking prerequisites...${NC}"
if ! command -v git &> /dev/null; then
echo -e "${RED}[ERROR] Git not found. Install git first.${NC}"
exit 1
fi
if ! command -v npm &> /dev/null; then
echo -e "${RED}[ERROR] npm not found. Install Node.js from https://nodejs.org/${NC}"
exit 1
fi
if ! command -v python3 &> /dev/null && ! command -v python &> /dev/null; then
echo -e "${RED}[ERROR] Python not found. Install Python 3.${NC}"
exit 1
fi
echo -e "${GREEN}[OK] Prerequisites met${NC}"
echo ""
# Get or prompt for API keys
get_env_or_prompt() {
local name="$1"
local prompt="$2"
local required="${3:-false}"
local val=""
# Check environment
val="${!name:-}"
if [ -z "$val" ]; then
if [ "$required" = "true" ]; then
read -rp "$prompt (required): " val
if [ -z "$val" ]; then
echo -e "${RED}[ERROR] $name is required${NC}"
exit 1
fi
else
read -rp "$prompt (optional, press Enter to skip): " val
fi
# Save to shell rc file
if [ -n "$val" ]; then
local shell_rc=""
if [ -f "$HOME/.zshrc" ]; then
shell_rc="$HOME/.zshrc"
elif [ -f "$HOME/.bashrc" ]; then
shell_rc="$HOME/.bashrc"
fi
if [ -n "$shell_rc" ]; then
echo "export $name=\"$val\"" >> "$shell_rc"
echo -e "${DARKGRAY} Saved $name to $shell_rc${NC}"
fi
fi
else
echo -e "${DARKGRAY} Found $name in environment${NC}"
fi
echo "$val"
}
echo -e "${YELLOW}[*] Configuring secrets...${NC}"
API_KEY=$(get_env_or_prompt "OPENCODE_API_KEY" "Enter your OpenAI-compatible API key" "true")
BRAVE_KEY=$(get_env_or_prompt "BRAVE_API_KEY" "Enter your Brave Search API key" "false")
# Detect or prompt for projects path
PROJECTS_PATH="${PROJECTS_PATH:-}"
if [ -z "$PROJECTS_PATH" ]; then
default_path="$HOME/projects"
read -rp "Enter your projects directory path [default: $default_path]: " PROJECTS_PATH
if [ -z "$PROJECTS_PATH" ]; then
PROJECTS_PATH="$default_path"
fi
if [ ! -d "$PROJECTS_PATH" ]; then
echo -e "${DARKGRAY} Creating projects directory: $PROJECTS_PATH${NC}"
mkdir -p "$PROJECTS_PATH"
fi
fi
echo -e "${GREEN}[OK] Projects path: $PROJECTS_PATH${NC}"
echo ""
# Backup existing config
if [ -f "$CONFIG_DIR/opencode.json" ]; then
backup="$CONFIG_DIR/opencode.json.backup.$(date +%Y%m%d%H%M%S)"
cp "$CONFIG_DIR/opencode.json" "$backup"
echo -e "${YELLOW}[*] Backed up existing config to: $backup${NC}"
fi
# Create config directory
mkdir -p "$CONFIG_DIR"
# Generate opencode.json from template
echo -e "${YELLOW}[*] Generating opencode.json...${NC}"
# Escape path for JSON (handle backslashes on Windows)
PROJECTS_PATH_ESCAPED="$PROJECTS_PATH"
if [ "$OS" = "windows" ]; then
# Double backslashes for JSON
PROJECTS_PATH_ESCAPED="${PROJECTS_PATH//\\//\\\\}"
fi
# Read template and substitute
sed -e "s|\\\${OPENCODE_API_KEY}|$API_KEY|g" \
-e "s|\\\${BRAVE_API_KEY}|$BRAVE_KEY|g" \
-e "s|\\\${PROJECTS_PATH}|$PROJECTS_PATH_ESCAPED|g" \
"$REPO_DIR/opencode.json.template" > "$CONFIG_DIR/opencode.json"
# Disable brave-search if no key
if [ -z "$BRAVE_KEY" ]; then
echo -e "${DARKGRAY} [!] No Brave API key - disabling brave-search MCP${NC}"
# Use python to safely modify JSON
python3 -c "
import json
with open('$CONFIG_DIR/opencode.json', 'r') as f:
config = json.load(f)
if 'brave-search' in config.get('mcp', {}):
config['mcp']['brave-search']['enabled'] = False
if 'env' in config['mcp']['brave-search']:
del config['mcp']['brave-search']['env']
with open('$CONFIG_DIR/opencode.json', 'w') as f:
json.dump(config, f, indent=2)
" 2>/dev/null || python -c "
import json
with open('$CONFIG_DIR/opencode.json', 'r') as f:
config = json.load(f)
if 'brave-search' in config.get('mcp', {}):
config['mcp']['brave-search']['enabled'] = False
if 'env' in config['mcp']['brave-search']:
del config['mcp']['brave-search']['env']
with open('$CONFIG_DIR/opencode.json', 'w') as f:
json.dump(config, f, indent=2)
"
fi
echo -e "${GREEN}[OK] Config written to $CONFIG_DIR/opencode.json${NC}"
echo ""
# Copy agents and skills
echo -e "${YELLOW}[*] Syncing agents and skills...${NC}"
# Remove old skills/agents to ensure clean sync
rm -rf "$CONFIG_DIR/agents" "$CONFIG_DIR/skills"
cp -r "$REPO_DIR/agents" "$CONFIG_DIR/"
cp -r "$REPO_DIR/skills" "$CONFIG_DIR/"
SKILL_COUNT=$(find "$CONFIG_DIR/skills" -maxdepth 1 -type d | wc -l)
SKILL_COUNT=$((SKILL_COUNT - 1)) # Exclude skills dir itself
echo -e "${GREEN}[OK] Copied 3 agents and $SKILL_COUNT skills${NC}"
echo ""
# Install global dependencies
echo -e "${YELLOW}[*] Installing global dependencies...${NC}"
GLOBAL_PACKAGES=(
"@colbymchenry/codegraph"
"@brave/brave-search-mcp-server"
"@modelcontextprotocol/server-filesystem"
"@modelcontextprotocol/server-github"
"@modelcontextprotocol/server-memory"
"@modelcontextprotocol/server-sequential-thinking"
"@playwright/mcp"
"@upstash/context7-mcp"
"mcp-remote"
"jina-mcp-tools"
"git-mcp-server"
"chrome-devtools-mcp"
)
# Install npm global deps (git-mcp-server replaces Python mcp-server-git)
for pkg in "${GLOBAL_PACKAGES[@]}"; do
echo -e "${DARKGRAY} Installing $pkg...${NC}" -n
if npm install -g "$pkg" 2>/dev/null; then
echo -e "${GREEN} OK${NC}"
else
echo -e "${YELLOW} SKIP (may already be installed)${NC}"
fi
done
echo ""
echo -e "${CYAN}========================================${NC}"
echo -e "${GREEN} Installation Complete! ${NC}"
echo -e "${CYAN}========================================${NC}"
echo ""
echo -e "${WHITE}Next steps:${NC}"
echo -e " 1. Restart opencode to load new config (plugins auto-install on startup)"
echo -e " 2. Run 'opencode' in your project directory"
echo -e " 3. Initialize CodeGraph: codegraph init"
echo -e " 4. For smart-tree MCP: install from https://github.com/anomalyco/smart-tree"
echo ""
echo -e "${DARKGRAY}Config location: $CONFIG_DIR${NC}"
echo ""
# Verify config
echo -e "${YELLOW}[*] Verifying config...${NC}"
if python3 -c "import json; config=json.load(open('$CONFIG_DIR/opencode.json')); print(f'[OK] Config valid - {len(config.get(\"mcp\", {}))} MCP servers configured')" 2>/dev/null || \
python -c "import json; config=json.load(open('$CONFIG_DIR/opencode.json')); print(f'[OK] Config valid - {len(config.get(\"mcp\", {}))} MCP servers configured')" 2>/dev/null; then
:
else
echo -e "${YELLOW}[WARN] Config may have syntax issues - please check $CONFIG_DIR/opencode.json${NC}"
fi