Au quotidien
Votre propre client
Brancher Claude Code, Codex, votre terminal et votre éditeur sur un serveur Pupitre en SSH, avec la clé privée que l’app a générée.
Une fois la machine prête, Pupitre n’est pas l’endroit où vous devez travailler. Le serveur est une machine Ubuntu ordinaire, jointe en SSH sous le compte dev, et tout ce qui parle SSH s’y branche — l’app Claude, l’app ChatGPT et son Codex, votre terminal, votre éditeur.
Cette page est la partie pratique : où est la clé, comment déclarer l’hôte une fois pour toutes, et ce qu’il faut remplir pour chaque client.
Ce que le serveur offre à un client
Rien de particulier, et c’est voulu :
- un accès SSH sur le port 22 — et sur le 443 aussi, si vous l’avez demandé à
core.hardening; - l’utilisateur
dev, dontauthorized_keysporte la moitié publique de chaque appareil de votre compte autorisé sur ce serveur ; - vos projets sous le dossier que vous avez choisi, possédés par
dev; - les runtimes activés dans les shells non interactifs également, pour qu’un client qui lance une commande sans shell de connexion trouve les mêmes
node,pythonetclaudeque vous ; tmux,systemd, la commandedev, et les bases sur127.0.0.1.
Ce dernier point sur les shells non interactifs est ce qui décide qu’un client distant sera agréable ou insupportable. Les modules de runtime écrivent leur activation dans .zshenv, que zsh lit pour tous les shells, exactement pour cette raison.
Où l’app garde la clé
Pupitre génère une clé ed25519 par serveur et la garde dans son propre dossier de données, en mode 0600. Elle ne réécrit jamais votre ~/.ssh/config : sur votre demande, elle y pose une ligne, une seule, décrite plus bas.
| Système | Dossier |
|---|---|
| macOS | ~/Library/Application Support/@pupitre/desktop |
| Windows | %APPDATA%\@pupitre\desktop |
| Linux | ~/.config/@pupitre/desktop |
À l’intérieur :
ssh/config un bloc Host par serveur, passé à ssh avec -F
ssh/known_hosts les clés d’hôte que l’app a épinglées
keys/device la clé de cet ordinateur, celle qui ouvre un serveur confié par votre organisation
keys/srv-xxxxxxx la clé d’un serveur que vous avez ajouté vous-même, en mode 0600
Chaque clé a son .pub à côté d’elle. Ouvrez ssh/config pour savoir quel serveur est lequel : chaque bloc porte son adresse, son port, son utilisateur et le chemin de sa clé — keys/device pour un serveur confié, keys/srv-… pour un serveur que vous avez ajouté.
Host pupitre-srv-m9k2p1
HostName 203.0.113.10
Port 22
User dev
IdentityFile /Users/vous/.pupitre/desktop/keys/srv-m9k2p1
IdentitiesOnly yes
Le chemin passe par ~/.pupitre/desktop, un lien que l’app garde pointé sur son dossier de données. Le dossier lui-même porte une espace dans son nom sur macOS, et souvent sur Windows ; OpenSSH lit un chemin entre guillemets, mais JetBrains Gateway analyse le même fichier avec son propre code et coupe IdentityFile et UserKnownHostsFile sur l’espace, guillemets ou non. Le lien est ce qui rend le bloc de l’app lisible par les deux.
Pointez vos clients sur ce fichier plutôt que d’en faire une copie ailleurs. Supprimer le serveur dans l’app emporte sa clé, et une copie posée ailleurs serait une orpheline qui ouvre toujours votre machine.
Déclarer l’hôte une fois
Tout ce qui suit demande que votre propre ~/.ssh/config connaisse le serveur : ssh, les éditeurs et les agents de code ne lisent que ce fichier, pas celui que l’app garde dans son dossier. L’app le fait pour vous. Dans Réglages › SSH, cochez Laisser ssh, mes éditeurs et mes agents de code joindre mes serveurs par leur nom : une ligne s’ajoute en tête de ~/.ssh/config, et rien d’autre n’y bouge.
Include "/Users/vous/Library/Application Support/@pupitre/desktop/ssh/config"
Chaque serveur de l’app répond dès lors à son nom SSH — le mot choisi à côté de son nom quand vous l’ajoutez, atelier par défaut pour un serveur nommé « Atelier », modifiable depuis la fiche du serveur dans Réglages › Serveurs, le réglage SSH le montre — avec la clé de l’app, IdentitiesOnly et la clé d’hôte épinglée. Un serveur dont le nom SSH est déjà celui d’un Host de votre fichier garde son identifiant seul, pupitre-srv-…. Décocher la case retire la ligne. Vérifiez :
ssh atelier "dev status"
Une machine qui répond avec ses projets est une machine que tous les clients de cette page peuvent désormais joindre. Si elle demande un mot de passe, la clé n’est pas celle que dev accepte : révélez la clé publique sur l’écran des serveurs et comparez-la à ~/.ssh/authorized_keys sur la machine.
Si vous préférez écrire l’entrée vous-même, recopiez les valeurs depuis le bloc de l’app, lien compris : un chemin qui contient une espace demande des guillemets à OpenSSH et casse JetBrains Gateway dans tous les cas.
Host atelier
HostName 203.0.113.10
Port 22
User dev
IdentityFile /Users/vous/.pupitre/desktop/keys/srv-m9k2p1
IdentitiesOnly yes
Claude Code
Deux chemins, qui arrivent au même endroit : ai.claude a déjà installé Claude Code pour dev, avec le contexte machine et les skills Pupitre.
Depuis l’app Claude. Ouvrez le menu d’environnement avant de démarrer une session et choisissez Add SSH connection. Elle demande quatre choses :
| Champ | Ce qu’on met |
|---|---|
| Name | Le nom que vous donnez à la machine |
| SSH Host | pupitre, ou dev@203.0.113.10 |
| SSH Port | 22, ou celui que vous avez choisi |
| Identity File | Le chemin de la clé de l’app, d’après le tableau plus haut |
C’est ce champ Identity File qui fait que la clé de l’app fonctionne ici sans cérémonie : donnez le chemin, rien d’autre n’a à bouger. Laissez-le vide si l’hôte se résout déjà par votre ~/.ssh/config.
Depuis un terminal. Ouvrez une session, gardez-la dans tmux pour qu’elle survive au réseau, et lancez l’outil là où est le projet :
ssh atelier
tmux new -A -s claude
cd ~/projects/votre-projet && claude
Dans les deux cas vous vous connectez une fois, depuis la session où vous êtes : l’outil affiche une URL, vous l’approuvez dans votre navigateur. C’est votre abonnement ; Pupitre ne revend rien et ne stocke aucun token pour vous.
Codex
ai.codex installe Codex par mise, et les shims sont sur le PATH de tous les shells — y compris le shell non interactif qu’ouvre un client distant. C’est exactement ce que l’app exige de la machine : elle démarre Codex sur l’hôte distant à travers votre shell de connexion.
Depuis l’app ChatGPT. Codex y ajoute un projet distant depuis un hôte SSH : elle lit les alias d’hôte concrets de votre ~/.ssh/config et les résout avec OpenSSH, si bien que le nom du serveur, déclaré plus haut, est ce qu’elle vous propose. Il n’y a pas de champ pour une clé — c’est la ligne IdentityFile du bloc de l’app qui désigne la sienne.
Depuis un terminal. Même forme que pour Claude Code :
ssh atelier
tmux new -A -s codex
cd ~/projects/votre-projet && codex
Claude Code et Codex cohabitent sans discussion. Ils voient les mêmes projets, les mêmes runtimes et les mêmes bases, parce qu’il n’y a qu’une machine.
Votre terminal
ssh atelier suffit, et le binaire de l’agent est aussi lié sous le nom dev : les opérations que l’app effectue existent dans un terminal nu.
dev status ce qui tourne, sur quel port, avec quelle mémoire
dev up mon-projet le démarre dans sa session tmux
dev restart all
dev logs mon-projet -f
dev sync mon-projet git pull, puis les dépendances
dev attach mon-projet affiche la ligne tmux à coller dans votre terminal
dev branch la branche de chaque projet
dev branch mon-projet main change ce projet de branche
dev db url la chaîne de connexion, pour un client sur votre poste
dev doctor un diagnostic court de la machine
L’agent lit son rattachement et sa licence dans des fichiers que seul root ouvre : la commande parle donc à sudo -n pupitred serve, que sudo lance sans mot de passe. dev db dump, dev db import et dev backup now passent par une session privilégiée, pour laquelle sudo demande le mot de passe sudo de dev dans le terminal. Taper sudo dev … vous-même ne change rien.
dev db accepte aussi shell, dump et import, et le moteur va de soi quand la machine n’a qu’une base — dev db url postgres quand elle en a deux.
Ajoutez --json à n’importe laquelle et vous obtenez la réponse de l’agent plutôt qu’un rendu de celle-ci, ce qui rend ces commandes utilisables par un script, ou par un agent qui travaille dans un terminal.
Votre éditeur
VS Code, Cursor et Windsurf se connectent en Remote SSH, Zed par zed://ssh, les IDE JetBrains par Gateway. Ils lisent la même entrée de ~/.ssh/config, et les modules editor.* préinstallent les backends distants pour que la première connexion soit immédiate plutôt qu’un téléchargement de dix minutes. Voir éditeurs distants.
Quand ça n’ouvre pas
- On vous demande un mot de passe. La clé n’est pas dans le
authorized_keysdedev. Recopiez la moitié publique depuis l’écran des serveurs, dans l’app. Permissions 0644 for ... are too open. La clé privée ne doit être lisible que par vous :chmod 600sur macOS et Linux. Sur Windows, la garder dans%APPDATA%suffit — une copie posée dans un dossier partagé, non.- Rien ne répond sur le port 22. Si votre réseau le filtre,
core.hardeningpeut mettre SSH sur le 443 également ; changezPortdans votre entrée. - La clé d’hôte a changé. Réinstaller une machine la change. L’app vous le demande de son côté ; dans votre
~/.ssh/known_hosts, retirez l’ancienne ligne. - Gateway dit
Could not verify host keysans rien vous demander. Le bloc de l’app pointe sur son propreknown_hostsen vérification stricte, et Gateway n’a pas pu lire le chemin. Vérifiez que~/.pupitretient un lien au nom du dossier de l’app et que rien d’autre n’a pris sa place ; l’app le repose à son prochain démarrage. codex: command not founddepuis un client distant. Le client a ouvert un shell qui n’a pas lu.zshenv. Vérifiez avecssh atelier 'which codex'.
La révocation fonctionne toujours
Un appareil retiré dans la console perd sa clé sur le serveur au prochain rendez-vous de l’agent — quoi que cette clé servait à ouvrir —, sauf si c’était la dernière clé du serveur. C’est la raison de pointer vos clients sur la clé de l’app plutôt que sur une copie.
Ce qui reste dans l’app
Pupitre reste l’endroit des choses qu’un client de conversation n’a pas à faire : inspecter la machine, installer et configurer les services, sécuriser, le rapport d’installation en direct, l’enregistrement des projets, les secrets, l’état des services que l’agent rapporte, les mises à jour et les alertes.
Son terminal est là le jour où vous en voulez un — la première connexion, des logs à regarder, une commande que vous préférez lancer là où l’installation a eu lieu. Ce n’est pas le prix d’entrée.