From 063ce96f8535f870e753a47deb300a274d3549dd Mon Sep 17 00:00:00 2001 From: anthonyivn2 Date: Wed, 4 Mar 2026 16:24:05 +0800 Subject: [PATCH] feat: add Gemini CLI as supported tool Add Gemini CLI (v0.26.0+) as a 5th supported AI coding tool alongside Claude Code, Cursor, GitHub Copilot, and OpenAI Codex. Changes: - Detect gemini CLI in tool selection (install.sh and install.ps1) - Install skills to .gemini/skills/ directory - Write MCP config to .gemini/settings.json (without defer_loading) - Generate GEMINI.md project instructions file - Update README with Gemini CLI in prerequisites and examples --- README.md | 9 ++-- install.ps1 | 128 +++++++++++++++++++++++++++++++++++++++++++++++++--- install.sh | 111 ++++++++++++++++++++++++++++++++++++++++++--- 3 files changed, 231 insertions(+), 17 deletions(-) diff --git a/README.md b/README.md index 431aa152..283ccac6 100644 --- a/README.md +++ b/README.md @@ -48,14 +48,15 @@ AI-Driven Development (vibe coding) on Databricks just got a whole lot better. T - [uv](https://github.com/astral-sh/uv) - Python package manager - [Databricks CLI](https://docs.databricks.com/aws/en/dev-tools/cli/) - Command line interface for Databricks -- AI coding environment +- AI coding environment (one or more): - [Claude Code](https://claude.ai/code) - [Cursor](https://cursor.com) + - [Gemini CLI](https://github.com/google-gemini/gemini-cli) ### Install in existing project By default this will install at a project level rather than a user level. This is often a good fit, but requires you to run your client from the exact directory that was used for the install. -_Note: Project configuration files can be re-used in other projects. You find these configs under .claude or .cursor_ +_Note: Project configuration files can be re-used in other projects. You find these configs under .claude, .cursor, or .gemini_ #### Mac / Linux @@ -83,7 +84,7 @@ bash <(curl -sL https://raw.githubusercontent.com/databricks-solutions/ai-dev-ki **Install for specific tools only** ```bash -bash <(curl -sL https://raw.githubusercontent.com/databricks-solutions/ai-dev-kit/main/install.sh) --tools cursor +bash <(curl -sL https://raw.githubusercontent.com/databricks-solutions/ai-dev-kit/main/install.sh) --tools cursor,gemini ``` @@ -123,7 +124,7 @@ irm https://raw.githubusercontent.com/databricks-solutions/ai-dev-kit/main/insta **Install for specific tools only** ```powershell -.\install.ps1 -Tools cursor +.\install.ps1 -Tools cursor,gemini ``` diff --git a/install.ps1 b/install.ps1 index 38e4a2a0..3fafb96a 100644 --- a/install.ps1 +++ b/install.ps1 @@ -1,7 +1,7 @@ # # Databricks AI Dev Kit - Unified Installer (Windows) # -# Installs skills, MCP server, and configuration for Claude Code, Cursor, OpenAI Codex, and GitHub Copilot. +# Installs skills, MCP server, and configuration for Claude Code, Cursor, OpenAI Codex, GitHub Copilot, and Gemini CLI. # # Usage: irm https://raw.githubusercontent.com/databricks-solutions/ai-dev-kit/main/install.ps1 -OutFile install.ps1 # .\install.ps1 [OPTIONS] @@ -142,7 +142,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" + Write-Host " --tools LIST Comma-separated: claude,cursor,copilot,codex,gemini" Write-Host " -f, --force Force reinstall" Write-Host " -h, --help Show this help" Write-Host "" @@ -472,14 +472,16 @@ function Invoke-DetectTools { $hasCodex = $null -ne (Get-Command codex -ErrorAction SilentlyContinue) $hasCopilot = ($null -ne (Get-Command code -ErrorAction SilentlyContinue)) -or (Test-Path "$env:LOCALAPPDATA\Programs\Microsoft VS Code\Code.exe") + $hasGemini = $null -ne (Get-Command gemini -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" } # If nothing detected, default to claude - if (-not $hasClaude -and -not $hasCursor -and -not $hasCodex -and -not $hasCopilot) { + if (-not $hasClaude -and -not $hasCursor -and -not $hasCodex -and -not $hasCopilot -and -not $hasGemini) { $claudeState = $true $claudeHint = "default" } @@ -494,6 +496,7 @@ function Invoke-DetectTools { @{ Label = "Cursor"; Value = "cursor"; State = $cursorState; Hint = $cursorHint } @{ Label = "GitHub Copilot"; Value = "copilot"; State = $copilotState; Hint = $copilotHint } @{ Label = "OpenAI Codex"; Value = "codex"; State = $codexState; Hint = $codexHint } + @{ Label = "Gemini CLI"; Value = "gemini"; State = $geminiState; Hint = $geminiHint } ) $result = Select-Checkbox -Items $items @@ -744,6 +747,7 @@ function Install-Skills { } "copilot" { $dirs += Join-Path $BaseDir ".github\skills" } "codex" { $dirs += Join-Path $BaseDir ".agents\skills" } + "gemini" { $dirs += Join-Path $BaseDir ".gemini\skills" } } } $dirs = $dirs | Select-Object -Unique @@ -922,6 +926,97 @@ args = ["$entryPath"] Add-Content -Path $Path -Value $tomlBlock -Encoding UTF8 } +function Write-GeminiMcpJson { + 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.mcpServers) { + $existing | Add-Member -NotePropertyName "mcpServers" -NotePropertyValue ([PSCustomObject]@{}) -Force + } + $dbEntry = [PSCustomObject]@{ + command = $script:VenvPython -replace '\\', '/' + args = @($script:McpEntry -replace '\\', '/') + env = [PSCustomObject]@{ DATABRICKS_CONFIG_PROFILE = $script:Profile_ } + } + $existing.mcpServers | Add-Member -NotePropertyName "databricks" -NotePropertyValue $dbEntry -Force + $existing | ConvertTo-Json -Depth 10 | Set-Content $Path -Encoding UTF8 + } else { + $pythonPath = $script:VenvPython -replace '\\', '/' + $entryPath = $script:McpEntry -replace '\\', '/' + $json = @" +{ + "mcpServers": { + "databricks": { + "command": "$pythonPath", + "args": ["$entryPath"], + "env": {"DATABRICKS_CONFIG_PROFILE": "$($script:Profile_)"} + } + } +} +"@ + Set-Content -Path $Path -Value $json -Encoding UTF8 + } +} + +function Write-GeminiMd { + param([string]$Path) + + if (Test-Path $Path) { return } # Don't overwrite existing file + + $content = @" +# Databricks AI Dev Kit + +You have access to Databricks skills and MCP tools installed by the Databricks AI Dev Kit. + +## Available MCP Tools + +The ``databricks`` MCP server provides 50+ tools for interacting with Databricks, including: +- SQL execution and warehouse management +- Unity Catalog operations (tables, volumes, schemas) +- Jobs and workflow management +- Model serving endpoints +- Genie spaces and AI/BI dashboards +- Databricks Apps deployment + +## Available Skills + +Skills are installed in ``.gemini/skills/`` and provide patterns and best practices for: +- Spark Declarative Pipelines, Structured Streaming +- Databricks Jobs, Asset Bundles +- Unity Catalog, SQL, Genie +- MLflow evaluation and tracing +- Model Serving, Vector Search +- Databricks Apps (Python and APX) +- And more + +## Getting Started + +Try asking: "List my SQL warehouses" or "Show my Unity Catalog schemas" +"@ + Set-Content -Path $Path -Value $content -Encoding UTF8 + Write-Ok "GEMINI.md" +} + function Write-McpConfigs { param([string]$BaseDir) @@ -967,6 +1062,14 @@ function Write-McpConfigs { } Write-Ok "Codex MCP config" } + "gemini" { + if ($script:Scope -eq "global") { + Write-GeminiMcpJson (Join-Path $env:USERPROFILE ".gemini\settings.json") + } else { + Write-GeminiMcpJson (Join-Path $BaseDir ".gemini\settings.json") + } + Write-Ok "Gemini CLI MCP config" + } } } } @@ -1014,6 +1117,10 @@ function Show-Summary { Write-Msg "$step. Use Copilot in Agent mode to access Databricks skills and MCP tools" $step++ } + if ($script:Tools -match 'gemini') { + Write-Msg "$step. Launch Gemini CLI in your project: gemini" + $step++ + } Write-Msg "$step. Open your project in your tool of choice" $step++ Write-Msg "$step. Try: `"List my SQL warehouses`"" @@ -1029,7 +1136,7 @@ function Invoke-PromptScope { $labels = @("Project", "Global") $values = @("project", "global") - $hints = @("Install in current directory (.cursor/ and .claude/)", "Install in home directory (~/.cursor/ and ~/.claude/)") + $hints = @("Install in current directory (.cursor/, .claude/, .gemini/)", "Install in home directory (~/.cursor/, ~/.claude/, ~/.gemini/)") $count = 2 $selected = 0 $cursor = 0 @@ -1039,8 +1146,8 @@ function Invoke-PromptScope { if (-not $isInteractive) { # Fallback: numbered list Write-Host "" - Write-Host " 1. (*) Project Install in current directory (.cursor/ and .claude/)" - Write-Host " 2. ( ) Global Install in home directory (~/.cursor/ and ~/.claude/)" + Write-Host " 1. (*) Project Install in current directory (.cursor/, .claude/, .gemini/)" + Write-Host " 2. ( ) Global Install in home directory (~/.cursor/, ~/.claude/, ~/.gemini/)" Write-Host "" Write-Host " Enter number to select (or press Enter for default): " -NoNewline $input_ = Read-Host @@ -1251,6 +1358,15 @@ function Invoke-Main { Install-Skills -BaseDir $baseDir } + # Write GEMINI.md if gemini is selected + if ($script:Tools -match 'gemini') { + if ($script:Scope -eq "global") { + Write-GeminiMd (Join-Path $env:USERPROFILE "GEMINI.md") + } else { + Write-GeminiMd (Join-Path $baseDir "GEMINI.md") + } + } + # Write MCP configs if ($script:InstallMcp) { Write-McpConfigs -BaseDir $baseDir diff --git a/install.sh b/install.sh index 61b98d42..7ed46779 100755 --- a/install.sh +++ b/install.sh @@ -2,7 +2,7 @@ # # Databricks AI Dev Kit - Unified Installer # -# Installs skills, MCP server, and configuration for Claude Code, Cursor, OpenAI Codex, and GitHub Copilot. +# Installs skills, MCP server, and configuration for Claude Code, Cursor, OpenAI Codex, GitHub Copilot, and Gemini CLI. # # Usage: bash <(curl -sL https://raw.githubusercontent.com/databricks-solutions/ai-dev-kit/main/install.sh) [OPTIONS] # @@ -17,7 +17,7 @@ # bash <(curl -sL https://raw.githubusercontent.com/databricks-solutions/ai-dev-kit/main/install.sh) --profile DEFAULT --force # # # Install for specific tools only -# bash <(curl -sL https://raw.githubusercontent.com/databricks-solutions/ai-dev-kit/main/install.sh) --tools cursor,codex,copilot +# bash <(curl -sL https://raw.githubusercontent.com/databricks-solutions/ai-dev-kit/main/install.sh) --tools cursor,codex,copilot,gemini # # # Skills only (skip MCP server) # bash <(curl -sL https://raw.githubusercontent.com/databricks-solutions/ai-dev-kit/main/install.sh) --skills-only @@ -112,7 +112,7 @@ while [ $# -gt 0 ]; do echo " --mcp-only Skip skills installation" echo " --mcp-path PATH Path to MCP server installation (default: ~/.ai-dev-kit)" echo " --silent Silent mode (no output except errors)" - echo " --tools LIST Comma-separated: claude,cursor,copilot,codex" + echo " --tools LIST Comma-separated: claude,cursor,copilot,codex,gemini" echo " -f, --force Force reinstall" echo " -h, --help Show this help" echo "" @@ -395,22 +395,25 @@ detect_tools() { local has_cursor=false local has_codex=false local has_copilot=false + local has_gemini=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 # Build checkbox items: "Label|value|on_or_off|hint" - local claude_state="off" cursor_state="off" codex_state="off" copilot_state="off" - local claude_hint="not found" cursor_hint="not found" codex_hint="not found" copilot_hint="not found" + local claude_state="off" cursor_state="off" codex_state="off" copilot_state="off" gemini_state="off" + local claude_hint="not found" cursor_hint="not found" codex_hint="not found" copilot_hint="not found" gemini_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" # If nothing detected, pre-select claude as default - if [ "$has_claude" = false ] && [ "$has_cursor" = false ] && [ "$has_codex" = false ] && [ "$has_copilot" = false ]; then + if [ "$has_claude" = false ] && [ "$has_cursor" = false ] && [ "$has_codex" = false ] && [ "$has_copilot" = false ] && [ "$has_gemini" = false ]; then claude_state="on" claude_hint="default" fi @@ -425,6 +428,7 @@ detect_tools() { "Cursor|cursor|${cursor_state}|${cursor_hint}" \ "GitHub Copilot|copilot|${copilot_state}|${copilot_hint}" \ "OpenAI Codex|codex|${codex_state}|${codex_hint}" \ + "Gemini CLI|gemini|${gemini_state}|${gemini_hint}" \ ) else # Silent: use detected defaults @@ -433,6 +437,7 @@ detect_tools() { [ "$has_cursor" = true ] && tools="${tools:+$tools }cursor" [ "$has_copilot" = true ] && tools="${tools:+$tools }copilot" [ "$has_codex" = true ] && tools="${tools:+$tools }codex" + [ "$has_gemini" = true ] && tools="${tools:+$tools }gemini" [ -z "$tools" ] && tools="claude" TOOLS="$tools" fi @@ -685,6 +690,7 @@ install_skills() { cursor) echo "$TOOLS" | grep -q claude || dirs+=("$base_dir/.cursor/skills") ;; copilot) dirs+=("$base_dir/.github/skills") ;; codex) dirs+=("$base_dir/.agents/skills") ;; + gemini) dirs+=("$base_dir/.gemini/skills") ;; esac done @@ -810,6 +816,76 @@ args = ["$MCP_ENTRY"] EOF } +write_gemini_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 = {} +cfg.setdefault('mcpServers', {})['databricks'] = {'command': '$VENV_PYTHON', 'args': ['$MCP_ENTRY'], 'env': {'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 +{ + "mcpServers": { + "databricks": { + "command": "$VENV_PYTHON", + "args": ["$MCP_ENTRY"], + "env": {"DATABRICKS_CONFIG_PROFILE": "$PROFILE"} + } + } +} +EOF +} + +write_gemini_md() { + local path=$1 + [ -f "$path" ] && return # Don't overwrite existing file + cat > "$path" << 'GEMINIEOF' +# Databricks AI Dev Kit + +You have access to Databricks skills and MCP tools installed by the Databricks AI Dev Kit. + +## Available MCP Tools + +The `databricks` MCP server provides 50+ tools for interacting with Databricks, including: +- SQL execution and warehouse management +- Unity Catalog operations (tables, volumes, schemas) +- Jobs and workflow management +- Model serving endpoints +- Genie spaces and AI/BI dashboards +- Databricks Apps deployment + +## Available Skills + +Skills are installed in `.gemini/skills/` and provide patterns and best practices for: +- Spark Declarative Pipelines, Structured Streaming +- Databricks Jobs, Asset Bundles +- Unity Catalog, SQL, Genie +- MLflow evaluation and tracing +- Model Serving, Vector Search +- Databricks Apps (Python and APX) +- And more + +## Getting Started + +Try asking: "List my SQL warehouses" or "Show my Unity Catalog schemas" +GEMINIEOF + ok "GEMINI.md" +} + write_mcp_configs() { step "Configuring MCP" @@ -846,6 +922,14 @@ write_mcp_configs() { [ "$SCOPE" = "global" ] && write_mcp_toml "$HOME/.codex/config.toml" || write_mcp_toml "$base_dir/.codex/config.toml" ok "Codex MCP config" ;; + gemini) + if [ "$SCOPE" = "global" ]; then + write_gemini_mcp_json "$HOME/.gemini/settings.json" + else + write_gemini_mcp_json "$base_dir/.gemini/settings.json" + fi + ok "Gemini CLI MCP config" + ;; esac done } @@ -885,6 +969,10 @@ summary() { msg "${step}. Use Copilot in ${B}Agent mode${N} to access Databricks skills and MCP tools" step=$((step + 1)) fi + if echo "$TOOLS" | grep -q gemini; then + msg "${step}. Launch Gemini CLI in your project: ${B}gemini${N}" + step=$((step + 1)) + fi msg "${step}. Open your project in your tool of choice" step=$((step + 1)) msg "${step}. Try: \"List my SQL warehouses\"" @@ -904,7 +992,7 @@ prompt_scope() { # Simple radio selector without Confirm button local -a labels=("Project" "Global") local -a values=("project" "global") - local -a hints=("Install in current directory (.cursor/ and .claude/)" "Install in home directory (~/.cursor/ and ~/.claude/)") + local -a hints=("Install in current directory (.cursor/, .claude/, .gemini/)" "Install in home directory (~/.cursor/, ~/.claude/, ~/.gemini/)") local count=2 local selected=0 local cursor=0 @@ -1086,6 +1174,15 @@ main() { # Install skills [ "$INSTALL_SKILLS" = true ] && install_skills "$base_dir" + # Write GEMINI.md if gemini is selected + if echo "$TOOLS" | grep -q gemini; then + if [ "$SCOPE" = "global" ]; then + write_gemini_md "$HOME/GEMINI.md" + else + write_gemini_md "$base_dir/GEMINI.md" + fi + fi + # Write MCP configs [ "$INSTALL_MCP" = true ] && write_mcp_configs "$base_dir"