Zum Inhalt springen

Rigs

Nur Fakten. Das Modell dahinter steht unter Rigs und Kapseln; eine Maschine öffnest du über die Anleitung.

Oberfläche Steuert Backend Wert Gekapselter Ausgang
Terminal (exec) Eine Shell über den Exec-Kanal der VM microVM smolvm Ja
Browser Headless Chromium (CDP), Firefox (WebDriver BiDi) oder WebKit (W3C WebDriver) microVM smolvm Ja
Computer X11-Desktop: Eingabe über den Hypervisor, Aufnahme über den Gast-Agenten QEMU qemu-hvf (macOS), qemu-kvm (Linux), qemu-tcg (unbeschleunigter Fallback, wird nie automatisch gewählt) Ja
Android Android über ADB Emulator von Google android-emulator Nein — der Emulator verwaltet sein eigenes Netz
iOS iOS-Simulator über WebDriverAgent CoreSimulator ios-simulator Nein — das Netz folgt dem Host-Mac

Das Terminal und die Oberfläche computer_use teilen den Oberflächenwert computer; das Terminal ist an seinem Exec-Image-Marker zu erkennen und wird nie als steuerbarer Desktop wiederverwendet (und umgekehrt). Ein Gespräch nutzt genau eine Terminalmaschine wieder.

Engine Wert Protokoll Live-Ansicht Standbilder
Chromium chromium (Standard) Chrome DevTools Protocol Screencast — der Browser schiebt Frames, sobald die Seite neu zeichnet JPEG
Firefox firefox WebDriver BiDi Abgefragte Standbilder (BiDi hat keinen Screencast), gedeckelt bei 6 fps JPEG
WebKit webkit W3C WebDriver (klassisch) Abgefragte Standbilder, vom ffmpeg des Hosts transkodiert PNG

Ein Rig läuft sein ganzes Leben mit einer Engine. Ein Gespräch kann je Engine ein Rig halten, und genau das macht den Vergleich nebeneinander möglich: „Firefox (VM)“ neben „Chromium (VM)“ zu öffnen sind zwei Maschinen, und eine zu schließen lässt die andere weiterlaufen.

Übergib engine an rig.open oder an das Werkzeug browser_use. Ein unbekannter Name wird abgelehnt statt durch den Standard ersetzt — nach einem Browser zu fragen und still einen anderen zu bekommen beantwortet eine Kompatibilitätsfrage mit der falschen Antwort.

Engine-spezifische Grenzen, benannt statt umgangen:

  • Firefox hat kein Neuladen, das den Cache umgeht (es lehnt das ignoreCache von BiDi rundweg ab), ein hartes Neuladen ist also ein normales.
  • WebKit hat ebenfalls kein Neuladen, das den Cache umgeht, und keinen Konsolenstrom (die Ausgabe wird eingefangen, indem console.* nach jeder Navigation eingehängt wird, sodass alles verloren geht, was während des Ladens geloggt wurde — jeder Konsolenauszug sagt das) und braucht ffmpeg auf dem Host für seine Live-Ansicht.
  • Keines von beiden legt über sein Protokoll einen Plattform-Barrierefreiheitsbaum offen, extract (a11y) liefert also eine aus dem DOM abgeleitete Näherung und kennzeichnet sie als solche.
  • Keines von beiden nimmt einen echten Datei-Drop an; ein Datei-Input lässt sich weiter auf Pfade in der Maschine richten.
Oberfläche Image Bezogen
Terminal ubuntu:24.04, auf den Digest gepinnt Automatisch beim ersten Boot, über das eigene gegatete Netz der Maschine
Browser (Chromium, Firefox, WebKit) debian:trixie-slim, auf den Digest gepinnt, plus die eigenen Pakete der Engine Automatisch beim ersten Boot, danach als vorgewärmtes Pack im Cache
Computer Ein qcow2-Desktop-Image mit Chromium, Firefox, WebKit und derselben CLI-Baseline eines von GitHub gehosteten Runners, die das Terminal vorwärmt Importieren unter Einstellungen → Server → Rigs (Downloads auf die Prüfsumme gepinnt, wo sie veröffentlicht sind)
Android System-Images von Google Über das Android-SDK
iOS Eine Xcode-Simulator-Runtime plus auf die Prüfsumme gepinntes WebDriverAgent Runtime über Xcode; die Automatisierungsbrücke aus Einstellungen → Server → Rigs

Nach dem ersten Boot jeder microVM-Art legt der Server eine schon entpackte Kopie unter dem Datenverzeichnis ab und bootet jede spätere Maschine daraus — auch vorgewärmte Images, in denen die Pakete schon installiert sind. Das Terminal wärmt einen CLI-Werkzeugsatz im Stil eines von GitHub gehosteten Runners vor (git, gcc, python3, jq, rsync, Archivwerkzeuge und der Rest der apt-Baseline; kein Docker und keine Sprach-Toolcaches). Das qcow2 für Computer backt dieselben CLI-Namen beim Image-Build ein, neben XFCE und den drei Browsern. Jeder Browser wärmt seine Engine vor. Alle drei Engines teilen eine Debian-Basis, nie aber ein Pack: der Cache ist auf das Image, die Engine und eine Audio-Revision geschlüsselt (audio-v1-<engine>), weil eine für eine Engine vorgewärmte Maschine — oder eine, die vorgewärmt wurde, bevor PulseAudio und ffmpeg zur Last gehörten — nichts von der anderen enthält. Das Terminal-Pack ist aus demselben Grund auf eine Werkzeugsatz-Revision geschlüsselt (tools-v1): ein Pack, das vorgewärmt wurde, bevor der Compiler zum Image gehörte, darf keine Maschine bedienen, die einen haben soll.

Es gibt kein fertiges Automatisierungs-Image, das sich lohnt — Chromiums chromedp/headless-shell kompiliert ALSA und PulseAudio beide heraus, es kann also nie Ton abgeben; das einzige gepflegte Firefox-Image ist 33× so groß wie die Debian-Basis und liefert trotzdem kein socat; ein gepflegtes WebKit-Image gibt es gar nicht. Jede Engine installiert also beim ersten Start (chromium, firefox-esr oder webkit2gtk-driver) und erreicht dabei die Debian-Archive (deb.debian.org, security.debian.org, cloudfront.debian.net). Chromium ist das Binary der Distribution, gestartet als chromium --headless=new.

Einstellungsschlüssel Überschreibt
rigs.smolvm.execImage Das Image für Terminal (VM)
rigs.smolvm.browserImage Das Image für Chromium Browser (VM)

Geschrieben über den auf Admins beschränkten Einstellungsspeicher des Arbeitsbereichs (Einstellungen → Server → Rigs → Eigene Images (dieser Arbeitsbereich)). Der Wert muss eine Registry-Referenz sein — lokale Pfade, Archive und flagartige Zeichenketten werden abgelehnt, am Feld und noch einmal beim Boot. Ein ungültig gespeicherter Wert wird laut ignoriert, und es bootet der Standard. Die eigene Registry des Images (plus bekannte Blob-CDN-Begleiter für Docker Hub, GHCR, Quay, GitLab und GCR) wird für den Pull durch das Ausgangstor gelassen.

Terminal-Image-Vertrag — bash vorhanden; git, curl, socat vorinstalliert oder eine Debian-/Ubuntu-apt-Basis (die Kapsel installiert diese drei plus einen CLI-Werkzeugsatz im Stil eines von GitHub gehosteten Runners beim ersten Start: Compiler, Python 3, jq, Archivwerkzeuge, rsync. Sprach-Toolcaches und Docker werden nicht installiert).

Browser-Image-Vertrag — eine Debian-/Ubuntu-apt-Basis (oder die Pakete schon installiert) mit bash und socat, plus einem chromium-Binary, das der Server selbst als chromium --headless=new startet, mit DevTools auf dem Gast-Loopback 9223, durchgereicht auf den Gast-Port 9222. PulseAudio und ffmpeg werden beim ersten Start für die Audio-Bahn installiert. Baue nicht FROM chromedp/headless-shell: das Upstream-headless.gn kompiliert ALSA und PulseAudio beide heraus, dieses Binary kann also keinen Ton abgeben. Die Überschreibung gilt nur für Chromium-Rigs — der Workload-Befehl, mit dem sie bootet, ist der von Chromium, und ihn an Firefox oder WebKit zu geben, würde ein Binary starten, das nicht da ist. Ein Firefox- oder WebKit-Rig ignoriert sie laut und bootet sein gepinntes Image.

Automatisierungsports — jede Browsermaschine leitet genau einen Loopback-Port des Hosts auf den Gast-Port 9222 weiter. Dahinter sitzen Chromiums DevTools und der Remote-Agent von Firefox auf dem Gast-Loopback 9223, mit einem socat-Relay davor (beide binden Loopback bedingungslos); der Treiber von WebKit nimmt --host und bindet die NIC des Gastes selbst. Firefox prüft zusätzlich den Header Host gegen seinen eigenen Port, der Client sendet also die gastseitige Authority, nicht die, die er angewählt hat.

Jede Aktion wird vollständig geparst: eine fehlerhafte Nutzlast liefert eine Nachricht, die das Feld nennt, nie eine Exception. Beobachtungsverben (mit ○ markiert) bleiben erlaubt, solange ein Mensch die Steuerung hält; verändernde Verben werden abgelehnt.

screenshot○, cursor_position○, mouse_move, left_click, right_click, middle_click, double_click, triple_click, left_mouse_down, left_mouse_up, left_click_drag, scroll, key, hold_key (0–60 s), type, wait○ (0–60 s), set_display, clipboard_read○, clipboard_write.

Koordinaten sind Gastpixel im aktuellen Modus des Gastes; jeder Screenshot nennt die Anzeigegröße. Tastenkombinationen nutzen die X11-Schreibweise (ctrl+s, alt+Tab, Return).

clipboard_read nimmt eine selection: clipboard (was ctrl+C füllt, der Standard), primary (X11, Auswahl wird kopiert) oder xdnd (ein laufender Drag). Ein leeres Ergebnis ist für alle drei eine normale Antwort. clipboard_write nimmt nur text — Bilder und Dateien laufen über die Datei-Bahn, weil die Argumente einer Aktion im Audit-Protokoll landen und Bildbytes dort nichts zu suchen haben. Inhalt der Zwischenablage kommt umzäunt als unvertrauenswürdige Daten zurück.

navigate (nur http/https), reload (hard optional), stop_loading, click (Selektor oder Koordinate), fill, type, key (DOM-Tastennamen), scroll, mouse_move, drag, left_mouse_down, left_mouse_up, extract○ (a11y | dom | console), screenshot○ (full_page optional), set_viewport (mindestens 320×240), history, wait_for○ (Selektor, 0.1–30 s), clipboard_read○, clipboard_write.

Extrahierter Seiteninhalt kommt umzäunt als unvertrauenswürdige Daten zurück.

Der Browser hat genau eine Zwischenablage, clipboard_read nimmt also keine selection. Beide Zwischenablage-Verben brauchen einen sicheren Kontext: eine über nacktes http:// ausgelieferte Seite hat gar keine Clipboard-API, und das Verb sagt das, statt eine leere zu melden — nimm dort type, das an der Einfügemarke einfügt, ohne über eine Zwischenablage zu gehen.

tap, swipe (50–5000 ms), type, key (Aliasse back, home, recents, enter, delete, backspace, tab, escape, search, menu, volume_up, volume_down, power oder ein beliebiges KEYCODE_*), screenshot○, ui_dump○, install_apk (begrenzt auf den Worktree des Rigs und das Datenverzeichnis des Servers), start_app, stop_app, clear_app_data, uninstall_app, open_url und shell. shell nimmt eine argv-Liste und läuft in Android, nie über eine Host-Shell; es deckt Entwicklerdiagnosen wie logcat, dumpsys und pm grant ab.

mobile_use hat keine Zwischenablage-Verben. Seit Android 10 darf nur die fokussierte App die Zwischenablage lesen.

tap, swipe (50–5000 ms), type, key (enter, backspace, tab, escape, Pfeiltasten oder ein druckbares Zeichen; optionale Modifikatoren command, control, option und shift), home, lock, unlock, screenshot○, ui_dump○, install_app (ein Simulator-Verzeichnis .app, begrenzt auf den Rig-Worktree oder das Datenverzeichnis des Servers), start_app, stop_app, uninstall_app, open_url und spawn. spawn nimmt argv und führt im Simulator über simctl aus; eine Host-Shell ruft es nie auf.

Koordinaten sind Punkte des iOS-Bildschirms, nicht Screenshot-Pixel. Der Live-Stream behält die feste Größe des Simulators und setzt ihn in Letterbox, statt das Gerät zu skalieren. Die Übertragung der Text-Zwischenablage vom Host zum Simulator und vom Simulator zum Host folgt derselben Berechtigungsrichtlinie je Benutzer und je Richtung wie bei anderen Rigs; Dateien und Bilder nimmt die Pasteboard-Bahn von iOS nicht an.

Jedes Rig legt ein eigenes CoreSimulator-Gerät und eine WebDriverAgent-Sitzung an. Beim Schließen stoppt WebDriverAgent, das Gerät wird heruntergefahren und gelöscht, und sein Registry-Eintrag verschwindet. iOS-Rigs laufen nur auf einem macOS-Server mit Xcode, einer installierten iOS-Runtime und der gepinnten Automatisierungsbrücke. Sie bieten kein Audio, kein Mikrofon, keinen Datei-Drop, keine Host-Shell und keine Zusicherung eines gekapselten Netzes.

Werkzeug Beschreibung
rig_list Listet die Rigs eines Arbeitsbereichs mit Oberfläche, Status, Anzeige und Steuerndem
rig_close Zerstört ein Rig und verwirft seine Platte
Phase Bedeutung
provisioning Bootet; das Statusdetail trägt den aktuellen Schritt wortgetreu
ready Erreichbar und nimmt Aktionen an
parked Im Leerlauf geparkt: vCPUs gestoppt, RAM bleibt resident; die nächste Aktion weckt es
closing Fährt herunter
closed Weg; die Zeile bleibt für den Audit-Trail
failed Gestorben oder nie hochgekommen; unterscheidbar, damit die Oberfläche einen neuen Versuch anbieten kann
Schließgrund Ausgelöst, wenn
requested Eine Person oder ein Agent hat darum gebeten
idleTimeout Leerlauf über das Doppelte des Leerlauf-Fensters hinaus, oder aus Speichergründen verdrängt
ttlExpired Die harte Lebensdauer ist abgelaufen
conversationEnded Das besitzende Gespräch ist zu Ende
workspaceGone Der Arbeitsbereich wurde gelöscht oder die Mitgliedschaft ist weg
serverShutdown Der Server stoppt
backendFailure Der Hypervisor darunter ist gestorben
Wert Terminal Browser Computer Mobil
Arbeitsspeicher 512 MB 2048 MB (Chromium); 2560 MB (Firefox, WebKit) 4096 MB 4096 MB
vCPUs 2 2 4 4
Harte TTL 8 h 2 h 2 h 2 h
Leerlauf-Fenster 45 min 15 min 15 min 15 min
Boot-Anzeige — 1280×800 1280×800 1080×1920
  • Standbilder der Agentenbahn sind auf 1280×800 gedeckelt; die Menschenbahn verhandelt bis 2560×1600.
  • Das Budget des Hosts an residentem Speicher für alle Rigs liegt standardmäßig bei 12 GB, gezählt in residenten Megabyte (eine geparkte VM hält ihr RAM weiter). Verdrängt wird die am längsten ungenutzte Maschine, und nie eine, die jemand steuert, beobachtet oder in der ein Terminal offen ist.
  • Ein offenes Terminal oder eine Zuschauerbahn hält das Rig vom Parken und vom Leerlauf-Abbau ab; die harte TTL gilt weiter.
Port Wo Reserviert für
7911 Terminal-Gast Der Port-Multiplexer, über den jede Weiterleitung läuft
9222, 9223 Browser-Gast Das Automatisierungs-Relay und der Endpunkt (WebKit bindet 9222 direkt und nutzt kein Relay)
80, 443 Loopback des Browser-Gastes Die HTTP-/HTTPS-Bahnen der Dev-Domain
  • Die Erkennung fragt die lauschenden TCP-Ports des Terminal-Gastes etwa alle 4 s ab, serverseitig.
  • Höchstens 16 Ports werden je Rig automatisch weitergeleitet; weitere stehen im Log, nicht in der Weiterleitung.
  • Die hostseitige Weiterleitung bindet Loopback und nimmt bevorzugt die eigene Portnummer des Gastes; Im lokalen Netzwerk teilen ergänzt einen vom Betriebssystem vergebenen LAN-Port.
  • Dev-Domains müssen name.test oder name.localhost entsprechen (Kleinbuchstaben, Label mit höchstens 63 Zeichen). Eine Domain bildet auf genau einen Port ab.
  • HTTPS der Dev-Domain nutzt eine serverlokale CA (EC P-256, unter <dataDir>/rigs/tls/, Schlüssel 0600 und nie in einem Gast) mit einem Wildcard-Blatt für *.test / *.localhost. Ohne openssl auf dem Host gibt es keine HTTPS-Bahn; nacktes HTTP wird weiter geroutet.
Oberfläche Standard-Zulassungsliste
Terminal Die Entwickler-Baseline der Sandbox (Forges, Paketregistries, Modellanbieter) + die apt-Spiegel von Ubuntu + der eigene Forge-Host des Worktrees
Browser usectrl.dev (die Produktseite) — plus die Debian-Archive beim ersten Boot jeder Engine, solange sie ihre Pakete installiert. Die Startseite ist ein lokales file://-Dokument und braucht keinen Ausgang
Computer Leer — alles verweigern — bis ein Aufrufer Hosts freigibt
Mobil Nicht durchgesetzt (vom Emulator verwaltetes Netz)

Jede microVM bekommt zusätzlich die Registry-Hosts ihres Images, nur für den Pull. Die Menge erlaubter Hosts des Zugangsdaten-Brokers leitet sich aus derselben Zulassungsliste ab: für einen Host, den der Gast nicht erreichen kann, wird kein Token ausgestellt.

Kopieren und Einfügen in beide Richtungen, und Dateien hinein- und hinausziehen. Das steht einer Person zur Verfügung, die ein Rig steuert; ein Agent bekommt die Zwischenablage über die Verben oben und gar keine Dateiübertragung (in der Kapsel hat er schon eine Shell).

Das Überschreiten der Zwischenablage ist je Benutzer und je Richtung geregelt. Einfügen vom Host ins Rig ist standardmäßig erlaubt; Herauskopieren vom Rig zum Host fragt nach (eine zehnminütige Freigabe, oder Immer erlauben unter Einstellungen → Server → Rigs → Zugriff auf die Zwischenablage). Die beiden Entscheidungen sind unabhängig und nie eine Einstellung des Arbeitsbereichs.

Bahn Route Trägt
Zwischenablage GET/POST /rig/clipboard/<rigId> Text, ein PNG/JPEG (≤16 MB) und die Gastpfade von Dateien auf der Zwischenablage
Dateien POST /rig/files/<rigId> Bis zu 64 Dateien, je ≤256 MB und ≤512 MB je Drop, mit optionalem Drop-Punkt in Gastpixeln
Dateien GET /rig/files/<rigId>?p=<base64url path> Die Bytes einer Datei, zurück nach draußen
  • HTTP, nicht RPC. Der RPC-Socket schließt eine Verbindung bei einem eingehenden Frame über 256 KB — ein DoS-Schutz, der für JSON-Befehle richtig und für einen eingefügten Screenshot tödlich ist. Bytes laufen über dieselbe Art von Route, über die schon Rig-Frames und das Audio von Besprechungen laufen.
  • Authentifizierung ist das signierte Ziel rig-files:<workspaceId>/<rigId> plus die Mitgliedschaft im Arbeitsbereich — ein eigenes Ziel, sodass eine URL, die geprägt wurde, um eine Maschine zu beobachten, nicht auch Dateien hineinschreiben kann.
  • Die Übernahme gilt. Die Zwischenablage zu schreiben und Dateien abzulegen ist verändernd und wird abgelehnt, solange jemand anderes die Steuerung hält; die Zwischenablage zu lesen und eine Datei herauszulesen ist Beobachtung und wird nicht abgelehnt.
  • Wo Drops landen: ~/Drops (Desktop), ~/drops (Terminal — neben dem Worktree, nie darin, sodass ein Drop nie als unversionierte Änderung auftaucht), /tmp/cc-drops (Browser). Der Server wählt das Verzeichnis; ein Aufrufer kann es nicht benennen. Vorhandene Dateien werden nie überschrieben — ein kollidierender Name landet als 2-name.ext.
  • Was der Gast erfährt: eine Browserseite bekommt am angeforderten Punkt ein echtes Drop-Ereignis (Input.dispatchDragEvent); ein Desktop bekommt die Dateien plus ihre URIs auf die Zwischenablage, weil kein Host einen XDND-Drag in ein beliebiges Toolkit erzeugen kann, ohne im Gast einen privilegierten Daemon laufen zu lassen. Die Antwort sagt, welches von beiden geschehen ist.
  • Hinausziehen gibt es nur auf dem Desktop und liest die XdndSelection des Gastes, solange ein Drag läuft. Eine Nutzlast, die mit dem identisch ist, was der Gast beim Beginn des Drucks schon hielt, gilt als veraltete Auswahl eines beendeten Drags, nicht als neue — X hat keinen Schritt „der Drag ist vorbei“.
  • Image-Anforderungen: das Desktop-Image muss Protokoll 2 oder neuer sein (gebaut, nachdem die Zwischenablage-Unterstützung eingebaut wurde). Ein älteres Image antwortet mit 404, und die App sagt, es neu zu bauen, statt eine kaputte Maschine zu melden.
  • Das Audit-Protokoll hält die Form fest, nie den Inhalt: Zeilen für clipboard_read, clipboard_write, drop_files und read_file tragen Anzahlen, Größen und Pfade. Eine Zwischenablage ist der Ort, an dem Zugangsdaten jeweils ein paar Sekunden leben, und nichts davon wird aufgeschrieben.
  • Rig-Werkzeuge deklarieren die Aktionsklasse enclosureControl (plus networkEgress und processSpawn an den Use-Werkzeugen; mobile_use und ios_use deklarieren außerdem packageInstall). rig_close deklariert enclosureControl; rig_list deklariert keine. Standardmäßig erlaubt; Nur-Lese-Modi verweigern sie pauschal; der Autonomieregler je Bereich kann sie auf Zuerst fragen herabstufen.
  • Domain-Ereignisse: RigClosedEvent (mit seinem Schließgrund), RigControlChanged (Übernahme / Rückgabe), RigReaped (Leerlauf, TTL oder Speicherverdrängung, mit dem steuernden Agenten). Ein Rig zu öffnen ist kein Ereignis. Siehe Domain-Ereignisse.
  • Speicher: rig_sessions und rig_action_log in der Datenbank jedes Arbeitsbereichs. Das Aktionsprotokoll zeichnet jedes Eingabeereignis mit seinem Prinzipal und einer monotonen Folge je Rig auf; getippter Text wird vor dem Schreiben auf Länge und Hash reduziert.
  • Datenverzeichnis: rigs/images/ (importierte qcow2-Images), rigs/smolvm/ (Laufzeitzustand je Rig), rigs/smolvm-packs/ (schon entpackte Maschinen-Packs), rigs/tls/ (die CA der Dev-Domain), rigs/run/ (QEMU-Overlays und Seeds).
  • Routen: die Live-Ansicht ist ein Tab in einem Bereich oder auf einer PR-Seite; /settings/server/rigs ist der Einstellungsbildschirm für Rigs.