Caricamento in corso...
Caricamento in corso...
Last synced: Today, 22:00
Technical reference for the OpenClaw framework. Real-time synchronization with the official documentation engine.
Use this file to discover all available pages before exploring further.
The Control UI is a small Vite + Lit single-page app served by the Gateway:
http://<host>:18789/gateway.controlUi.basePath/openclawIt speaks directly to the Gateway WebSocket on the same port.
If the Gateway is running on the same computer, open:
If the page fails to load, start the Gateway first:
openclaw gatewayAuth is supplied during the WebSocket handshake via:
connect.params.auth.tokenconnect.params.auth.passwordgateway.auth.allowTailscale: truegateway.auth.mode: "trusted-proxy"The dashboard settings panel keeps a token for the current browser tab session and selected gateway URL; passwords are not persisted. Onboarding usually generates a gateway token for shared-secret auth on first connect, but password auth works too when
gateway.auth.mode"password"When you connect to the Control UI from a new browser or device, the Gateway usually requires a one-time pairing approval. This is a security measure to prevent unauthorized access.
What you'll see: "disconnected (1008): pairing required"
If the browser retries pairing with changed auth details (role/scopes/public key), the previous pending request is superseded and a new
requestIdopenclaw devices listIf the browser is already paired and you change it from read access to write/admin access, this is treated as an approval upgrade, not a silent reconnect. OpenClaw keeps the old approval active, blocks the broader reconnect, and asks you to approve the new scope set explicitly.
Once approved, the device is remembered and won't require re-approval unless you revoke it with
openclaw devices revoke --device <id> --role <role>The Control UI supports a per-browser personal identity (display name and avatar) attached to outgoing messages for attribution in shared sessions. It lives in browser storage, is scoped to the current browser profile, and is not synced to other devices or persisted server-side beyond the normal transcript authorship metadata on messages you actually send. Clearing site data or switching browsers resets it to empty.
The same browser-local pattern applies to the assistant avatar override. Uploaded assistant avatars overlay the gateway-resolved identity on the local browser only and never round-trip through
config.patchui.assistant.avatarThe Control UI fetches its runtime settings from
/__openclaw/control-ui-config.jsonThe Control UI can localize itself on first load based on your browser locale. To override it later, open Overview -> Gateway Access -> Language. The locale picker lives in the Gateway Access card, not under Appearance.
enzh-CNzh-TWpt-BRdeesja-JPkofrarittrukidplthvinlfaDocs translations are generated for the same non-English locale set, but the docs site's built-in Mintlify language picker is limited to the locale codes Mintlify accepts. Thai (
thfaThe Appearance panel keeps the built-in Claw, Knot, and Dash themes, plus one browser-local tweakcn import slot. To import a theme, open tweakcn themes, choose or create a theme, click Share, and paste the copied theme link into Appearance. The importer also accepts
https://tweakcn.com/r/themes/<id>https://tweakcn.com/editor/theme?theme=amethyst-haze/themes/<id>amethyst-hazeImported themes are stored only in the current browser profile. They are not written to gateway config and do not sync across devices. Replacing the imported theme updates the one local slot; clearing it switches the active theme back to Claw if the imported theme was selected.
The Control UI ships a
manifest.webmanifest| Surface | What it does |
|---|---|
text ui/public/manifest.webmanifest | PWA manifest. Browsers offer "Install app" once it is reachable. |
text ui/public/sw.js | Service worker that handles text push |
text push/vapid-keys.json | Auto-generated VAPID keypair used to sign Web Push payloads. |
text push/web-push-subscriptions.json | Persisted browser subscription endpoints. |
Override the VAPID keypair through env vars on the Gateway process when you want to pin keys (for multi-host deployments, secrets rotation, or tests):
OPENCLAW_VAPID_PUBLIC_KEYOPENCLAW_VAPID_PRIVATE_KEYOPENCLAW_VAPID_SUBJECTmailto:openclaw@localhostThe Control UI uses these scope-gated Gateway methods to register and test browser subscriptions:
push.web.vapidPublicKeypush.web.subscribeendpointkeys.p256dhkeys.authpush.web.unsubscribepush.web.testAssistant messages can render hosted web content inline with the
[embed ...]gateway.controlUi.embedSandboxExample:
json5{ gateway: { controlUi: { embedSandbox: "scripts", }, }, }
Absolute external
http(s)[embed url="https://..."]gateway.controlUi.allowExternalEmbedUrls: truetext```bash} openclaw gateway --tailscale serve ``` Open: * `https://<magicdns>/` (or your configured `gateway.controlUi.basePath`) By default, Control UI/WebSocket Serve requests can authenticate via Tailscale identity headers (`tailscale-user-login`) when `gateway.auth.allowTailscale` is `true`. OpenClaw verifies the identity by resolving the `x-forwarded-for` address with `tailscale whois` and matching it to the header, and only accepts these when the request hits loopback with Tailscale's `x-forwarded-*` headers. For Control UI operator sessions with browser device identity, this verified Serve path also skips the device-pairing round trip; device-less browsers and node-role connections still follow the normal device checks. Set `gateway.auth.allowTailscale: false` if you want to require explicit shared-secret credentials even for Serve traffic. Then use `gateway.auth.mode: "token"` or `"password"`. For that async Serve identity path, failed auth attempts for the same client IP and auth scope are serialized before rate-limit writes. Concurrent bad retries from the same browser can therefore show `retry later` on the second request instead of two plain mismatches racing in parallel. <Warning> Tokenless Serve auth assumes the gateway host is trusted. If untrusted local code may run on that host, require token/password auth. </Warning>
textThen open: * `http://<tailscale-ip>:18789/` (or your configured `gateway.controlUi.basePath`) Paste the matching shared secret into the UI settings (sent as `connect.params.auth.token` or `connect.params.auth.password`).
If you open the dashboard over plain HTTP (
http://<lan-ip>http://<tailscale-ip>Documented exceptions:
gateway.controlUi.allowInsecureAuth=truegateway.auth.mode: "trusted-proxy"gateway.controlUi.dangerouslyDisableDeviceAuth=trueRecommended fix: use HTTPS (Tailscale Serve) or open the UI locally:
https://<magicdns>/http://127.0.0.1:18789/See Tailscale for HTTPS setup guidance.
The Control UI ships with a tight
img-srcdata:blob:http(s)What this means in practice:
/avatars/<id>blob:data:image/...blob:You do not need to change anything to get this behavior — it is always on and not configurable.
When gateway auth is configured, the Control UI avatar endpoint requires the same gateway token as the rest of the API:
GET /avatar/<agentId>GET /avatar/<agentId>?meta=1If you disable gateway auth (not recommended on shared hosts), the avatar route also becomes unauthenticated, in line with the rest of the gateway.
The Gateway serves static files from
dist/control-uibashpnpm ui:build
Optional absolute base (when you want fixed asset URLs):
bashOPENCLAW_CONTROL_UI_BASE_PATH=/openclaw/ pnpm ui:build
For local development (separate dev server):
bashpnpm ui:dev
Then point the UI at your Gateway WS URL (e.g.
ws://127.0.0.1:18789The Control UI is static files; the WebSocket target is configurable and can be different from the HTTP origin. This is handy when you want the Vite dev server locally but the Gateway runs elsewhere.
textOptional one-time auth (if needed): ```text} http://localhost:5173/?gatewayUrl=wss%3A%2F%2F<gateway-host>%3A18789#token=<gateway-token> ```
Example:
json5{ gateway: { controlUi: { allowedOrigins: ["http://localhost:5173"], }, }, }
Remote access setup details: Remote access.
© 2024 TaskFlow Mirror
Powered by TaskFlow Sync Engine