# install.ps1 — Link claude-meta config into ~/.claude/ $ErrorActionPreference = "Stop" $repoRoot = Split-Path -Parent (Split-Path -Parent $MyInvocation.MyCommand.Path) $sourceDir = Join-Path $repoRoot "home-claude" $claudeDir = Join-Path $env:USERPROFILE ".claude" # Verify source exists if (-not (Test-Path $sourceDir)) { Write-Host "ERROR: home-claude/ not found at $sourceDir" -ForegroundColor Red exit 1 } # Ensure ~/.claude/ is a real directory (never a symlink!) if (Test-Path $claudeDir) { $item = Get-Item $claudeDir -Force if ($item.Attributes -band [System.IO.FileAttributes]::ReparsePoint) { Write-Host "ERROR: ~/.claude/ is a symlink/junction. It must be a real directory." -ForegroundColor Red Write-Host "Claude Code Bug #764: symlinked ~/.claude/ breaks file detection." -ForegroundColor Red exit 1 } } else { New-Item -ItemType Directory -Path $claudeDir -Force | Out-Null Write-Host "Created ~/.claude/" -ForegroundColor Cyan } # Verify same volume for junctions $sourceVolume = (Get-Item $sourceDir).PSDrive.Name $targetVolume = (Get-Item $claudeDir).PSDrive.Name if ($sourceVolume -ne $targetVolume) { Write-Host "WARNING: Source ($sourceVolume`:) and target ($targetVolume`:) are on different volumes." -ForegroundColor Yellow Write-Host "Junctions require same volume. Falling back to file copy for directories." -ForegroundColor Yellow $useJunctions = $false } else { $useJunctions = $true } Write-Host "" Write-Host "Installing claude-meta config..." -ForegroundColor Cyan Write-Host " Source: $sourceDir" -ForegroundColor Gray Write-Host " Target: $claudeDir" -ForegroundColor Gray Write-Host "" $success = $true # --- File Symlinks --- $files = @("CLAUDE.md", "settings.json") foreach ($file in $files) { $src = Join-Path $sourceDir $file $dst = Join-Path $claudeDir $file if (-not (Test-Path $src)) { Write-Host " SKIP: $file (not in repo)" -ForegroundColor Yellow continue } # Remove existing file/link if (Test-Path $dst) { Remove-Item $dst -Force } # Try symlink first try { New-Item -ItemType SymbolicLink -Path $dst -Target $src -ErrorAction Stop | Out-Null Write-Host " SYMLINK: $file -> $src" -ForegroundColor Green } catch { # Fallback: copy Write-Host " WARNING: Symlink failed for $file (need Developer Mode?). Using copy." -ForegroundColor Yellow Copy-Item $src $dst -Force Write-Host " COPY: $file (changes won't auto-sync!)" -ForegroundColor Yellow $success = $false } } # --- Directory Junctions --- $dirs = @("skills", "rules") foreach ($dir in $dirs) { $src = Join-Path $sourceDir $dir $dst = Join-Path $claudeDir $dir if (-not (Test-Path $src)) { Write-Host " SKIP: $dir/ (not in repo)" -ForegroundColor Yellow continue } # Remove existing dir/junction if (Test-Path $dst) { $item = Get-Item $dst -Force if ($item.Attributes -band [System.IO.FileAttributes]::ReparsePoint) { # It's a junction/symlink — remove it cmd /c "rmdir `"$dst`"" 2>$null } else { Remove-Item $dst -Recurse -Force } } if ($useJunctions) { # Junction (no admin needed, same volume only) cmd /c "mklink /J `"$dst`" `"$src`"" | Out-Null if ($LASTEXITCODE -eq 0) { Write-Host " JUNCTION: $dir/ -> $src" -ForegroundColor Green } else { # Fallback: copy Copy-Item $src $dst -Recurse -Force Write-Host " COPY: $dir/ (changes won't auto-sync!)" -ForegroundColor Yellow $success = $false } } else { Copy-Item $src $dst -Recurse -Force Write-Host " COPY: $dir/ (different volume)" -ForegroundColor Yellow $success = $false } } # --- Validation --- Write-Host "" Write-Host "Validating..." -ForegroundColor Cyan $valid = $true foreach ($file in $files) { $dst = Join-Path $claudeDir $file if (Test-Path $dst) { $content = Get-Content $dst -Raw -ErrorAction SilentlyContinue if ($content) { Write-Host " OK: $file readable" -ForegroundColor Green } else { Write-Host " FAIL: $file exists but empty/unreadable" -ForegroundColor Red $valid = $false } } else { Write-Host " FAIL: $file not found" -ForegroundColor Red $valid = $false } } foreach ($dir in $dirs) { $dst = Join-Path $claudeDir $dir if (Test-Path $dst) { $count = (Get-ChildItem $dst -Recurse -File).Count Write-Host " OK: $dir/ ($count files)" -ForegroundColor Green } else { Write-Host " FAIL: $dir/ not found" -ForegroundColor Red $valid = $false } } # --- Summary --- Write-Host "" if ($valid) { Write-Host "Installation complete!" -ForegroundColor Green if (-not $success) { Write-Host "" Write-Host "NOTE: Some items were copied instead of linked." -ForegroundColor Yellow Write-Host "Enable Developer Mode (Settings > Developer) for symlinks," -ForegroundColor Yellow Write-Host "or re-run after changes with: .\scripts\install.ps1" -ForegroundColor Yellow } } else { Write-Host "Installation had errors. Check output above." -ForegroundColor Red exit 1 }