DocsStart
#Quickstart Shipping
One venture, from an empty directory to a backend answering curl: install the CLI, scaffold a venture with one module, build it, run it locally, hit it. Every command and every output below is from a real run on 2026-10-18, except two conveniences that say so where they appear — the optional fz symlink, and the deploy commands that need your own Cloudflare account — and nothing in that run deployed anything anywhere. The hands-on part is minutes — the one-time installs and first compiles around it add roughly 10-20 minutes (measured in that run: cargo install --locked cratefield-cli 1m35s, cargo install --locked worker-build 3m15s, npm install -g wrangler 16s, the wasm build ~5s once warm). Everything on this page is Shipping.
#Prerequisites
- Rust via rustup, stable (verified with 1.99.1), plus the wasm target:
rustup target add wasm32-unknown-unknown. worker-build, which compiles the venture to wasm — wrangler runs it as the custom build command and nothing in the scaffold installs it:cargo install --locked worker-build.- A recent clang for the wasm build. The D1 adapter compiles SQLite's C sources through
sqlite-wasm-rs, and the compiler must accept that shim's C11 attributes. Verified exactly: clang 18 works — on Debian 12, install it from apt.llvm.org and exportCC_wasm32_unknown_unknown=clang-18. Debian 12's stock clang 14 does not: it rejects the[[noreturn]]attributes insqlite-wasm-rs0.5.5. No other clang version is claimed either way. - Node.js (verified on v24.21.0) and wrangler v4 (verified with 4.151.1):
npm install -g wrangler. - git and curl.
#Install the CLI
$ cargo install --locked cratefield-cli
…
Finished `release` profile [optimized] target(s) in 1m 35s
Installing /root/.cargo/bin/cratefield-cli
Installed package `cratefield-cli v0.7.0` (executable `cratefield-cli`)The installed binary is named cratefield-cli, but it brands itself fz: "Factory Zero venture CLI", and every usage line it prints says fz. Every harness document says fz too, so the rest of this page does. One optional symlink bridges the names — a convenience, not a command from the run, which typed cratefield-cli out; without it, read fz below as cratefield-cli:
$ sudo ln -s ~/.cargo/bin/cratefield-cli /usr/local/bin/fzOne honesty note: the CLI has no --version flag yet — cargo install --list names the version instead.
#Scaffold a venture
$ mkdir venture-example && cd venture-example
$ fz init --name venture-example --host venture-example.factory0.dev --non-interactive
fz init: wrote venture.json (venture venture-example, host venture-example.factory0.dev, no modules yet)--non-interactive only suppresses the printed next-steps; init prompts nothing once --name and --host are given, and writes exactly one file, venture.json — the only file a venture edits:
{
"name": "venture-example",
"host": "venture-example.factory0.dev",
"public_url": "https://venture-example.factory0.dev",
"cors_origins": [
"https://venture-example.factory0.dev"
],
"modules": []
}Add one module, and "modules" lists waitlist:
$ fz add waitlist --non-interactive
fz add: added `waitlist` to venture.json — the desired composition only; nothing was deployed, provisioned or migratedThe catalog holds more — email-signup, cms, changelog, notifications, privacy, telemetry, device-auth, orgs, crm — all listed with their status on /modules/.
#Build the venture
The scaffold's version pins do not compile together yet. The generator pins
cratefield = { version = "0.1" }andcratefield-cli = { version = "0.1" }(hardcoded incrates/manifest/src/generate.rs), and the published 0.1.x lines sit on incompatible core majors:cratefield0.1.4 depends on cratefield-core ^0.4 (0.4.3),cratefield-cli0.1.1 on cratefield-core ^0.3 (0.3.1). Cargo resolves the graph — and then it carries two cores, and the first compile fails with E0599 inside cratefield-cli ("no method namedqueryfound for structSqliteDatabase… multiple different versions of cratecratefield_corein the dependency graph"). This is the published-set skew the harness README warns about ("depend on this repository by git for now"); issue #464 is the release-round that closed the earlier round of it. Until a release fixes the pin, build against a local checkout, as below.
$ git clone --depth 1 https://github.com/Cratefield/harness.git ../harness
$ fz build venture.json --out dist --harness-path ../harness
fz build: venture-example
module set: waitlist
modules: waitlist
composition: sha256:f05ec54df50948bab7d0beaf3e429f0ce7f1dc9045561184b3d5e357185d86c5
pins:
waitlist @ 0.1.1 sha256:0000000000000000000000000000000000000000000000000000000000000000
wrote 4 files to dist:
Cargo.toml
src/lib.rs
src/fz_main.rs
wrangler.toml
provenance.jsonThe generated Cargo.toml now carries path dependencies into that one checkout (cratefield = { path = "../harness/crates/facade", … }, cratefield-cli = { path = "../harness/crates/cli" }), so the graph holds exactly one core. Collect the migrations — a first compile, 24s in the verified run:
$ cd dist && cargo run --bin fz -- migrations collect
Finished `dev` profile [unoptimized + debuginfo] target(s) in 24.00s
Running `target/debug/fz migrations collect`After it, dist/ holds Cargo.toml, src/lib.rs, src/fz_main.rs, wrangler.toml, provenance.json and migrations/ — seven SQL files for waitlist (0001_waitlist_0001_init.sql through 0007_waitlist_0007_lock_backfill.sql) plus the .harness-lock.json lockfile beside them.
#Run it locally with wrangler
This is the scaffold's own target: your venture's Worker on a local workerd with a local D1. Apply the collected migrations, give the venture a signing secret, start the dev server:
$ wrangler d1 migrations apply venture-example --local
⛅️ wrangler 4.151.1
… (applies the seven waitlist migrations one per pass — all seven ✅)
$ printf 'HARNESS_SECRET=%s\n' "$(openssl rand -hex 32)" > .dev.vars
$ . "$HOME/.cargo/env" && export CC_wasm32_unknown_unknown=clang-18
$ wrangler dev --port 8792
[custom build] Running: worker-build --release
[custom build] [INFO]: Compiling to Wasm...
[custom build] [INFO]: :-)Done in 4.58s
[wrangler:info] Ready on http://localhost:8792Without .dev.vars, module actions answer 500 (the health endpoints below do not need it). The shell that starts wrangler must have the cargo bin directory on PATH and the wasm C compiler exported, because wrangler runs the custom build through /bin/sh. The first start compiles the wasm (the ~5s above is warm; a cold first build also compiles the dependency tree). Now hit it:
$ curl -fsS http://127.0.0.1:8792/__ready
{"ok":true}
$ curl -fsS http://127.0.0.1:8792/__health
{"venture":"venture-example","env":"development","harness_api":1,"harness_build":null,"mailer":"configured","captcha":"absent","mailers":[{"name":"resend","configured":false}],"modules":[{"name":"waitlist","version":"0.4.3","requires":["Database","Mailer","Signer"],"optional":["Captcha","RateLimiter"],"tables":["waitlist_entries","waitlist_send_cooldown","waitlist_position_lock"],"emits":["waitlist.joined","waitlist.confirmed"]}],"sidecars":[]}#Run it on the native runtime
The same harness also runs as a plain axum binary against SQLite — no Cloudflare anywhere. To be clear about what this exercises: it runs examples/venture-native in the harness clone, which composes its own module set (sample, email-signup, waitlist); the scaffold itself targets Workers:
$ cd ../harness
$ export HARNESS_SECRET=$(openssl rand -hex 32)
$ export DATABASE_URL=sqlite:///tmp/venture.db
$ export LISTEN_ADDR=127.0.0.1:8790
$ cargo run -p venture-native --release
{"message":"module migrations applied","level":"INFO","target":"venture_native",…}
{"message":"cratefield native runtime listening","addr":"127.0.0.1:8790","level":"INFO","target":"cratefield_runtime_native::server",…}The migrations apply to the SQLite file at boot, so the database appears with its schema the first time the binary starts. LISTEN_ADDR defaults to 127.0.0.1:8080; 8790 here only avoids clashing with wrangler. The same curls answer on this port too:
$ curl -fsS http://127.0.0.1:8790/__ready
{"ok":true}#Try the API
The health and surface endpoints work out of the box: GET /__ready, GET /__health and GET /__surface all answer 200 on both runtimes above. Module action routes do not — in the bare scaffold the waitlist join action's product enum is empty ("enum": [] on /__surface) and the action routes tried in the verified run (POST /, POST /waitlist, /waitlist/status) all answered 404. Joining a waitlist needs the module configured first — products, at minimum — and that configuration is the one step this page does not cover: the venture guide picks it up and carries it through to a production API.
#Deploy to Cloudflare
Optional, and yours, not this page's: with your own account,
$ wrangler login
$ wrangler d1 migrations apply venture-example --remote
$ wrangler deployWhat was verified without an account is that the artifact deploys: the dry run exits 0, requires no login, and produces the worker bundle — run as wrangler deploy --dry-run --outdir <dir> from dist/, with the same shell exports as the dev server:
index.js 32.3kb
⚡ Done in 5ms
Total Upload: 3363.77 KiB / gzip: 1070.00 KiB#Next steps
- The venture guide is the full path from here to a production API on your own domain, every human step called out.
- /modules/ for the whole catalog, with each module's status.
- /docs/mcp/ to wire agents to a venture over MCP.
- /docs/llms.txt for the agent guide.
Maintained on cratefield.com — commands last verified 2026-10-18 against cratefield-cli 0.7.0 and cratefield-core 0.9.0.