Configure OpenClaw Control UI: Access Your Gateway in Minute
Ever found yourself staring at a terminal, wishing you could just see your agent’s thought process or tweak a config file without opening a text editor? Managing backend services shouldn’t feel like a chore.
The Control UI is a lightweight Vite + Lit single-page app that gives you a visual handle on your Gateway. It talks directly to the Gateway via WebSockets on the same port. By default, you’ll find it at http://<host>:18789/, though you can set a custom path like /openclaw using gateway.controlUi.basePath.
Quick open (local)
Section titled “Quick open (local)”If you are running the Gateway on your local machine, just head over to:
If the page doesn’t load, make sure you’ve started the Gateway first:
openclaw gatewayAuth happens during the WebSocket handshake using connect.params.auth.token or connect.params.auth.password. The dashboard settings panel stores a token for your current session and gateway URL, but it won’t persist passwords. Since onboarding generates a gateway token by default, you can just paste it in when you first connect.
Device pairing (first connection)
Section titled “Device pairing (first connection)”When you connect from a new browser or device, the Gateway asks for a one-time pairing approval. This happens even if you’re on your own Tailnet with gateway.auth.allowTailscale: true. It is a simple security step to keep things locked down.
If you see “disconnected (1008): pairing required”, here is how you approve the device:
# List pending requestsopenclaw devices list
# Approve by request IDopenclaw devices approve <requestId>If you try to pair again with different auth details, the old request gets replaced by a new requestId. Just run openclaw devices list again to get the latest ID. Once you approve it, the device is remembered. You can always change this later using openclaw devices revoke --device <id> --role <role>. Check the Devices CLI for more on token rotation.
A few things to keep in mind:
- Local connections (
127.0.0.1) get auto-approved. - Remote connections (LAN, Tailnet) always need manual approval.
- Each browser profile has its own device ID.
- Clearing browser data means you’ll need to re-pair.
Language support
Section titled “Language support”The Control UI detects your browser locale on the first load, but you can change it anytime using the language picker in the Access card.
- It supports
en,zh-CN,zh-TW,pt-BR,de, andes. - Non-English translations load only when needed.
- Your choice is saved in browser storage.
- If a translation is missing, it defaults to English.
What it can do (today)
Section titled “What it can do (today)”The UI is packed with features to help you manage your setup:
- Chat: Talk to the model via Gateway WS with support for history, sending, aborting, and injecting messages.
- Tool Calls: See live tool output cards and agent events directly in the chat.
- Channels: Manage WhatsApp, Telegram, Discord, and Slack. You can check status, use QR login, and handle per-channel configs.
- Instances & Sessions: View the presence list and manage sessions with overrides for thinking or reasoning modes.
- Cron Jobs: Add, edit, or run jobs and view their history.
- Skills & Nodes: Install skills, update API keys, and view node capabilities.
- Approvals: Edit allowlists for
execcommands on the gateway or nodes. - Config Management: View or edit
~/.openclaw/openclaw.jsonwith a built-in schema and form rendering. - Debug & Logs: Check health snapshots, view model lists, and watch live gateway logs with filters.
- Updates: Run package or git updates and restart the system.
Regarding the Cron jobs panel:
- Isolated jobs default to an announce summary, but you can turn this off.
- Webhook mode is available if you set a valid HTTP(S) URL.
- You can set
cron.webhookTokenfor a dedicated bearer token. - Form validation helps you catch errors before you hit save.
Chat behavior
Section titled “Chat behavior”The chat.send command is non-blocking. It acknowledges your request immediately and then streams the response. If you send the same idempotencyKey again while a run is active, it just returns an in_flight status.
For long conversations, chat.history might truncate very large messages or omit heavy metadata to keep the UI snappy. If you need to stop a run, you can click Stop, type /stop, or use phrases like please stop. The chat.abort command can even stop all active runs for a specific session at once. If a run is aborted, the Gateway still saves whatever partial text was generated so you don’t lose the context.
Tailnet access (recommended)
Section titled “Tailnet access (recommended)”Integrated Tailscale Serve (preferred)
Section titled “Integrated Tailscale Serve (preferred)”The best way to handle remote access is to keep the Gateway on loopback and use Tailscale Serve as an HTTPS proxy:
openclaw gateway --tailscale serveThen just open:
https://<magicdns>/
If gateway.auth.allowTailscale is true, the UI can authenticate using Tailscale identity headers. This is a secure way to manage access without constantly typing passwords, provided you trust the host machine.
Bind to tailnet + token
Section titled “Bind to tailnet + token”Alternatively, you can bind directly to the tailnet:
openclaw gateway --bind tailnet --token "$(openssl rand -hex 32)"Then access it via:
http://<tailscale-ip>:18789/
You will need to paste that token into the UI settings.
Insecure HTTP
Section titled “Insecure HTTP”If you use plain HTTP over a LAN or Tailnet IP, the browser will block WebCrypto because it is not a secure context. OpenClaw blocks these connections by default to protect your device identity.
The best fix is to use HTTPS via Tailscale Serve or stick to http://127.0.0.1:18789/. If you absolutely must use insecure HTTP, there is a compatibility toggle:
{ gateway: { controlUi: { allowInsecureAuth: true }, bind: "tailnet", auth: { mode: "token", token: "replace-me" }, },}This toggle only helps with localhost sessions in non-secure contexts. It does not bypass pairing or remote device requirements. For emergencies only, there is a “break-glass” option:
{ gateway: { controlUi: { dangerouslyDisableDeviceAuth: true }, bind: "tailnet", auth: { mode: "token", token: "replace-me" }, },}This is a major security downgrade. Use it only if you have to, and turn it off immediately after.
Building the UI
Section titled “Building the UI”The Gateway serves files from dist/control-ui. If you want to build them yourself:
pnpm ui:build # auto-installs UI deps on first runIf you need a specific base path for your assets:
OPENCLAW_CONTROL_UI_BASE_PATH=/openclaw/ pnpm ui:buildFor active development, you can run a separate dev server:
pnpm ui:dev # auto-installs UI deps on first runDebugging/testing: dev server + remote Gateway
Section titled “Debugging/testing: dev server + remote Gateway”Since the Control UI is made of static files, you can point it at any Gateway WebSocket. This is great for running the Vite dev server locally while your Gateway sits on a remote server.
- Start the dev server:
pnpm ui:dev - Open the URL with the
gatewayUrlparameter:
http://localhost:5173/?gatewayUrl=ws://<gateway-host>:18789If you need to pass a token one time:
http://localhost:5173/?gatewayUrl=wss://<gateway-host>:18789#token=<gateway-token>Using the URL fragment (#token=) is safer because fragments aren’t sent to the server. The UI will store the gatewayUrl in localStorage and clean up the URL for you. Just remember that if you are using a remote setup, you must explicitly set your allowed origins in the config:
{ gateway: { controlUi: { allowedOrigins: ["http://localhost:5173"], }, },}Related
Section titled “Related”- Dashboard — gateway dashboard
- WebChat — browser-based chat interface
- TUI — terminal user interface
- Health Checks — gateway health monitoring
Next Steps
Section titled “Next Steps”- Set up your first Cron Job
- Learn more about Tailscale integration
OpenClaw Expert
Still stuck?
If this page didn't answer your case, ask OpenClaw Expert for step-by-step guidance.