open-form init
Scaffold a forms workspace with npm create open-form: forms, themes and agent skills, installed with the package manager you ran it with.
npm create open-form@latest my-formscreate-open-form runs
open-form init from @open-form-build/core with the arguments you pass. npm
needs -- before flags: npm create open-form@latest my-forms -- --no-git.
npx @open-form-build/cli init my-forms does the same.
Creates the workspace in my-forms, making the folder if it doesn't exist.
Without a directory, an interactive run asks for one (default my-forms); a
non-interactive run uses my-forms.
If the target isn't empty, an interactive run asks before writing and a
non-interactive run stops unless you pass --force. Only .git and
.DS_Store don't count, so a folder holding just a .env still asks.
Init never replaces a file you already have. It writes only the template files
that are missing and lists the ones it kept. An existing package.json keeps
its name, scripts and dependency versions; init only adds the scripts and
dependencies it lacks. The one exception is the built-in skills: init refreshes
them in .agents/skills/ and turns each .claude/skills/<name> into a link, as
sync:skills does.
Flags
| Flag | Default | Description |
|---|---|---|
-f, --force | off | Scaffold into a non-empty directory. |
-n, --name <name> | folder name | The package.json name, lowercased and made npm-safe. Without it, an existing package.json keeps its name. |
--pm <pm> | auto-detected | Package manager: pnpm, npm, yarn or bun. |
--database <database> | asks; sqlite without a terminal | Where responses are stored: sqlite or postgres. |
--vercel | asks after Postgres; off without a terminal | Add api/index.ts and vercel.json to deploy the whole project to Vercel. Implies --database postgres. |
--no-install | off | Skip installing dependencies. |
--no-git | off | Skip git init and the initial commit. |
The new package.json depends on @open-form-build/core: forms import from
it, and its open-form CLI runs the scripts.
Without --pm, init uses the package manager that launched it (from
npm_config_user_agent) and falls back to pnpm. Either way, init installs
with that package manager, prints the next steps for it, and writes its commands
into the new AGENTS.md, README.md and themes/README.md: npx open-form …
and npm run dev for npm, yarn open-form … and yarn dev for yarn,
bunx open-form … and bun run dev for bun. Any of those files you already had
stays as it is.
What it generates
my-forms/
├── forms/
│ └── contact/
│ └── index.tsx # a starter contact form
├── themes/
│ └── README.md # reference themes for new forms go here
├── .agents/
│ └── skills/ # the five agent skills
├── .claude/
│ └── skills/ # symlinks into .agents/skills/
├── open-form.config.ts # project config
├── AGENTS.md # agent rules
├── CLAUDE.md # symlink to AGENTS.md
├── README.md
├── package.json
├── tsconfig.json
├── .env, .env.example # --database postgres: the connection string, a placeholder
├── api/, vercel.json # --vercel: the Vercel Function and its routes
└── .gitignore # node_modules, dist, .open-form/, .env*, exported responses- Database — an interactive run asks where responses go: SQLite (a file
in
.open-form/, nothing to set up) or Postgres. For Postgres, init addspgtopackage.json, writes.env.examplewith a placeholderOPEN_FORM_DATABASE_URL, and asks for the connection string without echoing it. It goes into.envonly (owner-readable, ignored by git), never into a committed file; leave it empty to add it later. Without a terminal, init takes it fromOPEN_FORM_DATABASE_URLin the environment, if set. A.envthat already sets it is left alone. - Vercel — after Postgres, an interactive run asks whether you'll deploy
to Vercel (no by default). Yes, or
--vercel, writesapi/index.tsandvercel.jsonas in Vercel, addsapi/**/*totsconfig.jsonand.vercelto.gitignore, and ends with the environment variables to set in the Vercel project. Files you already have are kept.--vercelwith--database sqlitestops with an error: Vercel has no disk for SQLite. - Time zone — init writes your computer's time zone into
open-form.config.tsastimeZone(falling back toUTC), so form open and close dates mean the same in dev and in production. Change it if your forms run on another clock. - Install — runs
installwith the chosen package manager. If it fails, init prints the last lines of output and lists the install in the next steps. - Git —
git initand a first commit, unless the folder is already inside a repository (a package in a monorepo, for example) or git isn't installed; then init says nothing about git. If the commit fails, usually because git has nouser.nameoruser.email, init keeps the new repository and prints git's message. An existing.gitignorekeeps its rules; init only adds the lines it's missing. - On Windows,
CLAUDE.mdand the.claude/skills/entries are copies instead of symlinks.
After init
Init ends with the next steps for its package manager:
cd my-forms
npm run devcdis left out when you scaffold into the current folder. A path with spaces or other special characters is quoted, so you can paste the line as is.<pm> installis added before the last step when dependencies weren't installed: with--no-install, or when the install failed.- If an existing
package.jsonkept adevscript of its own, the last step is<exec> open-form devinstead (pnpm exec,npx,yarnorbunx).
Studio is at http://localhost:3000/studio. Then ask your agent: "Create a
registration form for our meetup."