CLI Reference

Every command shipped with @saastro/forms — init, install-deps, and add.

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 with FormBuilder
  • src/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:

  1. Verifies you’re running it inside a consumer project (not the @saastro/forms source repo).
  2. Reads components.json to discover the project’s path aliases and component directory.
  3. Ensures lib/utils.ts exists (the shadcn cn() helper). Creates it if not.
  4. Runs shadcn@latest add <missing-components> --yes to install whichever components are missing.
  5. 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:

  1. Reads components.json.
  2. Ensures lib/utils.ts exists.
  3. 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.25 or ^4)
  • react-hook-form (^7)
  • react-day-picker (^9)
  • date-fns (^4)

The package manager is detected from your lockfile in this priority order:

  1. pnpm-lock.yamlpnpm add ...
  2. bun.lock or bun.lockbbun add ...
  3. yarn.lockyarn add ...
  4. 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.