CLI Reference
@saastro/forms ships a small CLI that runs through npx. It scaffolds
example forms and installs the shadcn/ui components those forms need.
npx @saastro/forms <command>
Run with no arguments to print the inline help.
init
Scaffold two zero-config example forms in src/components/.
npx @saastro/forms init
Creates:
src/components/ExampleForm.tsx— programmatic form built withFormBuildersrc/components/ExampleFormJson.tsx— same form expressed as JSON config (useful as a starting point for storing forms in a database or CMS)
If either file already exists, it is left untouched and the CLI reports
exists <path> instead of create <path>.
After running init, you’ll be reminded to call:
npx @saastro/forms install-deps
This installs any shadcn components the examples reference but are missing from your project.
Use the generated form
import { ExampleForm } from '@/components/ExampleForm';
export default function ContactPage() {
return <ExampleForm />;
}
The example uses import.meta.glob so every .tsx file in
@/components/ui/ is automatically wired into the form. Add new components
to that folder and they’ll be available without any registration step.
install-deps
Read your project’s components.json (the shadcn config) and install every
shadcn component the example forms need, skipping any that are already
present.
npx @saastro/forms install-deps
What it does:
- Verifies you’re running it inside a consumer project (not the
@saastro/formssource repo). - Reads
components.jsonto discover the project’s path aliases and component directory. - Ensures
lib/utils.tsexists (the shadcncn()helper). Creates it if not. - Runs
shadcn@latest add <missing-components> --yesto install whichever components are missing. - If the batch install fails (rare), retries one component at a time so a single broken package doesn’t block the rest.
When to run it:
- After the first
init. - Any time you add a field type whose required components you haven’t installed yet — the runtime fallback also tells you to run this command.
What if I don’t have a components.json?
install-deps aborts safely and tells you to run npx shadcn@latest init
first. Once shadcn is initialised in your project, re-run install-deps.
add <name>
Legacy command to install a single component by name. Kept for backwards
compatibility — prefer install-deps for everyday use.
npx @saastro/forms add input
npx @saastro/forms add command
What it does:
- Reads
components.json. - Ensures
lib/utils.tsexists. - Runs
shadcn@latest add <name>for the single component requested.
Most projects should run install-deps instead, which installs the full set
needed by @saastro/forms in one call.
Troubleshooting
”Detected that you’re inside the @saastro/forms package”
You ran install-deps from the package source, not your consumer project.
Switch into your app directory (e.g. apps/web) and run the command from
there.
”No components.json found”
shadcn isn’t initialised in this project yet. Run:
npx shadcn@latest init
…answer the prompts, then re-run npx @saastro/forms install-deps.
A specific component fails to install
install-deps falls back to one-at-a-time installation when the batch run
fails. If a particular component still fails, install it manually:
npx shadcn@latest add <component-name>
…and re-run install-deps to verify everything else is in place.
Peer dependencies (installed automatically since 0.2.1)
install-deps also verifies that the peer dependencies are present in
your package.json and installs any that are missing:
zod(^3.25or^4)react-hook-form(^7)react-day-picker(^9)date-fns(^4)
The package manager is detected from your lockfile in this priority order:
pnpm-lock.yaml→pnpm add ...bun.lockorbun.lockb→bun add ...yarn.lock→yarn add ...package-lock.json(or none) →npm install ...
react and react-dom are intentionally not auto-installed — every React
project already has them, and choosing between React 18 and 19 is a
project decision.