Blog
Dans les coulisses de l'app compagnon Mac : Architecture d'un gestionnaire de sessions leger
L'app compagnon Mac est l'epine dorsale silencieuse de Tactic Remote — un utilitaire de barre de menus qui gere les sessions tmux, execute un serveur HTTP/WebSocket integre et maintient votre Mac eveille pendant le travail actif avec l'IA.
Suivez les mises à jour produit et ingénierie de cette catégorie.
Voir la catégorieL'app compagnon Mac est la partie la moins visible de Tactic Remote et sans doute la plus importante. Elle tourne dans votre barre de menus, gere chaque session Claude Code sur votre machine, sert l'API a laquelle votre iPhone se connecte, et gere le travail ingrat de maintenir les sessions en vie a travers les cycles de veille et les changements de reseau. Cet article explique son fonctionnement et les raisons de nos choix architecturaux.
Contraintes de conception
Nous avons etabli trois contraintes des le debut du developpement :
- L'app doit etre imperceptible au repos. Les developpeurs executent deja des dizaines de processus en arriere-plan. Un gestionnaire de sessions qui consomme du CPU ou de la memoire de maniere notable au repos est inacceptable.
- Elle doit gerer plusieurs sessions simultanees. De nombreux developpeurs executent deux ou trois taches Claude Code en parallele — une pour une branche de fonctionnalite, une pour les tests, une pour la documentation.
- Elle doit survivre gracieusement a la mise en veille du Mac et aux changements de reseau. Un developpeur ferme son portable, marche jusqu'a un cafe, l'ouvre a nouveau, et tout doit se reconnecter en quelques secondes.
Ces contraintes ont faconne chaque couche de l'architecture.
Le modele de serveur integre
Plutot que d'executer un processus serveur separe, l'app compagnon integre directement un serveur HTTP et WebSocket. C'etait un choix delibere par rapport a l'alternative de distribuer un daemon autonome.
Pourquoi integre ? Un daemon separe necessite sa propre gestion de cycle de vie — configuration launchd, surveillance des processus, rotation des logs et recuperation apres plantage. Chacun de ces elements est un point de defaillance potentiel et une charge de support. En integrant le serveur dans l'app elle-meme, le cycle de vie est simple : quand l'app tourne, le serveur tourne. Quand l'app se ferme, tout s'arrete proprement.
Le serveur integre se lie a un port configurable (48736 par defaut) soit uniquement sur localhost (pour le mode reseau local avec une couche proxy reseau separee), soit sur toutes les interfaces. Il expose une API REST pour la gestion des sessions et les requetes de statut, ainsi qu'un endpoint WebSocket pour le streaming terminal en temps reel et le push d'approbations.
Au repos, le serveur maintient les sockets ouverts mais n'effectue aucun travail. Dans nos benchmarks, l'app compagnon au repos sans session active consomme environ 18 Mo de memoire et un CPU negligeable — comparable a un utilitaire de barre de menus typique.
tmux comme ossature des sessions
Chaque session Claude Code geree par Tactic Remote s'execute au sein d'une session tmux. Nous avons choisi tmux plutot que des alternatives comme screen ou la gestion directe de PTY pour plusieurs raisons :
Persistance des sessions. Les sessions tmux survivent independamment du processus qui les a creees. Si l'app compagnon plante et redemarre, les sessions tmux et leurs processus Claude Code continuent de fonctionner sans interruption. L'app se rattache simplement aux sessions existantes au demarrage.
Capture sans interference. La commande capture-pane de tmux nous permet de lire le contenu du terminal sans injecter d'entree ni modifier le processus en cours d'execution. C'est critique — nous devons streamer la sortie du terminal vers l'iPhone sans aucun risque de perturber le fonctionnement de Claude Code.
Sessions nommees. Chaque session Claude Code recoit un nom de session tmux previsible (par exemple, claude-remote-0, claude-remote-1), ce qui rend simple l'enumeration, l'attachement et la gestion programmatique des sessions.
Mature et universel. tmux est inclus avec macOS ou s'installe trivialement via Homebrew. Il beneficie de decennies de stabilite et gere les cas limites (redimensionnement du terminal, Unicode, sequences d'echappement) que nous aurions autrement du resoudre nous-memes.
L'app compagnon interroge les sessions tmux actives a un intervalle configurable (200ms par defaut) pour capturer le contenu frais du terminal. Lorsque le contenu change, elle pousse le delta par WebSocket aux clients connectes. Cette approche par interrogation est intentionnellement simple — nous avons evalue des mecanismes de notification bases sur le systeme de fichiers et les avons trouves moins fiables selon les versions de macOS que l'interrogation directe a cet intervalle.
Gestion du cycle de vie des sessions
Une session Claude Code dans Tactic Remote traverse un cycle de vie defini :
- Creation — L'iPhone envoie une requete "demarrer une session". L'app compagnon cree une nouvelle session tmux et lance Claude Code a l'interieur avec le repertoire de travail et la description de tache specifies.
- Surveillance active — Le contenu du terminal est capture et streame. Les demandes d'approbation du systeme de hook de Claude Code sont interceptees et transmises a l'iPhone via WebSocket et notification push.
- Detection d'inactivite — Si une session n'a pas de changement de sortie terminal pendant une periode configurable, sa frequence d'interrogation diminue pour reduire l'utilisation des ressources.
- Completion — Claude Code se termine. L'app compagnon detecte la sortie, capture la sortie finale et notifie l'iPhone.
- Nettoyage — La session tmux est conservee pendant une periode de retention configurable (30 minutes par defaut) pour que les utilisateurs puissent consulter la sortie, puis nettoyee automatiquement.
Gerer plusieurs sessions simultanees signifie multiplexer ces cycles de vie independamment. Chaque session a sa propre boucle de capture, son propre canal WebSocket et sa propre machine a etats. L'app compagnon supporte actuellement jusqu'a 8 sessions simultanees, une limite basee sur des tests pratiques de ressources plutot que sur des contraintes architecturales.
Prevention de la mise en veille du Mac
C'etait l'un des defis d'ingenierie les moins evidents. macOS se met en veille de maniere agressive lorsqu'il detecte de l'inactivite, et une tache Claude Code executee dans tmux ne genere pas le type d'entree utilisateur que macOS reconnait comme de l'"activite".
L'app compagnon utilise l'API IOPMAssertionCreateWithName pour maintenir une assertion d'alimentation chaque fois qu'au moins une session Claude Code est activement en cours d'execution. Le type d'assertion est kIOPMAssertPreventUserIdleSystemSleep, qui empeche la mise en veille du systeme tout en permettant l'extinction de l'ecran. Lorsque toutes les sessions sont terminees ou arretees, l'assertion est liberee immediatement.
Nous avons envisage d'utiliser caffeinate comme processus externe mais l'avons rejete pour la meme raison que nous avons rejete un daemon separe — cela ajoute de la complexite au cycle de vie. L'API d'assertions IOKit nous donne un controle precis et s'integre proprement au suivi de sessions propre a l'app.
Integration dans la barre de menus
L'app compagnon se presente sous forme d'icone dans la barre de menus avec une interface deroulante minimale. Le menu affiche :
- Statut de connexion — Si le serveur fonctionne, sur quel port il est lie, et si un Cloudflare Tunnel est actif.
- Sessions actives — Un decompte des sessions Claude Code en cours avec de brefs indicateurs de statut.
- Acces par QR code — Une option en un clic pour afficher un QR code contenant l'URL de connexion et le jeton d'authentification pour l'appairage avec l'iPhone.
- Actions rapides — Demarrer/arreter le serveur, ouvrir les parametres, copier l'URL de connexion.
Nous avons intentionnellement evite de construire une interface fenetree complete. Le role de l'app compagnon est d'etre une infrastructure, pas une destination. Les developpeurs interagissent avec Tactic Remote via leur iPhone ; l'app Mac ne devrait necessiter d'attention que lors de la configuration initiale et des modifications de configuration occasionnelles.
Integration de Cloudflare Tunnel
Lorsque le mode Cloudflare Tunnel est active, l'app compagnon gere le processus cloudflared comme processus enfant. Elle demarre cloudflared avec les identifiants de tunnel configures, surveille sa sante via l'endpoint de metriques local et le redemarre automatiquement si le tunnel tombe.
L'integration gere un probleme de timing subtil : le tunnel doit etre pleinement etabli avant que l'iPhone puisse s'y connecter. L'app compagnon attend que cloudflared signale une connexion saine (generalement 1 a 3 secondes apres le lancement) avant d'annoncer l'URL du tunnel comme disponible. Pendant cette fenetre, l'icone de la barre de menus affiche un etat distinct de "connexion en cours".
Si le processus du tunnel plante, l'app compagnon tente jusqu'a 3 redemarrages avec un backoff exponentiel (2s, 4s, 8s) avant de marquer le mode tunnel comme echoue et de notifier les clients connectes de basculer en mode local si disponible.
Authentification
Chaque requete API et connexion WebSocket requiert un Bearer Token. Le jeton est genere au premier lancement et stocke dans le Trousseau macOS. Il est inclus dans le QR code affiche lors de la configuration, de sorte que l'appairage se fait en un seul scan plutot qu'une copie manuelle du jeton.
Le jeton est une valeur aleatoire de 256 bits, generee a l'aide de SecRandomCopyBytes. Nous avons choisi un modele de jeton statique plutot qu'une authentification basee sur les sessions car le modele de menace principal est l'acces reseau non autorise, pas le controle d'acces multi-utilisateurs. Pour les equipes necessitant une authentification par utilisateur, nous recommandons de placer Cloudflare Access devant le tunnel.
Ce que nous avons envisage et rejete
Une app Electron complete. La surcharge memoire a elle seule a disqualifie cette option — la ligne de base d'Electron est de 80-150 Mo, soit environ 5 a 8 fois ce que notre app native Swift utilise au repos.
Un daemon CLI autonome. Plus simple a construire initialement, mais plus difficile a gerer pour les utilisateurs non techniques et impossible a integrer avec les conventions de la barre de menus macOS.
Gestion directe des PTY au lieu de tmux. Plus de controle, mais nous aurions du reimplementer la persistance des sessions, les cas limites d'emulation de terminal et la gestion du cycle de vie des processus que tmux gere deja de maniere fiable.
Un LaunchAgent pour le demarrage automatique. Nous l'avons implemente mais en option plutot que par defaut. Les developpeurs ont des opinions bien arretees sur ce qui s'execute a la connexion, et nous respectons cela.
Profil de performance
Sous charge typique (2 sessions actives, 1 iPhone connecte), l'utilisation des ressources de l'app compagnon :
| Metrique | Valeur |
|---|---|
| Memoire (RSS) | 22-35 Mo |
| CPU (repos, aucun changement de sortie) | < 0,1% |
| CPU (streaming actif, 2 sessions) | 1-3% |
| E/S disque | Negligeable (pas de journalisation sur disque par defaut) |
| Reseau (mode local, streaming actif) | 10-50 Ko/s |
Ces chiffres ont ete mesures sur un MacBook Pro M2 sous macOS 14. Les performances sur les Mac Intel sont comparables, avec une utilisation CPU legerement plus elevee pendant le streaming actif.
Perspectives
L'architecture de l'app compagnon a ete concue pour supporter des capacites au-dela de ce que nous avons livre aujourd'hui. La couche de gestion des sessions peut accueillir le partage de sessions (plusieurs iPhones surveillant la meme session), l'enregistrement de sessions (capture de l'historique complet du terminal pour relecture), et une integration plus riche avec les API d'extensibilite de Claude Code a mesure qu'elles evoluent.
Pour les instructions de configuration, consultez Premiers pas. Pour le depannage specifique a l'app compagnon Mac, consultez Problemes courants.
Essayez Tactic Remote
Pilotez vos agents de programmation depuis votre téléphone
Connectez-vous à Claude Code, Codex et aux autres agents sur votre Mac, PC Windows ou Linux. Consultez leur progression et envoyez la prochaine instruction depuis votre iPhone ou iPad.