Files
cadcraft/docs/control-protocol.md
T
Valentin KleinandClaude Opus 5.5 24a3954b39 Light and System interface themes (System follows the OS appearance live) (#179)
* Light and System interface themes (System follows the OS appearance live)

CADCraft had one hard-coded dark interface: Tokens::get() always returned
Tokens::DARK and Visuals::dark() was installed once at startup.

- theme.rs: Tokens::LIGHT (light grey chrome, dark text) beside the unchanged
  Tokens::DARK; Tokens::get() returns the palette of the theme in use (a
  UI-thread thread-local set once per frame). Both egui styles are built from
  the tokens and egui is switched to the shown theme, so standard widgets,
  menus and popups follow too. The drawing area (canvas, grid, axes,
  selection, grips, ViewCube, UCS icon) keeps its model-space colours in both
  themes: drawing colours are not part of the interface theme.
- ThemePref { System, Light, Dark } in UiState (`theme`), resolved every
  frame against ctx.system_theme(), so System follows the OS (winit, or the
  browser's prefers-color-scheme) live without touching the saved choice.
  No reported appearance: System shows Dark (SYSTEM_FALLBACK). Default stays
  Dark (today's look).
- View > Interface Theme > Use System Setting / Light / Dark (ui.theme.system,
  ui.theme.light, ui.theme.dark) and ui.theme {theme} for scripts and the
  control channel; ui.inspect reports the theme shown.
- Hard-coded colours on the command line (history, border, keywords,
  AutoComplete list), the status-bar message and the layer status icon go
  through tokens; overlays drawn on the canvas use a new canvas_ink token.
- Desktop app: the choice persists via eframe storage (`persistence`
  feature, key cadcraft.prefs); window geometry and egui memory are not
  persisted, as before.

Fixes #59.

Co-Authored-By: Claude Opus 5.5 <[email protected]>

* Document the theme field away from other PRs' edits to avoid merge conflicts

Co-Authored-By: Claude Opus 5.5 <[email protected]>

---------

Co-authored-by: Claude Opus 5.5 <[email protected]>
2026-10-10 12:16:20 -04:00

2.6 KiB

CADCraft control protocol

Start the desktop app with --control PORT (or CADCRAFT_CONTROL_PORT=PORT). It listens on 127.0.0.1:PORT for JSON lines: one request per line, one reply per line.

{"id": 1, "method": "cmdline.input", "params": {"text": "circle 0,0 5"}}
{"id": 1, "ok": true, "result": {"prompt": "Command:", "output": ["Command: CIRCLE"], ...}}

Errors come back as {"id": …, "ok": false, "error": "message"}.

Method Params What it does
cmdline.input {text} Type a line at the command line exactly like a user. Starts commands by name/alias and answers prompts (points x,y, @dx,dy, @d<a, distances, keywords, empty = Enter). Spaces act as Enter except at text prompts.
cmdline.script {text} Run a multi-line script (like .scr files).
cmdline.key {key: "enter"|"escape"} Press Enter or Escape.
cmdline.state Current prompt, keywords, accepted input kinds, history tail.
engine.execute {command, params} Run any command with JSON parameters. Never opens a dialog.
engine.commands Every command: id, label, menu path, shortcut, aliases, params doc, enabled.
drawing.inspect {entities?, limit?} Drawing summary (counts, extents, layers, styles, blocks, layouts, selection, undo) and entities with handles and geometry.
ui.inspect UI state, canvas rect, view, cursor and snap, performance counters.
ui.menu.list / ui.menu.invoke {command} The menu tree; invoke an item like a click (interactive).
ui.pointer {x, y, space?: "world"|"screen", button?, action?: "click"|"move"} Click in the drawing area (world coordinates by default). Right button = Enter.
ui.click / ui.move {x, y, button?, shift?} Real egui pointer events in screen points (reach every widget).
ui.key / ui.text {key, cmd?, shift?, alt?} / {text} Synthetic keyboard input.
ui.set UiState fields Show/hide palettes, toolbars, command line, ViewCube…; theme: "system"|"light"|"dark" (also engine.execute with ui.theme {theme}); ui.inspect reports the theme shown (theme: light/dark).
ui.resize {width, height} Resize the window.
ui.screenshot {path?} PNG of the window (needs a presented frame).
ui.render {path?, width?, height?} Headless render of the current view of the drawing.
app.open / app.save / app.quit {path} File operations.

The MCP server (cadcraft-cli mcp --connect 127.0.0.1:PORT) wraps this protocol; headless (cadcraft-cli mcp) it serves the same methods from an in-process session.