Command line¶
freedyn2 run model.yaml [-o result.csv] [--workdir DIR] [-- runtime options]
freedyn2 view model.yaml [result.csv] [--no-run] [--export page.html] [--port N] [-- runtime options]
freedyn2 check model.yaml [result.csv | --run] [-- runtime options]
freedyn2 examples [name [-o DIR]]
freedyn2 convert model.fds [-o model.yaml] [--profile v2|legacy] [--force]
freedyn2 rename model.yaml OLD NEW [--section SECTION]
freedyn2 import-onshape <assembly address> [-o model.yaml] [--no-meshes] [--force | --update] [--record DIR]
freedyn2 gui [model ...] [--browser] [--port N] [--new-instance]
freedyn2 update-check
freedyn2 mcp [--workdir DIR]
freedyn2 setup-mcp [--client claude-desktop|claude-code|all] [--remove] [--dry-run]
freedyn2 config [KEY [VALUE] | KEY --unset]
freedyn2 doctor
freedyn2 compare model.fds ... --legacy <FreeDyn>
| command | |
|---|---|
run |
read the model (.yaml, or a legacy .fds), build it (and its plugin), simulate; reports build and simulation time |
view |
the viewer in the browser; simulates again on every save |
check |
the checks of the model and its results; exit status 1 on errors or failed references |
examples |
list the example models that come with FreeDyn, or copy one into the current directory |
convert |
write a legacy .fds model as a YAML model file (below) |
rename |
rename an element and every reference to it (below) |
import-onshape |
write an Onshape assembly as a YAML model file (Coming from Onshape) |
gui |
the app: start page, recent models, examples, a window per model (freedyn2-gui is the same without a console); --browser: in the web browser; --new-instance: do not hand the models to a running app |
update-check |
ask GitHub whether a newer release is out and print the answer (no download); see update notice |
mcp |
the MCP server for assistants (stdio) |
setup-mcp |
register the MCP server with Claude Desktop and Claude Code (below) |
config |
show or set the user configuration, e.g. freedyn2 config compiler zig (below) |
doctor |
what this installation finds: runtime, compiler, directories, MCP registration (below) |
compare |
legacy FreeDyn against freedyn2 on .fds models (needs the legacy program) |
.fds models of the legacy FreeDyn are read by run, view and check; --profile legacy
runs them with the legacy algorithms (for comparisons), the default v2 with freedyn2's.
convert¶
freedyn2 convert crank.fds # crank.yaml next to it
freedyn2 convert crank.fds -o models/crank.yaml --profile legacy
writes the model that run, view and check read from the .fds as a YAML
model file: the elements in the order of the .fds, comments naming
the .fds blocks they come from (BodyID, ConstraintID, …), every number exactly as
imported. The YAML runs as the .fds does with the same profile: freedyn2 run crank.yaml
gives the results of freedyn2 run crank.fds --profile v2 (with --profile legacy: of
--profile legacy; no --profile is needed for the YAML, it carries the settings).
| option | |
|---|---|
-o FILE |
the YAML file, or a directory for <model>.yaml in it (default: next to the .fds) |
--profile v2\|legacy |
the solver settings (and, for legacy, the Euler-parameter bodies) written to the YAML; default v2 |
--force |
overwrite an existing file (without it, convert stops) |
- Spline data in files (
PathToSplineData) stay in their files, referenced relative to the YAML file; inline data (XData,YData) are written asx,y. - Names must be identifiers in YAML. Constraints are named by their
ConstraintIDin an.fds, so a joint1becomesjoint_1(and its channelsjoint_1.dx.lambda, …); bodies, forces and drivers with other characters in their names are renamed the same way. The comment at the element gives the.fdsname. Measures, parameters and splines are used in expressions by name and are not renamed: a name that is not an identifier is an error. - The written file is read back and compared with the imported model; what cannot be written or would read back differently is an error naming the element, so nothing is left out.
- Joint frames become quaternions and are turned back into rotation matrices when the YAML is
read, and body orientations are normalized again: in the comparison models the results agree
with the
.fdsbitwise or to 1e-12 (round-off).
rename¶
freedyn2 rename crank.yaml rod1 crank_arm
freedyn2 rename car.yaml wheel_center hub_point --section points # a sensor has the name too
renames an element (body, joint, force, sensor, driver, output, measure, parameter, input,
spline, point, frame) and every reference to it: body1/body2, the frame of measures,
point and orientation fields, mirror, from, in, the expressions of forces, drivers and
outputs, formulas (=2 * k), the channels of checks (rod1.R_z). Only these places change:
comments, formatting and order stay as they are, and a word in a comment that happens to be the
name is not touched. The file is written only if the renamed model is valid.
--section says which element is meant where several have the name (a point and a sensor
wheel_center). The new name must be an identifier that no element uses yet.
Result files of earlier runs keep the old channel names.
Runtime options¶
Everything after -- goes to the solver freedyn2_run and overrides the model's solver
section:
| option | |
|---|---|
--end-time T, --step H, --output-step H, --alpha A |
the solver values |
--tolerance E, --fixed-step |
step size control (legacy adaptive models) / none |
--newton-fixed N |
real-time mode: exactly N Newton corrections per step |
--linear-solver klu\|sparselu\|dense |
the linear solver (default KLU) |
--step-log FILE, --timing, --timing-log FILE |
diagnosis: step sizes and Newton iterations per step; the distribution of the time per step; times per step |
--input NAME=VALUE |
a runtime input held constant (repeatable) |
--inputs FILE.csv |
runtime inputs over time: header t,NAME,..., linear between the rows, held before the first and after the last; a step uses the value at its end time |
freedyn2 run model.yaml -- --end-time 2 --step 1e-4
freedyn2 run examples/input_oscillator.yaml -- --input F=1.5 --inputs ramp.csv
setup-mcp¶
freedyn2 setup-mcp registers the MCP server of this installation with the assistants, so that
they start freedyn2 mcp themselves:
- Claude Desktop: the entry
mcpServers.freedyn2inclaude_desktop_config.json(Windows%APPDATA%\Claude\, macOS~/Library/Application Support/Claude/, Linux~/.config/Claude/) is set; everything else in the file stays, the previous file is kept asclaude_desktop_config.json.bak, a missing file is created. Restart Claude Desktop afterwards. - Claude Code: with
claudeon the PATH,claude mcp add --scope user freedyn2 -- <freedyn2> mcpis run; without it the command is printed.
The command registered is the absolute path of this installation's freedyn2 program (or this
Python with -m fdgen.cli). --client picks one (default all), --remove unregisters,
--dry-run only shows what would change. Running it again changes nothing that is already
right. Exit status 0: done or nothing to do; 1: failed (e.g. a claude_desktop_config.json
that is not valid JSON is left alone). The Windows installer runs
freedyn2 setup-mcp --client claude-desktop (and --remove when uninstalling).
config¶
freedyn2 config # all values, and where the file is
freedyn2 config compiler zig # set one (true, false and numbers are JSON, the rest text)
freedyn2 config compiler # show one
freedyn2 config compiler --unset # back to the default
| key | |
|---|---|
compiler |
the C compiler for model plugins: a path or a command, zig, msvc or auto (see below) |
update_check |
false: never ask GitHub for a newer release |
The file is config.json in the configuration directory (Windows %APPDATA%\freedyn2, else
~/.config/freedyn2); FREEDYN2_HOME puts it and the other per-user directories below one
directory.
doctor¶
freedyn2 doctor prints what this installation finds – for a support request, paste it:
the version, Python, where FreeDyn is installed, the runtime freedyn2_run, the C compiler
(which one, where it was found, its version), the plugin cache, the configuration, data and log
directories, whether the MCP server is registered with Claude Desktop and Claude Code, and
whether pywebview is installed. Exit status 1 if the runtime or the compiler is missing.
C compiler¶
Models with expression forces, drivers or outputs are compiled into a model plugin. The compiler is the first of:
- the environment variable
CC - the configuration:
freedyn2 config compiler ... cc,gcc,clang,clon the PATH- Windows: Visual Studio (or the Build Tools) with the C++ tools, found with
vswhere - zig, if the Python package
ziglangis installed:pip install freedyn2[compiler](orpip install ziglang)
CC and compiler take a path or a command (gcc-13, zig cc) or one of
| value | |
|---|---|
zig |
zig from the ziglang package (python -m ziglang cc), else zig on the PATH; on Windows it builds MinGW-ABI DLLs |
msvc |
Visual Studio without a developer prompt: vcvars64.bat is run once, its environment is kept in the cache directory |
auto |
the order above (the default) |
zig is the compiler that comes with pip: nothing else to install, on Windows too. Its first plugin takes some seconds longer (zig builds its C runtime parts once, into its own cache).
Environment¶
| variable | |
|---|---|
CC |
the C compiler for model plugins (see C compiler) |
FREEDYN2_PLUGIN_CACHE |
where compiled plugins are kept (default: plugins in the cache directory, ~/.cache/freedyn2/plugins, Windows %LOCALAPPDATA%\freedyn2\cache\plugins; off: no cache) |
FREEDYN2_HOME |
all per-user directories (configuration, data, cache, logs) below this one |
FREEDYN2_RUN |
a freedyn2_run to use instead of the installed one |
FREEDYN2_CHROMIUM |
a Chromium for the MCP screenshot tool |
FREEDYN2_NO_UPDATE_CHECK |
1: the app does not ask GitHub for a newer release |