Skip to main content

CLI Reference

FluidCAD ships a command-line tool alongside the library. It opens FluidCAD's start screen in your browser, scaffolds a project, opens one project 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

The start screen, npx fluidcad on its own, is the exception: it runs from any folder, and the projects it opens need no npm i of their own.

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
fluidcadOpen the start screen in the browser: your projects, new projects, and the engine each one runs on
fluidcad initScaffold a new project in the current directory
fluidcad serveOpen one project in the browser and watch its 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​

npx fluidcad

Opens FluidCAD's start screen in your browser: the same one the desktop app shows, with your recent projects, New Project and Open Project, and the engine each project runs on. It is the one command you can run from anywhere; it is not tied to a project folder. (npx fluidcad start is the same command by its name.)

Every project opens in a tab of its own, and the start screen stays in its tab. Opening a project that is already open brings its tab forward. New Project asks where the project should live and what to call it, creates the folder, and sets the project up in it, the same scaffold as fluidcad init. Close a project from the ⋯ menu on its card; FluidCAD refuses while its tab has unsaved changes.

Each project runs on the engine its fluidcad.json pins, the way the desktop app runs it: a pin that is not on your machine is downloaded once and kept in ~/.fluidcad/engines, and an unpinned project is pinned to the version of fluidcad you ran. The start screen and the desktop app share the recent projects, the previews and the downloaded engines, so a project opened in one is on the other's list too. See Project configuration.

Leave the command running while you work. Ctrl+C stops FluidCAD and every project it opened. Running npx fluidcad again while it runs opens the running one in a new tab instead of starting a second.

FlagDescriptionDefault
-p, --port <port>Port for the start screen — if it's taken, the first free port above it is used3100
--no-openDon't launch a browser, only print the start screen's linkopens by default
--projects <dir>Keep every project in this folder (see below)projects live anywhere
--host <address>The address to listen on; 0.0.0.0 lets other machines reach FluidCAD (see below)127.0.0.1
--public-url <url>The origin browsers reach FluidCAD at behind a reverse proxy, such as https://cad.example.comnone

The link it prints carries a key for the session, so that no other page or user on your machine can drive FluidCAD through it. Open it yourself when the browser does not open on its own (over SSH, say), and don't share it.

Every project's page is served by the start server itself, at /p/<name>/, which stands in for the project's engine: the engine runs on this machine's loopback address only, and the start server forwards its page, its calls and its live connection to it. That is what lets a browser on another machine work on a project, below.

A projects folder​

npx fluidcad --projects ~/cad

With --projects, one folder holds every project. The start screen lists the projects in it, all of them rather than the recent ones. New Project asks only for a name, creates <dir>/<name> and sets the project up there. Open Project is not offered, since every project in the folder is already on the screen, and nothing outside the folder can be opened: the start server refuses any path that is not a project in it, which is what makes the folder the boundary when the start screen is reached from another machine. The folder has to exist.

Reaching FluidCAD from other machines​

npx fluidcad --projects /srv/cad --host 0.0.0.0 --no-open

--host 0.0.0.0 binds the start screen to every address of the machine, so a browser on another machine (or in a container's network) can open it, and open projects in it: each project's page goes through the start server, at /p/<name>/, and the engines themselves stay on loopback where nothing else can reach them. Pair it with --projects, so that the machine's other folders stay out of reach.

What keeps it yours:

  • The link npx fluidcad prints carries the session's key. Anyone who has it can use FluidCAD as you, and can read and change every project it opens, so keep it private. Without it a browser gets a page saying where the link is.
  • The key becomes an HttpOnly, SameSite=Strict cookie, and every call that changes something has to come from FluidCAD's own pages.
  • Nothing is encrypted by FluidCAD itself. Before leaving a private network, put an HTTPS reverse proxy in front of it (Caddy, nginx, Tailscale Serve, Cloudflare Tunnel), forwarding WebSocket upgrades too, and tell FluidCAD the origin it is reached at:
npx fluidcad --projects /srv/cad --host 127.0.0.1 --public-url https://cad.example.com --no-open

With --public-url, the link it prints uses that origin, calls from pages at that origin are accepted, and, when it is https://, the session cookie is marked Secure so it is never sent in the clear. Bound to 127.0.0.1 behind the proxy on the same machine, the start server is not reachable any other way.

One start server is one session, for one person or a group who share the link. It has no accounts of its own.


fluidcad init​

npx fluidcad init

Scaffolds a project in the current directory:

my-app/
├── init.js ← required project entry point
├── part1.part.js ← an empty part to start modeling in
├── 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. part1.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.

Where fluidcad opens the start screen, serve opens one project, runs it on the fluidcad it was installed with, and suits CI and scripts. 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.