Skip to main content

Web Control UI

The Control UI is a browser-based interface for managing the OpenClaw Gateway. It’s a Vite + Lit single-page app served directly from the Gateway.

Quick access

Local (same machine as Gateway): Remote (LAN/Tailnet):
  • http://<gateway-host>:18789/
  • https://<magicdns>/ (Tailscale Serve, recommended)
If the page fails to load, start the Gateway first:

Features

The Control UI provides full Gateway management through the browser:

Chat

  • Send messages to the model via Gateway WebSocket
  • View session history with chat.history
  • Stream tool calls and live tool output cards
  • Abort in-flight runs with Stop button or /stop command
  • Inject assistant notes directly to transcript (chat.inject)
  • Partial abort retention: See partial assistant output when runs are stopped

Channels

  • View status of all channels (WhatsApp, Telegram, Discord, Slack, plugins)
  • QR code login for WhatsApp
  • Per-channel configuration via forms
  • Enable/disable channels
  • Channel authentication and pairing

Configuration

  • View and edit ~/.openclaw/openclaw.json
  • Schema-driven form rendering (including plugin and channel schemas)
  • Raw JSON editor for advanced use
  • Apply and restart Gateway with validation
  • Base-hash guard prevents concurrent edit clobbers

Sessions

  • List all Gateway sessions
  • Per-session thinking/verbose overrides
  • Switch active session context
  • View token counts and history metadata

Nodes

  • List connected nodes (macOS, iOS, Android)
  • View node capabilities and permissions
  • Invoke node commands
  • Node status and connection health

Exec Approvals

  • Edit Gateway or node allowlists for exec commands
  • Configure ask policy: never, on-miss, always
  • Security modes: deny, allowlist, ask, allow
  • Add/remove allowlist patterns
  • View last-used metadata for cleanup

Cron Jobs

  • List scheduled jobs with run history
  • Add/edit/enable/disable jobs
  • Run jobs manually
  • Configure delivery modes:
    • Announce summary (with channel/target)
    • Webhook (with optional bearer token)
    • None (internal-only)
  • Isolated vs main-session jobs

Skills

  • View installed skills and status
  • Enable/disable skills
  • Install new skills
  • Update skill API keys

Logs

  • Live tail of Gateway log files
  • Filter by level, category, subsystem
  • Export logs to file
  • Search log content

Debug

  • Status/health/models snapshots
  • Event log viewer
  • Manual RPC calls to Gateway
  • Presence list and refresh
  • Instance coordination

Updates

  • Run package/git updates
  • Restart Gateway with validation
  • View restart report

Authentication

The Control UI authenticates during WebSocket handshake: Token-based:
Password-based:
The onboarding wizard generates a gateway token by default.

Device pairing

When connecting from a new browser or device, Gateway requires one-time pairing approval: What you’ll see: “disconnected (1008): pairing required” To approve:
Once approved, the device is remembered. Revoke with:
Notes:
  • Local connections (127.0.0.1) are auto-approved
  • Remote connections (LAN, Tailnet) require explicit approval
  • Each browser profile generates unique device ID
  • Clearing browser data requires re-pairing
See Devices CLI for management.

Remote access

Keep Gateway on loopback and let Tailscale proxy with HTTPS:
Open: https://<magicdns>/ By default, Serve requests authenticate via Tailscale identity headers (tailscale-user-login) when gateway.auth.allowTailscale: true. OpenClaw verifies identity by resolving x-forwarded-for with tailscale whois. Disable Tailscale auth:

Bind to tailnet

Open: http://<tailscale-ip>:18789/ Paste token in UI Settings.

SSH tunnel

Open: http://localhost:18789/ See Gateway remote access for details.

WebChat channel

The Control UI Chat tab uses the WebChat channel:
  • Native Gateway WebSocket integration (no separate server)
  • Deterministic routing: replies always return to WebChat
  • Uses same sessions and routing rules as other channels
  • Shared history with macOS/iOS apps via Gateway sessions
Configuration:
  • No dedicated webchat.* config block
  • Uses gateway.port, gateway.bind, gateway.auth.* settings
See WebChat for protocol details.

Chat behavior

Non-blocking sends:
  • chat.send acks immediately with {runId, status: "started"}
  • Response streams via chat events
  • Re-sending same idempotencyKey returns:
    • {status: "in_flight"} while running
    • {status: "ok"} after completion
History size limits:
  • chat.history responses are size-bounded for UI safety
  • Gateway may truncate long text fields
  • Oversized messages replaced with [chat.history omitted: message too large]
Abort behavior:
  • Click Stop button (calls chat.abort)
  • Type /stop (or stop|esc|abort|wait|exit|interrupt)
  • chat.abort supports {sessionKey} to abort all runs for session
  • Partial assistant text persisted with abort metadata
Inject notes:
  • chat.inject appends assistant note to transcript
  • Broadcasts chat event for UI-only update
  • No agent run, no channel delivery

Insecure HTTP

Over plain HTTP (http://<lan-ip> or http://<tailscale-ip>), browsers run in non-secure context and block WebCrypto. By default, OpenClaw blocks Control UI connections without device identity. Recommended fix: Use HTTPS or local access:
  • https://<magicdns>/ (Tailscale Serve)
  • http://127.0.0.1:18789/ (on gateway host)
Downgrade (token-only over HTTP):
This disables device identity + pairing. Use only on trusted networks. See Tailscale setup for HTTPS guidance.

Building the UI

The Gateway serves static files from dist/control-ui:
Dev server then open:
Dev server notes:
  • gatewayUrl stored in localStorage after load
  • token stored in localStorage; password kept in memory only
  • When gatewayUrl set, explicit credentials required (no config fallback)
  • Use wss:// for TLS (Tailscale Serve, HTTPS proxy)
  • gatewayUrl only accepted in top-level window (not embedded)
For cross-origin setups, add UI origin to gateway.controlUi.allowedOrigins:
See Remote access for setup details.

Base path configuration

Optional URL prefix for reverse proxies:
Rebuild UI with matching base:

Cron jobs panel

Delivery modes:
  • Announce summary: Post to channel/target (channel and target fields appear)
  • Webhook: POST to URL with optional bearer token (set cron.webhookToken in config)
  • None: Internal-only runs (no delivery)
Job types:
  • Isolated jobs: Separate context, delivery defaults to announce
  • Main-session jobs: Use main session, webhook and none modes available
Legacy fallback: Stored jobs with notify: true can still use cron.webhook until migrated.

Troubleshooting

Connection fails with “pairing required”

  1. List pending devices:
  1. Approve:
  1. Or use local access (auto-approved):

WebSocket connection fails

  1. Verify Gateway is running:
  1. Check port is listening:
  1. Test WebSocket:

“device identity required” over HTTP

Browser blocked WebCrypto in non-secure context. Fix:
  • Use HTTPS: https://<magicdns>/ (Tailscale Serve)
  • Use local: http://127.0.0.1:18789/
  • Or downgrade: Set gateway.controlUi.allowInsecureAuth: true
See Insecure HTTP section above.

Config changes not saving

  1. Check for concurrent edits:
    • UI includes base-hash guard
    • Reload UI and try again
  2. Verify config file writable:
  1. Check Gateway logs for validation errors: