diff --git a/README.md b/README.md index 85206b6..ff0b7ca 100644 --- a/README.md +++ b/README.md @@ -67,7 +67,13 @@ The script is idempotent and accepts an optional custom target directory: ./scripts/install-skills.sh --uninstall # remove the symlinks ``` -Once the symlinks are in place, restart Claude Code. Mention a Compose performance symptom in a prompt and Claude Code matches the trigger vocabulary in the skill frontmatter, then loads the relevant `SKILL.md` automatically. +```powershell +.\scripts\install-skills.ps1 # install to %USERPROFILE%\.claude\skills +.\scripts\install-skills.ps1 C:\path\to\skills # custom target +.\scripts\install-skills.ps1 --uninstall # remove the links +``` + +Once the links are in place, restart Claude Code. Mention a Compose performance symptom in a prompt and Claude Code matches the trigger vocabulary in the skill frontmatter, then loads the relevant `SKILL.md` automatically. ### Android Studio Agent mode and Gemini diff --git a/scripts/install-skills.ps1 b/scripts/install-skills.ps1 new file mode 100644 index 0000000..75c776e --- /dev/null +++ b/scripts/install-skills.ps1 @@ -0,0 +1,89 @@ +#!/usr/bin/env pwsh +# install-skills.ps1 — link every Compose performance skill into a target +# skills directory so flat-layout skill loaders (Claude Code, Android Studio +# Agent mode, Gemini) discover them. +# +# Background. Claude Code expects ~/.claude/skills//SKILL.md. +# This repo organizes 26 skills under //SKILL.md for human +# readability. Without links the loader cannot find the SKILL.md files. +# This script flattens the layout into the target directory by linking +# each skill folder. +# +# Usage: +# ./scripts/install-skills.ps1 # install to ~/.claude/skills +# ./scripts/install-skills.ps1 C:\custom\path # install to a custom dir +# ./scripts/install-skills.ps1 --uninstall # remove links from default target +# ./scripts/install-skills.ps1 --uninstall C:\p # remove links from a custom dir + +$ErrorActionPreference = 'Stop' + +$RepoRoot = (Resolve-Path (Join-Path $PSScriptRoot '..')).Path + +$positional = @($args) +$mode = 'install' +if ($positional.Count -ge 1 -and $positional[0] -eq '--uninstall') { + $mode = 'uninstall' + $positional = @($positional | Select-Object -Skip 1) +} +$Target = if ($positional.Count -ge 1) { $positional[0] } else { Join-Path $HOME '.claude/skills' } + +if ($mode -eq 'uninstall') { + if (-not (Test-Path -LiteralPath $Target -PathType Container)) { + Write-Host "Target directory does not exist: $Target" + exit 0 + } + Write-Host "Uninstalling Compose performance skill links from $Target" + $removed = 0 + foreach ($link in Get-ChildItem -LiteralPath $Target -Force) { + if (-not $link.Attributes.HasFlag([System.IO.FileAttributes]::ReparsePoint)) { continue } + $targetPath = $link.Target + if ($targetPath -is [array]) { $targetPath = $targetPath[0] } + if (-not $targetPath) { continue } + if ($targetPath.StartsWith($RepoRoot + [System.IO.Path]::DirectorySeparatorChar, [System.StringComparison]::OrdinalIgnoreCase)) { + [System.IO.Directory]::Delete($link.FullName, $false) + Write-Host " removed: $($link.Name)" + $removed++ + } + } + Write-Host "" + Write-Host "Removed $removed symlinks." + exit 0 +} + +New-Item -ItemType Directory -Force -Path $Target | Out-Null +Write-Host "Installing Compose performance skills" +Write-Host " source: $RepoRoot" +Write-Host " target: $Target" +Write-Host "" + +$linked = 0 +$skipped = 0 +$skillFiles = Get-ChildItem -LiteralPath $RepoRoot -Recurse -Filter 'SKILL.md' -File | + Where-Object { + $_.FullName -notmatch '[\\/]docs[\\/]' -and + $_.FullName -notmatch '[\\/]scripts[\\/]' + } +foreach ($skillMd in $skillFiles) { + $skillDir = $skillMd.Directory.FullName + $slug = $skillMd.Directory.Name + $link = Join-Path $Target $slug + + $existing = Get-Item -LiteralPath $link -Force -ErrorAction SilentlyContinue + if ($existing -and $existing.Attributes.HasFlag([System.IO.FileAttributes]::ReparsePoint)) { + $skipped++ + continue + } + elseif ($existing) { + Write-Host " WARN: $slug already exists at $link and is not a symlink; skipping" + $skipped++ + continue + } + + New-Item -ItemType Junction -Path $link -Target $skillDir | Out-Null + Write-Host " link: $slug" + $linked++ +} + +Write-Host "" +Write-Host "Linked $linked skills, skipped $skipped." +Write-Host "Restart Claude Code (or your agent) to pick them up."