Install and run

goofi is one binary with the app compiled into it. Two commands bring a fresh clone up, and there is never a third.

Prerequisites

Three tools, none of them goofi's: 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 and there is nothing to choose.

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 provisions every precondition cargo has and cannot provide 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 will not fall back to the previous bundle: one that does not match the binary around it is the wrong app. goofi serves the app and never opens one: it prints the URL, and the opening is yours.

The nodes come with it

Everything 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. So cargo run carries all 67 types and there is nothing to pass.

--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 against both interpreters. A terminal is asked before anything is installed, and without one those nodes are simply unavailable rather than silently missing. 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, so no Node.js is needed and the result is headless for life with no flag to remember at every run.

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.