symgraph 2026.6.13

Semantic code intelligence library and MCP server - build knowledge graphs of codebases
Documentation
param(
    [switch]$Mcp,
    [switch]$Help
)

$ErrorActionPreference = "Stop"

if ($Help) {
    Write-Host "Usage: install.ps1 [OPTIONS]"
    Write-Host ""
    Write-Host "Install symgraph from GitHub releases."
    Write-Host ""
    Write-Host "Options:"
    Write-Host "  -Mcp     Configure symgraph as an MCP server for Claude Code and Claude Desktop"
    Write-Host "  -Help    Show this help message"
    Write-Host ""
    Write-Host "Environment variables:"
    Write-Host "  SYMGRAPH_VERSION       Version to install (default: latest)"
    Write-Host "  SYMGRAPH_INSTALL_DIR   Installation directory (default: ~/.symgraph)"
    exit 0
}

$Repo = "grahambrooks/symgraph"
$InstallDir = if ($env:SYMGRAPH_INSTALL_DIR) { $env:SYMGRAPH_INSTALL_DIR } else { Join-Path $env:USERPROFILE ".symgraph" }
$Version = if ($env:SYMGRAPH_VERSION) { $env:SYMGRAPH_VERSION } else { "latest" }
$Arch = "x64"

# Resolve version
if ($Version -eq "latest") {
    $ReleaseUrl = "https://api.github.com/repos/$Repo/releases/latest"
    try {
        $Release = Invoke-RestMethod -Uri $ReleaseUrl -UseBasicParsing
        $Version = $Release.tag_name -replace "^v", ""
    } catch {
        Write-Error "Failed to resolve latest version: $_"
        exit 1
    }
    Write-Host "Resolved latest version: $Version"
}

# Strip leading 'v' if present
$Version = $Version -replace "^v", ""

$ZipName = "symgraph-$Version-windows-x64.zip"
$DownloadUrl = "https://github.com/$Repo/releases/download/v$Version/$ZipName"

Write-Host "Installing symgraph $Version for windows/$Arch..."

$TmpDir = Join-Path ([System.IO.Path]::GetTempPath()) "symgraph-install-$([System.Guid]::NewGuid())"
New-Item -ItemType Directory -Path $TmpDir -Force | Out-Null

try {
    $ZipPath = Join-Path $TmpDir $ZipName
    Invoke-WebRequest -Uri $DownloadUrl -OutFile $ZipPath -UseBasicParsing

    Expand-Archive -Path $ZipPath -DestinationPath $TmpDir -Force

    # Install binary and manifest
    $BinDir = Join-Path $InstallDir "bin"
    New-Item -ItemType Directory -Path $BinDir -Force | Out-Null

    Copy-Item -Path (Join-Path $TmpDir "symgraph.exe") -Destination (Join-Path $BinDir "symgraph.exe") -Force

    $ManifestPath = Join-Path $TmpDir "manifest.json"
    if (Test-Path $ManifestPath) {
        Copy-Item -Path $ManifestPath -Destination (Join-Path $InstallDir "manifest.json") -Force
    }
} finally {
    Remove-Item -Recurse -Force $TmpDir -ErrorAction SilentlyContinue
}

# Add to PATH for current user if not already present
$UserPath = [Environment]::GetEnvironmentVariable("Path", "User")
$BinDir = Join-Path $InstallDir "bin"

if ($UserPath -notlike "*$BinDir*") {
    [Environment]::SetEnvironmentVariable("Path", "$BinDir;$UserPath", "User")
    $env:Path = "$BinDir;$env:Path"
    Write-Host ""
    Write-Host "Added $BinDir to your user PATH."
    Write-Host "Restart your terminal for the change to take effect."
}

Write-Host ""
Write-Host "symgraph $Version installed to $BinDir\symgraph.exe"

# Configure as MCP server
if ($Mcp) {
    $SymgraphBin = Join-Path $BinDir "symgraph.exe"

    function Configure-McpJson {
        param([string]$FilePath, [string]$Label)

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

        if (Test-Path $FilePath) {
            $Config = Get-Content $FilePath -Raw | ConvertFrom-Json
        } else {
            $Config = [PSCustomObject]@{}
        }

        if (-not ($Config | Get-Member -Name "mcpServers" -ErrorAction SilentlyContinue)) {
            $Config | Add-Member -NotePropertyName "mcpServers" -NotePropertyValue ([PSCustomObject]@{})
        }

        $ServerConfig = [PSCustomObject]@{
            command = $SymgraphBin
            args = @("serve")
        }

        if ($Config.mcpServers | Get-Member -Name "symgraph" -ErrorAction SilentlyContinue) {
            $Config.mcpServers.symgraph = $ServerConfig
        } else {
            $Config.mcpServers | Add-Member -NotePropertyName "symgraph" -NotePropertyValue $ServerConfig
        }

        $Config | ConvertTo-Json -Depth 10 | Set-Content $FilePath -Encoding UTF8
        Write-Host "  Configured ${Label}: $FilePath"
    }

    Write-Host ""
    Write-Host "Configuring MCP server..."

    # Claude Code: ~/.claude/settings.json
    $ClaudeCodeConfig = Join-Path $env:USERPROFILE ".claude\settings.json"
    Configure-McpJson -FilePath $ClaudeCodeConfig -Label "Claude Code"

    # Claude Desktop: %APPDATA%\Claude\claude_desktop_config.json
    $DesktopConfig = Join-Path $env:APPDATA "Claude\claude_desktop_config.json"
    Configure-McpJson -FilePath $DesktopConfig -Label "Claude Desktop"

    Write-Host ""
    Write-Host "Restart Claude Code / Claude Desktop to pick up the new MCP server."
}