Blog
Einblick in die Mac-Begleit-App: Architektur eines schlanken Sitzungsmanagers
Die Mac-Begleit-App ist das stille Rückgrat von Tactic Remote — ein Menüleisten-Dienstprogramm, das tmux-Sitzungen verwaltet, einen eingebetteten HTTP/WebSocket-Server betreibt und Ihren Mac während aktiver KI-Arbeit wach hält.
Weitere Produkt- und Engineering-Updates aus dieser Kategorie.
Kategorie öffnenDie Mac-Begleit-App ist der am wenigsten sichtbare Teil von Tactic Remote und wohl der wichtigste. Sie läuft in Ihrer Menüleiste, verwaltet jede Claude Code-Sitzung auf Ihrem Rechner, stellt die API bereit, mit der sich Ihr iPhone verbindet, und erledigt die unscheinbare Arbeit, Sitzungen über Ruhephasen und Netzwerkwechsel hinweg am Leben zu halten. Dieser Beitrag erklärt, wie sie funktioniert und warum wir die architektonischen Entscheidungen getroffen haben, die wir getroffen haben.
Design-Einschränkungen
Wir haben früh in der Entwicklung drei Einschränkungen festgelegt:
- Die App muss im Leerlauf unmerklich sein. Entwickler führen bereits Dutzende von Hintergrundprozessen aus. Ein Sitzungsmanager, der im Ruhezustand spürbar CPU oder Arbeitsspeicher verbraucht, ist inakzeptabel.
- Sie muss mehrere gleichzeitige Sitzungen bewältigen. Viele Entwickler führen zwei oder drei Claude Code-Aufgaben gleichzeitig aus — eine für einen Feature-Branch, eine für Tests, eine für Dokumentation.
- Sie muss den Ruhezustand des Mac und Netzwerkwechsel elegant überstehen. Ein Entwickler klappt sein Notebook zu, geht in ein Café, öffnet es wieder, und alles sollte sich innerhalb von Sekunden neu verbinden.
Diese Einschränkungen prägten jede Schicht der Architektur.
Das eingebettete Server-Modell
Anstatt einen separaten Serverprozess auszuführen, bettet die Begleit-App einen HTTP- und WebSocket-Server direkt ein. Dies war eine bewusste Entscheidung gegenüber der Alternative, einen eigenständigen Daemon auszuliefern.
Warum eingebettet? Ein separater Daemon erfordert ein eigenes Lifecycle-Management — launchd-Konfiguration, Prozessüberwachung, Log-Rotation und Absturzwiederherstellung. Jeder dieser Aspekte ist ein potenzieller Fehlerpunkt und eine Support-Last. Durch die Einbettung des Servers in die App selbst wird der Lebenszyklus einfach: Wenn die App läuft, läuft der Server. Wenn die App beendet wird, stoppt alles sauber.
Der eingebettete Server bindet sich an einen konfigurierbaren Port (Standard 48736), entweder nur an localhost (für den lokalen Netzwerkmodus mit einer separaten Netzwerk-Proxy-Schicht) oder an alle Schnittstellen. Er bietet eine REST-API für Sitzungsverwaltung und Statusabfragen sowie einen WebSocket-Endpunkt für Echtzeit-Terminalstreaming und Genehmigungs-Push.
Im Leerlauf hält der Server offene Sockets, führt aber keine Arbeit aus. In unseren Benchmarks verbraucht die Begleit-App im Ruhezustand ohne aktive Sitzungen etwa 18 MB Arbeitsspeicher und vernachlässigbare CPU — vergleichbar mit einem typischen Menüleisten-Dienstprogramm.
tmux als Sitzungs-Rückgrat
Jede von Tactic Remote verwaltete Claude Code-Sitzung läuft innerhalb einer tmux-Sitzung. Wir haben tmux gegenüber Alternativen wie screen oder direkter PTY-Verwaltung aus mehreren Gründen gewählt:
Sitzungspersistenz. tmux-Sitzungen überleben unabhängig vom Prozess, der sie erstellt hat. Wenn die Begleit-App abstürzt und neu startet, laufen die tmux-Sitzungen und ihre Claude Code-Prozesse ungestört weiter. Die App verbindet sich beim Start einfach wieder mit den bestehenden Sitzungen.
Erfassung ohne Störung. Der capture-pane-Befehl von tmux ermöglicht es uns, Terminalinhalte zu lesen, ohne Eingaben zu injizieren oder den laufenden Prozess zu verändern. Das ist entscheidend — wir müssen die Terminalausgabe an das iPhone streamen, ohne jegliches Risiko, den Betrieb von Claude Code zu stören.
Benannte Sitzungen. Jede Claude Code-Sitzung erhält einen vorhersehbaren tmux-Sitzungsnamen (z.B. claude-remote-0, claude-remote-1), was das Aufzählen, Verbinden und programmgesteuerte Verwalten von Sitzungen unkompliziert macht.
Ausgereift und universell. tmux wird mit macOS ausgeliefert oder ist trivial über Homebrew installierbar. Es hat Jahrzehnte der Stabilität hinter sich und bewältigt Randfälle (Terminal-Größenänderung, Unicode, Escape-Sequenzen), die wir sonst selbst lösen müssten.
Die Begleit-App fragt aktive tmux-Sitzungen in einem konfigurierbaren Intervall (Standard 200ms) ab, um aktuelle Terminalinhalte zu erfassen. Wenn sich der Inhalt ändert, werden die Unterschiede per WebSocket an verbundene Clients gesendet. Dieser Polling-Ansatz ist bewusst einfach gehalten — wir haben dateisystembasierte Benachrichtigungsmechanismen evaluiert und fanden sie über macOS-Versionen hinweg weniger zuverlässig als direktes Polling in diesem Intervall.
Sitzungs-Lifecycle-Management
Eine Claude Code-Sitzung in Tactic Remote durchläuft einen definierten Lebenszyklus:
- Erstellung — Das iPhone sendet eine „Sitzung starten"-Anfrage. Die Begleit-App erstellt eine neue tmux-Sitzung und startet Claude Code darin mit dem angegebenen Arbeitsverzeichnis und der Aufgabenbeschreibung.
- Aktive Überwachung — Terminalinhalte werden erfasst und gestreamt. Genehmigungsanfragen vom hook-System von Claude Code werden abgefangen und per WebSocket und Push-Benachrichtigung an das iPhone weitergeleitet.
- Leerlauferkennung — Wenn eine Sitzung für einen konfigurierbaren Zeitraum keine Änderungen in der Terminalausgabe aufweist, wird die Abfragefrequenz reduziert, um Ressourcen zu sparen.
- Abschluss — Claude Code beendet sich. Die Begleit-App erkennt das Ende, erfasst die letzte Ausgabe und benachrichtigt das iPhone.
- Bereinigung — Die tmux-Sitzung wird für einen konfigurierbaren Aufbewahrungszeitraum (Standard 30 Minuten) beibehalten, damit Benutzer die Ausgabe überprüfen können, und dann automatisch bereinigt.
Die Verwaltung mehrerer gleichzeitiger Sitzungen bedeutet, diese Lebenszyklen unabhängig zu multiplexen. Jede Sitzung hat ihre eigene Erfassungsschleife, ihren eigenen WebSocket-Kanal und ihre eigene Zustandsmaschine. Die Begleit-App unterstützt derzeit bis zu 8 gleichzeitige Sitzungen — ein Limit basierend auf praktischen Ressourcentests, nicht auf architektonischen Einschränkungen.
Verhinderung des Mac-Ruhezustands
Dies war eine der weniger offensichtlichen technischen Herausforderungen. macOS geht aggressiv in den Ruhezustand, wenn es Inaktivität erkennt, und eine Claude Code-Aufgabe, die in tmux läuft, erzeugt nicht die Art von Benutzereingaben, die macOS als „Aktivität" erkennt.
Die Begleit-App verwendet die IOPMAssertionCreateWithName-API, um eine Energieassertion zu halten, wann immer mindestens eine Claude Code-Sitzung aktiv läuft. Der Assertionstyp ist kIOPMAssertPreventUserIdleSystemSleep, der den Systemruhezustand verhindert, während das Display sich dennoch ausschalten darf. Wenn alle Sitzungen abgeschlossen oder beendet werden, wird die Assertion sofort freigegeben.
Wir haben in Betracht gezogen, caffeinate als externen Prozess zu verwenden, es aber aus demselben Grund abgelehnt, aus dem wir einen separaten Daemon abgelehnt haben — es fügt Lifecycle-Komplexität hinzu. Die IOKit-Assertions-API gibt uns präzise Kontrolle und integriert sich sauber in die eigene Sitzungsverfolgung der App.
Menüleisten-Integration
Die Begleit-App präsentiert sich als Menüleisten-Symbol mit einem minimalen Dropdown-Interface. Das Menü zeigt:
- Verbindungsstatus — Ob der Server läuft, an welchen Port er gebunden ist und ob ein Cloudflare Tunnel aktiv ist.
- Aktive Sitzungen — Anzahl laufender Claude Code-Sitzungen mit kurzen Statusanzeigen.
- QR-Code-Zugang — Eine Ein-Klick-Option zur Anzeige eines QR-Codes mit der Verbindungs-URL und dem Authentifizierungstoken für die iPhone-Kopplung.
- Schnellaktionen — Server starten/stoppen, Einstellungen öffnen, Verbindungs-URL kopieren.
Wir haben bewusst darauf verzichtet, eine vollständige Fenster-Oberfläche zu bauen. Die Aufgabe der Begleit-App ist es, Infrastruktur zu sein, kein Ziel. Entwickler interagieren mit Tactic Remote über ihr iPhone; die Mac-App sollte nur bei der Ersteinrichtung und gelegentlichen Konfigurationsänderungen Aufmerksamkeit erfordern.
Cloudflare Tunnel-Integration
Wenn der Cloudflare Tunnel-Modus aktiviert ist, verwaltet die Begleit-App den cloudflared-Prozess als Kindprozess. Sie startet cloudflared mit den konfigurierten Tunnel-Zugangsdaten, überwacht dessen Zustand über den lokalen Metriken-Endpunkt und startet ihn bei einem Tunnel-Abbruch automatisch neu.
Die Integration behandelt ein subtiles Timing-Problem: Der Tunnel muss vollständig aufgebaut sein, bevor sich das iPhone darüber verbinden kann. Die Begleit-App wartet, bis cloudflared eine gesunde Verbindung meldet (typischerweise 1-3 Sekunden nach dem Start), bevor sie die Tunnel-URL als verfügbar ankündigt. Während dieses Zeitfensters zeigt das Menüleisten-Symbol einen eigenen „Verbindungsaufbau"-Zustand an.
Wenn der Tunnel-Prozess abstürzt, versucht die Begleit-App bis zu 3 Neustarts mit exponentiellem Backoff (2s, 4s, 8s), bevor sie den Tunnel-Modus als fehlgeschlagen markiert und verbundene Clients benachrichtigt, auf den lokalen Modus zurückzufallen, sofern verfügbar.
Authentifizierung
Jede API-Anfrage und WebSocket-Verbindung erfordert ein Bearer Token. Das Token wird beim ersten Start generiert und im macOS-Schlüsselbund gespeichert. Es ist im QR-Code enthalten, der während der Einrichtung angezeigt wird, sodass die Kopplung ein einzelner Scan ist statt eines manuellen Token-Kopierens.
Das Token ist ein 256-Bit-Zufallswert, generiert mit SecRandomCopyBytes. Wir haben ein statisches Token-Modell gegenüber sitzungsbasierter Authentifizierung gewählt, da das primäre Bedrohungsmodell unbefugter Netzwerkzugriff ist, nicht Mehrbenutzerzugriffskontrolle. Für Teams, die benutzerspezifische Authentifizierung benötigen, empfehlen wir Cloudflare Access vor dem Tunnel.
Was wir erwogen und verworfen haben
Eine vollständige Electron-App. Allein der Speicher-Overhead schloss dies aus — Electrons Baseline liegt bei 80-150 MB, etwa dem 5-8-fachen dessen, was unsere native Swift-App im Ruhezustand verbraucht.
Ein eigenständiger CLI-Daemon. Anfangs einfacher zu bauen, aber schwieriger für nicht-technische Benutzer zu verwalten und unmöglich mit den macOS-Menüleisten-Konventionen zu integrieren.
Direkte PTY-Verwaltung anstelle von tmux. Mehr Kontrolle, aber wir hätten Sitzungspersistenz, Terminal-Emulations-Randfälle und Prozess-Lifecycle-Management neu implementieren müssen — Dinge, die tmux bereits zuverlässig handhabt.
Ein LaunchAgent für den Autostart. Wir haben dies implementiert, aber als Opt-in statt als Standard eingerichtet. Entwickler haben starke Meinungen darüber, was beim Login läuft, und wir respektieren das.
Leistungsprofil
Unter typischer Last (2 aktive Sitzungen, 1 verbundenes iPhone) der Ressourcenverbrauch der Begleit-App:
| Metrik | Wert |
|---|---|
| Arbeitsspeicher (RSS) | 22-35 MB |
| CPU (Leerlauf, keine Ausgabeänderungen) | < 0,1% |
| CPU (aktives Streaming, 2 Sitzungen) | 1-3% |
| Festplatten-I/O | Vernachlässigbar (standardmäßig keine Protokollierung auf Festplatte) |
| Netzwerk (lokaler Modus, aktives Streaming) | 10-50 KB/s |
Diese Werte wurden auf einem MacBook Pro M2 mit macOS 14 gemessen. Die Leistung auf Intel-Macs ist vergleichbar, mit leicht höherer CPU-Auslastung während des aktiven Streamings.
Ausblick
Die Architektur der Begleit-App wurde so konzipiert, dass sie Fähigkeiten über das hinaus unterstützt, was wir bisher ausgeliefert haben. Die Sitzungsverwaltungsschicht kann Sitzungsfreigabe (mehrere iPhones überwachen dieselbe Sitzung), Sitzungsaufzeichnung (vollständige Terminalhistorie für die Wiedergabe erfassen) und reichere Integration mit den Erweiterbarkeits-APIs von Claude Code aufnehmen, sobald diese sich weiterentwickeln.
Für Einrichtungsanleitungen siehe Erste Schritte. Für die Fehlerbehebung der Mac-Begleit-App im Speziellen siehe Häufige Probleme.
Tactic Remote ausprobieren
Coding-Agenten vom Smartphone aus steuern
Verbinde dich mit Claude Code, Codex und anderen Agenten auf deinem Mac-, Windows- oder Linux-Rechner. Prüfe den Fortschritt und sende die nächste Anweisung vom iPhone oder iPad.