claude-meta/scripts/install.ps1

161 lines
5.3 KiB
PowerShell

# 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
}