<p align="center">
  <img src="brand/arboretum-logo-on-dark.png" alt="Arboretum" width="300">
</p>

<p align="center">
  Un dashboard web auto-hébergé pour vos worktrees git et les sessions Claude Code qui tournent dessus — depuis n'importe quel appareil.
</p>

<p align="center">
  <a href="README.md">English</a> · <strong>Français</strong>
</p>

**Statut : MVP.** Le dashboard worktree-first, la découverte et la reprise de sessions, le cycle de vie des worktrees multi-repo, le démarrage de sessions sur votre branche principale ou n'importe quel worktree, les états de session en temps réel, le terminal web, la supervision mobile (PWA installable, Web Push quand une session vous attend, répondre à une demande sans ouvrir de terminal) et les groupes de travail (piloter plusieurs repos liés depuis une seule session Claude) sont implémentés et testés.

---

## Le problème

Travailler avec des agents de code IA a changé notre usage de git : une feature = un worktree = une session Claude Code, plusieurs en parallèle. Mais l'outillage n'a pas suivi :

- `git worktree list` sur plusieurs repos est fastidieux, les worktrees s'accumulent, chacun a besoin de ses `node_modules` et `.env`.
- Les sessions Claude Code sont éparpillées : certaines tournent dans des terminaux, d'autres sont reprenables depuis l'historique, sans vue consolidée de *celle qui attend votre intervention*.
- Quand vous vous éloignez de votre poste, une session bloquée sur une demande de permission reste bloquée.

## Ce que fait Arboretum

Un unique daemon Node.js que vous lancez sur votre machine de dev (`npx @johanleroy/git-arboretum`), servant une interface web utilisable depuis votre ordinateur, téléphone ou tablette :

- **Dashboard worktree-first, multi-repo** — chaque worktree de chaque repo enregistré, avec son état git (branche, ahead/behind, fichiers modifiés) *et* l'état de sa session Claude Code (busy / en attente d'entrée / idle / reprenable).
- **Cycle de vie complet des worktrees** — créer (avec des hooks post-création par repo : `npm ci`, copie de `.env`…), adopter des worktrees créés à la main, supprimer avec garde-fous, élaguer les orphelins.
- **Découverte & reprise de sessions** — les sessions lancées dans votre propre terminal apparaissent automatiquement ; reprenez les sessions mortes, observez ou forkez les vivantes. Ne corrompt jamais une session vivante. Masquez les anciennes qui encombrent la liste (un clic efface tout l'historique externe ; elles restent reprenables).
- **Terminal web** — terminal xterm.js complet vers chaque session managée, qui survit aux déconnexions du navigateur ; vraiment plein écran, avec l'invite ancrée en bas et tout l'historique défilable au-dessus.
- **Supervision depuis votre téléphone** — PWA installable avec notifications push quand une session vous attend ; répondez à une demande (ses options, ou refusez) sans ouvrir de terminal.
- **Groupes de travail** — regroupez des repos liés (ex. une API, son frontend web et sa doc) dans un groupe nommé, puis lancez **une seule session Claude qui les couvre tous à la fois** (via le flag `--add-dir` du CLI) : une conversation unique avec un contexte partagé travaillant à travers chaque repo, plus une vue unifiée de tous leurs worktrees et une grille multi-terminaux côte à côte. Une session de groupe peut d'abord créer le même worktree de branche dans chaque repo, ou tourner directement sur les checkouts principaux.
- **Extension VS Code** — une extension native (pas un webview) qui amène l'arbre en direct, les terminaux de session natifs, les alertes d'attente et les actions git directement dans votre éditeur. Voir [Extension VS Code](#extension-vs-code).

---

## Prérequis

- **Node.js ≥ 22.16** — requis, pas seulement recommandé. Arboretum persiste son état avec `node:sqlite` (`DatabaseSync`), natif et stable seulement à partir de cette version. (`.nvmrc` fixe `22`.)
- **Le CLI `claude`** sur votre `PATH` si vous voulez qu'Arboretum lance et gère des sessions Claude Code. Arboretum enveloppe le CLI interactif que vous utilisez déjà — installez-le et authentifiez-le comme d'habitude.
- Un **dépôt git** (ou plusieurs) que vous voulez gérer.

## Démarrage rapide

Deux chemins, selon ce que vous voulez :

- **Juste l'utiliser (la plupart des gens).** Arboretum est un paquet npm publié — vous **n'avez pas besoin de cloner ce dépôt**. Pointez npm vers le registre et lancez-le (ci-dessous). À faire sur la machine où tournent vos sessions Claude Code.
- **Lancer depuis les sources.** Ne clonez le dépôt que pour développer Arboretum ou lancer une version non publiée.

### Le lancer (recommandé)

Arboretum est publié sur un registre npm Gitea auto-hébergé. Pointez le scope `@johanleroy` dessus une fois par machine — ajoutez à `~/.npmrc` :

```
@johanleroy:registry=https://git.lidge.fr/api/packages/johanleroy/npm/
```

Aucun token nécessaire — le paquet est en lecture publique. Puis lancez-le depuis n'importe où :

```bash
npx @johanleroy/git-arboretum
```

Au premier démarrage, Arboretum affiche un **token d'accès** unique et l'URL à ouvrir :

```
┌──────────────────────────────────────────────────────────────────┐
│  First start — your access token (shown once, store it safely):    │
└──────────────────────────────────────────────────────────────────┘

  <votre-token-ici>

  Login at: http://127.0.0.1:7317/
```

Ouvrez l'URL, collez le token pour vous connecter, et c'est parti. Le token est stocké **hashé** — il n'est affiché qu'une seule fois, alors gardez-le en lieu sûr (un gestionnaire de mots de passe). Vous pourrez gérer vos tokens plus tard depuis les **Réglages**.

`npx` télécharge et lance la dernière version publiée à chaque fois. Pour l'installer une bonne fois — et obtenir la commande `arboretum` sur votre `PATH`, dont se sert le [service d'arrière-plan](#le-faire-tourner-en-service-darrière-plan) —, installez-le plutôt globalement :

```bash
npm i -g @johanleroy/git-arboretum
arboretum          # identique à la commande npx, depuis le binaire installé
```

### Lancer depuis les sources

Nécessaire uniquement pour **développer** Arboretum ou lancer une version non publiée — pas pour simplement l'utiliser. Clonez le dépôt, installez les dépendances, buildez, puis démarrez le daemon :

```bash
git clone https://git.lidge.fr/johanleroy/arboretum.git
cd arboretum
nvm use            # ou assurez-vous d'avoir Node ≥ 22.16
npm install
npm run build      # build shared → server → web (l'ordre compte)
node packages/server/dist/index.js
```

## Utiliser Arboretum

1. **Ajoutez un dépôt.** Depuis le dashboard, enregistrez un repo git local par son chemin. Configurez éventuellement des **hooks post-création** (ex. `npm ci`, `cp ../.env .env`) exécutés automatiquement à chaque création d'un nouveau worktree pour ce repo.
2. **Créez ou adoptez des worktrees.** Créez un nouveau worktree + branche en un clic (les hooks s'exécutent pour vous), ou adoptez un worktree créé à la main. Chaque worktree affiche sa branche, son ahead/behind et son nombre de fichiers modifiés.
3. **Démarrez ou reprenez une session.** Lancez une session Claude Code sur la branche principale du repo ou n'importe quel worktree, ou reprenez-en une démarrée dans votre terminal — Arboretum découvre les sessions existantes automatiquement et les reprend toujours dans leur répertoire de travail d'origine.
4. **Suivez les états en direct.** Chaque session indique si elle est *busy*, *en attente de votre entrée* ou *idle*. Ouvrez le **terminal web** pour interagir directement ; il survit aux déconnexions du navigateur (fermer l'onglet ne tue pas la session).
5. **Supervisez depuis votre téléphone.** Installez la PWA, et quand une session bascule en *attente*, vous recevez une notification push. Répondez à la demande — choisissez l'une de ses options ou refusez-la — directement depuis le dashboard, sans terminal.

## Extension VS Code

Vous préférez rester dans votre éditeur ? Arboretum fournit une **extension VS Code native** (`packages/vscode`) — pas un webview. Elle se connecte au même daemon et l'expose avec les primitives natives de VS Code :

- Un arbre **Repositories** et **Groups** en direct (repos → worktrees → sessions) dans l'Activity Bar, mis à jour en temps réel via le WebSocket du daemon.
- **Terminaux natifs** : attachez-vous (ou observez) n'importe quelle session dans un vrai terminal VS Code — vous bénéficiez du rendu, du scrollback et du copier-coller de VS Code gratuitement.
- Un compteur en **status bar** et des **notifications** natives quand une session attend, avec réponses Oui/Non sans ouvrir de terminal.
- Les mutations git (créer un worktree, commit, push, promouvoir) et la **conscience du workspace** — le worktree de votre dossier ouvert est mis en évidence, avec « démarrer une session / créer un worktree ici » en un clic.

Elle est distribuée en **VSIX privé**. Buildez-la et packagez-la depuis le monorepo :

```bash
npm run build:vscode
cd packages/vscode && npx @vscode/vsce package --no-dependencies   # → git-arboretum-0.1.0.vsix
```

Puis installez-la via **Extensions : Installer à partir d'un VSIX…** (ou `code --install-extension git-arboretum-0.1.0.vsix`), lancez **Arboretum: Sign In** et collez un token. Détails complets dans [`packages/vscode/README.md`](packages/vscode/README.md).

## Accès distant depuis votre téléphone

Arboretum se bind sur `127.0.0.1` par défaut et **refuse** de se binder sur une adresse non-loopback sans dérogation explicite. La façon recommandée (et sûre) de l'atteindre depuis d'autres appareils est **[Tailscale Serve](https://tailscale.com/kb/1242/tailscale-serve)** — HTTPS valide, identité tailnet, aucun port ouvert :

```bash
# Expose le daemon local en HTTPS dans votre tailnet
tailscale serve --bg 7317
```

Puis démarrez Arboretum en autorisant l'origine de votre tailnet (le check Origin strict doit la connaître) :

```bash
npx @johanleroy/git-arboretum --allow-origin https://<machine>.<tailnet>.ts.net
```

Ouvrez `https://<machine>.<tailnet>.ts.net` depuis n'importe quel appareil de votre tailnet. **Web Push exige HTTPS**, donc Tailscale Serve (ou un autre front HTTPS) est aussi ce qui active les notifications mobiles. Sur **iOS**, installez d'abord l'app à l'écran d'accueil, puis autorisez les notifications.

> ⚠️ Un terminal web, c'est de l'exécution de code à distance **par conception**. N'exposez jamais Arboretum directement sur l'internet public.

## Le faire tourner en service d'arrière-plan

Le plus rapide pour faire tourner Arboretum en service qui survit à la déconnexion et redémarre au boot, c'est l'installeur intégré. Installez une version figée globalement, puis lancez `install` — il détecte votre OS, écrit le fichier de service, le démarre et affiche le token unique :

```bash
npm i -g @johanleroy/git-arboretum
arboretum install --allow-origin https://MACHINE.TAILNET.ts.net
```

Cela met en place un **service systemd utilisateur** sous Linux (`~/.config/systemd/user/arboretum.service`) ou un **LaunchAgent launchd** sous macOS (`~/Library/LaunchAgents/fr.lidge.arboretum.plist`). Tous les flags du daemon (`--port`, `--allow-origin`, `--db`, …) sont propagés au service. Gérez-le avec :

```bash
arboretum status      # état du service (+ où lire les logs)
arboretum uninstall   # arrête et supprime le service
```

Les logs vivent dans `journalctl --user -u arboretum -f` (Linux) ou `~/Library/Logs/arboretum/` (macOS). Lancez d'abord `arboretum install --dry-run …` pour afficher le unit/plist et les commandes exactes sans rien modifier.

<details>
<summary>Vous préférez configurer systemd à la main ? (Linux)</summary>

Créez `~/.config/systemd/user/arboretum.service` :

```ini
[Unit]
Description=Arboretum — git worktree & Claude Code dashboard
After=network-online.target
Wants=network-online.target

[Service]
ExecStart=%h/.local/bin/arboretum --port 7317 --allow-origin https://MACHINE.TAILNET.ts.net
Restart=on-failure
RestartSec=5
KillSignal=SIGTERM
TimeoutStopSec=10
Environment=NODE_ENV=production

[Install]
WantedBy=default.target
```

```bash
which arboretum                    # ajustez ExecStart au vrai chemin si besoin
systemctl --user daemon-reload
systemctl --user enable --now arboretum
loginctl enable-linger "$USER"     # démarre le service au boot, sans session ouverte
journalctl --user -u arboretum -f  # logs
```
</details>

> Le **token d'accès** unique est affiché par `arboretum install` (et au tout premier lancement manuel sur base vierge). Le token est hashé et n'est jamais réaffiché — conservez-le en lieu sûr.

## Configuration

Commandes : `arboretum` démarre le daemon (par défaut), `arboretum serve` en est un alias explicite, `arboretum install` / `uninstall` / `status` gèrent le service d'arrière-plan, et `arboretum help` affiche l'aide.

Les options du daemon sont des flags CLI :

| Flag | Défaut | Description |
|---|---|---|
| `--port <n>` | `7317` | Port d'écoute. |
| `--bind <addr>` | `127.0.0.1` | Adresse de bind. Une adresse non-loopback est refusée sauf si `--i-know-this-exposes-a-terminal` est défini. |
| `--allow-origin <url>` | — | Origine `Origin` autorisée supplémentaire (répétable). Nécessaire pour l'accès Tailscale/HTTPS. |
| `--db <path>` | `<data>/arboretum.db` | Chemin de la base SQLite. |
| `--vapid-contact <mailto/url>` | `mailto:arboretum@localhost` | Sujet de contact VAPID pour le Web Push. |
| `--print-token` | `false` | Indication sur le réaffichage du token (les tokens sont hashés et ne peuvent pas être réaffichés). |
| `--i-know-this-exposes-a-terminal` | `false` | Reconnaître le bind sur une adresse non-loopback. **À éviter** — préférez Tailscale Serve. |

`arboretum install` accepte tous les flags du daemon ci-dessus (propagés tels quels au service), plus :

| Flag | Description |
|---|---|
| `--bin-path <path>` | Utilise ce binaire dans le service au lieu de `node` + le script embarqué. |
| `--label <id>` | Label launchd (macOS uniquement, défaut `fr.lidge.arboretum`). |
| `--dry-run` | Affiche le unit/plist et les commandes sans rien appliquer. |
| `--no-enable` | Écrit le fichier de service sans l'activer/le démarrer. |

L'état (la base SQLite) vit dans `$XDG_DATA_HOME/arboretum` (par défaut `~/.local/share/arboretum`).

## Modèle de sécurité

Un terminal web, c'est de l'exécution de code à distance *par conception*. Les garde-fous d'Arboretum sont structurants :

- Se bind sur `127.0.0.1` par défaut ; refuse les binds non-loopback sans flag explicite.
- Authentifie **chaque** requête `/api/**` **et** chaque upgrade `/ws` avec des tokens révocables, et applique un **check `Origin` strict** (le cookie `SameSite=Strict` ne couvre pas les upgrades WebSocket — c'est le garde-fou anti cross-site hijacking).
- Les tokens sont stockés **hashés** (sha256) et comparés en temps constant ; le bootstrap token n'est affiché qu'une seule fois. Le cookie de session est un payload signé HMAC, `HttpOnly` et `SameSite=Strict`, et reçoit automatiquement le flag `Secure` quand la requête arrive en HTTPS (p. ex. derrière Tailscale Serve). Le login est rate-limité avec backoff exponentiel.
- Envoie des en-têtes HTTP durcis (CSP, `X-Frame-Options`, `nosniff`, `Referrer-Policy`, HSTS conditionnel, `no-store` sur l'API), restreint le dossier de données à `0o700` et la base à `0o600`, et **chiffre les secrets sensibles au repos** (AES-256-GCM).
- Tient un **journal d'audit** des opérations sensibles et offre l'**export/effacement RGPD** des données (Réglages → Sécurité & conformité).

Tailscale Serve est **la** façon d'atteindre Arboretum depuis d'autres appareils — pas seulement une recommandation : HTTPS valide, identité tailnet, aucun port ouvert. Le flag `--i-know-this-exposes-a-terminal` est une trappe de secours, pas un mode de déploiement ; n'exposez jamais Arboretum directement sur internet.

Voir [`SECURITY.md`](SECURITY.md) pour le modèle de menace complet et [`docs/ENTERPRISE_DEPLOYMENT.md`](docs/ENTERPRISE_DEPLOYMENT.md) pour le durcissement en environnement réglementé.

## Ce qui le distingue

| | Arboretum | GitKraken Agent Mode / Conductor / Nimbalyst | Happy / CloudCLI | Anthropic Remote Control |
|---|---|---|---|---|
| Interface web, tout appareil | ✅ | ❌ apps desktop | ✅ | ✅ |
| Gestion visuelle des worktrees (multi-repo) | ✅ | ✅ (mono-repo, desktop) | ❌ | ❌ |
| Découvre & reprend les sessions de terminal *existantes* | ✅ | ❌ | partiel | ❌ |
| 100 % auto-hébergé — zéro trafic via des serveurs tiers | ✅ | ✅ | serveur relais | ❌ relayé via Anthropic |
| Linux-first | ✅ | variable | ✅ | l'app desktop n'a pas de build Linux |
| Open source | MIT | ❌ / partiel | MIT / AGPL | ❌ |

Le Remote Control d'Anthropic est excellent pour piloter *une* session depuis votre téléphone. Arboretum est la couche qu'il ne fournit pas : le tableau consolidé et auto-hébergé de tous vos worktrees et sessions, à travers tous vos repos.

## Une note sur l'usage de Claude

Arboretum enveloppe le CLI Claude Code **interactif** dans un PTY — la même chose que vous lancez dans votre terminal, affichée dans votre navigateur. Il n'utilise pas l'Agent SDK ni le mode headless. Les politiques d'usage d'Anthropic autour de l'usage programmatique peuvent évoluer ; Arboretum suivra les sorties du CLI et documentera tout impact de façon transparente.

## Développement

Arboretum est un monorepo npm workspaces : `@arboretum/shared` (protocole WS/REST, source de vérité), `@johanleroy/git-arboretum` (le daemon Fastify, le paquet publié), `@arboretum/web` (la SPA Vue 3) et `git-arboretum` (l'extension VS Code — buildée séparément avec `npm run build:vscode`).

```bash
npm run build        # build shared → server → web (l'ordre compte)
npm run typecheck    # tsc -b shared + server
npm test             # vitest sur les packages
npm run dev:server   # daemon en watch
npm run dev:web      # serveur de dev Vite (proxifie /api et /ws vers le daemon sur :7317)
```

Scripts d'acceptation end-to-end (lancez `npm run build` d'abord) :

```bash
node packages/server/scripts/acceptance-p1.mjs   # cœur : daemon + client WS réel
node packages/server/scripts/acceptance-p2.mjs   # découverte & reprise de sessions
node packages/server/scripts/acceptance-p3.mjs   # worktrees & corrélation de sessions
node packages/server/scripts/acceptance-p4.mjs   # Web Push + commande WS `answer`
node packages/server/scripts/acceptance-p5.mjs   # groupes de travail : CRUD + broadcast WS + CASCADE
```

## Soutenir le projet

Arboretum est un projet personnel libre et auto-financé. S'il vous fait gagner du temps, vous pouvez soutenir son développement :

[![Buy Me a Coffee](https://img.shields.io/badge/Buy%20Me%20a%20Coffee-johanleroy-FFDD00?logo=buymeacoffee&logoColor=black)](https://buymeacoffee.com/johanleroy)

## Licence

MIT — voir [LICENSE](LICENSE).
