[generate] & [project]

The [generate] and [project] tables — output directory, targets, project identity, and grouping.

The [generate] table controls what forgedb generate emits; [project] says which project a schema belongs to. Both are read at generate time.

[generate]#

[generate]
output = "generated"
targets = ["all"]
KeyTypeDefaultMeaning
outputstring"generated"Output directory, resolved against the schema's directory.
targetsstring[]required inside a declared [generate] tableWhich targets to emit.

targets is required, and ["all"] means all#

If you write a [generate] table, you must write targets. It used to be optional, where absent meant every target — the inverse of what an absent list normally reads as, and a set the build cache's package prune has no way to state. A project with no forgedb.toml at all, or one with no [generate] table, still takes the built-in ["all"]; what is refused is a half-declared table that leaves the most consequential key to be guessed.

error: forgedb.toml:4:1: `[generate].targets` is required.

["all"] genuinely means all — including ffi, the browser replica, the REST SDKs and the three native runtime bindings. Under the old "absent means everything" reading those opt-in targets were reachable only by listing them, so all quietly skipped them.

Valid values#

They are the same runtime × mode vocabulary the CLI speaks, hyphen-joined where a mode is required, so one spelling means one thing in both places:

ValueEquivalent command
allforgedb generate all
rustforgedb generate rust
apiforgedb generate api
openapiforgedb generate openapi
stubsforgedb generate stubs
ffiforgedb generate ffi
node-sdk / bun-sdkforgedb generate node --sdk / ... bun --sdk
python-sdkforgedb generate python --sdk
rust-sdkforgedb generate rust --sdk
go-sdkforgedb generate go --sdk
node-runtime / bun-runtimeforgedb generate node --runtime / ... bun --runtime
python-runtimeforgedb generate python --runtime
go-runtimeforgedb generate go --runtime
browser-replicaforgedb generate browser --replica

An unknown value is now a positioned error listing that set, not a silent no-op — targets = ["napi"] used to emit nothing at all.

`typescript` and `wasm` were renamed

The pre-runtime spellings typescript and wasm still work and warn, naming their replacements (node-sdk, browser-replica). They are not silently accepted: typescript was legal here while forgedb generate typescript was a hard error, and a deprecated value that behaves identically and says nothing is how the two spellings drifted apart in the first place.

CLI flags override these

--output on the forgedb generate command takes precedence over the [generate] value, which in turn takes precedence over the built-in default. See configuration precedence.

There is no `schema` key

[generate].schema was removed. A config governs every schema beneath it, so it cannot name one — the same file may be the nearest ancestor of several apps. The schema is named by the invocation (--schema) or found beside you (schema.forge). A config that still sets the key fails with a diagnostic saying so.

[project]#

[project]
id = "my-app-7f3a9c2e"
version = "0.1.0"
isolated = true
KeyTypeDefaultMeaning
idstring(generated by init)The project id. Committed, and never derived from a package name.
versionstring(unset)Metadata. Deliberately affects nothing.
isolatedbooltrueDo the schemas beneath this config form their own project?

A project is the unit of build cache, lockfile and target directory. Apps in one project compile the substrate once between them; apps in different projects do not share pins.

How the id is decided#

forgedb init generates one and writes it here — a directory slug plus entropy, so ~/.forgedb/projects/ stays readable:

[project]
id = "storefront-7f3a9c2e"

Commit it. The id keys the build cache, so a teammate or a CI runner that resolves a different one is working in a different project.

A tree with no id still resolves: the fallback is a hash of the root's absolute path, with a warning. That is a perfectly good key — two paths hash differently — but it is not stable: move the directory and the id changes, which re-keys the cache and forces a cold rebuild. forgedb project show prints a value you can paste to pin it.

The id is generated, not derived. Two projects both named api in two repositories get different ids. The one way two projects share an id is a copied directory, where the copy inherited the original's [project].id — that is refused, with a diagnostic naming the file and key to change.

isolated, and why absent means true#

isolated = true stops the upward walk: these schemas are their own project. false joins the enclosing one.

An omitted isolated means true, which is the opposite of how a missing boolean usually reads. It has to be: otherwise adding a config at a monorepo root for an unrelated reason would silently absorb every app beneath it into one project, re-unifying pins that were deliberately apart. Grouping is opt-in, and forgedb init always writes the field — --isolated / --no-isolated decide it, and with neither, init joins an enclosing project if it finds one and reports which.

Declaring name at a config that is not the project root is an error: it reads as authoritative and is not.

Search documentation

Find pages across the ForgeDB docs