Skip to main content

CLI Reference

FluidCAD ships a command-line tool alongside the library. It scaffolds a project, opens FluidCAD in your browser, writes STEP/STL/PNG files without opening the UI, and exposes the MCP server that lets AI agents drive your workspace.

FluidCAD is installed per-project, so the CLI is run through npx from inside the project:

npm i fluidcad
npx fluidcad --help
note

A global install (npm install -g fluidcad) is not supported — the engine and your editor's type hints both resolve from the project's node_modules. If you see Cannot find module 'fluidcad' imported from …, run npm i fluidcad inside the project.

CommandWhat it does
fluidcad initScaffold a new project in the current directory
fluidcad serveOpen FluidCAD in the browser and watch the workspace
fluidcad export stepWrite a STEP file
fluidcad export stlWrite an STL mesh
fluidcad export pngCapture a PNG of the viewport
fluidcad mcpRun the MCP server over stdio

Every command accepts --help, and npx fluidcad --version prints the installed version.


fluidcad init​

npx fluidcad init

Scaffolds a project in the current directory:

my-app/
├── init.js ← required project entry point
├── box.part.js ← starter model
├── jsconfig.json ← enables editor type hints
└── fluidcad.json ← project configuration: engine pin, unit

init.js is required — the viewer cannot run a .part.js file without it. Don't edit it.

The command refuses to run if init.js already exists, so it can't clobber a project. box.part.js, jsconfig.json and fluidcad.json are only written when they're missing, so re-running it in a half-set-up folder fills in the gaps.

FlagDescriptionDefault
--unit <unit>Project length unit written to fluidcad.json: mm, cm, m, in or ftthe unit for new projects from the Settings dialog, mm unless changed
npx fluidcad init --unit in # an inch project

Without the flag, the unit comes from Settings ▸ Units ▸ Unit for new projects in the FluidCAD UI (the gear in the top bar). The desktop app's New Project uses the same setting.

See Project configuration for what fluidcad.json holds.


fluidcad serve​

npx fluidcad serve

Opens FluidCAD in your browser: the 3D viewport, every interactive modelling tool, and a code editor. It renders the model you had open last (or the first .fluid.js it finds in a new project) and watches the workspace, so an edit made anywhere — the in-page editor, your own editor, an AI agent through MCP — rebuilds the model. Press Ctrl+C to stop.

This is the primary way to run FluidCAD. The VS Code and Neovim extensions drive the same server if you'd rather stay in your own editor.

FlagDescriptionDefault
-w, --workspace <path>Path to your projectCurrent directory
-p, --port <port>Server port — if it's taken, the first free port above it is used3100
--no-openDon't launch a browser — for CI and remote sessionsopens by default
npx fluidcad serve # open FluidCAD in your browser
npx fluidcad serve --no-open # start the server only (CI, SSH)
npx fluidcad serve -w ./my-app # serve a project in another directory
npx fluidcad serve -p 4000 # start at port 4000 (4001, 4002, … if busy)

The startup banner names the engine version that is actually running, so a project whose fluidcad.json pin disagrees with it says so before anything is rebuilt.

note

The code editor is hidden until you open it, from the ☰ menu or with Ctrl+B. It docks to the left and takes width from the scene rather than covering it, so the model stays fully visible.


fluidcad export​

npx fluidcad export step # every shape → <entry>.step
npx fluidcad export stl --resolution fine -o parts/bracket.stl
npx fluidcad export png --view front --open

Writes a STEP, STL, or PNG file straight from the terminal — the same exports the Export dialog produces, without opening the UI.

How the model gets rendered​

The CLI works in one of two modes, chosen automatically:

  • Attached — a FluidCAD server is already running for the workspace (started by fluidcad serve or an editor extension). The CLI finds it through .fluidcad/instance.json and exports the scene that server is currently showing. Nothing is re-rendered, and no second server is started.
  • Ephemeral — nothing is running. The CLI forks its own server on a free port, renders your entry file, exports, and shuts the server down again.

Because an attached server's scene wins, passing --entry while one is running only prints a warning — what the server shows is what gets exported. Stop the server to export a different file.

Common flags​

These apply to all three formats:

FlagDescriptionDefault
-w, --workspace <path>Path to your projectCurrent directory
-e, --entry <file>Which .fluid.js to renderThe workspace's only one
-o, --out <path>Output file<entry>.<ext> in the current directory
-p, --port <port>Export from the running server on this port instead of discovering oneAuto-discovered
--timeout <sec>Seconds to wait for the server (and, for png, for a browser)60

If the workspace holds more than one .fluid.js file, --entry is required — the CLI won't guess.

fluidcad export step​

FlagDescriptionDefault
--shapes <ids...>Export a subset of the scene's shapesAll shapes (an assembly: the whole assembly)
--list-shapesPrint the scene's shapes and exit without exporting—
--no-colorsWrite plain geometry instead of per-shape colorscolors on
npx fluidcad export step --no-colors -o build/housing.step

fluidcad export stl​

FlagDescriptionDefault
--shapes <ids...>Export a subset of the scene's shapesAll shapes (an assembly: the whole assembly)
--list-shapesPrint the scene's shapes and exit without exporting—
--resolution <r>Mesh resolution: coarse, medium, fine, or custommedium
--linear-deflection <length>Custom linear deflection, in document units—
--angular-deflection <deg>Custom angular deflection, in degrees—
--scale-to <mm|document>Write the STL in millimetres (what slicers expect) or keep the document's unitmm

The two deflection flags imply --resolution custom, and custom needs both of them:

npx fluidcad export stl --linear-deflection 0.01 --angular-deflection 0.1

Passing a deflection alongside --resolution fine is an error rather than a silent override.

Picking shapes​

--list-shapes prints what the scene contains, numbered:

3 shapes:
1 a1f2… SOLID Extrude
2 b7c4… SOLID Fillet
3 c9e0… SOLID Housing

--shapes then takes any mix of:

  • a position from that listing — --shapes 1 2
  • a feature name — --shapes Housing (case-insensitive; exports every shape that feature produced)
  • a shape id — --shapes a1f2…

Positions and names survive a re-render; shape ids are minted fresh every time the model rebuilds, so don't hard-code them in a script.

npx fluidcad export step --list-shapes
npx fluidcad export step --shapes 1,3 -o build/plates.step
npx fluidcad export stl --shapes Housing --resolution fine

Assemblies​

When the scene is a *.assembly.js file, export step and export stl write the whole assembly by default: every inserted part where it sits. STEP keeps the structure — one product per part, one component per instance, sub-assemblies nested — so it opens as an assembly tree elsewhere. STL flattens every placed part into one mesh.

npx fluidcad export step # robot.assembly.js → robot.step, the full tree
npx fluidcad export stl --resolution fine
npx fluidcad export step --shapes 1 # a single part template instead, in its own frame

Mates are solved in the viewer, and the CLI has no viewer, so parts land where the source places them (insert().translate() / .rotate()). The CLI prints a note when that is the case; for the mated layout, export from the viewer's Export menu.

fluidcad export png​

FlagDescriptionDefault
--width <px>Image width800
--height <px>Image height800
--view <name>Camera view (see below)iso-ftr
--margin <px>Crop/fit margin20
--transparentTransparent backgroundoff
--show-axesShow the origin axesoff
--no-gridHide the ground gridgrid shown
--no-auto-cropKeep the full frame instead of cropping to the modelcrop on
--no-fitDon't fit the camera to the modelfit on
--openOpen the viewport in a browser to render the captureoff

--view takes current (whatever the connected browser is looking at) or a named view:

Orthographicfront, back, left, right, top, bottom
Isometriciso-ftr, iso-fbr, iso-ftl, iso-fbl, iso-btr, iso-bbr, iso-btl, iso-bbl

Isometric names read as front/back, top/bottom, left/right — iso-fbl is the front-bottom-left corner.

npx fluidcad export png --view top --width 1600 --height 1200
npx fluidcad export png --transparent --no-grid -o docs/hero.png
warning

PNG capture needs a browser. Screenshots are rendered by the FluidCAD viewport itself, so a browser has to be connected to the server. Pass --open and the CLI launches one and waits for it; otherwise open the server URL yourself before the --timeout runs out.

If a server is already attached and no browser is on it, the command fails immediately and tells you the URL to open — re-run with --open, or stop that server so the CLI can spawn its own.


fluidcad mcp​

npx fluidcad mcp

Runs the FluidCAD MCP server over stdio, so an LLM agent can drive your workspace: take screenshots, inspect geometry, measure, edit source, and look up the API. It's bundled with the fluidcad package — there's nothing extra to install.

You don't normally run this by hand; you register it with an MCP client.

Claude Code — register at user scope so it's available in every project:

claude mcp add --scope user FluidCAD -- npx -y fluidcad mcp

Claude Desktop / Cursor — add to claude_desktop_config.json or ~/.cursor/mcp.json:

{
"mcpServers": {
"FluidCAD": {
"command": "npx",
"args": ["-y", "fluidcad", "mcp"]
}
}
}

opencode — run opencode mcp add, or add to ~/.config/opencode/opencode.json:

{
"$schema": "https://opencode.ai/config.json",
"mcp": {
"FluidCAD": {
"type": "local",
"command": ["npx", "-y", "fluidcad", "mcp"],
"enabled": true
}
}
}

Then install the companion skill so agents follow the FluidCAD workflow:

npx skills add Fluid-CAD/FluidCAD

The agent drives a running workspace, so start one first — with fluidcad serve or an editor extension — and the MCP server attaches to it.

See the MCP README for the full tool surface and transport details.