control-ui skill
Operate and troubleshoot the OpenClaw Control UI: navigate connected clients, organize sessions, build session dashboards, and handle direct or Tailscale-hosted Gateways.
Is the control-ui skill safe?
Clean: nothing in its files matched our rules. We read 4 files in the folder on 2026-11-08.
No findings.
Install the control-ui skill
A skill is a folder. Copy it into your agent's skills folder and the agent loads it when the task matches its description.
git clone --depth 1 https://github.com/openclaw/openclaw.git /tmp/openclaw mkdir -p ~/.claude/skills cp -r /tmp/openclaw/skills/control-ui ~/.claude/skills/control-ui
In the Claude apps, zip the folder and upload it from the Skills settings. The folder on GitHub
The instructions your agent would load
SKILL.md as published, without the frontmatter. Read it on GitHub
Control UI
Use OpenClaw's typed UI tools for state and layout. Use browser automation only to inspect or interact with rendered pixels.
Mental model
in the /dashboards gallery.
- A sidebar item is a session, not a dashboard page.
- Each session owns one board. The board contains tabs and widgets.
- Pinning a session keeps it in the sidebar. Sessions with a stored board appear
the page or take screenshots.
- screen changes connected Control UI layout and navigation. It does not read
them. It does not edit board content.
- sessions_list finds sessions. sessions renames, groups, pins, or archives
plugin widgets. show_widget authors or updates custom HTML/SVG widgets.
- dashboard reads and arranges the current session's board and registered
Do not replace these operations with shell calls or raw Gateway RPC when the typed tool exists.
Start safely
published through Tailscale or another HTTPS proxy.
- Identify the target session and whether the Control UI is local/direct or
visible session before authoring any widget. A tab is only a partition inside one session's board; it never creates a sidebar row.
- If the user wants a dedicated sidebar dashboard, choose or create its
dashboard task to the intended visible session first. Board widgets are keyed by session and cannot be moved to another session afterward.
- If the current turn is running in a temporary or parent session, hand the
- Read current state before changing it:
- use sessions_list to resolve the session;
- use dashboard with action: "read" for the current session;
- inspect existing tabs, stable widget names, owners, sizes, and panel layout.
Dashboard tools intentionally operate on the current session.
- If the task targets another session's board, move the work into that session.
Read hosting.md before opening or repairing a remote Control UI. Read dashboards.md before creating or restructuring a board. For bulk session archiving with retained exceptions, use session archive cleanup. Use the visualize skill for widget composition, libraries, interactive code explanations, and dashboard content. Keep session and board organization here.
Navigate and arrange the UI
Use screen for direct client commands:
docked panels.
- navigate to open a session by sessionKey;
- sidebarshow / sidebarhide for the session sidebar;
- splitright / splitdown, focus, and close_pane for panes;
- terminalshow / terminalhide and browsershow / browserhide for
screen broadcasts to every connected Control UI that advertises UI commands; it cannot select one browser tab. Check which clients are connected before sending a command. If it reports no capable client, ask the user to open the Control UI and retry.
Use the in-app browser or an available browser-control tool when the task needs DOM inspection, clicking, typing, or screenshots. Reuse the existing signed-in Control UI tab when possible.
Build a session dashboard
slug IDs.
- Call dashboard read. Reuse suitable tabs and widget names.
- Create or rename tabs with tabcreate / tabupdate; use short lowercase
- Add content with the correct owner:
pin: true and report;
- native text, metrics, tables, charts, and links: show_widget with
show_widget with pin: true;
- self-contained custom HTML/SVG or registered-source content:
pluginKind. Do not embed Grafana or another external application in an inside show_widget; widget sandboxes reject child-frame URLs and navigation. Use an ordinary user-clicked link to open the application, fetch an exact HTTPS API through declared capabilities.netOrigins, use a Gateway data binding, or install/use a trusted plugin widget instead.
- trusted plugin widgets: dashboard widget_put with an advertised
new widget_code updates the widget in place.
- Use a stable name when calling show_widget. Reusing the same name with
presets and board order over pixel placement.
- Arrange with widgetmove, widgetresize, and tab reordering. Prefer size
panel. If no Control UI is connected, the command returns unavailable; have the user open the session and retry.
- Pin the current session with sessions patch when it should stay prominent.
- Call dashboard focus_tab to show the intended tab in the dashboard side
presentation: "expanded" expands the dashboard; "split" shows it beside chat in the current panel layout. The human can use Expand side panel for a full-width dashboard, Collapse to bring chat back, or close the panel for chat alone.
- Choose the presentation after focusing the tab. set_presentation with
Never create a fake top-level page for a dashboard. For a dedicated dashboard, use a dedicated session, pin that session, and build its board from inside it.
Update without breaking the board
with the new owner or registered kind.
- Read first and mutate the smallest unit.
- Keep stable tab IDs and widget names unless replacement is intentional.
- Do not change a widget's content owner in place. Remove it, then recreate it
content may require approval again.
- Capability grants are bound to exact widget bytes and revision. Changed
the board.
- Resetting a conversation preserves its board. Deleting the session deletes
Verify the result
Use two layers of proof:
order, and sizes; sessions_list shows the expected session metadata.
- State: dashboard read shows the expected tabs, widgets, names, owners,
More skills from openclaw/openclaw
- A1passwordSet up and use 1Password CLI for sign-in, desktop integration, and reading or injecting secrets.
- Aacp-routerRoute plain-language requests for Claude Code, Cursor, Copilot, OpenClaw ACP, OpenCode, Gemini CLI, Grok Build, Qwen, Kiro, Kimi, iFlow, Factory Droid, Kilocode, or explicit ACP harness work into either OpenClaw ACP runtime sessions or direct acpx-driven sessions ("telephone game" flow). For coding-agent thread requests, read this skill first, then use only `sessions_spawn` for thread creation. Codex chat binding defaults to the native Codex app-server plugin unless ACP is explicit or background spawn needs ACP.
- Aadd-model-providerAdd and live-prove a model provider with non-interactive config one-liners, without exposing credentials.
- Aagent-transcriptRequested GitHub PR/issue agent transcripts: redact, trim, preview, and insert safely.
- Aapple-notesCreate, view, edit, delete, search, move, or export Apple Notes via the memo CLI on macOS.
- Aapple-remindersList, add, edit, complete, or delete Apple Reminders and reminder lists via remindctl.
- Aauto-qaRun OpenClaw-wide autonomous QA and live/stress campaigns across independent subsystem lanes, with verified fixes and a resumable evidence report.
- AautoreviewStructured code review through the shared OpenClaw agent-skills installation.
- Abear-notesCreate, search, and manage Bear notes via grizzly CLI.
- Ablock-kitUse proactively for structured or interactive Slack replies, and when asked to author or validate native Slack Block Kit JSON.
- AblogwatcherMonitor blogs and RSS/Atom feeds for updates using the blogwatcher CLI.
- AblucliBluOS CLI (blu) for discovery, playback, grouping, and volume.