grit setup creates a new project the way an installer does. It asks for a starter and for the services the project will use, then runs the steps that make the result runnable: dependencies, local services, migrations, sample data, the first commit.

It is not grit new with questionsgrit new is the fast, scriptable scaffold and its behaviour is frozen, so a build script that runs it keeps working. grit setup is the guided path, and it can ask questions and change what the project starts with. Keeping them apart is why a change to one cannot surprise somebody relying on the other. Setup only creates new projects; use grit upgrade on one that exists.

Quick start

Terminal
$grit setup myapp

The wizard asks for:

  • the architecture: single, double, triple, desktop, api, mobile or full
  • the frontend: Next.js or TanStack Router, when the shape has one
  • the starter: blank or blog
  • the database: Postgres, MySQL, SQLite or in-memory
  • Redis, storage and mail: local, external or off
  • the built-in plugins that fit the chosen shape
  • whether to run grit start at the end

Starters

A starter is the example content the project begins with. Both are the same scaffold:blank is that scaffold with the built-in Blog example removed, and blog keeps it exactly as grit new writes it. There is no separate template repository, so a starter cannot fall behind the scaffold.

An api or mobile project always starts blank: it has no web or admin pages for the Blog's screens to live on.

A blank project's edited filesRemoving the Blog means editing a handful of files the scaffold owns: the nav menu, the seeder, the landing page. Those files then read as edited, so grit upgrade leaves them alone and reports them. That is deliberate: the templates still contain the Blog, so an upgrade that rewrote them would put the Blog links back, pointing at pages the starter removed. The trade is a handful of files that stop receiving framework fixes, and grit upgrade --diff shows what you are missing in them.

Non-interactive use

Pass --yes with the answers as flags. This is the shape for CI and scripts, and a project name is required. Setup refuses to prompt when it has no terminal, rather than hanging.

Terminal
$grit setup myapp --yes \
$ --arch triple --frontend next --starter blank \
$ --db sqlite --redis off --storage local --mail log \
$ --no-docker --no-git --no-start

Services

Redis, storage and mail are written into .env. Each one can point at a local container, at an external provider, or be off.

Terminal
# Local, started with docker compose
$grit setup myapp --redis local --storage minio --mail mailhog
# External
$grit setup myapp --redis external --redis-url redis://...
$grit setup myapp --storage s3 --storage-endpoint ... --storage-access-key ... --storage-secret-key ...
$grit setup myapp --mail resend --mail-api-key ...
# Off
$grit setup myapp --redis off --storage local --mail log

Credentials go into .env, which setup writes with owner-only permissions because it now holds real values rather than placeholders. No external secret is printed back to the terminal.

What it runs

  1. Scaffolds the project with the chosen architecture, frontend and theme.
  2. Applies the starter.
  3. Configures .env for Redis, storage and mail.
  4. Installs the built-in plugins that fit the shape.
  5. Installs dependencies and tidies the Go module.
  6. Starts local services with Docker, unless --no-docker.
  7. Migrates the database and seeds sample data.
  8. Initialises git and makes the first commit.
  9. Offers to run grit start.

Every step after the scaffold is a command you could run by hand, and when one fails setup prints that command rather than stopping with nothing to do next. A failed pnpm install does not cost you the migration or the first commit: neither needs node.

Flags

FlagMeaning
--archsingle, double, triple, desktop, api, mobile or full
--frontendnext or tanstack
--starterblank or blog
--dbpostgres, mysql, sqlite or memory
--themeatlas, aurora, pulse, coral, amber, sky, mono or emerald
--redislocal, external or off
--redis-urlExternal Redis URL
--storageminio, s3, r2, local or off
--storage-*S3 or R2 endpoint, keys, bucket, region and public URL
--mailmailhog, log, resend, mailgun, postmark, sendgrid, ses or smtp
--mail-*From address, API key, domain, endpoint and stream
--smtp-*SMTP host, port, username, password and encryption
--ses-region, --aws-*Amazon SES region and credentials
--pluginA built-in plugin to install; repeat or comma-separate
--i18nAdd internationalisation
--yesUse the flags and defaults, with no prompts
--hereScaffold into the current directory
--forceAllow scaffolding into a directory that is not empty
--no-installSkip pnpm install
--no-dockerDo not start local services
--no-migrateSkip migrations
--no-seedSkip sample data
--no-gitSkip git init and the first commit
--starStar MUKE-coder/grit without asking
--start, --no-startRun, or do not run, grit start at the end

The logins it prints

The closing summary lists what the project exposes, with the login for each:

GORM Studio http://localhost:8080/studio | admin / <generated>
Sentinel http://localhost:8080/sentinel/ui | admin / <generated>
Admin http://localhost:3001 | admin@example.com / admin123

GORM Studio and Sentinel get a generated local password each. The admin password is admin123 in development unless SEED_ADMIN_PASSWORD is set, and when it is set setup says so rather than echoing it. All of these are development credentials. Change them before production.

If the seed step was skipped, no admin login is shown: run grit seed to create it.

Contributedgrit setup was contributed by daljo25 in #170.

Something wrong, unclear, or missing on this page?

Open an issue: your feedback shapes Grit, and we fix docs fast.

Raise an issue on GitHub