The feature picker
The feature menu, the dependency graph, and how auto-selection works.
The starter is a menu. Every feature is either core (always present) or
prunable (yours to include or leave out). The picker — interactive or via
--features — is where you choose, and the generator resolves your choice
against the feature dependency graph before anything is copied.
Core vs prunable features
Two features are core and can never be deselected — they're the spine every app needs:
| Feature | Requires |
|---|---|
| auth — Authentication | — |
| orgs — Organizations | auth |
The remaining twelve are prunable. In the interactive picker they all start
checked; in --features you name the ones you want.
| Feature | Requires |
|---|---|
| jobs — Background jobs | — |
| email — Transactional email | jobs |
| billing — Billing (Stripe) | orgs, email, jobs |
| flags — Feature flags / entitlements | billing |
| usage — Usage tracking | billing, flags, jobs |
| api-keys — API keys + public API | orgs |
| files — File uploads | orgs |
| audit-log — Audit log | orgs |
| marketing — Marketing pages | billing |
| admin — Admin panel | orgs, billing, flags |
| observability — Observability | — |
| agents — Agent development tooling | — |
(There are 14 features total; this is the definitive list from features.json,
the single source of truth the CLI reads.)
Dependencies are resolved automatically
Each feature declares what it requires. When you select a feature, the
generator pulls in the transitive closure of its requirements — you never
have to hand-trace the graph.
For example, selecting usage gives you:
usage → requires billing, flags, jobs
billing → requires orgs, email, jobs
email → requires jobs
flags → requires billingSo --features usage resolves to usage, billing, flags, jobs, email — plus
the core auth and orgs. Everything else is pruned.
In the interactive flow, because @clack/prompts' multi-select is a static list
that can't grey out a dependent live as you toggle, the dependency awareness is
applied after you submit: the generator auto-adds every required dependency
and prints a note telling you which selection pulled each one in, so the choice
stays explicit. Dependencies win over deselection — if you uncheck a feature
that a checked feature needs, it comes back.
Core is always in the closure
auth and orgs are seeded into every resolution before your requests are
even considered, so any selection — including --features core — is a
well-formed app.
Features can't be added after generation
The graph is resolved once, at generate time. A generated app has no
features.json and no way to "turn on" a feature later — the code for pruned
features simply isn't there. If you find you need a feature you left out,
regenerate the app with it selected.
This is why the add <block> command can only install blocks
whose required features your app already has: blocks compose existing features,
they don't introduce them.
Choosing a starting point
- Prototyping or unsure? Take the full app (interactive defaults, or
--yeswith no--features) and prune later by regenerating. - Know exactly what you need? Name it:
--features billing,files,audit-log. The generator adds the dependencies. - Want the leanest base?
--features core— justauthandorgs.