Skip to content

feat: add a non-interactive seamless init - #156

Merged
Bccorb merged 1 commit into
mainfrom
feat/init-non-interactive
Aug 1, 2026
Merged

feat: add a non-interactive seamless init#156
Bccorb merged 1 commit into
mainfrom
feat/init-non-interactive

Conversation

@Bccorb

@Bccorb Bccorb commented Aug 1, 2026

Copy link
Copy Markdown
Contributor

Closes #152. Part of #154. Stacked on #155, review that first (this PR's diff is only its own commit).

The core item on the feedback list: init had no flag form for email, auth mode, or admin mode, so it could not run from CI, a Dockerfile, or a script without allocating a pty. The workaround was an expect script, which required knowing the prompt order, which required reading the source.

seamless init my-app --local --yes --email=you@example.com

Flags

--yes (-y) answers every remaining question with the option its prompt marks (recommended). Each question also gets its own flag, honored with or without --yes:

Flag Question Default under --yes
--web=<id|alias> Web example first selectable web template
--api=<id|alias> Backend framework first selectable api template
--email=<address> Owner email (becomes the admin) required
--auth=<docker|local> How the auth server runs docker
--admin=<api|image|source|none> Where the console is hosted api

The template defaults come from registry order rather than a hardcoded id, so they stay a registry concern. Values are validated in runCLI (against the registry for --web/--api, against the mode lists for --auth/--admin) before a directory is created, so a bad value never leaves a husk behind.

What --yes will not decide

Three things it stops on instead of guessing:

  • Managed or local, with a portal session and neither --local nor --app <id>. That decides where the project's auth lives for good.
  • Scaffolding into a non-empty directory. Starter files overwrite anything with the same name; that takes --force. The comment in initMode.ts already said the option hint is not consent, and a blanket "assume yes" is not either.
  • Rotating an application's existing service token, which invalidates the old one and breaks whatever is deployed on it. Also --force.

A template that would prompt for OAuth provider credentials is scaffolded with none configured (there is no flag form for a per-provider secret) and says so.

Parsing

init's argument handling moves out of the dispatcher into parseInitArgs. The old code treated every -- argument that was not --local as a template alias, so any new switch would have been read as a template name.

Checks

npm run build and npm test pass (781 passed, 4 skipped). Smoke-tested end to end with stdin closed: a full scaffold with no prompts, plus each guard rail (missing --email, non-empty directory without --force, bad --admin value) failing with the right message and leaving nothing on disk.

`--yes` (-y) answers every question with the option the prompt marks as
recommended, so a scaffold runs from CI, a Dockerfile, or a script with no
terminal attached. Each question also gets its own flag, honored with or without
--yes: --web and --api choose the starters (by id or alias), --email sets the
owner who becomes the admin, --auth picks how the auth server runs, and --admin
picks where the console is hosted. Values are validated against the registry and
the known modes in runCLI, before a directory is created.

--yes stops rather than guessing in three places. Managed or local needs --app
or --local, because that decides where the project's auth lives for good.
Scaffolding into a non-empty directory needs --force, because starter files
overwrite anything with the same name. Rotating an application's existing
service token needs --force, because it breaks whatever is deployed on the old
one.

init's argument parsing moves into parseInitArgs so the new switches are not
mistaken for template flags or for the project name.

Closes #152
Base automatically changed from feat/init-flag-ergonomics to main August 1, 2026 04:00
@Bccorb
Bccorb merged commit 5d56fb5 into main Aug 1, 2026
2 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

feat: non-interactive seamless init --yes with full flag coverage

1 participant