forma-dsl
Declarative solid modelling

A model is
a document
you can diff.

forma-dsl writes geometry as configuration, in an HCL-like syntax you can already read: declare parameters, nest blocks, reuse components. The document is solved by the Manifold CSG kernel compiled to WebAssembly - unchanged in Node and in the browser.

Watch it build something
Sheet 01forma-dsl
Package
npm i forma-dsl
Version
-
Kernel
Manifold · WASM
Runtime deps
-
Output
Mesh · binary STL
Licence
MIT
§ 02

The language, running

Nothing here is a recording. The source types itself, and the solid beside it is the real library compiling that text in your browser - the same code the editor runs.

drag to orbit · move a slider
waiting
tris - solve -
§ 03

What you get

01

Parameters, not constants

A param block declares a typed input with bounds. The editor reads them and builds the controls; your build script passes them in.

02

Components that compose

Name a parameterised block once and call it like any builtin. Nesting is the operator: children in a row are a union, and that is the whole rule.

03

Content-addressed geometry

Every node carries a 128-bit digest of its content. A component used twenty times is one node, evaluated once - and an edit re-solves only what changed.

04

Errors that point at a line

Every failure carries a source location, so the editor underlines the mistake instead of printing a stack trace at you.

05

One runtime dependency

Just manifold-3d. Hand-written TypeScript declarations ship with the package, so the API is typed from either language.

06

Node and browser, same code

Render to a mesh for a viewer or to binary STL for a slicer. No build step, no platform branch, no headless browser in CI.

§ 04

Start in a minute

Install it, write a document, and hand the parts to a viewer or a slicer. One context is reused across renders: the digest cache is what makes the second one cheap, and collect is what keeps a long run bounded.

Three calls carry most of the work:

  • render(source, options) Compiles a document and evaluates one model into parts, each carrying a mesh for a renderer and the solid it came from.
  • describeParameters(source) Reads the declared inputs without solving anything. It is how the editor builds its controls, and how a build script knows what it may pass.
  • toBinarySTL(part.concrete) A buffer a slicer will open, written straight to disk or handed to the browser as a download.

The same document renders in CI. There is no browser to drive and no display to fake: the kernel is WebAssembly, so a part that comes out of your laptop comes out of a runner too, and a pull request can check the geometry rather than the code that produced it.

The reference manual covers every declaration, block, function and error, each with usage and troubleshooting - and the editor runs the whole thing in the browser with no install at all.

build.js
§ 05

Or build it from a Makefile

forma-dsl-cli is the same kernel with no browser around it. forma render part.forma -o part.stl solves a document and writes a binary STL, which is what puts a .forma file in a build, a CI job or a release pipeline.

Three commands, and the pipe is the point:

  • forma render Solves a document and writes the STL. -o - sends it to stdout and keeps the summary on stderr, so it pipes into whatever comes next.
  • forma params The document describing itself, as a table or as --json - which is how a script builds every variant without being told what they are.
  • forma models Names the models a document declares, so --model can be given one that exists.

Three exit codes, because a script has to tell them apart: 0 worked, 1 the document did not build, 2 the invocation was wrong. A failure prints as file:line:column: with the source and a caret under the column - where an editor and a CI annotation can both find it.

It knows nothing about the language itself. Every block it accepts and every error it reports comes from the same package the editor and the server import, so a block added to the language is one it renders without being told.

§ 06

Or describe it, and let a model write it

forma-dsl-mcp is a Model Context Protocol server over stdio. It carries the language - the guide, the block reference, the worked examples and the full manual - and it runs the geometry kernel, so the model it is talking to is answered with a solved part rather than with its own guess about one.

Three tools, and the measurements are the point:

  • forma_write Builds the document and, only if it renders, writes it. What comes back is a table of every part with its bounding box, volume, triangle count and genus - so "is this the size I asked for, and is it actually a solid?" is answered before the work is handed over.
  • forma_read Reads a document back and builds it, so an existing file can be measured before it is edited.
  • forma_export_stl Renders a part - or every part union - straight to binary STL.

A document that does not render is refused rather than written, and a part that silently solved to nothing is called out by name. Where the model guesses a block or an attribute that does not exist, the refusal names every one that does.

Where the files go is the client's decision, not the server's: it asks over MCP's roots capability and reads and writes only inside the directories it is handed.

shell