Documentation · Agent guide · Developer README
benchup reads and edits BenchUp .bup projects from a shell or an AI coding agent (Claude Code, Codex, Cursor…), without opening the app. It reads every project format the app saves, including files with a viewport preview. Lengths are millimetres and Z is up.
The command is built from this repository with Rust 1.95 or newer:
cargo install --locked --path crates/benchup-cli # installs `benchup` in ~/.cargo/binMake sure ~/.cargo/bin is on your PATH. The installed command does not update itself: run the same command again after pulling changes. The desktop app is installed separately.
benchup guide # conventions, workflow and woodworking recipes
benchup new shelf.bup --name "Shelf" # create an empty project
benchup tools # list the tools
benchup tools create_board # one tool's JSON schema
benchup scene shelf.bup # scene summary: objects, sizes, grain, stock, joints
benchup get shelf.bup 79 # one entity in detail, with its faces
benchup call shelf.bup create_board '{"name":"Side","origin_mm":[0,0,0],"size_mm":[18,300,900],"grain_axis":"z"}'
echo '{"ids":[79],"delta_mm":[0,0,10]}' | benchup call shelf.bup move -
benchup call shelf.bup --batch ops.jsonl # several calls as ONE undo step, all-or-nothing
benchup call shelf.bup --batch ops.jsonl --dry-run --brief # try it without saving, compact output
benchup call shelf.bup check_model # overlaps without joints, joints that cannot be cut, ...
benchup call shelf.bup get_cut_list # boards by material and size
benchup undo shelf.bup
benchup redo shelf.bup
benchup mcp shelf.bup # the same tools over MCP (stdio)
benchup open shelf.bup # open it in the BenchUp desktop app
benchup open shelf.bup --app target/debug/benchup-app # or in a specific executableA batch file has one call per line. Blank lines and lines starting with # are skipped:
{"tool": "create_board", "arguments": {"name": "Left", "origin_mm": [0, 0, 0], "size_mm": [18, 300, 900]}}
{"tool": "create_board", "arguments": {"name": "Right", "origin_mm": [782, 0, 0], "size_mm": [18, 300, 900]}}
{"tool": "create_board", "arguments": {"name": "Shelf", "origin_mm": [18, 0, 400], "size_mm": [764, 300, 18]}}In a batch, "$N.field" is a value from the result of call N (counting from 1): "$1.created[0]", "$3.joint_id", "$2.face_id". A reference to a list of ids inside a list is spliced in, so "ids": ["$1.created", "$2.created"] joins both; other lists, such as a point, stay one item. Text that is not exactly a reference, such as "$12.50 hardware", is kept as written, and a single call never resolves references:
{"tool": "create_board", "arguments": {"name": "Side", "origin_mm": [0, 0, 0], "size_mm": [18, 300, 900]}}
{"tool": "create_board", "arguments": {"name": "Shelf", "origin_mm": [9, 0, 400], "size_mm": [500, 300, 18]}}
{"tool": "add_joint", "arguments": {"a": "$2.created[0]", "b": "$1.created[0]", "kind": "tongue_groove"}}- Output: JSON on stdout. Exit status is
0on success,1when a tool reported an error ({"ok": false, "error", "hint"}, file unchanged), and2for a usage or I/O error (message on stderr). - History: each
callis one entry in the project history, labelled “Agent edit” (in the app's language); a batch is one entry. You can undo it in BenchUp or withbenchup undo. - Atomic saves: the file is written through a temporary file and a rename. If the file changed on disk since it was read (for example, BenchUp saved it), the command refuses to overwrite it.
benchup mcpreads the file again before each call, so it carries on from what BenchUp saved. - Views and cameras: the CLI keeps the camera of each view saved in the file, so editing a project does not move the user's views. It cannot list, change or render views yet; use BenchUp's views and Tools → Screenshot for that.
- Shared projects: local copies of shared projects are refused unless you pass
--allow-shared, because edits would diverge from the server. - Opening in the app:
benchup openhands the file to the installed desktop app (by bundle id on macOS, through the.bupfile association on Linux and Windows).--app <executable>, or theBENCHUP_APPenvironment variable, starts that executable instead, which is handy for a development build. The app must be installed separately: download it. - Not live: the CLI edits the file, not a running BenchUp window. Run
benchup openagain after a change to reload it; if the project has unsaved changes in the app, BenchUp asks first. Saving in BenchUp overwrites the file without checking for outside changes, so save or discard your app edits before editing with the CLI. Live editing through a local bridge is planned (#13).
Agents should read benchup guide first (over MCP, the get_guide tool); it is the agent guide. It explains the conventions (the front faces -Y), which board is a in a joint, the batch workflow, woodworking recipes and current limitations.
To make Claude Code reach for the CLI on its own, install the skill:
cp -r crates/benchup-cli/skill/benchup ~/.claude/skills/With Claude Code, either let it call the CLI directly ("use benchup to add a shelf to shelf.bup"), or register the MCP server:
claude mcp add benchup -- benchup mcp /path/to/shelf.bup