Skip to content

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.

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:

Terminal window
openclaw gateway

Auth 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.

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:

Terminal window
# List pending requests
openclaw devices list
# Approve by request ID
openclaw 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.

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, and es.
  • Non-English translations load only when needed.
  • Your choice is saved in browser storage.
  • If a translation is missing, it defaults to English.

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 exec commands on the gateway or nodes.
  • Config Management: View or edit ~/.openclaw/openclaw.json with 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.webhookToken for a dedicated bearer token.
  • Form validation helps you catch errors before you hit save.

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.

The best way to handle remote access is to keep the Gateway on loopback and use Tailscale Serve as an HTTPS proxy:

Terminal window
openclaw gateway --tailscale serve

Then 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.

Alternatively, you can bind directly to the tailnet:

Terminal window
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.

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.

The Gateway serves files from dist/control-ui. If you want to build them yourself:

Terminal window
pnpm ui:build # auto-installs UI deps on first run

If you need a specific base path for your assets:

Terminal window
OPENCLAW_CONTROL_UI_BASE_PATH=/openclaw/ pnpm ui:build

For active development, you can run a separate dev server:

Terminal window
pnpm ui:dev # auto-installs UI deps on first run

Debugging/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.

  1. Start the dev server: pnpm ui:dev
  2. Open the URL with the gatewayUrl parameter:
http://localhost:5173/?gatewayUrl=ws://<gateway-host>:18789

If 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"],
},
},
}

AI Setup Assistant

OpenClaw

OpenClaw Expert

Still stuck?

If this page didn't answer your case, ask OpenClaw Expert for step-by-step guidance.