# Instalador de Suzuri para la terminal. # # irm https://suzuri.app/install.ps1 | iex # # Deja UNA sola copia del codigo en la carpeta de skills de Claude Code, y un # atajo `suzuri` en el PATH que apunta a esa copia. Asi la misma instalacion # sirve para las dos cosas: Claude ve la skill en todos tus proyectos, y tu # escribes `suzuri` en cualquier terminal. # # No instala Node ni toca el registro mas alla del PATH del usuario. No pide # administrador. Todo vive dentro de tu perfil. $ErrorActionPreference = 'Stop' $Base = 'https://suzuri.app/skill' $SkillDir = Join-Path $env:USERPROFILE '.claude\skills\suzuri-vault' $BinDir = Join-Path $env:LOCALAPPDATA 'Programs\Suzuri' $Shim = Join-Path $BinDir 'suzuri.cmd' # Los mismos 12 archivos que publica /skill (INSTALL.md no hace falta: esas # instrucciones son para el agente, y este script ya hace su trabajo). $Files = @( 'SKILL.md', 'bin/vault.mjs', 'bin/lib/blocks.mjs', 'bin/lib/config.mjs', 'bin/lib/crypto.mjs', 'bin/lib/diff3.mjs', 'bin/lib/gdrive.mjs', 'bin/lib/merge.mjs', 'bin/lib/secrets.mjs', 'bin/lib/vaultfile.mjs', 'reference/google-setup.md', 'reference/note-format.md' ) function Say([string]$m) { Write-Host $m } function Ok ([string]$m) { Write-Host " OK $m" -ForegroundColor Green } function Bad([string]$m) { Write-Host " -- $m" -ForegroundColor Red } Say '' Say 'Suzuri - instalacion para la terminal' Say '' # --- 1. Node --------------------------------------------------------------- # El CLI es JavaScript, asi que Node hace falta de verdad. No lo instalamos por # ti: meter un runtime en el equipo de alguien sin preguntar no esta bien. $nodeV = $null try { $nodeV = (& node --version) 2>$null } catch { } if (-not $nodeV) { Bad 'No encuentro Node.' Say '' Say ' Suzuri necesita Node 18 o superior. Instalalo desde https://nodejs.org' Say ' (o con: winget install OpenJS.NodeJS.LTS) y vuelve a ejecutar esta linea.' Say '' return } $major = 0 if ($nodeV -match 'v(\d+)') { $major = [int]$Matches[1] } if ($major -lt 18) { Bad "Node $nodeV es demasiado antiguo (hace falta 18 o superior)." Say ' Actualizalo desde https://nodejs.org y vuelve a ejecutar esta linea.' Say '' return } Ok "Node $nodeV" # --- 2. Windows ------------------------------------------------------------ # La contrasena maestra se guarda en el Administrador de credenciales de # Windows. En otro sistema no hay donde guardarla. if ($env:OS -ne 'Windows_NT') { Bad 'Esta version solo funciona en Windows (usa su almacen de credenciales).' Say '' return } # --- 3. Descarga ----------------------------------------------------------- Say '' Say " Descargando en $SkillDir" $done = 0 foreach ($f in $Files) { $dest = Join-Path $SkillDir ($f -replace '/', '\') $dir = Split-Path $dest -Parent if (-not (Test-Path $dir)) { New-Item -ItemType Directory -Path $dir -Force | Out-Null } try { Invoke-WebRequest -Uri "$Base/$f" -OutFile $dest -UseBasicParsing $done++ } catch { Bad "No se pudo bajar $f : $($_.Exception.Message)" Say '' Say ' No se ha instalado nada a medias que puedas usar. Reintenta;' Say ' si sigue fallando, la guia manual esta en https://suzuri.app/terminal' Say '' return } } Ok "$done archivos" # Comprobacion real: que el CLI arranca de verdad, no solo que los bytes estan. $entry = Join-Path $SkillDir 'bin\vault.mjs' try { & node $entry help *> $null if ($LASTEXITCODE -ne 0) { throw "salio con codigo $LASTEXITCODE" } Ok 'El CLI responde' } catch { Bad "Los archivos estan pero el CLI no arranca: $($_.Exception.Message)" Say '' return } # --- 4. El atajo `suzuri` -------------------------------------------------- if (-not (Test-Path $BinDir)) { New-Item -ItemType Directory -Path $BinDir -Force | Out-Null } # %* pasa los argumentos tal cual, con sus comillas: las rutas con espacios # ("C:\Mis notas\baul.suzuri") llegan enteras. $shimBody = "@echo off`r`nnode `"$entry`" %*`r`n" [System.IO.File]::WriteAllText($Shim, $shimBody, (New-Object System.Text.UTF8Encoding($false))) Ok 'Atajo suzuri.cmd' # --- 5. PATH del usuario --------------------------------------------------- # Solo el PATH del usuario (nunca el del sistema): no hace falta administrador # y no afecta a nadie mas en el equipo. $userPath = [Environment]::GetEnvironmentVariable('Path', 'User') if (-not $userPath) { $userPath = '' } $already = ($userPath -split ';' | Where-Object { $_.TrimEnd('\') -ieq $BinDir.TrimEnd('\') }).Count -gt 0 if ($already) { Ok 'Ya estaba en tu PATH' } else { $sep = '' if ($userPath -and -not $userPath.EndsWith(';')) { $sep = ';' } [Environment]::SetEnvironmentVariable('Path', "$userPath$sep$BinDir", 'User') Ok 'Anadido a tu PATH' } # En ESTA sesion tambien, para que los pasos de abajo funcionen ya. if (($env:Path -split ';' | Where-Object { $_.TrimEnd('\') -ieq $BinDir.TrimEnd('\') }).Count -eq 0) { $env:Path = "$env:Path;$BinDir" } # --- 6. Que sigue ---------------------------------------------------------- Say '' Say ' Listo. Dos cosas quedan instaladas:' Say '' Say ' suzuri el comando, en cualquier terminal' Say ' la skill Claude Code la ve en todos tus proyectos' Say '' Say ' Ahora, dos pasos que solo puedes dar tu:' Say '' Say ' suzuri use "C:\ruta\a\mis-notas.suzuri" donde esta tu baul' Say ' suzuri set-password tu contrasena, la tecleas tu' Say '' Say ' Y para comprobarlo:' Say '' Say ' suzuri status' Say '' Say ' Si `suzuri` no se reconoce, abre una terminal nueva (el PATH se lee al abrir).' Say ' Google Drive es opcional: suzuri drive-setup --help' Say ''