Skip to content
case-studyétude de casiOSIDE mobile

Comment nous avons construit Onepilot : un IDE mobile avec IA pour iPhone

Les décisions techniques, les compromis d'architecture et les leçons tirées de la construction d'un vrai émulateur de terminal avec déploiement d'agents IA sur iOS — des tunnels SSH au rendu VT100.

8 min readSofiane El Mokaddam, ELM Labs

En résumé

  • Nous avons construit un vrai émulateur de terminal VT100 sur iOS — pas une WebView, un vrai terminal avec codes d'échappement ANSI, positionnement de curseur et scrollback
  • Les connexions SSH utilisent Citadel (Swift pur) avec des sessions PTY interactives qui survivent à la mise en arrière-plan
  • L'assistant de déploiement permet d'installer et configurer des agents IA de code sur n'importe quel serveur depuis votre téléphone
  • L'architecture agent-agnostique accepte n'importe quel fournisseur LLM, framework d'agent ou canal de messagerie

Pourquoi nous avons construit un terminal pour iPhone

L'idée est née d'un vrai problème. Nous gérons des serveurs — pour nos propres produits, pour des clients, pour des projets perso. Quand quelque chose tombe en panne à 23h, les options sur mobile sont limitées. Les applications SSH existantes permettent de se connecter et de taper des commandes, mais ça s'arrête là.

Nous voulions plus. Nous voulions nous connecter en SSH à un serveur, déployer un agent IA de code, lui donner des instructions via Telegram, et surveiller son travail — le tout depuis le téléphone. Pas de laptop nécessaire. Pas un hack de bureau à distance, pas un terminal web, mais une app iOS native qui fonctionne comme un vrai environnement de développement.

C'est Onepilot.

Le problème difficile : un vrai terminal sur iOS

La première décision était la plus déterminante. Comment afficher un terminal sur iOS ?

Option 1 : WebView avec xterm.js

La voie facile. Encapsuler xterm.js dans une WKWebView, faire passer les données SSH par JavaScript. La plupart des apps de terminal mobile font ça. Ça fonctionne, mais les compromis sont importants :

  • Latence. Chaque frappe traverse le pont native-vers-JS, est traitée par xterm.js, puis le rendu repasse dans l'autre sens. Sur une connexion rapide ça ajoute 10-20ms. Sur une lente, ça s'accumule.
  • Mémoire. Une WebView est un moteur de navigateur complet. Sur un iPhone avec 6 Go de RAM partagés entre toutes les apps, ça compte.
  • Clavier. La gestion du clavier iOS dans les WebViews est notoirement fragile. Les mappings de touches personnalisés, la barre de caractères spéciaux, les séquences Ctrl/Escape — tout nécessite des contournements qui cassent entre les versions d'iOS.

Option 2 : Rendu VT100 natif

La voie difficile. Parser les séquences d'échappement VT100/ANSI en Swift, maintenir une grille de caractères, rendre avec CoreText. C'est ce que font les terminaux desktop comme iTerm2 et Terminal.app.

Nous avons choisi cette voie, en utilisant SwiftTerm — un émulateur de terminal open-source écrit en Swift par Miguel de Icaza. SwiftTerm gère la machine d'état VT100, le positionnement du curseur, les attributs de couleur, le buffer de scrollback et le rendu du texte.

Le résultat : un terminal qui se sent natif parce qu'il l'est. Pas de latence de pont, pas de surcharge WebView, rendu CoreText direct à 120fps sur les écrans ProMotion.

Le pipeline de données

PTY serveur → canal SSH → Citadel → ByteBuffer → feed SwiftTerm → rendu CoreText

Chaque morceau de sortie SSH arrive sous forme de ByteBuffer depuis Citadel (une bibliothèque SSH en Swift pur construite sur SwiftNIO). Nous le convertissons en tableau d'octets et le passons directement au moteur terminal de SwiftTerm. Pas d'étape d'encodage de chaîne, pas de parsing intermédiaire — des octets bruts à l'état du terminal aux pixels.

L'entrée circule en sens inverse. Quand vous tapez une touche sur le clavier mobile personnalisé, elle devient une séquence d'octets (avec les codes d'échappement appropriés pour les touches spéciales), passe par le TTYStdinWriter de Citadel, et arrive au PTY du serveur. L'aller-retour semble instantané.

SSH sur iOS : la stack Citadel

Nous avons évalué trois bibliothèques SSH pour iOS :

BibliothèqueLangageAsyncSupport PTYMaintenance
NMSSHObjective-C (libssh2)NonLimitéAbandonné
ShoutSwift (libssh2)NonLimitéMinimal
CitadelSwift pur (SwiftNIO)Oui (async/await)CompletActif

Citadel était le choix évident. Construit sur SwiftNIO, ce qui signifie un support async/await correct, pas de threads bloquants, et un multiplexage I/O efficace.

Survivre à l'arrière-plan

iOS est agressif pour tuer les tâches en arrière-plan. Une connexion SSH inactive pendant 30 secondes peut être terminée par l'OS. Nous gérons cela avec :

  1. Assertions de tâches en arrière-plan — demander du temps d'exécution supplémentaire quand l'app est mise en arrière-plan
  2. Vérifications de santé de connexion — paquets keepalive périodiques pour détecter les connexions mortes
  3. Reconnexion automatique — quand une connexion tombe, reconnecter et restaurer l'état du terminal depuis le buffer de scrollback de SwiftTerm

Le problème du clavier mobile

Un terminal a besoin de touches qu'un clavier de téléphone n'a pas. Ctrl, Échap, Tab, flèches, pipe, tilde, backtick — essentiels pour le travail en shell et absents ou enterrés sur iOS.

Nous avons construit un clavier personnalisé qui se place au-dessus du clavier iOS standard :

  • Rangée du haut : Esc, Tab, Ctrl, flèches, pipe, symboles courants
  • Appui long : Maintenir Ctrl et taper une lettre pour Ctrl+C, Ctrl+Z, etc.
  • Gestes de balayage : Balayer sur le terminal pour naviguer dans le scrollback

Chaque touche génère la séquence d'échappement correcte — Tab envoie \t, Échap envoie \x1b, Ctrl+C envoie \x03. Ce sont des opérations au niveau des octets, pas des chaînes.

Déploiement d'agents IA

C'est là que Onepilot se distingue de toutes les autres apps SSH mobiles. Nous n'avons pas juste construit un terminal — nous avons construit un centre d'opérations IA.

L'assistant de configuration

Déployer un agent IA de code sur un serveur distant nécessite normalement :

  1. Se connecter en SSH au serveur
  2. Installer Node.js (ou Python, ou le runtime nécessaire)
  3. Installer le package de l'agent
  4. Configurer les clés API du fournisseur LLM
  5. Configurer les canaux de messagerie (Telegram, Discord, Slack)
  6. Configurer l'agent comme service système
  7. Configurer le redémarrage automatique en cas de crash

C'est beaucoup d'étapes sur un clavier de téléphone. Notre assistant automatise tout le processus. Vous choisissez un serveur, sélectionnez votre fournisseur LLM et votre clé API, choisissez un canal de messagerie, et l'assistant exécute les commandes d'installation via SSH.

Architecture agent-agnostique

Nous avons intentionnellement évité de nous coupler à un seul fournisseur d'IA. Onepilot supporte plus de 23 fournisseurs LLM :

  • APIs commerciales : Claude (Anthropic), GPT (OpenAI), Gemini (Google), Mistral, Cohere
  • Modèles open-source : Ollama, LM Studio, vLLM, llama.cpp
  • Plateformes cloud : AWS Bedrock, Azure OpenAI, Google Vertex AI, Together AI, Fireworks

Le framework d'agent que nous utilisons (OpenClaw) est conçu pour fonctionner avec n'importe quel endpoint API compatible OpenAI. Vous pouvez faire tourner une instance Ollama locale sur votre serveur avec un coût API de 0 € et obtenir un agent de code IA pleinement fonctionnel.

Le Soul Designer

Chaque agent IA a un prompt système qui façonne son comportement. Notre Soul Designer vous permet de personnaliser la personnalité, l'expertise et les garde-fous de votre agent directement depuis l'app. Vous voulez un agent spécialisé en Python qui refuse de toucher aux bases de production ? Configurez ça dans le Soul Designer. Vous en voulez un qui écrit des commentaires détaillés et exécute toujours les tests ? Configurez-le.

Au-delà du terminal

Un terminal est nécessaire mais pas suffisant pour le développement mobile. Onepilot inclut :

  • Navigateur de fichiers avec coloration syntaxique pour 20+ langages, propulsé par tree-sitter
  • Intégration Git — diffs, historique de commits, gestion de branches, le tout via une UI native
  • Gestionnaire de tâches cron — créer, éditer, activer/désactiver les tâches planifiées
  • Gestion multi-serveur — basculer entre les serveurs sans se déconnecter

Chaque fonctionnalité fonctionne via la même connexion SSH. Pas de protocole séparé, pas d'agent tournant sur le serveur (à part l'agent IA), pas de logiciel spécial à installer. Si vous pouvez vous y connecter en SSH, Onepilot peut le gérer.

Décisions d'architecture que nous referions

SwiftUI plutôt qu'UIKit. Le modèle déclaratif de SwiftUI a permis de construire des UI complexes avec une petite équipe. La vue terminal elle-même est un wrapper UIKit UIViewRepresentable autour de SwiftTerm — car le rendu du terminal nécessite un contrôle au pixel que le canvas SwiftUI ne fournit pas.

Citadel plutôt que les wrappers libssh2. L'intégration async/await seule en valait la peine. Pas de pyramides de callbacks, pas de casse-tête de synchronisation de threads.

Isolation par acteur pour l'état SSH. Le modèle d'acteur de Swift empêche les data races dans la gestion des sessions SSH. Le SSHSessionManager est un acteur, ce qui signifie que les accès concurrents à l'état de connexion sont sérialisés automatiquement.

Supabase pour le backend. Authentification, synchronisation des identifiants serveur (chiffrés), gestion des abonnements et analytics — le tout géré par Supabase. Les politiques de sécurité au niveau des lignes garantissent que les utilisateurs ne peuvent accéder qu'à leurs propres données.

Ce que nous avons appris

Le mobile n'est pas une limitation — c'est une contrainte qui force le bon design. Chaque fonctionnalité devait fonctionner sur un écran de 6,1 pouces avec un clavier tactile. Cette contrainte a produit une meilleure UX que ce que nous aurions construit pour desktop.

Le terminal est la fondation, pas le produit. Les utilisateurs ne veulent pas une app de terminal. Ils veulent résoudre des problèmes sur leurs serveurs. Le terminal est le mécanisme. Le déploiement d'agents, la gestion de fichiers et l'intégration Git sont ce qui le rend utile.

Agent-agnostique bat agent-spécifique. Le paysage de l'IA évolue trop vite pour miser sur un seul fournisseur. Les utilisateurs apportent leurs propres clés API, leurs propres préférences de modèle, leurs propres workflows.

Essayez-le

Onepilot est gratuit pour commencer. Connectez-vous en SSH à vos serveurs, déployez des agents IA, gérez votre infrastructure — depuis votre iPhone. Pas d'abonnement requis pour les fonctionnalités de base.

Si vous construisez quelque chose de similaire ou avez des questions sur le SSH mobile, l'émulation de terminal ou l'architecture d'agents IA, contactez-nous. Nous sommes heureux de partager ce que nous avons appris.

Prêt à avancer ?

30 minutes, sans engagement. On en parle.

Essayez Onepilot — gratuit sur l'App Store

Articles similaires