Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
83 changes: 80 additions & 3 deletions install.ps1
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
#
# Databricks AI Dev Kit - Unified Installer (Windows)
#
# Installs skills, MCP server, and configuration for Claude Code, Cursor, OpenAI Codex, GitHub Copilot, Gemini CLI, and Antigravity.
# Installs skills, MCP server, and configuration for Claude Code, Cursor, OpenAI Codex, GitHub Copilot, Gemini CLI, Antigravity and OpenCode.
#
# Usage: irm https://raw.githubusercontent.com/databricks-solutions/ai-dev-kit/main/install.ps1 -OutFile install.ps1
# .\install.ps1 [OPTIONS]
Expand Down Expand Up @@ -233,7 +233,7 @@ while ($i -lt $args.Count) {
Write-Host " --mcp-only Skip skills installation"
Write-Host " --mcp-path PATH Path to MCP server installation"
Write-Host " --silent Silent mode (no output except errors)"
Write-Host " --tools LIST Comma-separated: claude,cursor,copilot,codex,gemini,antigravity"
Write-Host " --tools LIST Comma-separated: claude,cursor,copilot,codex,gemini,antigravity,opencode"
Write-Host " --skills-profile LIST Comma-separated profiles: all,data-engineer,analyst,ai-ml-engineer,app-developer"
Write-Host " --skills LIST Comma-separated skill names to install (overrides profile)"
Write-Host " --list-skills List available skills and profiles, then exit"
Expand Down Expand Up @@ -569,16 +569,18 @@ function Invoke-DetectTools {
$hasGemini = $null -ne (Get-Command gemini -ErrorAction SilentlyContinue)
$hasAntigravity = ($null -ne (Get-Command antigravity -ErrorAction SilentlyContinue)) -or
(Test-Path "$env:LOCALAPPDATA\Programs\Antigravity\Antigravity.exe")
$hasOpencode = $null -ne (Get-Command opencode -ErrorAction SilentlyContinue)

$claudeState = $hasClaude; $claudeHint = if ($hasClaude) { "detected" } else { "not found" }
$cursorState = $hasCursor; $cursorHint = if ($hasCursor) { "detected" } else { "not found" }
$codexState = $hasCodex; $codexHint = if ($hasCodex) { "detected" } else { "not found" }
$copilotState = $hasCopilot; $copilotHint = if ($hasCopilot) { "detected" } else { "not found" }
$geminiState = $hasGemini; $geminiHint = if ($hasGemini) { "detected" } else { "not found" }
$antigravityState = $hasAntigravity; $antigravityHint = if ($hasAntigravity) { "detected" } else { "not found" }
$opencodeState = $hasOpencode; $opencodeHint = if ($hasOpencode) { "detected" } else { "not found" }

# If nothing detected, default to claude
if (-not $hasClaude -and -not $hasCursor -and -not $hasCodex -and -not $hasCopilot -and -not $hasGemini -and -not $hasAntigravity) {
if (-not $hasClaude -and -not $hasCursor -and -not $hasCodex -and -not $hasCopilot -and -not $hasGemini -and -not $hasAntigravity -and -not $hasOpencode) {
$claudeState = $true
$claudeHint = "default"
}
Expand All @@ -595,6 +597,7 @@ function Invoke-DetectTools {
@{ Label = "OpenAI Codex"; Value = "codex"; State = $codexState; Hint = $codexHint }
@{ Label = "Gemini CLI"; Value = "gemini"; State = $geminiState; Hint = $geminiHint }
@{ Label = "Antigravity"; Value = "antigravity"; State = $antigravityState; Hint = $antigravityHint }
@{ Label = "OpenCode"; Value = "opencode"; State = $opencodeState; Hint = $opencodeHint }
)

$result = Select-Checkbox -Items $items
Expand Down Expand Up @@ -1163,6 +1166,13 @@ function Install-Skills {
} else {
$dirs += Join-Path $BaseDir ".agents\skills"
}
}
"opencode" {
if ($script:Scope -eq "global") {
$dirs += Join-Path $env:USERPROFILE ".config\opencode\skills"
} else {
$dirs += Join-Path $BaseDir ".opencode\skills"
}
}
}
}
Expand Down Expand Up @@ -1517,6 +1527,60 @@ Try asking: "List my SQL warehouses" or "Show my Unity Catalog schemas"
Write-Ok "GEMINI.md"
}

function Write-OpenCodeMcpJson {
param([string]$Path)

$dir = Split-Path $Path -Parent
if (-not (Test-Path $dir)) {
New-Item -ItemType Directory -Path $dir -Force | Out-Null
}

# Backup existing
if (Test-Path $Path) {
Copy-Item $Path "$Path.bak" -Force
Write-Msg "Backed up $(Split-Path $Path -Leaf) -> $(Split-Path $Path -Leaf).bak"
}

# Try to merge with existing config
if ((Test-Path $Path) -and (Test-Path $script:VenvPython)) {
try {
$existing = Get-Content $Path -Raw | ConvertFrom-Json
} catch {
$existing = $null
}
}

if ($existing) {
if (-not $existing.mcp) {
$existing | Add-Member -NotePropertyName "mcp" -NotePropertyValue ([PSCustomObject]@{}) -Force
}
$dbEntry = [PSCustomObject]@{
type = "local"
command = @($script:VenvPython -replace '\\', '/') + @($script:McpEntry -replace '\\', '/')
environment = [PSCustomObject]@{ DATABRICKS_CONFIG_PROFILE = $script:Profile_ }
enabled = $true
}
$existing.mcp | Add-Member -NotePropertyName "databricks" -NotePropertyValue $dbEntry -Force
$existing = $existing | ConvertTo-Json -Depth 10
$Utf8NoBomEncoding = New-Object System.Text.UTF8Encoding $False
[System.IO.File]::WriteAllLines($Path, $existing, $Utf8NoBomEncoding)
} else {
$config = [PSCustomObject]@{
'$schema' = 'https://opencode.ai/config.json'
mcp = @{
databricks = @{
type = 'local'
command = @($script:VenvPython -replace '\\', '/') + @($script:McpEntry -replace '\\', '/')
environment = [PSCustomObject]@{ DATABRICKS_CONFIG_PROFILE = $script:Profile_ }
enabled = $true
}
}
} | ConvertTo-Json -Depth 3
$Utf8NoBomEncoding = New-Object System.Text.UTF8Encoding $False
[System.IO.File]::WriteAllLines($Path, $config, $Utf8NoBomEncoding)
}
}

function Write-McpConfigs {
param([string]$BaseDir)

Expand Down Expand Up @@ -1589,6 +1653,15 @@ function Write-McpConfigs {
Write-GeminiMcpJson (Join-Path $env:USERPROFILE ".gemini\antigravity\mcp_config.json")
Write-Ok "Antigravity MCP config"
}
"opencode" {
if ($script:Scope -eq "global") {
Write-OpenCodeMcpJson (Join-Path $env:USERPROFILE ".config\opencode\opencode.json")
} else {
Write-OpenCodeMcpJson (Join-Path $BaseDir "opencode.json")

}
Write-Ok "OpenCode CLI MCP config"
}
}
}
}
Expand Down Expand Up @@ -1643,6 +1716,10 @@ function Show-Summary {
if ($script:Tools -match 'antigravity') {
Write-Msg "$step. Open your project in Antigravity to use Databricks skills and MCP tools"
$step++
}
if ($script:Tools -match 'opencode') {
Write-Msg "$step. Open your project in Opencode to use Databricks skills and MCP tools"
$step++
}
Write-Msg "$step. Open your project in your tool of choice"
$step++
Expand Down
66 changes: 63 additions & 3 deletions install.sh
Original file line number Diff line number Diff line change
Expand Up @@ -503,26 +503,29 @@ detect_tools() {
local has_copilot=false
local has_gemini=false
local has_antigravity=false
local has_opencode=false

command -v claude >/dev/null 2>&1 && has_claude=true
{ [ -d "/Applications/Cursor.app" ] || command -v cursor >/dev/null 2>&1; } && has_cursor=true
command -v codex >/dev/null 2>&1 && has_codex=true
{ [ -d "/Applications/Visual Studio Code.app" ] || command -v code >/dev/null 2>&1; } && has_copilot=true
{ command -v gemini >/dev/null 2>&1 || [ -f "$HOME/.gemini/local/gemini" ]; } && has_gemini=true
{ [ -d "/Applications/Antigravity.app" ] || command -v antigravity >/dev/null 2>&1; } && has_antigravity=true
command -v opencode >/dev/null 2>&1 && has_opencode=true

# Build checkbox items: "Label|value|on_or_off|hint"
local claude_state="off" cursor_state="off" codex_state="off" copilot_state="off" gemini_state="off" antigravity_state="off"
local claude_hint="not found" cursor_hint="not found" codex_hint="not found" copilot_hint="not found" gemini_hint="not found" antigravity_hint="not found"
local claude_state="off" cursor_state="off" codex_state="off" copilot_state="off" gemini_state="off" antigravity_state="off" opencode_state="off"
local claude_hint="not found" cursor_hint="not found" codex_hint="not found" copilot_hint="not found" gemini_hint="not found" antigravity_hint="not found" opencode_hint="not found"
[ "$has_claude" = true ] && claude_state="on" && claude_hint="detected"
[ "$has_cursor" = true ] && cursor_state="on" && cursor_hint="detected"
[ "$has_codex" = true ] && codex_state="on" && codex_hint="detected"
[ "$has_copilot" = true ] && copilot_state="on" && copilot_hint="detected"
[ "$has_gemini" = true ] && gemini_state="on" && gemini_hint="detected"
[ "$has_antigravity" = true ] && antigravity_state="on" && antigravity_hint="detected"
[ "$has_opencode" = true ] && opencode_state="on" && opencode_hint="detected"

# If nothing detected, pre-select claude as default
if [ "$has_claude" = false ] && [ "$has_cursor" = false ] && [ "$has_codex" = false ] && [ "$has_copilot" = false ] && [ "$has_gemini" = false ] && [ "$has_antigravity" = false ]; then
if [ "$has_claude" = false ] && [ "$has_cursor" = false ] && [ "$has_codex" = false ] && [ "$has_copilot" = false ] && [ "$has_gemini" = false ] && [ "$has_antigravity" = false ] && [ "$has_opencode" = false ]; then
claude_state="on"
claude_hint="default"
fi
Expand All @@ -539,6 +542,7 @@ detect_tools() {
"OpenAI Codex|codex|${codex_state}|${codex_hint}" \
"Gemini CLI|gemini|${gemini_state}|${gemini_hint}" \
"Antigravity|antigravity|${antigravity_state}|${antigravity_hint}" \
"Opencode|opencode|${opencode_state}|${opencode_hint}" \
)
else
# Silent: use detected defaults
Expand All @@ -549,6 +553,7 @@ detect_tools() {
[ "$has_codex" = true ] && tools="${tools:+$tools }codex"
[ "$has_gemini" = true ] && tools="${tools:+$tools }gemini"
[ "$has_antigravity" = true ] && tools="${tools:+$tools }antigravity"
[ "$has_opencode" = true ] && tools="${tools:+$tools }opencode"
[ -z "$tools" ] && tools="claude"
TOOLS="$tools"
fi
Expand Down Expand Up @@ -1095,6 +1100,13 @@ install_skills() {
else
dirs+=("$base_dir/.agents/skills")
fi
;;
opencode)
if [ "$SCOPE" = "global" ]; then
dirs+=("$HOME/.config/opencode/skills")
else
dirs+=("$base_dir/.opencode/skills")
fi
;;
esac
done
Expand Down Expand Up @@ -1280,6 +1292,42 @@ with open('$path', 'w') as f: json.dump(cfg, f, indent=2); f.write('\n')
EOF
}

write_opencode_mcp_json() {
local path=$1
mkdir -p "$(dirname "$path")"

# Backup existing file before any modifications
if [ -f "$path" ]; then
cp "$path" "${path}.bak"
msg "${D}Backed up ${path##*/} → ${path##*/}.bak${N}"
fi

if [ -f "$path" ] && [ -f "$VENV_PYTHON" ]; then
"$VENV_PYTHON" -c "
import json, sys
try:
with open('$path') as f: cfg = json.load(f)
except: cfg = {'\$schema' : 'https://opencode.ai/config.json'}
cfg.setdefault('mcp', {})['databricks'] = {'type':'local', 'command': ['$VENV_PYTHON','$MCP_ENTRY'], 'enabled': True, 'environment': {'DATABRICKS_CONFIG_PROFILE': '$PROFILE'}}
with open('$path', 'w') as f: json.dump(cfg, f, indent=2); f.write('\n')
" 2>/dev/null && return
fi

cat > "$path" << EOF
{
"\$schema" : "https://opencode.ai/config.json",
"mcp": {
"databricks": {
"type": "local",
"command": ["$VENV_PYTHON","$MCP_ENTRY"],
"enabled": true,
"environment": {"DATABRICKS_CONFIG_PROFILE": "$PROFILE"}
}
}
}
EOF
}

write_mcp_toml() {
local path=$1
mkdir -p "$(dirname "$path")"
Expand Down Expand Up @@ -1485,6 +1533,14 @@ write_mcp_configs() {
fi
write_gemini_mcp_json "$HOME/.gemini/antigravity/mcp_config.json"
ok "Antigravity MCP config"
;;
opencode)
if [ "$SCOPE" = "global" ]; then
write_opencode_mcp_json "$HOME/.config/opencode/opencode.json"
else
write_opencode_mcp_json "$base_dir/opencode.json"
fi
ok "Opencode CLI MCP config"
;;
esac
done
Expand Down Expand Up @@ -1532,6 +1588,10 @@ summary() {
if echo "$TOOLS" | grep -q antigravity; then
msg "${step}. Open your project in Antigravity to use Databricks skills and MCP tools"
step=$((step + 1))
fi
if echo "$TOOLS" | grep -q onpencode; then
msg "${step}. Open your project in Opencode to use Databricks skills and MCP tools"
step=$((step + 1))
fi
msg "${step}. Open your project in your tool of choice"
step=$((step + 1))
Expand Down