Développement
lazyshell est un projet Go sans génération de code ni étape de build exotique :
go build, go test, golangci-lint.
Construire et tester
$ make build # go build -o bin/lazyshell ./cmd/lazyshell
$ make test # go test -race ./...
$ make lint # golangci-lint run
L'intégration continue exécute les mêmes commandes sur ubuntu-latest et
macos-latest, plus un budget de performance
(go test -run TestPerfBudget ./...). La version de golangci-lint est
épinglée dans le workflow, pour que la CI et make lint ne puissent pas diverger.
Structure des paquets
cmd/
lazyshell/ point d'entrée
spike-pty/ spike pty de la phase 1 (référence, hors binaire livré)
pkg/
app/ amorçage : charge la config, construit le SessionManager, lance gui.Run()
session/ SessionManager : CRUD (New, Kill, List) ; Session{cmd, ptmx, scrollback,
status} ; Env() (au lancement) et Stats() (CPU/RSS/disque par OS)
screen/ émulateur de terminal derrière le panneau de sortie (vim/htop/less)
gui/ init gocui, layout, raccourcis, souris, panneaux, onglets, aide, thème,
notifications, stats
tasks/ TaskManager (goroutines d'affichage et de lecture uniquement)
agent/ détection d'état des agents IA (sans config + par hooks)
hook/ canal de hooks autoritaire pour les sessions d'agent
config/ config utilisateur et config de projet (lazyshell.yml)
keys/ définition des raccourcis
i18n/ chaînes et traductions
version/ métadonnées --version (injectées par goreleaser)
docs/
adr/ décisions d'architecture
repports/ rapports d'analyse historiques
Décisions d'architecture
-
Bibliothèque de base :
github.com/jesseduffield/gocui, aveclazycore/pkg/boxlayoutpour la découpe liste / sortie et l'empilement en mode portrait. -
Raccourcis : des
Binding{ViewName, Key, Modifier, Handler}plats passés àg.SetKeybinding, à la manière de lazydocker — pas de pile de contextes et de contrôleurs à la lazygit. -
Tâches asynchrones :
pkg/tasksne possède que les goroutines d'affichage et de lecture, jamais le process shell sous-jacent. Changer de sélection annule le lecteur de la session précédente, pas son pty : le shell continue de tourner quoi qu'il y ait à l'écran. -
Pty :
github.com/creack/pty, un pty par session,pty.Setsizepropagé depuis la taille calculée du panneau au redimensionnement, et un véritable émulateur de terminal — pas un simple filtrage ANSI — pour que les applications plein écran fonctionnent réellement. -
Cycle de vie des process :
pkg/session.Managerpossède lamap[sessionID]*Sessionet garde les shells vivants à travers les changements de sélection, découplé depkg/tasks. -
Couplage agent contenu : hors de
notify.goetstats.go, rien danspkg/sessionnipkg/guine connaît de format propre à un agent — tout est danspkg/agentetpkg/hook.
ADR
ROADMAP.md raconte l'histoire phase par phase : ce qui est construit, ce qui reste ouvert, et pourquoi.
Contribuer
- Périmètre. Windows est hors périmètre assumé (pas de pty Unix). Le mode détaché / démon (« les agents continuent avec le portable fermé ») l'est aussi, sauf demande réelle.
- API de contrôle par les agents (un agent qui crée des panneaux ou lit la sortie d'autres sessions via une socket) : écartée pour l'instant. La socket de hooks est entrante et déclarative uniquement ; un verbe sortant serait une décision séparée, délibérément pas encore prise.
-
Avant d'ouvrir une pull request :
make testetmake lintdoivent passer, et la course (-race) doit rester verte.