[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"]| Key | Type | Default | Meaning |
|---|---|---|---|
output | string | "generated" | Output directory, resolved against the schema's directory. |
targets | string[] | required inside a declared [generate] table | Which 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:
| Value | Equivalent command |
|---|---|
all | forgedb generate all |
rust | forgedb generate rust |
api | forgedb generate api |
openapi | forgedb generate openapi |
stubs | forgedb generate stubs |
ffi | forgedb generate ffi |
node-sdk / bun-sdk | forgedb generate node --sdk / ... bun --sdk |
python-sdk | forgedb generate python --sdk |
rust-sdk | forgedb generate rust --sdk |
go-sdk | forgedb generate go --sdk |
node-runtime / bun-runtime | forgedb generate node --runtime / ... bun --runtime |
python-runtime | forgedb generate python --runtime |
go-runtime | forgedb generate go --runtime |
browser-replica | forgedb 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| Key | Type | Default | Meaning |
|---|---|---|---|
id | string | (generated by init) | The project id. Committed, and never derived from a package name. |
version | string | (unset) | Metadata. Deliberately affects nothing. |
isolated | bool | true | Do 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.
Related#
[runtime]and[storage]— the generate-time behavior knobs.- Configuration overview — discovery, precedence, and the tier model.