Command line
Rendering parts from a terminal with foundry: installing it, rendering with your own parameters, and saving defaults.
foundry renders any part in the catalogue to an STL file. It compiles the same OpenSCAD sources the
app does, with a native OpenSCAD instead of the browser's, so it suits scripts and batch jobs: a
drawer's worth of Gridfinity bins in one loop, every part at your printer's tolerance, a part as a
step in a Makefile. For one part at a time, the app is quicker.
#Install
You need:
- Python 3.10 or newer.
- Git, to clone the repository with its submodules: the upstream libraries the parts are built
on (BOSL2, gridfinity-rebuilt-openscad and the rest) live in
vendor/as git submodules. - An OpenSCAD development snapshot. Every part renders with OpenSCAD's Manifold backend, which the stable release does not have. Download a snapshot for your system from openscad.org.
Then, on macOS or Linux:
git clone --recurse-submodules https://github.com/dnnsmnstrr/connector-foundry.git
cd connector-foundry
python3 -m venv .venv
.venv/bin/pip install -e .
.venv/bin/foundry list
On Windows, in PowerShell:
git clone --recurse-submodules https://github.com/dnnsmnstrr/connector-foundry.git
cd connector-foundry
py -m venv .venv
.venv\Scripts\pip install -e .
.venv\Scripts\foundry list
Keep the -e: foundry reads the catalogue and the part sources from the checkout it was installed
from, so an editable install is what keeps it working (and up to date after a git pull). Activate
the environment (source .venv/bin/activate, or .venv\Scripts\Activate.ps1 on Windows) to type
plain foundry, as the rest of this guide does. Cloned without --recurse-submodules? Run
git submodule update --init --recursive.
#Tell foundry where OpenSCAD is
foundry runs the command openscad. If the snapshot is not on your PATH under that name, point
OPENSCAD_BIN at it:
export OPENSCAD_BIN=/Applications/OpenSCAD.app/Contents/MacOS/OpenSCAD # macOS: inside the app bundle
export OPENSCAD_BIN=~/Applications/OpenSCAD-x86_64.AppImage # Linux: the AppImage
$env:OPENSCAD_BIN = "C:\path\to\openscad.exe" # Windows: where the snapshot installed it
Put the line in your shell's profile to keep it. If foundry cannot start OpenSCAD it says so —
'openscad' not found. Install an OpenSCAD dev snapshot … — and an --backend error from
OpenSCAD itself means it found the stable release instead of a snapshot.
#Find a part
foundry list
lists every part, grouped by system:
Gridfinity
gridfinity/base [exact ] MIT Bin base
gridfinity/bin [exact ] MIT Bin
gridfinity/baseplate [exact ] MIT Baseplate
The first column is the part's id, which every other command takes; then how far to trust it
(exact or parametric, see Getting started), its licence
and its name. To see a part's parameters and their defaults:
foundry defaults show gridfinity/bin
catalogue default: {'gx': 1, 'gy': 1, 'gz': 3, 'filled': False, 'divx': 1, 'divy': 1, 'scoop': True, 'tabs': True, 'lip': True, 'magnets': False, 'screws': False}
user override: (none)
effective: {'gx': 1, 'gy': 1, 'gz': 3, 'filled': False, 'divx': 1, 'divy': 1, 'scoop': True, 'tabs': True, 'lip': True, 'magnets': False, 'screws': False}
The names are the ones in the app's sidebar. A part's print note — which side goes on the bed, and what each parameter is for — is in the catalogue table.
#Render a part
foundry render gridfinity/base --gx 2 --gy 1 --magnets -o out/
writes out/gridfinity_base.stl: the part's id with / as _. Render variants of one part into
folders of their own, or the second overwrites the first.
| Option | Does |
|---|---|
-o, --out DIR |
where the STL goes (default out/, created if missing) |
--set NAME=VALUE |
sets any parameter; repeat it for more than one |
--gx N, --gy N |
shorthand for --set gx=N, --set gy=N (the Gridfinity parts) |
--magnets, --no-magnets, --screws, --no-screws |
shorthand for the Gridfinity hole options |
--no-user-config |
ignore your saved defaults and settings (below) for this render |
--set reads true and false as booleans, anything that parses as a number as a number, and the
rest as text. A few examples:
# A 2 x 3 bin, 6 units (42 mm) tall, with magnet holes
foundry render gridfinity/bin --gx 2 --gy 3 --set gz=6 --magnets -o out/bins/
# A 4 x 2 openGrid board in the thin "lite" variant
foundry render opengrid/board --set cells_x=4 --set cells_y=2 --set variant=lite -o out/
# A GoPro buckle that takes a square M5 nut
foundry render gopro/female --set nut_sides=4 --set nut_dia=11.5 -o out/
And because it is a command, a loop renders a set:
for w in 1 2 3; do
foundry render gridfinity/bin --gx "$w" --gy 1 -o "out/bin-${w}x1/"
done
Mistakes stop before anything renders, and say what would work: a parameter the part does not have
('nope' is not a parameter of gf_base(). Accepts: gx, gy, magnets, …), a value that is not one of
a parameter's options (variant='lit' is not one of 'full', 'lite', 'heavy'), or a number under a
part's minimum.
#Save your defaults
If you always want a parameter set one way — magnet holes in every Gridfinity base — save it once
instead of passing it every time. foundry render then applies it on its own:
foundry defaults set gridfinity/base --magnets # from now on
foundry defaults set gridfinity/bin --set gz=6 --set lip=false
foundry defaults show gridfinity/base # catalogue default, yours, and the result
foundry defaults list # every part you saved defaults for
foundry defaults clear gridfinity/base --param magnets # forget one ...
foundry defaults clear gridfinity/base # ... or all of that part's
Settings work the same way for every part at once: the constants in lib/constants.scad that
depend on your printer rather than on a part.
Gridfinity pitch is limited to 36–48 mm and MOD-GRID pitch to 6–12 mm; the browser's Settings panel
stores these same system pitches for its parts and grid helpers.
foundry settings set --fit-clearance 0.25 # the gap where printed parts fit together (0.15 by default)
foundry settings set --circle-detail fine # draft, normal or fine: how finely curves are faceted
foundry settings set --set GRIDFINITY_PITCH=42.2 --set MODGRID_PITCH=8.1 # system XY pitches (mm)
foundry settings show
foundry settings clear
A render takes the catalogue's defaults, then your saved defaults and settings, then what you pass on
the command line, each overriding the one before. --no-user-config leaves out the middle layer, to
render a part exactly as the catalogue defines it.
They are saved as OpenSCAD Customizer files, one per part, under ~/.config/connector-foundry/
(or $XDG_CONFIG_HOME/connector-foundry/), so a saved default also opens as a parameter set in the
OpenSCAD GUI. The web and desktop apps keep their own defaults; the two do not share them. User
overrides covers both.
#Render the whole catalogue
foundry build --all -o out/
renders every part at its catalogue defaults (your saved defaults are not applied), one STL per part, one after another.
#Use OpenSCAD directly
Every part is a module in a file under parts/, so it can go into designs of your own. Library-style
includes in the vendored upstreams (include <BOSL2/std.scad>) need vendor/ on OpenSCAD's library
path, as foundry arranges for its own renders:
OPENSCADPATH="$PWD/vendor" openscad assemblies/gridfinity-to-gopro.scad
A part's file only defines its module, so opening one shows nothing. A file of your own in the repository's root that includes the part and calls it does:
include <parts/gridfinity/base.scad>
gf_base(gx = 2, gy = 1, magnets = true);
A part's id is its file: gridfinity/base is parts/gridfinity/base.scad, and the module it
defines takes the parameters foundry defaults show lists. The slot convention and joints explain how parts attach
to one another.
#For contributors
foundry preview --all renders the gallery images in docs/img/, cut out on a transparent
background; foundry goldens prints (and with --update records) every part's bounding box and
volume for the tests, and foundry readme regenerates the README's catalogue table. AGENTS.md says which command proves which
kind of change.