- leaga_skills.ps1: expune skill-urile in ~/.claude/skills prin symlink (citit si de Claude Code, si de opencode), fara copiere - rutare zona->skill in reguli_lucru pct. 7, README, AGENTS.md; skill-ul devine proprietarul procedurii, docurile raman referinta conditionata - rec_skills.md: decizia, inventarul si cum se adauga un skill nou
163 lines
6.2 KiB
PowerShell
163 lines
6.2 KiB
PowerShell
# leaga_skills.ps1 - expune folderul canonic de agent-skills al ROA catre agenti, fara sa dubleze fisiere.
|
|
# Creeaza cate un link de director (symlink) pentru fiecare skill din sursa in folderul global
|
|
# %USERPROFILE%\.claude\skills. Atat Claude Code cat si opencode citesc %USERPROFILE%\.claude\skills\<nume>\SKILL.md,
|
|
# deci un singur set de link-uri serveste ambele gazde.
|
|
# Link-urile de director cer Developer Mode pe Windows sau o consola de administrator (mklink /D).
|
|
# Utilizare:
|
|
# powershell -File COMUN\utile\leaga_skills.ps1 # leaga toate skill-urile
|
|
# powershell -File COMUN\utile\leaga_skills.ps1 -DryRun # doar listeaza ce ar face
|
|
# powershell -File COMUN\utile\leaga_skills.ps1 -Force # inlocuieste si link-urile care arata in alta parte
|
|
param(
|
|
[string]$Source = (Join-Path $PSScriptRoot '..\skills'),
|
|
[string]$Target = (Join-Path $env:USERPROFILE '.claude\skills'),
|
|
[switch]$DryRun,
|
|
[switch]$Force
|
|
)
|
|
|
|
$ErrorActionPreference = 'Stop'
|
|
|
|
function Normalize-Cale {
|
|
param([string]$Cale)
|
|
if (-not $Cale) { return '' }
|
|
([System.IO.Path]::GetFullPath($Cale)).TrimEnd('\')
|
|
}
|
|
|
|
function Ia-TintaLink {
|
|
# PowerShell 5.1 da Target ca string, PowerShell 7 ca lista de string-uri
|
|
param($Item)
|
|
$t = $Item.Target
|
|
if ($t -is [array]) { return ($t | Select-Object -First 1) }
|
|
return $t
|
|
}
|
|
|
|
function Sterge-Link {
|
|
# sterge doar link-ul (reparse point), niciodata continutul din tinta
|
|
param([string]$Link)
|
|
try {
|
|
if (Test-Path -LiteralPath $Link -PathType Container) {
|
|
[System.IO.Directory]::Delete($Link, $false)
|
|
} else {
|
|
Remove-Item -LiteralPath $Link -Force
|
|
}
|
|
return $true
|
|
} catch {
|
|
return $false
|
|
}
|
|
}
|
|
|
|
function Creeaza-Link {
|
|
# intoarce $true la succes; $script:EroareLink primeste mesajul la esec
|
|
param([string]$Link, [string]$Dir)
|
|
$script:EroareLink = ''
|
|
try {
|
|
New-Item -ItemType SymbolicLink -Path $Link -Target $Dir -ErrorAction Stop | Out-Null
|
|
return $true
|
|
} catch {
|
|
$script:EroareLink = $_.Exception.Message
|
|
}
|
|
$r = & cmd /c mklink /D "$Link" "$Dir" 2>&1
|
|
if ($LASTEXITCODE -eq 0) { return $true }
|
|
$script:EroareLink = (($r | ForEach-Object { [string]$_ }) -join ' ').Trim()
|
|
return $false
|
|
}
|
|
|
|
if (-not (Test-Path -LiteralPath $Source -PathType Container)) {
|
|
Write-Output ('leaga_skills: nu gasesc folderul sursa ' + $Source + ' - nimic de facut.')
|
|
exit 0
|
|
}
|
|
$skilluri = @(Get-ChildItem -LiteralPath $Source -Directory | Sort-Object Name)
|
|
if ($skilluri.Count -eq 0) {
|
|
Write-Output ('leaga_skills: ' + $Source + ' nu contine niciun subfolder de skill - nimic de facut.')
|
|
exit 0
|
|
}
|
|
|
|
if (-not (Test-Path -LiteralPath $Target -PathType Container)) {
|
|
if ($DryRun) {
|
|
Write-Output ('DryRun - as crea folderul tinta ' + $Target)
|
|
} else {
|
|
New-Item -ItemType Directory -Force -Path $Target | Out-Null
|
|
Write-Output ('creat folderul tinta ' + $Target)
|
|
}
|
|
}
|
|
|
|
$creat = 0; $ok = 0; $atentionat = 0; $anuntPrivilegii = $false
|
|
|
|
foreach ($s in $skilluri) {
|
|
$dir = $s.FullName
|
|
$link = Join-Path $Target $s.Name
|
|
$item = Get-Item -LiteralPath $link -Force -ErrorAction SilentlyContinue
|
|
|
|
if (-not $item) {
|
|
if ($DryRun) {
|
|
Write-Output (' ar crea ' + $s.Name + ' -> ' + $dir)
|
|
$creat++
|
|
continue
|
|
}
|
|
if (Creeaza-Link -Link $link -Dir $dir) {
|
|
Write-Output (' creat ' + $s.Name + ' -> ' + $dir)
|
|
$creat++
|
|
} else {
|
|
Write-Output (' EROARE ' + $s.Name + ' - ' + $script:EroareLink)
|
|
$atentionat++
|
|
if (-not $anuntPrivilegii) {
|
|
Write-Output ' Link-urile de director cer Windows Developer Mode (Settings > Privacy & security > For developers)'
|
|
Write-Output ' sau o consola PowerShell pornita ca administrator. Alternativ, copiaza manual folderele de skill.'
|
|
$anuntPrivilegii = $true
|
|
}
|
|
}
|
|
continue
|
|
}
|
|
|
|
if ($item.LinkType) {
|
|
$actual = Normalize-Cale (Ia-TintaLink $item)
|
|
if ($actual -eq (Normalize-Cale $dir)) {
|
|
Write-Output (' ok ' + $s.Name + ' (link deja corect)')
|
|
$ok++
|
|
continue
|
|
}
|
|
Write-Output ('Atentie: ' + $link + ' arata catre ' + $actual + ', nu catre ' + $dir)
|
|
if (-not $Force) {
|
|
Write-Output (' sarit ' + $s.Name + ' - ruleaza cu -Force ca sa il inlocuiesc.')
|
|
$atentionat++
|
|
continue
|
|
}
|
|
if ($DryRun) {
|
|
Write-Output (' ar lega ' + $s.Name + ' (inlocuieste link-ul gresit) -> ' + $dir)
|
|
$creat++
|
|
continue
|
|
}
|
|
if (-not (Sterge-Link -Link $link)) {
|
|
Write-Output (' EROARE ' + $s.Name + ' - nu pot sterge link-ul vechi.')
|
|
$atentionat++
|
|
continue
|
|
}
|
|
if (Creeaza-Link -Link $link -Dir $dir) {
|
|
Write-Output (' refacut ' + $s.Name + ' -> ' + $dir)
|
|
$creat++
|
|
} else {
|
|
Write-Output (' EROARE ' + $s.Name + ' - ' + $script:EroareLink)
|
|
$atentionat++
|
|
if (-not $anuntPrivilegii) {
|
|
Write-Output ' Link-urile de director cer Windows Developer Mode (Settings > Privacy & security > For developers)'
|
|
Write-Output ' sau o consola PowerShell pornita ca administrator.'
|
|
$anuntPrivilegii = $true
|
|
}
|
|
}
|
|
continue
|
|
}
|
|
|
|
# nume ocupat de un director/fisier real - nu il atingem niciodata
|
|
$tip = 'fisier'
|
|
if ($item.PSIsContainer) { $tip = 'director real' }
|
|
Write-Output (' sarit ' + $s.Name + ' - ' + $tip + ' exista deja la ' + $link + '; nu il sterg si nu il suprascriu.')
|
|
$atentionat++
|
|
}
|
|
|
|
Write-Output ''
|
|
if ($DryRun) {
|
|
Write-Output ('leaga_skills (DryRun): ' + $creat + ' de creat, ' + $ok + ' ok, ' + $atentionat + ' atentionari')
|
|
} else {
|
|
Write-Output ('leaga_skills: ' + $creat + ' create, ' + $ok + ' ok, ' + $atentionat + ' atentionari')
|
|
}
|
|
exit 0
|