Command-line Tool
cppmodel-tool is a command-line tool for the CppModel workspace, meant for CI jobs and scripts. It lists your simulations, reads their executions, reads or replaces the inputs and parameters the next execution will use, and runs parameter sweeps.
The tool ships prebuilt in the CppModel SDK as bin/cppmodel-tool (bin\cppmodel-tool.exe on Windows; see Installation). It needs nothing installed besides the SDK.
If you use Claude Code, you don't need this tool: the CppModel Claude Code plugin reaches the workspace through the CppModel MCP server.
Credentials
The tool reads CPPMODEL_USERNAME and CPPMODEL_PASSWORD from the environment or from a .env file:
CPPMODEL_USERNAME=...
CPPMODEL_PASSWORD=...
By default it uses the nearest .env in the current directory or one of its parents. Pass --env <file> to use a different file. Variables already set in the environment take precedence. The tool never opens a browser to log in.
The workspace comes from your account. If your account belongs to several workspaces, pick one with --workspace <id> or CPPMODEL_WORKSPACE.
The login is cached in .cppmodeltoken in the current directory, the same way simulations cache it. Keep both .env and .cppmodeltoken out of version control.
fetch: read and post workspace data
cppmodel-tool fetch [--workspace <id>] [--env <file>] [command]
(none) list your simulations
<simulation> latest execution of a simulation
executions <simulation> execution history
execution <simulation> <id> one execution
inputs <simulation> inputs/parameters pending for the next execution
set-inputs <simulation> <file.json> replace that pending document
delete <simulation> --yes delete the simulation with all its executions (irreversible)
fingerprint <file> CppModel.BinaryFingerprint of a built simulation (no login)
runs <simulation> <binary> number of executions run by that binary
run <simulation> <binary> <index> its index-th execution, oldest first from 0
<simulation> is the name passed to CppModel_create(), CMODEL_SIMULATE() or set in the C++ Simulation constructor.
<binary> is a fingerprint or the path of a built simulation. Every execution records the fingerprint of the binary that ran it as the parameter CppModel.BinaryFingerprint. It stays the same until the binary is rebuilt, so runs and run find the executions of one particular build:
cppmodel-tool fetch run "Velocity profile" build/VelocityProfile 0
- Output: responses are printed to stdout as JSON.
- Exit codes:
0on success,1for a failed request or login,2for a usage error. - Inputs are one-shot: a document posted with
set-inputsis used by the next execution of the simulation. Post it right before each run, then fetch the execution afterwards to confirm the values were applied.
sweep: run a simulation over many values
cppmodel-tool sweep <plan.json> <out-dir> [--dry-run] [--timeout <seconds>] [--workspace <id>] [--env <file>]
A sweep runs one built simulation once per combination in a plan, without editing or rebuilding it. For each run it posts that run's inputs and parameters, runs the binary, fetches the execution the run created, and checks that the execution used exactly the posted values.
A plan either lists values to combine (a grid):
{
"simulation": "Velocity profile",
"binary": "build/VelocityProfile",
"base": "defaults",
"parameters": { "Max Acceleration [m/s^2]": [2.0, 4.0, 6.0] },
"inputs": {
"Desired Velocity [mm/s]": {
"slow": { "x": [0, 300], "y": [30, 60] },
"fast": { "x": [0, 300], "y": [100, 200] }
}
}
}
or lists the runs explicitly, in place of parameters and inputs:
"runs": [
{ "name": "baseline" },
{ "name": "heavy load", "parameters": { "Load [kg]": 12 }, "inputs": { "Desired Velocity [mm/s]": { "x": [0], "y": [150] } } }
]
simulationis the name the simulation reports under.binaryis relative to the project root: the folder of the.envin use, or the current directory without one. The binary also runs from that folder. On Windows, include.exe.baseis what every run starts from before its own values are applied:"defaults"(the default) uses the fallback values in the code for everything that isn't varied;"current"starts from the document pending now, or otherwise the latest execution's values; an inline document can be given instead.- Inputs are series of
x(milliseconds) andyvalues, held until the nextx. - Names: the sweep warns about any varied name that the latest execution didn't record. Those are usually typos, since the code silently uses its fallback for a name it never reads.
Run with --dry-run first: it writes every run's document and lists the runs, but posts and runs nothing. Use --timeout for a real sweep.
<out-dir> then holds each run's posted document, console output and execution record, and a summary.json with one row per run: its values, exit code, whether it passed and whether the posted values were applied.
Nothing else may run the same simulation with the same account during a sweep (no ctest, no CI job, no run started from the workspace), because it would use a document meant for a sweep run. The sweep stops at the first run that didn't use its values, and a document that was pending before the sweep is restored at the end.
The sweep exits with 0 when every run was verified (passed or failed), 1 when it stopped early, 2 for a usage error and 130 after Ctrl-C.