Install and run

goofi is one binary with the app compiled into it. A fresh clone comes up with two commands.

Prerequisites

Three tools have to be on PATH: rustup, Node.js, and uv. The compiler version is pinned in rust-toolchain.toml at 1.97.1, so rustup fetches the right one on the first build.

a fresh clone
# rustup, Node.js and uv must be on PATH.
# The Rust toolchain itself is pinned in rust-toolchain.toml (1.97.1),
# so rustup fetches the right one on the first build.

git clone https://github.com/dav0dea/goofi-pipe
cd goofi-pipe
git checkout rust-rewrite

cargo run -p goofi-init   # once per clone
cargo run                 # prints the URL

goofi-init does the setup cargo needs and cannot do for itself: it builds the two Python interpreters, installs the goofi package into each, installs the app's dependencies, and writes the cargo config that points pyo3 at the free-threaded interpreter. That last one must happen before cargo starts, because cargo reads .cargo/config.toml only at startup. It is idempotent, so re-run it after a version bump.

cargo run then builds the app whenever a frontend source is newer than the last bundle, and fails if it cannot. It does not fall back to the previous bundle, because a bundle that does not match the binary around it is the wrong app. goofi serves the app, prints its URL, and does not open a browser.

The nodes come with it

Every node goofi ships lives in node-bundles/, one directory per bundle, and every bundle is built at goofi's build time and embedded, the Rust built-ins included. cargo run therefore carries all 67 types without a flag.

--extra-nodes adds a root of your own, scanned after the shipped bundles:

cargo run -- --extra-nodes ~/my-nodes

goofi-init installs every shipped bundle's requirements. At startup goofi checks every scanned root's requirements against both interpreters. A terminal is asked before anything is installed, and without one the nodes that need them are listed as unavailable. See Bundles.

Without the app

GOOFI_HEADLESS=1 is --headless spelled as an environment variable, and it applies to the build as well. Set for cargo build, it leaves the app out of the binary entirely: Node.js is not needed, and the binary is headless without the flag at run time.

GOOFI_HEADLESS=1 cargo build --release   # the app is left out of the binary entirely

A headless instance serves the API alone: /control, /data, /term and /mcp. The app's routes are never mounted, and the layout op group goes with them.

What you get

This reference was generated from goofi 3.1.0 answering its own ops. That instance registered 57 ops and 67 node types: 47 in Rust and 20 in Python across 4 bundles, with 9 panel types and 6 viewer kinds.

This reference describes goofi 3.1.0(537cd394), generated from a running instance on 2026-09-06.