DOC
CLI Go (v5+) — fonctionnement
CLI Go (v5+) — fonctionnement
Source :
framework/cli/· Spec détaillée :docs/spec-cli-go.md
À partir de v5, ulk est distribué comme un binaire Go unique (ulk) qui remplace progressivement install.sh. Le script bash devient un wrapper mince qui délègue au binaire si présent, sinon retombe sur l’ancienne logique.
Architecture
ulk (cobra root)
├── install cmd/install.go
├── update cmd/update.go
├── uninstall cmd/uninstall.go
├── status cmd/status.go → modules ✓/○ + version
├── verify cmd/status.go → chemins + prérequis + LLM locaux
└── check cmd/status.go → CLIs + skills installés
internal/
├── installer/
│ ├── modules.go catalogue des 14 modules
│ ├── state.go ~/.ulk/state.json (persistance atomique)
│ ├── installer.go orchestration de la copie
│ └── rollback.go backup/restore
├── config/
│ └── hooks.go fusion settings.json (hooks)
└── registry/
└── diff.go checksums SHA256 (pour update)
tui/
├── wizard.go sélecteur de modules interactif (bubbletea)
├── progress.go barre de progression (lipgloss)
└── status.go affichage statut
Flux ulk install
1. Charger state.json (~/.ulk/state.json)
└─ premier run → NewState() avec modules par défaut
2. Si premier run + pas de --no-tui :
└─ TUI wizard (bubbletea) → l'utilisateur coche/décoche les modules
3. Pour chaque module activé, Installer.Run() :
├─ copyCommands() framework/commands/ → ~/.claude/commands/ulk/
├─ copySubagents() .claude/agents/*.md → ~/.claude/agents/ulk-*.md
├─ copyUlkSkills() framework/skills/ → ~/.claude/skills/ulk-*/
├─ copyCommunitySkills() framework/community-skills/ → ~/.claude/skills/<prefix>*/
└─ mergeHooks() .claude/hooks-examples/*.json → ~/.claude/settings.json
4. Save(state) — écrit state.json atomiquement (tmp+rename)
└─ seulement si toutes les étapes ont réussi
L’écriture atomique (os.WriteFile puis os.Rename) garantit qu’un crash en cours ne corrompt pas l’état existant : soit l’ancien state.json reste en place, soit le nouveau est complet.
Les 14 modules
Définis dans internal/installer/modules.go. Chaque module a :
| Champ | Rôle |
|---|---|
Key | clé dans state.json (ex : figma-skills) |
Flag | flag CLI (ex : --with-figma-skills) |
Label / Description | affichés dans le TUI wizard |
EnabledByDefault | true pour les 4 essentiels (Figma, Swift, Flutter, context-audit) |
RemoveGlobs | chemins relatifs à ~/.claude/ à effacer sur uninstall --module |
DependsOn | modules requis avant celui-ci |
Modules disponibles : figma-skills, swift-skills, flutter-skills, context-audit, vps, agent-teams, addy-skills, a11y-skills, obsidian-skills, nothing-design, memory-loop, xavier-hook, cli-telemetry, cwb-app-icon.
State persistant — ~/.ulk/state.json
{
"version": "5.0.0",
"source": "github.com/izo/ulk",
"installedAt": "2026-04-26T12:00:00Z",
"updatedAt": "2026-04-26T12:00:00Z",
"modules": { "figma-skills": true, "vps": false },
"checksums": { "commands/ulk/bruce.md": "sha256:..." },
"claudeDir": "/Users/x/.claude",
"backup": { "path": "/tmp/ulk-backup-...", "version": "4.9.0" }
}
Trois usages :
- Savoir quels modules sont actifs (pour
statusetuninstall --module) - Détecter les fichiers modifiés (
updatecompare checksums avant copie) - Pointer vers le backup pour rollback automatique
Update intelligent
ulk update utilise internal/registry/diff.go :
- Calcule les checksums SHA256 par bucket (commands, subagents, ulk-skills, community-skills)
- Compare avec ceux dans
state.json - Affiche un diff (Added / Modified / Removed) avec
--check(dry-run) - Sans
--check: applique les changements + rollback automatique en cas d’erreur
Rollback
internal/installer/rollback.go :
- Avant install/update :
Backup()snapshot uniquement les chemins ulk-owned (préserve les configs tierces) - Sur erreur :
Restore()restaure le backup - Manuel :
ulk rollbackrevient à l’état précédent
TUI
Trois composants bubbletea/lipgloss dans tui/ :
| Fichier | Rôle |
|---|---|
wizard.go | sélecteur de modules à l’install (cases à cocher, preview, navigation clavier) |
progress.go | barre de progression pendant copie/merge |
status.go | affichage tabulaire pour ulk status |
Le wizard se lance automatiquement au premier run sauf si --no-tui ou --dry-run.
Distribution
| Cible | Outil |
|---|---|
| Build multi-arch | goreleaser (4 cibles : darwin/linux × arm64/amd64) |
| Release GitHub | .github/workflows/release.yml (tests Go pré-release) |
| Homebrew | tap OSS via goreleaser-homebrew-action (template framework/cli/homebrew/ulk.rb.template) |
Relation avec install.sh
install.sh est désormais un wrapper mince :
if command -v ulk >/dev/null 2>&1; then
exec ulk install "$@" # délègue au binaire Go
fi
# fallback : ancienne logique bash
Le binaire Go est la v5 ; le bash est conservé comme fallback de compatibilité jusqu’en v5.1, puis sera supprimé.
Build local
cd framework/cli
make build # binaire dans ./bin/ulk
make test # 75+ tests unitaires
make release-dry # simule une release goreleaser
Couverture cible :
config/hooks95% (≥90% requis)installer/state90% Load / 75% Saveregistry/diff85%installer/rollback85% / 80%
Voir aussi
- Spec complète — décomposition par tâche (ULK-160 à ULK-180)
- Audit ingénierie — décision Go vs alternatives
framework/cli/Makefile— toutes les commandes de build/test