README : remise à jour et simplification, nouvelle capture d'écran

Le README avait pris du retard sur les versions 0.5 et 0.6. Ajouts : serveurs
MCP (format mcp.json compatible Claude Desktop, transports stdio et HTTP),
compactage automatique du contexte, commandes app et oai, téléchargement de
modèles depuis l'UI.

Corrections : le mode agent donne désormais terminal, écriture/édition de
fichiers, mémoire, web et MCP — pas seulement « shell + mémoire ». La section
Windows ne parle plus de « jean tools ». Tableaux de config et de variables
d'environnement complétés (COMPACT, CRAWL4AI_KEY, JEAN_MODEL_DIRS, HF_TOKEN,
JEAN_DL_CONNS).

Structure resserrée : commandes regroupées par usage plutôt que par ordre
historique, sections longues raccourcies sans perte d'information.
This commit is contained in:
nathaninline committed 2026-08-03 17:26:49 +02:00
1 parent 7b0a5dbf75
commit 0e6763920b
2 files changed
+169 -217

No files matched your search

+169 -217
View File
@@ -2,325 +2,277 @@
![Interface web d'AJEAN](docs/ui.png)
**Un gestionnaire mono-binaire pour serveurs [llama.cpp](https://github.com/ggml-org/llama.cpp) auto-hébergés — avec une interface web intégrée, un chat terminal, et un compilateur de backend qui détecte automatiquement le matériel.**
Dépose un seul binaire sur une machine, lance `jean llamacpp install`, et AJEAN clone, configure et compile llama.cpp pour le matériel de *cette* machine (CUDA / ROCm / Metal / Vulkan / CPU) — aucun flag à retenir. Ensuite `jean start` et tu as un endpoint compatible OpenAI avec un chat web par-dessus.
**Un seul binaire pour faire tourner [llama.cpp](https://github.com/ggml-org/llama.cpp) chez toi : il compile le backend pour ton matériel, tient le service, et te donne un chat web complet par-dessus.**
```
télécharge le binaire → jean llamacpp install → jean edit → jean start → c'est parti
```
Aucune dépendance à l'exécution, aucun flag CMake à retenir, aucun conteneur. Tu obtiens un endpoint compatible OpenAI et une interface web avec chat, mémoire, accès internet et outils.
---
## Pourquoi
## Ce que ça fait
Faire tourner llama.cpp comme un vrai service, ça veut dire d'habitude : trouver les bons flags CMake pour ton GPU, écrire une unité systemd, gérer une clé API, changer de modèle, garder le build à jour… AJEAN transforme tout ça en quelques sous-commandes derrière un binaire statique unique, **sans dépendance à l'exécution** (à part llama.cpp lui-même, que AJEAN peut compiler pour toi).
**Le backend, tout seul.** `jean llamacpp install` clone et compile llama.cpp avec les bons flags pour *cette* machine : CUDA (capacité de calcul détectée par GPU, donc le multi-GPU marche), ROCm, Metal, Vulkan, ou repli CPU. `jean llamacpp update` récupère le dernier commit, arrête le service le temps de recompiler, et le redémarre.
## Fonctionnalités
**Le service.** `jean install` écrit l'unité systemd, la règle sudoers et les dossiers. Ensuite `start` / `stop` / `status` / `logs`. Sous Windows et macOS, voir plus bas.
- **`jean llamacpp install` / `update`** — clone et compile llama.cpp avec les bons flags **détectés automatiquement** pour l'hôte :
- **CUDA** quand un GPU NVIDIA + `nvcc` sont présents (compute capability détectée par GPU via `nvidia-smi`, donc les machines multi-GPU compilent pour toutes les cartes)
- **ROCm/HIP** (AMD), **Metal** (macOS / Apple Silicon), **Vulkan**, ou repli **CPU**
- `update` récupère le dernier commit, arrête le service le temps de recompiler, puis le redémarre
- **Intégration systemd** — `jean install` écrit l'unité, une règle sudoers `systemctl` sans mot de passe, et les dossiers de données
- **Interface web** (`jean web`) — chat, changement de modèle/preset, mode agent, accès internet/mémoire, panneau « Accès OpenAI », et réglages d'apparence (thème sombre/clair/doux, mode complet/simple) synchronisés entre appareils
- **Chat terminal** (`jean chat`) — réponses en streaming
- **Accès internet** (`jean internet`) — branche un serveur [Crawl4AI](https://github.com/unclecode/crawl4ai) et l'IA gagne 4 outils web (`web_search` DuckDuckGo, `web_open`, `web_read`, `web_grep`), actifs seulement si le mode agent est actif et le serveur joignable
- **Mémoire persistante à 3 modes** (`jean memory`) — l'IA garde des notes Markdown entre les sessions ; réglable en `off` / `ondemand` (utilisée seulement quand tu le demandes) / `always` (proactive)
- **Accès distant chiffré** (`jean link`) — connecte ce serveur à [ajean.link](https://ajean.link) par une connexion **sortante** (aucun port à ouvrir, marche même en CGNAT). Le chat est **chiffré de bout en bout** : le relais ne voit jamais tes conversations (voir [Sécurité — boîte noire](#sécurité--boîte-noire))
- **Presets** (`jean switch`) — garde plusieurs profils `config.env` et bascule entre eux
- **Protection par clé API** (`jean set-api-key`) — auth Bearer pour exposer le serveur publiquement ; la clé est stockée à part pour survivre aux changements de preset
- **Benchmark** (`jean bench`) — tok/s prefill/decode honnêtes avec un corpus varié
- **Auto-mise à jour** (`jean update`) — récupère la dernière release GitHub et remplace le binaire en place (`--check` pour seulement vérifier)
- **Binaire unique** — statique (`CGO_ENABLED=0`) sur Linux et Windows, se cross-compile trivialement ; la build macOS ajoute juste Cocoa pour l’icône de barre de menus
**Le chat web** (`jean web`, ou `jean app` pour ouvrir le navigateur d'un coup). Changement de modèle et de preset, réglages d'apparence synchronisés entre appareils, prompt système éditable, téléchargement de modèles depuis un lien `.gguf`, et un compactage automatique du contexte quand la conversation devient longue.
## Démarrage rapide
**Le mode agent** (`jean agent on`) — un seul interrupteur qui donne à l'IA ses vrais outils :
### 1. Récupère le binaire
| Outil | Rôle |
|---|---|
| terminal | exécute une commande (bash sous Unix, `cmd.exe` sous Windows) |
| write / edit | écrit un fichier, ou le modifie par remplacement exact |
| mem_* | mémoire Markdown persistante entre les sessions |
| web_* | recherche et lecture de pages, via Crawl4AI |
| mcp__* | les outils de tes serveurs MCP |
Prends un binaire pré-compilé depuis la page [Releases](../../releases), ou [compile depuis les sources](#compiler-depuis-les-sources) :
**Accès distant chiffré** (`jean link`) — une connexion sortante vers [ajean.link](https://ajean.link), donc aucun port à ouvrir, et ça marche en CGNAT. Le chat est chiffré de bout en bout : le relais ne voit jamais tes conversations.
## Démarrage
### 1. Le binaire
```bash
# exemple : Linux x86_64
curl -L -o jean https://github.com/nathaninline/jean/releases/latest/download/jean-linux-amd64
chmod +x jean
sudo mv jean /usr/local/bin/jean
```
### 2. Installe (unité systemd, dossiers, sudoers)
(Autres cibles sur la page [Releases](../../releases) : Linux/macOS/Windows, amd64 et arm64.)
### 2. Installe et compile
```bash
sudo jean install
sudo jean install # unité systemd, sudoers, dossiers
jean llamacpp install # compile llama.cpp pour ton GPU
```
### 3. Compile un backend llama.cpp pour cette machine
Nécessite `git` et `cmake`, plus le toolkit de ton accélérateur (CUDA, ROCm…) pour le GPU.
```bash
jean llamacpp install
```
AJEAN détecte ton accélérateur, compile `llama-server`, et pointe la config sur le nouveau binaire. Nécessite `git` et `cmake` (plus le toolkit correspondant, ex. CUDA, si tu veux l'accélération GPU).
### 4. Pointe-le sur un modèle et démarre
### 3. Démarre
```bash
jean edit # règle MODEL=/chemin/vers/ton-modele.gguf
jean start
jean test # vérifie que le modèle répond
jean web # http://<hôte>:8090
```
### 5. (optionnel) Interface web
```bash
jean web # http://<hôte>:8090
```
## Windows
AJEAN fonctionne aussi sur Windows. Les différences avec Linux :
- **Pas de systemd.** `jean start` lance `jean serve` en arrière-plan (processus détaché), suivi via un fichier PID. `stop` / `restart` / `status` / `logs` agissent dessus — aucun droit administrateur requis. `enable` / `disable` (démarrage au boot) ne sont pas gérés : utilise une tâche planifiée ou `sc.exe` si tu en as besoin.
- **`JEAN_HOME`** vaut par défaut `%ProgramData%\jean` (repli `%LOCALAPPDATA%\jean`). Surcharge avec la variable d'environnement `JEAN_HOME`.
- **`jean install`** crée seulement le dossier de données et un `config.env` de départ (pas de sudoers ni de symlink). Ajoute toi-même le dossier de `jean.exe` au `PATH` pour l'appeler de partout.
- **`jean edit`** ouvre `notepad` par défaut (surchargeable via `%EDITOR%`).
- **`jean tools`** exécute les commandes via `cmd /C` (au lieu de `bash`).
```powershell
# depuis PowerShell
jean install # crée %ProgramData%\jean\config.env
jean edit # règle BIN=...\llama-server.exe et MODEL=...\modele.gguf
jean start
jean status
jean logs # suit %ProgramData%\jean\jean.log
```
`jean llamacpp install` peut compiler llama.cpp si `git` et `cmake` sont présents ; sinon récupère un binaire `llama-server.exe` pré-compilé et pointe `BIN` dessus avec `jean edit`.
## macOS
Comme sous Windows, tu peux lancer AJEAN **d'un simple clic** : la page [Releases](../../releases) publie `Jean-macos-arm64.zip` / `Jean-macos-amd64.zip`, un bundle **`Jean.app`**. Dézippe, glisse-le dans *Applications*, ouvre-le : AJEAN démarre son UI web sur `http://localhost:8090`, l'ouvre dans le navigateur et pose son **icône dans la barre de menus** (en haut à droite) — pendant exact du system tray Windows, avec « Ouvrir AJEAN » / « Quitter ». Pas de fenêtre de Terminal, pas d'icône dans le Dock.
L'app n'est **pas signée** par un certificat Apple (seulement ad-hoc) : au premier lancement, fais **clic droit → Ouvrir** (ou *Réglages Système → Confidentialité et sécurité → Ouvrir quand même*).
Pour l'usage CLI, prends le binaire nu `jean-darwin-arm64` (ou `-amd64`) et mets-le dans `/usr/local/bin/jean` : hors bundle, il garde son comportement en ligne de commande. Les services utilisent **launchd** (pas systemd).
## Commandes
```
Application :
app lance l'UI web + ouvre le navigateur (auto au double-clic)
web [PORT] UI web seule (défaut :8090)
chat [prompt-système] chat dans le terminal
Service :
start | stop | restart gérer le service systemd
start | stop | restart gérer le service
status | logs état / logs en direct
enable | disable démarrage au boot
edit éditer $JEAN_HOME/config.env
set-api-key [clé] protéger llama-server (Bearer) ; vide = générer, "" = retirer
set-web-key [clé] protéger l'API de pilotage 'jean web' ; vide = générer, "" = retirer
vram utilisation GPU/VRAM (nvidia-smi)
gpu [index…] liste les GPU / choisit le(s)quel(s) utiliser (gpu all = tous)
test vérifie que le modèle répond (health + completion)
bench [N] mesure prefill + decode tok/s
test | bench [N] vérifier que ça répond / mesurer les tok/s
vram | gpu [index…] VRAM / choix des GPU (gpu all = tous)
set-api-key [clé] protéger llama-server (Bearer)
set-web-key [clé] protéger l'API de pilotage
Presets :
switch [N] choisir un preset dans configs/ (interactif ou par numéro)
Capacités de l'IA :
agent [on|off|status] active TOUS les outils (terminal, fichiers, mémoire)
memory [off|ondemand|always] mode mémoire
internet [on|off|url <url>|key <clé>] accès web via Crawl4AI
Interaction :
chat [system-prompt] chat terminal streamé
web [PORT] interface web (défaut :8090)
internet [on|off|status|url <url>] accès web de l'IA via un serveur Crawl4AI
memory [off|ondemand|always|status] mode mémoire de l'IA (off / sur demande / auto)
Presets et backend :
switch [N] changer de preset (configs/)
llamacpp install|update|status
Accès distant (ajean.link) :
link [token] démarre le lien au relais en arrière-plan (token = 1re fois / pour le changer)
link start | restart | stop démarre / redémarre / arrête le service de lien
link code génère un code d'appairage (valable 10 min, usage unique) pour le portail
link status | logout état du lien / oublier le token
Mode agent :
agent [on|off|status] active TOUS les outils du modèle (shell complet + mémoire) — un seul interrupteur
Backend (llama.cpp) :
llamacpp install clone + compile llama.cpp (détecte CUDA/ROCm/Metal/CPU), règle BIN
llamacpp update git pull + recompile le backend existant (arrête/redémarre le service)
llamacpp status commit courant, backend détecté, commits de retard sur origin
link <token> enregistre le token et démarre le lien
link start|restart|stop gérer le service de lien
link code code d'appairage (10 min, usage unique)
link status|logout
Installation :
install installer (unité systemd, sudoers, dossiers)
uninstall désinstaller
update [--check] mettre à jour jean depuis les releases GitHub (--check = signale sans installer)
version affiche la version installée
install | uninstall
update [--check] se mettre à jour depuis les releases GitHub
version
```
### Options de `jean llamacpp`
```
install [--dir=CHEMIN] [--ref=REF_GIT] [--force] [--no-switch]
update [--ref=REF_GIT] [--clean] [--no-restart] [--force]
```
- `--dir=` — où cloner (défaut `$JEAN_HOME/backends/llama.cpp`)
- `--ref=` — compiler une branche/tag/commit précis
- `--clean` — vide `build/` et recompile de zéro
- `--no-switch` — ne touche pas à `config.env` (install seulement)
- `--no-restart` — laisse le service arrêté après la mise à jour
## Configuration
Tout vit sous **`$JEAN_HOME`** (défaut `/etc/jean` sur Linux/macOS, `%ProgramData%\jean` sur Windows). Le service lit `config.env` :
Tout vit sous **`$JEAN_HOME`** (`/etc/jean` sous Linux/macOS, `%ProgramData%\jean` sous Windows). Le service lit `config.env` :
| Clé | Signification | Défaut |
|-----|---------------|--------|
| `BIN` | chemin vers `llama-server` (réglé par `llamacpp install`) | — |
| `MODEL` | nom de fichier (cherché dans les dossiers de modèles) ou chemin complet vers le `.gguf` | — |
| `MODEL` | nom de fichier ou chemin complet du `.gguf` | — |
| `HOST` / `PORT` | adresse / port d'écoute | `0.0.0.0` / `8080` |
| `CTX` | taille du contexte | `32768` |
| `NGL` | couches à déporter sur le GPU | `999` |
| `NGL` | couches déportées sur le GPU | `999` |
| `BATCH` / `UBATCH` | batch / micro-batch | `2048` / `512` |
| `THREADS` / `THREADS_BATCH` | threads CPU | `0` (auto) |
| `CUDA_VISIBLE_DEVICES` | GPU à utiliser (réglé par `jean gpu`) | tous |
| `KV_TYPE` (`_K`/`_V`) | quantization du cache KV | — |
| `KV_TYPE` (`_K` / `_V`) | quantization du cache KV | — |
| `CUDA_VISIBLE_DEVICES` | GPU utilisés (réglé par `jean gpu`) | tous |
| `REASONING` | passthrough du mode raisonnement | — |
| `REASONING_BUDGET` | plafond de tokens de réflexion passé à llama-server ; `-1` = illimité | `-1` |
| `CRAWL4AI_URL` | URL du serveur Crawl4AI pour l'accès internet (réglé par `jean internet url`) | — |
| `MEM_MODE` | mode mémoire de l'IA : `off` / `ondemand` / `always` (réglé par `jean memory`) | `always` |
| `REASONING_BUDGET` | plafond de tokens de réflexion ; `-1` = illimité | `-1` |
| `COMPACT` | compactage automatique du contexte (`off` pour couper) | activé |
| `MEM_MODE` | mémoire : `off` / `ondemand` / `always` | `always` |
| `CRAWL4AI_URL` / `CRAWL4AI_KEY` | serveur d'accès internet | — |
| `EXTRA_ARGS` | ajouté tel quel à `llama-server` | — |
La clé API (quand elle est définie avec `jean set-api-key`) est stockée dans `$JEAN_HOME/.api_key`, séparément de `config.env`.
La clé API (`jean set-api-key`) vit dans `$JEAN_HOME/.api_key`, à part, pour survivre aux changements de preset.
**Modèles sur un autre disque.** Les `.gguf` n'ont pas à vivre dans `$JEAN_HOME` : dans l'éditeur de preset de l'UI web, section *Modèle → Dossiers de modèles*, ajoutez le dossier de votre disque externe. Ses modèles apparaissent alors dans la liste déroulante, groupés par dossier. La liste est enregistrée dans `$JEAN_HOME/model_dirs.json` (elle survit donc aux changements de preset) et peut aussi être fournie par `JEAN_MODEL_DIRS` (dossiers séparés par `:`, `;` sous Windows). Les téléchargements, eux, atterrissent toujours dans `$JEAN_HOME`.
**Modèles sur un autre disque.** Les `.gguf` n'ont pas à vivre dans `$JEAN_HOME` : dans l'éditeur de preset de l'UI, section *Modèle → Dossiers de modèles*, ajoute le dossier de ton disque externe. Ses modèles apparaissent dans la liste, groupés par dossier. Enregistré dans `model_dirs.json`, donc conservé d'un preset à l'autre.
### API de pilotage à distance
### Variables d'environnement
`jean web` expose une API HTTP pour piloter AJEAN à distance : status, VRAM, liste/sélection de presets (switch de modèle), démarrage/arrêt/redémarrage du service, chat. Pour l'exposer sur internet en sécurité, protège-la par une clé :
| Variable | Rôle | Défaut |
|----------|------|--------|
| `JEAN_HOME` | racine des données | `/etc/jean`, `%ProgramData%\jean` |
| `JEAN_MODEL_DIRS` | dossiers de modèles (`:`, `;` sous Windows) | — |
| `JEAN_SERVICE` | nom de l'unité systemd | `jean` |
| `HF_TOKEN` | token Hugging Face pour les modèles privés | — |
| `JEAN_DL_CONNS` | connexions parallèles au téléchargement | — |
| `EDITOR` | éditeur pour `jean edit` | `nano` / `notepad` |
```
jean set-web-key # génère une clé aléatoire
jean web 8090 # sert l'API/UI sur :8090
## Les outils de l'IA
### Mémoire
L'IA tient des pages Markdown sous `$JEAN_HOME/MEMORY/`, relues et mises à jour entre les sessions. Trois modes, indépendants du mode agent :
```bash
jean memory always # (défaut) elle cherche avant de répondre et sauve d'elle-même
jean memory ondemand # outils dispo, mais seulement quand tu le demandes
jean memory off # coupée
```
Chaque appel `/api/*` doit alors présenter la clé (la page HTML/JS, elle, reste publique car sans secret) :
### Accès internet
```
Authorization: Bearer <clé>
```
Endpoints utiles pour un client :
| Méthode | Endpoint | Rôle |
|---------|----------|------|
| GET | `/api/ping` | vérifie connectivité + validité de la clé (200 / 401) |
| GET | `/api/status` | état du service (active, health, port) |
| GET | `/api/vram` | usage GPU/VRAM |
| GET | `/api/presets` | liste des presets (avec l'actif) |
| POST | `/api/switch` `{"n":<index 1-based>}` | switch de modèle/preset |
| POST | `/api/start` · `/api/stop` · `/api/restart` | piloter le service |
| POST | `/api/chat` `{"messages":[…]}` | chat (flux SSE) |
La clé est stockée dans `$JEAN_HOME/.web_key`, distincte de `.api_key` (pilotage ≠ accès complétions), et relue à chaud à chaque requête. Le pilotage du service est cross-platform (systemd sous Linux, supervision par PID-file sous Windows).
> ⚠️ La clé voyage en clair en HTTP. Pour une exposition publique, place AJEAN derrière un reverse-proxy HTTPS (Caddy, nginx) ou un tunnel (Tailscale, Cloudflare Tunnel).
### Accès internet de l'IA (Crawl4AI)
Par défaut l'IA n'a pas accès au web. En branchant un serveur [Crawl4AI](https://github.com/unclecode/crawl4ai) (Chrome headless), elle gagne quatre outils : `web_search` (DuckDuckGo), `web_open` (récupère une page → métadonnées + plan), `web_read` (lit une plage de lignes) et `web_grep` (regex dans une page ouverte).
**AJEAN ne fournit pas le serveur Crawl4AI, il s'y branche** — c'est à toi de l'héberger (sur la même machine ou ailleurs), typiquement en Docker :
Par défaut l'IA n'a pas le web. En branchant un serveur [Crawl4AI](https://github.com/unclecode/crawl4ai), elle gagne `web_search` (DuckDuckGo), `web_open`, `web_read` et `web_grep`. **AJEAN ne fournit pas le serveur, il s'y branche :**
```bash
docker run -d -p 11235:11235 --shm-size=1g unclecode/crawl4ai:latest
jean internet url http://localhost:11235
jean internet on
jean internet status
```
Puis côté AJEAN :
Les outils web ne sont proposés au modèle que si le mode agent est actif, l'accès internet activé **et** le serveur joignable — sinon ils n'existent pas, donc il ne peut pas les inventer.
### Serveurs MCP
AJEAN parle le [Model Context Protocol](https://modelcontextprotocol.io) : tu branches des serveurs tiers (fichiers, bases de données, API…) et leurs outils s'ajoutent à ceux de l'IA, nommés `mcp__<serveur>__<outil>`.
La configuration se fait dans l'interface web (section *Serveurs MCP*) ou en éditant `$JEAN_HOME/mcp.json`, au **même format que Claude Desktop** — un fichier existant se réutilise tel quel :
```json
{
"mcpServers": {
"fs": { "command": "npx", "args": ["-y", "@modelcontextprotocol/server-filesystem", "/data"] },
"api": { "url": "https://exemple.com/mcp" }
}
}
```
Les transports **stdio** et **HTTP** sont gérés. Comme le terminal, un serveur MCP exécute du code sur ta machine : ses outils ne sont donnés au modèle que si le mode agent est actif.
## Windows
- **Pas de systemd** : `jean start` lance le service en arrière-plan (suivi par fichier PID), `stop` / `restart` / `status` / `logs` agissent dessus, sans droits administrateur. `enable` / `disable` ne sont pas gérés — passe par une tâche planifiée.
- `JEAN_HOME` vaut `%ProgramData%\jean` (repli `%LOCALAPPDATA%\jean`).
- `jean install` crée seulement le dossier de données et un `config.env` de départ.
- Le terminal de l'IA passe par `cmd.exe`. Elle le sait, et elle écrit ses fichiers par l'outil dédié plutôt que par le shell — c'est ce qui lui permet de produire des scripts contenant des guillemets.
```powershell
jean install
jean edit # BIN=...\llama-server.exe et MODEL=...\modele.gguf
jean start
jean status
```
`jean llamacpp install` compile aussi sous Windows si `git` et `cmake` sont là ; sinon récupère un `llama-server.exe` pré-compilé et pointe `BIN` dessus.
## macOS
La page [Releases](../../releases) publie `Jean-macos-arm64.zip` / `Jean-macos-amd64.zip`, un bundle **`Jean.app`**. Dézippe, glisse dans *Applications*, ouvre : l'UI démarre sur `http://localhost:8090`, s'ouvre dans le navigateur, et l'icône se pose dans la **barre de menus**. Pas de Terminal, pas d'icône dans le Dock.
L'app n'est signée qu'en ad-hoc : au premier lancement, **clic droit → Ouvrir**.
Pour la ligne de commande, prends le binaire nu `jean-darwin-arm64` : hors bundle, il se comporte en CLI classique. Les services passent par **launchd**.
## Accès distant via ajean.link
`jean link` ouvre une connexion **sortante** vers le relais : ton serveur reste injoignable de l'extérieur, mais tu y accèdes de partout.
```bash
jean internet url http://localhost:11235 # URL de ton serveur Crawl4AI
jean internet on # active l'accès web
jean internet status # vérifie que le serveur est joignable
jean link <token> # token fourni sur ajean.link
jean link code # code d'appairage à saisir dans le portail
```
Les outils web ne sont proposés au modèle que si **trois conditions** sont réunies : le **mode agent** est actif (`jean agent on`), l'accès internet est activé, **et** le serveur Crawl4AI répond. Sinon ils n'apparaissent pas — le modèle ne peut donc pas les inventer. Réglable aussi depuis l'interface web (section « Accès internet ») et disponible à distance via ajean.link (les outils s'exécutent sur ton serveur, à travers la boîte noire chiffrée).
### Mémoire de l'IA (3 modes)
L'IA peut tenir une mémoire persistante — des pages Markdown sous `$JEAN_HOME/MEMORY/` qu'elle relit et met à jour entre les sessions. Le comportement se règle en trois modes, indépendamment du mode agent :
```bash
jean memory always # (défaut) l'IA cherche avant de répondre et sauve d'elle-même
jean memory ondemand # outils dispo, mais utilisés seulement quand tu le demandes
jean memory off # mémoire coupée : aucun accès en lecture ni écriture
jean memory status
```
### Accès distant via ajean.link
Plutôt que d'exposer un port, `jean link` ouvre une connexion **sortante** vers le relais [ajean.link](https://ajean.link) : ton serveur reste injoignable depuis l'extérieur, mais tu y accèdes quand même depuis n'importe où — idéal derrière une box ou en CGNAT.
```bash
jean link <token> # token fourni sur ajean.link ; démarre le lien en arrière-plan
jean link code # un code d'appairage à saisir une fois dans le portail
```
`jean link` tourne comme un **service** (au même titre que `jean` lui-même) : la commande rend la main aussitôt, le lien continue en tâche de fond. Gestion : `jean link restart`, `jean link stop`, `jean link status`. (Pas besoin de `jean web` : l'UI est servie dans le tunnel.)
Une fois lié, tu retrouves depuis le portail :
- l'**interface web** de ton serveur, à distance, avec un **chat chiffré de bout en bout** ;
- la gestion de **plusieurs serveurs** et d'**agents** depuis un tableau de bord ;
- en option, un **endpoint compatible OpenAI** (voir ci-dessous).
Le lien tourne comme un service : la commande rend la main, la connexion continue en tâche de fond. Pas besoin de `jean web` — l'UI est servie dans le tunnel. Tu retrouves depuis le portail l'interface de ton serveur avec un chat chiffré, la gestion de plusieurs machines, et en option un endpoint compatible OpenAI.
C'est un service optionnel et payant ; tout le reste d'AJEAN est et restera open source et gratuit.
### Sécurité — boîte noire
`jean link` est conçu pour que le relais ajean.link soit un **pur tube aveugle** : il transporte tes données mais ne peut pas les lire.
Le relais est conçu comme un **tube aveugle** : il transporte tes données sans pouvoir les lire.
- **Chat chiffré de bout en bout.** Le chat entre ton navigateur et ton serveur AJEAN est chiffré (X25519 + AES-GCM) : le relais ne voit ni tes prompts ni les réponses, seulement de l'opaque. La clé est dérivée de ton mot de passe (protocole **OPAQUE**) et ne quitte jamais ton navigateur.
- **Empreinte vérifiée.** `jean link` affiche une empreinte de la clé de la machine, à confirmer une fois dans le portail — ça défait toute tentative d'interception par le relais.
- **Appairage authentifié.** En plus de l'empreinte, tu autorises ton navigateur avec un **code d'appairage** (`jean link code`) : à usage unique et valable 10 min, il garantit que seul *ton* navigateur peut piloter le serveur — même un relais compromis ne peut pas forger de commande.
- **Aucun chat en clair par le relais.** L'ancien chemin en clair est refusé à travers le tunnel ; seul le chemin chiffré transporte du contenu.
- **Code servi hors du relais.** Le portail web est livré par une origine indépendante (GitHub Pages), pas par le relais — donc même compromis, le relais ne peut pas injecter de code piégé pour voler ta clé.
- **Chat chiffré de bout en bout** (X25519 + AES-GCM). La clé est dérivée de ton mot de passe via **OPAQUE** et ne quitte jamais ton navigateur.
- **Empreinte vérifiée.** `jean link` affiche l'empreinte de la clé de la machine, à confirmer une fois dans le portail — ça défait toute interception par le relais.
- **Appairage authentifié.** Un code à usage unique (`jean link code`) garantit que seul *ton* navigateur pilote le serveur ; même compromis, le relais ne peut pas forger de commande.
- **Code servi hors du relais.** Le portail vient d'une origine indépendante (GitHub Pages) : le relais ne peut pas injecter de code pour voler ta clé.
> Reste visible du relais : des métadonnées techniques sans contenu (machine en ligne, nom du modèle chargé, VRAM) — jamais tes conversations.
Reste visible du relais : des métadonnées techniques (machine en ligne, modèle chargé, VRAM) — jamais tes conversations.
#### Endpoint OpenAI (`<machine>.oai.ajean.link`) — opt-in
### Endpoint OpenAI (opt-in)
Pour brancher des outils tiers (OpenCode, etc.), AJEAN peut exposer un endpoint compatible OpenAI **par machine** : `https://<machine>.oai.ajean.link/v1`. L'authentification est la clé API de ton `llama-server` (`jean set-api-key`), présentée en `Authorization: Bearer <clé>`. C'est **désactivé par défaut**.
Pour brancher des outils tiers, AJEAN expose au besoin `https://<machine>.oai.ajean.link/v1`, authentifié par la clé de ton `llama-server`. **Désactivé par défaut**, activable par machine depuis l'UI (panneau *Accès OpenAI*), sans redémarrage.
Tu l'actives par machine depuis l'**interface web** (panneau « Accès OpenAI ») : le drapeau est relu **en direct** par le tunnel, sans redémarrage. *(Ancien mécanisme : la variable d'environnement `JEAN_LINK_ALLOW_OAI=1` sur le service — encore acceptée pour rétro-compatibilité, mais le toggle de l'UI est désormais la voie recommandée.)*
Le VPS fait un simple **passthrough SNI** : le TLS est terminé sur *ta* machine (Let's Encrypt via TLS-ALPN-01, à travers le tunnel), le relais ne voit que du chiffré.
Contrairement aux premières versions, ce flux **n'est pas en clair chez le relais** : le VPS fait un simple **passthrough SNI** et le TLS est terminé sur *ta* machine (certificat Let's Encrypt obtenu par l'agent en TLS-ALPN-01, à travers le tunnel). Le relais ne voit donc que des octets chiffrés. L'accès reste soumis au service ajean.link (partie hébergée) : la fonctionnalité doit être ouverte pour ton compte.
## API de pilotage
### Variables d'environnement
`jean web` expose une API HTTP pour piloter AJEAN à distance. Protège-la avant de l'exposer :
| Variable | Signification | Défaut |
|----------|---------------|--------|
| `JEAN_HOME` | racine des données | `/etc/jean` (ou `$HOME/JEAN`) |
| `JEAN_SERVICE` | nom de l'unité systemd | `jean` |
| `EDITOR` | éditeur pour `jean edit` | `nano` |
```bash
jean set-web-key # génère une clé
```
Chaque appel `/api/*` présente alors `Authorization: Bearer <clé>` :
| Méthode | Endpoint | Rôle |
|---------|----------|------|
| GET | `/api/ping` | connectivité + validité de la clé |
| GET | `/api/status` · `/api/vram` | état du service · GPU |
| GET | `/api/presets` | liste des presets (avec l'actif) |
| POST | `/api/switch` `{"n":<index>}` | changer de modèle |
| POST | `/api/start` · `/api/stop` · `/api/restart` | piloter le service |
| POST | `/api/chat` `{"messages":[…]}` | chat (flux SSE) |
> ⚠️ La clé voyage en clair en HTTP. Pour une exposition publique, mets un reverse-proxy HTTPS devant, ou utilise `jean link`.
## Compiler depuis les sources
Nécessite Go 1.25+. AJEAN est un binaire 100 % Go (l'UI web est embarquée via `go:embed`) :
Go 1.25+. AJEAN est 100 % Go, l'UI est embarquée via `go:embed` :
```bash
git clone https://github.com/nathaninline/jean.git
cd jean
CGO_ENABLED=0 go build -o jean ./cmd/jean
# cross-compilation, ex. Linux depuis n'importe quel hôte :
GOOS=linux GOARCH=amd64 CGO_ENABLED=0 go build -o jean-linux-amd64 ./cmd/jean
```
> Compiler **AJEAN** ne nécessite que Go. Compiler le **backend llama.cpp** (`jean llamacpp install`) nécessite `git`, `cmake`, et le toolkit de ton accélérateur (CUDA, ROCm, etc.).
## Comment ça marche
- `jean serve` est l'`ExecStart` de systemd : il lit `config.env`, construit la liste d'arguments de `llama-server`, et fait un `exec` dessus pour que systemd supervise directement llama.cpp.
- `jean llamacpp` gère le checkout llama.cpp à côté de l'endroit où pointe `BIN`, en gérant le piège classique du « dossier de build relocalisé » (cache CMake) et en arrêtant le service pendant la recompilation pour éviter le *Text file busy*.
> Compiler **AJEAN** ne demande que Go. Compiler le **backend llama.cpp** demande `git`, `cmake` et le toolkit de ton accélérateur.
## Arborescence
- `cmd/jean/` — point d'entrée (`main()`) + ressources Windows (.syso, icône, versioninfo).
- `internal/jean/` — tout le code, fichiers préfixés par domaine (`web_*`, `chat_*`, `llm_*`, `backend_*`, `relay_*`, `sys_*` — carte dans `doc.go`).
- `internal/jean/ui/` — UI web embarquée. `index.html` est **généré** : les sources vivent dans `ui/src/` (`styles.css`, `js/NN-*.js` concaténés dans l'ordre alphabétique, `index.tmpl.html`). Pour modifier l'UI : éditer `ui/src/` puis lancer `go generate ./internal/jean` (outil `tools/assemble-ui`, multiplateforme ; le fichier assemblé reste committé car `go:embed` et `ajean-app/build-server-ui.ps1` le lisent tel quel).
- `cmd/jean/` — point d'entrée + ressources Windows (icône, versioninfo).
- `internal/jean/` — tout le code, fichiers préfixés par domaine (`web_*`, `chat_*`, `llm_*`, `backend_*`, `relay_*`, `sys_*`, `mcp_*`) ; carte dans `doc.go`.
- `internal/jean/ui/` — UI web embarquée. **`index.html` est généré** : les sources vivent dans `ui/src/`. Pour modifier l'interface, éditer `ui/src/` puis lancer `go generate ./internal/jean`.
## Licence
[MIT](LICENSE). Le fichier `internal/jean/ui/marked.min.js` embarqué est [Marked](https://github.com/markedjs/marked), également MIT.
[MIT](LICENSE). Le `marked.min.js` embarqué est [Marked](https://github.com/markedjs/marked), également MIT.
BIN
View File
Binary file not shown.

Before

Width:  |  Height:  |  Size: 119 KiB

After

Width:  |  Height:  |  Size: 118 KiB