---
title: "Panels — Robion user manual"
description: "Every panel: files and the editor, diff, GIT, web preview and the element picker, 3D model and customizer, media, LOG, controls, activity, statistics, Jira, MCP."
url: "https://robion.app/docs/panels/"
lang: en
---

# Panels

Every panel a person meets in the Robion desktop: what it shows, how it opens (tree, ⌘K, a
shortcut, the agent) and what can be done in it. The design panel is only pointed at here —
[workshop.md](https://robion.app/docs/workshop/) has the whole maker flow.

## Opening, closing, arranging

- Files open from the tree in the side panel (⌘B **Toggle Side Panel**), from ⌘K (**Commands…**;
  files are searched in the active task from 2 characters) or from the agent (open_file;
  open_files shows up to 16 files as a grid). They land as tabs in a group beside the side panel.
- **Max. open files** (⚙): "the next file closes the one open the longest; 0 = no limit;
  unsaved files are never closed". Tab right-click: **maximize panel**, **close panel**, **close
  all tabs**; double-click a tab or ⇧⌘↩ maximizes; ⌘W closes; ⌥⌘L is **Reset Layout**.
- Window menu (since 0.20.8): the tool panels **Activity** ⇧⌘A, **Statistics** ⇧⌘U, **Jira**
  ⇧⌘J, **MCP Servers** ⇧⌘M, **Controls** ⇧⌘O, **Log** ⇧⌘L, **Browser** ⇧⌘B; the screens
  **Overview** ⌘0, **Board**, **Inbox** ⌘I, **Automations**; then **Waiting Agent** ⌘J,
  **Commands…** ⌘K, **Recent Panels** ⌘E, **Task 1–9** ⌘1–9. The tree and git are not in it: they
  sit in the side panel (⌘B). Searching is Edit → **Find** ▸ **Find File…** ⌘F, **Search in
  Files…** ⇧⌘F, **Search Terminals…** ⌥⌘F. Help → **Keyboard Shortcuts** ⌘/ lists them all.

## File panel (viewer, editor)

- A text file opens editable at once; **autosave** fires about 0.8 s after typing stops (⌘S
  saves now); the header shows the line count and "unsaved…" in amber until saved. A write the
  server refuses because the agent changed the file meanwhile is shown; autosave then waits
  until you save or **reload**. Over 2 MB: **read-only**; binary: a hex view (up to 16 MB). The
  scroll position survives a project switch and a relaunch (since 0.20). **open in editor**
  (⌥↵) hands the file to the external editor.
- Typing: long lines wrap, brackets pair and lines auto-indent (since 0.20.10); each is a
  switch in ⚙ → **Appearance** (**Wrap long lines**, **Brackets**, **Auto-indent**). No
  completion, no lint — a place to fix a value, not an IDE.
- Wrapping per file (since 0.20.31): **wrap** in the header (bright while on) or a right-click
  in the text → **wrap long lines** switches wrapping for this file only, without touching the
  setting; the choice sticks with the tab (a relaunch brings it back) and a file without one
  follows ⚙ → **Appearance**. Toggling back to the setting's value forgets the choice. The
  right-click menu also has **find…** ⌘F, **go to line…** ⌘⌥G and **open in editor** ⌥↵; the
  markdown panel's **source** view has the same button and menu.
- Find in the file (since 0.20.10): ⌘F with the caret in the editor opens a find/replace bar
  above the text (**Find**, **Replace**, **next**, **previous**, **all**, **match case**,
  **regexp**, **by word**, **replace**, **replace all**); ⌘G / ⇧⌘G step through the matches,
  ⌘⌥G asks for a line number, Esc closes the bar. With the focus outside an editor ⌘F is still
  **Find File…**.
- Header buttons: **3D** on `.scad`, `.py`, `.step`/`.stp`, `.stl`, `.3mf`, `.glb`,
  `.kicad_pcb`; **DRC** on `.kicad_pcb`, **ERC** on `.kicad_sch`.
- Viewer by type: images (`png jpg gif webp bmp ico avif svg`), PDF, DXF, Gerber/Excellon
  layers (`gbr ger gtl gbl gto gbo gts gbs gtp gbp gko gm1 gm2 drl xln`) → media panel; `.md`
  → markdown panel; `.html`/`.htm` → HTML panel; `.scad .kicad_pcb .stl .3mf .glb .step .stp`
  → 3D panel; anything else, `.py` included, → the text editor (**3D** renders a build123d
  script on request).

## Markdown and HTML panels

- Markdown: **preview** renders it; **source** switches the same panel to the editor with
  autosave (since 0.20). Each view keeps its own scroll position across a project switch, a
  relaunch and a trip to the other view (the editor since 0.20, the preview since 0.20.4).
  HTML: the page renders in a sandboxed frame served from the task
  folder (relative CSS, scripts and images resolve); **source**, **reload** and the ⌖ picker
  (see the web preview) work here too.

## Media panel (images, SVG, PDF, DXF, Gerber)

- Images and SVG as they are; DXF converted to SVG inside the app (no external tool); Gerber
  and drill files rendered to SVG by the server; PDF page by page (**fit width**, − / +).
- "drag pans · wheel zooms · ⟳ rotates · ☾ darkens white backgrounds": **fit**, **⟳ 90°**,
  **☾ dark** (remembered). A save reloads the file. **Δ original** compares with the baseline
  "before the last agent turn" (the slider swipes, **◐ blend** overlays); "the file was not in
  the baseline (new file) or no baseline captured" when there is nothing to compare with.

## Diff panel

- Title "Δ <file>". Opens from a file row of the **GIT** section, a commit's files, or the
  agent (open_diff; request_review opens diffs only for up to three files). Scopes: **since the
  last agent turn** (baseline snapshot vs. now, see GIT), **staged**, **unstaged**, one commit.
  Over 5000 lines the rest is cut ("open the source instead").
- Review notes: "click a line number to select the line, shift+click extends the selection",
  write in **NOTE TO AGENT** ("what the agent should do with the selected lines — ⌘⏎ sends");
  **send to agent** delivers "the next prompt: file, line range, the lines themselves and your
  note". Refused when the diff belongs to no task or the agent is waiting for a permission or
  a choice ("send the note afterwards").

## GIT section of the side panel

- Under the tree in the side panel (⌘B); ⇧⌘G shows it; the caption folds it. It follows the
  active task and its checkout (the caption switches checkouts, 0.20), refreshes on any file
  change and says "not a git repository" outside git. Header: the branch, **↑n** unpushed
  commits in amber (they want an action), **↓n** behind, dim.
- Review: a baseline snapshot of the working tree is taken on every agent turn (or by **capture
  baseline**; before that "no baseline captured yet — one is taken on every agent turn (M3), or
  manually"). Files differing from it list under **since the last agent turn** (the ✓ reviewed
  button and the "awaiting review" header are gone since 0.20.16 — the list is the review). The
  agent's request_review puts its note on the task timeline and opens the side panel with the
  GIT section lit for a moment (0.18).
- **uncommitted changes**: a checkbox per file (**stage** / **unstage**), a click opens the
  diff. **earlier on this branch** = commits above the default branch (on it: **recent
  commits**); a commit row expands to its files. **worktrees** lists the checkouts.
- Commit (0.20.15): under the uncommitted list a **commit message…** field and a **commit**
  button commit exactly what the checkboxes staged, in the task's checkout (its worktree, or
  the project root). The button is disabled with the reason as its tooltip: "nothing staged —
  tick the files to commit first", "write a commit message first"; the server refuses the
  same rather than committing nothing. No amend, no automatic add of unstaged files. Hooks run
  as in a terminal; "committed <sha> <subject>" or what git/the hook printed appears under the
  field.
- Push (0.20.15): its own **push** section, apart from the commit field, shows `branch →
upstream` and **n unpushed commits** (amber), **nothing to push**, or **no upstream yet** (the
  would-be `origin/<branch>` in italics). **push…** does not push
  yet: it opens a question naming the destination — "push <branch> → origin/<branch>?", or for
  a branch without an upstream "<branch> has no upstream yet — push --set-upstream origin
  <branch>?" (shown in italics as the would-be destination) — with **push now** and **cancel**.
  Never force. Git's answer stays below as text: "pushed to origin/<branch>" with the remote's
  messages, or the rejection ("! [rejected] … fetch first"), an authentication failure (no
  password prompt: the push fails instead of hanging), "detached HEAD — there is no branch to
  push". Both actions refresh the section.

## Web preview panel

- Opens from the **preview :port** button in the top bar when the task has a port (⚙ → project
  → **Port range**: "each task gets two ports (PORT, ROBION_PORTS)"), from Window → **Browser**
  (⇧⌘B), ⌘K **open web preview**, a **link** control, or the agent (open_url).
- Loopback only: "only local previews (localhost) render in the app — use ↗ to open it in the
  browser". Until the server answers: "nothing is listening on port N yet … retrying every 2 s
  — start the dev server in the task terminal (PORT is set)". Remote server: "port N is
  listening on the remote machine — tunnel it to preview here" → **open a tunnel and preview
  here**.
- ⌖ **select element**: click an element, choose **change** or **question**, write "what should
  the agent do with this element — ⌘⏎ sends", optionally **attach screenshot**; it goes out "as
  the next prompt: page, selector, element text and your note". When the agent asks for a pick
  (request_element_pick) the preview opens with its note as a chip. Refusals: "this preview
  belongs to no agent task", "the page is not ready for picking yet". The agent's own
  screenshots (preview_screenshot) capture this panel as you see it and go to the agent only.

## 3D panel (model viewport)

- Formats: OpenSCAD `.scad`, build123d `.py` (via **3D**), STEP, STL, 3MF, GLB, KiCad
  `.kicad_pcb`. Rendering runs on the server with OpenSCAD, Python with build123d and
  kicad-cli, found automatically or set in ⚙ → **Tools** (**Detected tools** shows version and
  path or "not found"). A missing tool shows "<tool> not found. Install it or set … in
  config.json" in the panel; **3D render timeout** kills a render after the set time.
- Header: **model** / **source** (the code, read-only here), **refresh**, **fit**, the readout
  "N △ · x × y × z mm · volume · took s", **output** (the tool's log), **Δ original** ("show
  the baseline version (before the last agent turn) as a translucent ghost"), **⌸ bed** (draws
  the **Print bed** from ⚙ → Tools and says "the model fits" / "the model does not fit"),
  **SpaceMouse** (3Dconnexion over WebHID), **DRC** on boards.
- "drag rotates · wheel zooms · right button pans · double-click fits"; the panel re-renders
  when the file changes on disk. "WebGL context was lost — close the panel and open it again".
  Live customizer: a controls panel whose viewport is the model re-renders on every slider
  change (OpenSCAD gets `-D key=value`, a Python model reads `ROBION_PARAMS`) — [workshop.md](https://robion.app/docs/workshop/).

## CHECKS panel (KiCad DRC / ERC)

- The **DRC** / **ERC** button of a `.kicad_pcb` / `.kicad_sch` file panel or of the 3D panel;
  the tab reads "DRC <file>". kicad-cli runs on the server; the header says "N errors · N
  warnings · took s" or "no findings". Filters **all** / **errors** / **warnings**, **incl.
  excluded**, **run again**, **output** (the raw log).

## LOG panel

- Window → **Log** (⇧⌘L); one per project; it also opens by itself when an agent defines
  sources. Only the agent defines them ("no log sources defined — an agent adds them with
  set_log_sources") — ask it to watch a file or a streaming command.
- Command sources need approval: "Command log sources run shell commands in this project and
  need your approval." → **Allow commands** → "Run the command log sources of “<project>”? They
  execute shell commands on this machine and restart until removed."
- "no log lines yet — sources stream only while this panel is open": nothing is collected while
  the panel is closed. Filters: source chips (click toggles one), **all levels** or "≥ level",
  text "filter (or /regex/)"; **follow the tail** vs "paused (scroll to the bottom to follow
  again)"; **clear the view**. Times are local HH:MM:SS.mmm; errors red, warnings amber.
  Right-click a line → **send this line to the agent** (source, level, time and the line arrive
  as the next prompt; the agent pulls the surrounding lines with query_logs).
- Robion's own logs, worth adding as file sources: `~/Library/Application Support/Robion/logs/`
  holds `server.log`, `desktop.log` (renderer errors, crash screens), `events.jsonl` (hook
  payloads when **Log hook events** is on), `setup-<branch>.log`, `teardown-<task>.log`.

## CONTROLS panel

- Window → **Controls** (⇧⌘O) or ⌘K **open controls**: the **CONTROLS** overview with a
  **project** section (the persistent launcher) and a **task** section (knobs of the open task,
  gone when it closes). A panel an agent defines opens (or focuses) as a tab of its own named
  after its label (**open as a tab** from the overview); up to 12 named panels per scope, each
  with its own values, groups (collapse/expand), pages (**general** is the default) and viewport.
- Empty: "No controls yet. Ask the agent in a task — “make me buttons for the dev server on
  port 7700, tests and lint” — and it defines them here through the Robion MCP (set_controls)."
  `/robion:cockpit` builds a panel from what the project has (package.json scripts, Makefile…).
- Kinds you can meet: buttons (a **confirm** dialog before running; hotkeys 1–9 — "press N
  while the panel has focus", also on the stream deck), toggles (**on**/**off**), numbers and
  sliders, selects (dropdown or segments), text, checklists, status badges (static, a live
  probe, or a run button's state "not run yet" / "running…" / "stopped"), progress bars, steps
  pipelines, links (loopback URL → web panel, else the browser), image tiles (refresh when the
  file changes; a click opens it), choices cards (image, description, fact chips; single or
  multi), galleries, tables. Tooltips say what a button does: "runs: …", "types into the
  agent: …", "opens: …", "sets: …", "stops what “…” started", "starts an agent task: …".
- A run button starts a shell task; its **output** viewport shows "running…", "finished
  (exit 0)" or "failed (exit N)" with **stop**, **to a tab**, hide; a silent button pulses and
  only a failure shows a terminal; a failed run offers **send the failure to the agent**. Send
  buttons type into the agent's pane (task scope: that task; project scope: your active task —
  "needs an active Claude Code task in this project"). Task buttons start a new agent task. The
  agent reads values when it asks (get_controls); changes also reach it with your next prompt.
- Probes: port, file and http probes sample by themselves while the panel is open; a command
  probe stays **paused** until **allow** ("Allow the agent-defined command probes to run
  automatically in “<project>”?"); revoke under ⚙ → project → **command probes**.
- **edit** opens ⚙ → project → **panels (JSON)**: "an array of panels, each with
  name/label/icon, controls, values, groups and viewport. Edit the JSON to rename, reorder or
  delete; a button's ${key} must name a toggle/number/select/text/checklist of the same panel."
  A popped-out tab of a removed panel says "This controls panel no longer exists (the agent
  removed it)." The phone renders the same cockpit.

## Activity panel (task timeline)

- Window → **Activity** (⇧⌘A), ⌘K **open activity**, or a task tab's right-click
  **activity…**: "task timeline: prompts, waits, decisions, results, restores" (rows typed
  task, prompt, permission, question, decision, message, done, idle, error, ended, note; source
  desktop, phone or agent). The header sums "new tokens (in + out + cache write) · out tokens ·
  turns / prompts / tools · running · waiting for you". request_review notes land here.

## STATISTICS panel

- ⇧⌘U, the rail's **USAGE** widget or ⌘K **open statistics**; it reads Claude Code transcripts
  (the **Usage statistics** switch in ⚙). Ranges **today** / **7 d** / **30 d** / **90 d** /
  **all**, **all projects** / **this project only**; KPIs (sessions, prompts, turns, tool
  calls, output tokens, agents ran, waited for you, median wait, interrupts, failures), charts
  (tokens, agent time, activity, "when you prompt"), tables (projects — a click selects the
  project — models, tools, MCP, skills). The rail shows the 5h session and week limits when
  **Track subscription limits** is on ("limits: sign in in Claude Code (/login)" otherwise).

## JIRA panel

- Window → **Jira** (⇧⌘J). "Jira is not connected — connect it in ⚙ → automations (issue
  trackers)"; the token comes from id.atlassian.com → Security → API tokens and lives in the
  keychain. Read-only: Robion never writes to a tracker.
- Search "ticket key, text, or jql: …", scopes **mine** / **active sprint** / **epics** /
  **recent**, **load more**. An issue shows description, fields, sub-tasks, in epic, links,
  attachments, comments; **open in Jira**, **copy key**, **create task** ("new task named after
  the ticket key; the agent gets the description as its prompt; with a worktree per project
  settings (branch rb/<KEY>-…)"). Offline: "Jira unreachable — showing the last known version".

## MCP panel

- Window → **MCP Servers** (⇧⌘M): the MCP servers Claude Code knows, **this project only** or
  **all projects**; columns **server**, **where** (user = ~/.claude.json, folder, .mcp.json,
  plugin), **state** (unchecked, "running · N ms", sign-in, error, "disabled in N folders",
  rejected, awaiting approval, plugin disabled), **tools**, **~tokens** (what the tool
  definitions cost in every context), calls. **check** / **check all** starts each server and
  lists its tools. "read-only — servers are added and removed in Claude Code (claude mcp add /
  remove, /mcp)".

## Design panel

- **DESIGN**: the design record of a Maker Pack task. The anchor tab of a workshop project; in
  a development project the **DESIGN** button in the top bar opens it for a task with a record,
  and it opens by itself when the agent writes `design.json`. All details: [workshop.md](https://robion.app/docs/workshop/).

## Recent panels (⌘E)

- Window → **Recent Panels**: the open panels, most recently used first. The top row is the
  panel active before the current one, so ⌘E + ↩ bounces between the last two; ⌘E again or ↓
  walks down. Agent terminals lead with their state dot, files with an icon and their folder.

## When a panel breaks

- One panel: "panel crashed — The rest of the app keeps running. Close the tab, or reopen it
  after the bug is fixed." A viewer that cannot read a file says "file cannot be displayed".
- The workspace: "the workspace crashed — Other projects, the Inbox and settings keep running."
  Buttons **try again**, **start from the default layout** ("the saved layout is the usual
  culprit"), **copy the error**; the error is in `logs/desktop.log` (since 0.19).
- The app: "Robion crashed — Something broke outside the workspace." **reload the window**
  "almost always helps; the server and the agents keep running."
