Files
OneCAD/docs/book/src/dev/commands.md
T
bherbruckandClaude Opus 5.5 296683229d Rename SolveCraft to SolidCraft everywhere, with compatibility shims (#389)
* WIP deep rename (not for push)

* WIP2

* WIP3

* WIP4 wxs fix

* rustfmt

* Rename the remaining identifiers in merged crash-report code

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RjGw4gA5ZvKrU8MQP6sBgT

---------

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-12 17:17:01 -04:00

2.1 KiB

The command engine

Every user-visible action is a command: a CommandSpec registered in crates/engine/src/cmd/, with a dotted, lower-case id (solid.extrude, sketch.create, timeline.rollback). The toolbar, dialogs, marking menu, S box, scripts, the CLI, the control channel and MCP all run commands through Session::execute(id, params). Commands take JSON parameters and never open dialogs; a dialog is a front-end form that builds the parameters.

CommandSpec::new("solid.fillet", "Fillet", fillet)
    .at("SOLID", "MODIFY")      // toolbar tab and panel ("" = not on the toolbar)
    .icon("fillet")             // drawn in code, crates/ui-egui/src/icons.rs
    .key("F")                   // default shortcut
    .params("edges: [[x,y,z] | {body, index}]; radius: expr; …"),

run is fn(&mut Session, &Value) -> Result<Value>, and enabled is fn(&Session) -> Result<(), String>; the error string is the disabled-button tooltip. The params string is the one-line documentation shown by solidcraft-cli commands, MCP's list_commands and the command reference.

A command that changes the design is undoable by default: the session snapshots the document before it runs, and a failing command leaves the document unchanged. Feature commands add a feature to the timeline and let the document evaluate it; they validate their inputs first (units, ranges, references) and return BadParams instead of building a broken feature.

Only the registry's own dotted ids name commands (matched ignoring case); any other id fails with unknown command.

Adding a command

  1. Add a CommandSpec to the right file in crates/engine/src/cmd/ and implement run.
  2. Write engine tests that measure the result: volume, area, and face/edge/vertex counts against values you can derive by hand.
  3. The hostile-input test (hostile_params_never_panic in crates/engine/src/tests.rs) runs your command automatically with every documented parameter set to junk. It must return errors, never panic.
  4. For UI work, add a scenario (see Test harnesses).