Control UI (Browser)
Die Control UI ist eine kleine Vite + Lit Single-Page-App, die vom Gateway bereitgestellt wird:
- Standard:
http://<host>:18789/ - Optionaler Präfix: setze
gateway.controlUi.basePath(z. B./openclaw)
Sie kommuniziert direkt mit dem Gateway-WebSocket auf demselben Port.
Schnell öffnen (lokal)
Wenn das Gateway auf demselben Computer läuft, öffne:
Wenn die Seite nicht lädt, starte zuerst das Gateway: openclaw gateway.
Authentifizierung erfolgt beim WebSocket-Handshake über:
connect.params.auth.tokenconnect.params.auth.passwordDas Dashboard-Einstellungspanel speichert ein Token für die aktuelle Browser-Tab-Sitzung und die gewählte Gateway-URL; Passwörter werden nicht gespeichert. Der Einrichtungsassistent generiert standardmäßig ein Gateway-Token — füge es hier beim ersten Verbinden ein.
Gerätekopplung (erste Verbindung)
Wenn du dich von einem neuen Browser oder Gerät mit der Control UI verbindest, verlangt das Gateway
eine einmalige Kopplungsgenehmigung — selbst wenn du im selben Tailnet bist
mit gateway.auth.allowTailscale: true. Das ist eine Sicherheitsmaßnahme gegen
unbefugten Zugriff.
Was du siehst: „disconnected (1008): pairing required”
Um das Gerät zu genehmigen:
# Ausstehende Anfragen auflisten
openclaw devices list
# Nach Request-ID genehmigen
openclaw devices approve <requestId>
Einmal genehmigt, wird das Gerät gespeichert und benötigt keine erneute Genehmigung, es sei denn
du widerrufst es mit openclaw devices revoke --device <id> --role <role>. Siehe
Geräte-CLI für Token-Rotation und Widerruf.
Hinweise:
- Lokale Verbindungen (
127.0.0.1) werden automatisch genehmigt. - Remote-Verbindungen (LAN, Tailnet usw.) erfordern explizite Genehmigung.
- Jedes Browser-Profil generiert eine eindeutige Geräte-ID, daher erfordert ein Browserwechsel oder das Löschen der Browserdaten eine erneute Kopplung.
Sprachunterstützung
Die Control UI kann sich beim ersten Laden basierend auf deiner Browser-Sprache lokalisieren, und du kannst sie später über die Sprachauswahl in der Access-Karte ändern.
- Unterstützte Locales:
en,zh-CN,zh-TW,pt-BR,de,es - Nicht-englische Übersetzungen werden im Browser lazy geladen.
- Das gewählte Locale wird im Browser-Speicher gespeichert und bei zukünftigen Besuchen wiederverwendet.
- Fehlende Übersetzungsschlüssel fallen auf Englisch zurück.
Was sie kann (aktuell)
- Mit dem Modell via Gateway-WS chatten (
chat.history,chat.send,chat.abort,chat.inject) - Streaming-Tool-Calls + Live-Tool-Ausgabekarten im Chat (Agent-Events)
- Kanäle: WhatsApp/Telegram/Discord/Slack + Plugin-Kanäle (Mattermost usw.) Status + QR-Login + kanalspezifische Konfiguration (
channels.status,web.login.*,config.patch) - Instanzen: Präsenzliste + Aktualisierung (
system-presence) - Sitzungen: Liste + sitzungsspezifische Thinking/Fast/Verbose/Reasoning-Overrides (
sessions.list,sessions.patch) - Cron-Jobs: Liste/Hinzufügen/Bearbeiten/Ausführen/Aktivieren/Deaktivieren + Ausführungsverlauf (
cron.*) - Skills: Status, Aktivieren/Deaktivieren, Installieren, API-Key-Updates (
skills.*) - Nodes: Liste + Fähigkeiten (
node.list) - Exec-Genehmigungen: Gateway- oder Node-Allowlists bearbeiten + Ask-Richtlinie für
exec host=gateway/node(exec.approvals.*) - Konfiguration:
~/.openclaw/openclaw.jsonanzeigen/bearbeiten (config.get,config.set) - Konfiguration: Anwenden + Neustart mit Validierung (
config.apply) und letzte aktive Sitzung wecken - Konfigurationsschreibvorgänge enthalten einen Base-Hash-Schutz gegen das Überschreiben gleichzeitiger Änderungen
- Konfigurations-Schema + Formulardarstellung (
config.schema, einschließlich Plugin- + Kanal-Schemas); Raw-JSON-Editor bleibt verfügbar - Debug: Status-/Health-/Modell-Snapshots + Event-Log + manuelle RPC-Aufrufe (
status,health,models.list) - Logs: Live-Tail der Gateway-Dateilogs mit Filter/Export (
logs.tail) - Update: Paket-/Git-Update + Neustart ausführen (
update.run) mit Neustartbericht
Hinweise zum Cron-Jobs-Panel:
- Für isolierte Jobs wird die Zustellung standardmäßig als Zusammenfassungsankündigung gesendet. Du kannst auf „keine” umschalten, wenn du rein interne Runs möchtest.
- Kanal-/Zielfelder erscheinen, wenn Ankündigung ausgewählt ist.
- Webhook-Modus nutzt
delivery.mode = "webhook"mitdelivery.toals gültige HTTP(S)-Webhook-URL. - Für Hauptsitzungs-Jobs sind Webhook- und Keine-Zustellmodi verfügbar.
- Erweiterte Bearbeitungssteuerungen umfassen Löschen-nach-Ausführung, Agent-Override löschen, Cron-Exakt/Stagger-Optionen, Agent-Modell/Thinking-Overrides und Best-Effort-Zustellungsschalter.
- Formularvalidierung ist inline mit Feldebenen-Fehlern; ungültige Werte deaktivieren den Speichern-Button bis zur Korrektur.
- Setze
cron.webhookToken, um ein dediziertes Bearer-Token zu senden; wenn weggelassen, wird der Webhook ohne Auth-Header gesendet. - Veralteter Fallback: gespeicherte Legacy-Jobs mit
notify: truekönnen weiterhincron.webhooknutzen, bis sie migriert werden.
Chat-Verhalten
chat.sendist nicht-blockierend: Es bestätigt sofort mit{ runId, status: "started" }und die Antwort streamt überchat-Events.- Erneutes Senden mit demselben
idempotencyKeygibt{ status: "in_flight" }während der Ausführung und{ status: "ok" }nach Abschluss zurück. chat.history-Antworten sind größenbeschränkt für UI-Sicherheit. Wenn Transkripteinträge zu groß sind, kann das Gateway lange Textfelder kürzen, schwere Metadatenblöcke weglassen und übergroße Nachrichten durch einen Platzhalter ersetzen ([chat.history omitted: message too large]).chat.injecthängt eine Assistenten-Notiz an das Sitzungstranskript an und sendet einchat-Event für reine UI-Updates (kein Agent-Run, keine Kanalzustellung).- Stoppen:
- Klicke Stopp (ruft
chat.abortauf) - Tippe
/stop(oder eigenständige Abbruch-Phrasen wiestop,stop action,stop run,stop openclaw,please stop), um out-of-band abzubrechen chat.abortunterstützt{ sessionKey }(ohnerunId), um alle aktiven Runs für diese Sitzung abzubrechen
- Klicke Stopp (ruft
- Partielle Beibehaltung bei Abbruch:
- Wenn ein Run abgebrochen wird, kann partieller Assistententext weiterhin in der UI angezeigt werden
- Das Gateway speichert abgebrochenen partiellen Assistententext in der Transkript-History, wenn gepufferter Output existiert
- Gespeicherte Einträge enthalten Abbruch-Metadaten, damit Transkript-Konsumenten Abbruch-Partials von normaler Ausgabe unterscheiden können
Tailnet-Zugang (empfohlen)
Integriertes Tailscale Serve (bevorzugt)
Halte das Gateway auf Loopback und lass Tailscale Serve es mit HTTPS proxyen:
openclaw gateway --tailscale serve
Öffne:
https://<magicdns>/(oder dein konfiguriertergateway.controlUi.basePath)
Standardmäßig können Control-UI-/WebSocket-Serve-Anfragen sich über Tailscale-Identity-Header
(tailscale-user-login) authentifizieren, wenn gateway.auth.allowTailscale true ist. OpenClaw
verifiziert die Identität, indem es die x-forwarded-for-Adresse per
tailscale whois auflöst und mit dem Header abgleicht, und akzeptiert diese nur, wenn die
Anfrage auf Loopback mit Tailscales x-forwarded-*-Headern ankommt. Setze
gateway.auth.allowTailscale: false (oder erzwinge gateway.auth.mode: "password"),
wenn du auch für Serve-Traffic ein Token/Passwort verlangen möchtest.
Tokenlose Serve-Auth setzt voraus, dass der Gateway-Host vertrauenswürdig ist. Wenn nicht vertrauenswürdiger lokaler
Code auf diesem Host laufen könnte, verlange Token/Passwort-Auth.
Tailnet-Bind + Token
openclaw gateway --bind tailnet --token "$(openssl rand -hex 32)"
Dann öffne:
http://<tailscale-ip>:18789/(oder dein konfiguriertergateway.controlUi.basePath)
Füge das Token in den UI-Einstellungen ein (wird als connect.params.auth.token gesendet).
Unsicheres HTTP
Wenn du das Dashboard über unverschlüsseltes HTTP öffnest (http://<lan-ip> oder http://<tailscale-ip>),
läuft der Browser in einem nicht-sicheren Kontext und blockiert WebCrypto. Standardmäßig
blockiert OpenClaw Control-UI-Verbindungen ohne Geräteidentität.
Empfohlene Lösung: Verwende HTTPS (Tailscale Serve) oder öffne die UI lokal:
https://<magicdns>/(Serve)http://127.0.0.1:18789/(auf dem Gateway-Host)
Verhalten des Unsicher-Auth-Schalters:
{
gateway: {
controlUi: { allowInsecureAuth: true },
bind: "tailnet",
auth: { mode: "token", token: "replace-me" },
},
}
allowInsecureAuth ist ein reiner lokaler Kompatibilitätsschalter:
- Er erlaubt localhost-Control-UI-Sitzungen ohne Geräteidentität in nicht-sicheren HTTP-Kontexten fortzufahren.
- Er umgeht keine Kopplungsprüfungen.
- Er lockert keine Remote-(nicht-localhost-)Geräteidentitätsanforderungen.
Nur für Notfälle:
{
gateway: {
controlUi: { dangerouslyDisableDeviceAuth: true },
bind: "tailnet",
auth: { mode: "token", token: "replace-me" },
},
}
dangerouslyDisableDeviceAuth deaktiviert Control-UI-Geräteidentitätsprüfungen und ist eine
schwerwiegende Sicherheitsabsenkung. Nach Notfallnutzung schnell zurücksetzen.
Siehe Tailscale für HTTPS-Setup-Anleitung.
UI bauen
Das Gateway liefert statische Dateien aus dist/control-ui. Baue sie mit:
pnpm ui:build # installiert UI-Abhängigkeiten beim ersten Lauf automatisch
Optionaler absoluter Basispfad (wenn du feste Asset-URLs möchtest):
OPENCLAW_CONTROL_UI_BASE_PATH=/openclaw/ pnpm ui:build
Für lokale Entwicklung (separater Dev-Server):
pnpm ui:dev # installiert UI-Abhängigkeiten beim ersten Lauf automatisch
Richte dann die UI auf deine Gateway-WS-URL (z. B. ws://127.0.0.1:18789).
Debugging/Testing: Dev-Server + Remote-Gateway
Die Control UI besteht aus statischen Dateien; das WebSocket-Ziel ist konfigurierbar und kann sich vom HTTP-Ursprung unterscheiden. Das ist praktisch, wenn du den Vite-Dev-Server lokal nutzt, aber das Gateway woanders läuft.
- UI-Dev-Server starten:
pnpm ui:dev - Eine URL wie diese öffnen:
http://localhost:5173/?gatewayUrl=ws://<gateway-host>:18789
Optionale einmalige Auth (wenn nötig):
http://localhost:5173/?gatewayUrl=wss://<gateway-host>:18789#token=<gateway-token>
Hinweise:
gatewayUrlwird nach dem Laden in localStorage gespeichert und aus der URL entfernt.tokenwird aus dem URL-Fragment importiert, in sessionStorage für die aktuelle Browser-Tab-Sitzung und gewählte Gateway-URL gespeichert und aus der URL entfernt; es wird nicht in localStorage gespeichert.passwordwird nur im Arbeitsspeicher gehalten.- Wenn
gatewayUrlgesetzt ist, fällt die UI nicht auf Konfigurations- oder Umgebungszugangsdaten zurück. Gibtoken(oderpassword) explizit an. Fehlende explizite Zugangsdaten sind ein Fehler. - Verwende
wss://, wenn das Gateway hinter TLS liegt (Tailscale Serve, HTTPS-Proxy usw.). gatewayUrlwird nur in einem Top-Level-Fenster akzeptiert (nicht eingebettet), um Clickjacking zu verhindern.- Nicht-Loopback-Control-UI-Deployments müssen
gateway.controlUi.allowedOriginsexplizit setzen (vollständige Origins). Das gilt auch für Remote-Dev-Setups. gateway.controlUi.dangerouslyAllowHostHeaderOriginFallback=trueaktiviert den Host-Header-Origin-Fallback-Modus, ist aber eine gefährliche Sicherheitsabsenkung.
Beispiel:
{
gateway: {
controlUi: {
allowedOrigins: ["http://localhost:5173"],
},
},
}
Remote-Zugang-Setup-Details: Remote-Zugang.