StackbaseStackbase

Command Line Interface

Reference for all stackbase CLI commands - init, migrate, upgrade, and diff.

The stackbase CLI is the entry point for scaffolding new projects and keeping them in sync with the latest template. It is distributed as an npm package.

pnpm dlx stackbase@latest <command>

Run help command to see all available commands and options in the CLI.


Commands

init

Scaffolds a new project from the Stackbase template.

pnpm dlx stackbase@latest init [project-name] [options]

Arguments

ArgumentDescription
project-nameOptional. The name of the project to create. If omitted, you will be prompted.

Options

FlagDescription
-t, --template <type>Project template: base, web, or api (fullstack supported as alias). Defaults to base if --yes is set.
-p, --package-manager <manager>Package manager to use: pnpm, npm, or bun. Auto-detected from your environment if omitted.
--no-gitSkip Git repository initialization.
--skip-installSkip dependency installation.
--docker / --no-dockerExplicitly include or skip Docker container setup and Compose files.
--k8s, --kubernetes / --no-k8s, --no-kubernetesExplicitly include or skip Kubernetes deployment manifests and Ingress configuration.
--observability (--obs) / --no-observability (--no-obs)Explicitly include or skip Prometheus and Grafana observability stack (base and api).
--studio / --no-studioExplicitly include or skip Prisma Studio GUI for database management.
-y, --yesSkip all prompts and use defaults (base template, best available package manager, Docker included, Prisma Studio included).
-v, --verbosePrint detailed output for each step.

Templates

Stackbase provides separate, dedicated standalone templates for each architecture:

TemplateBest ForIncludes
baseComplete application starterWeb (apps/web), API (apps/api), email preview (apps/email), Prisma Studio (apps/studio), all shared packages, Docker, Observability, and Kubernetes manifests
webFrontend-led productsWeb app (apps/web), Prisma Studio (apps/studio), UI, auth, db, email, storage packages, and Docker
apiBackend servicesAPI (apps/api), Prisma Studio (apps/studio), db, auth, storage, contracts, rate-limit packages, Docker, and Observability

fullstack is supported as a backwards-compatible alias for base.

What init does internally

  1. Resolves the latest commit SHA on main from the GitHub API - this SHA becomes the baseline for future upgrades.
  2. Downloads the selected template from templates/<template> via archive download into a temporary directory (no .git history).
  3. Interactively presents template-aware optional feature prompts (Kubernetes and Observability are only offered for templates that contain those resources).
  4. Replaces Stackbase project identifiers with your project name across all relevant files.
  5. Cleans up CLI-specific fields from package.json (bin, files, homepage, repository, etc.), strips unsupported optional scripts, and resets version to 1.0.0.
  6. Configures the chosen package manager (replaces catalog versions and workspace: protocols if needed, updates packageManager field, adjusts Dockerfiles).
  7. Copies .env.example files to .env.local / .env.production with a shared generated BETTER_AUTH_SECRET.
  8. Deletes internal repository content and unselected optional feature files (e.g. Docker, Kubernetes, Observability, Studio).
  9. Writes a .stackbase.json manifest recording the commit SHA, canonical template (base, web, or api), project name, optional feature selections, and a SHA-256 hash of every tracked file in its final post-mutation state.
  10. Initialises a Git repository and creates the initial commit (unless --no-git is specified).

Examples

# Interactive - prompts for name, template, package manager, etc.
pnpm dlx stackbase@latest init

# Non-interactive base (full-stack) project with default flags
pnpm dlx stackbase@latest init my-app --yes

# Frontend-only project with Bun runtime
pnpm dlx stackbase@latest init my-web -t web -p bun

# Backend API with observability and no Docker
pnpm dlx stackbase@latest init my-api -t api --observability --no-docker

# Fully automated CI/CD scaffold with explicit feature flags
pnpm dlx stackbase@latest init my-app -t base -p pnpm --docker --k8s --obs --studio --no-git

# Scaffold without installing dependencies
pnpm dlx stackbase@latest init my-app --skip-install

migrate

Moves a project created with Build Elevate onto the Stackbase release line.

pnpm dlx stackbase@latest migrate [options]

Run the command from a project root containing .build-elevate.json. It converts the legacy manifest, updates unchanged files, and preserves local edits as conflicts.

FlagDescription
--dry-runPreview updates and conflicts without writing files or converting the manifest.
--forceUse the latest Stackbase hashes as the baseline while keeping conflicting local files.
-y, --yesSkip the confirmation prompt.

See Migrate from Build Elevate for the complete workflow, conflict handling, verification, and backup cleanup.


upgrade

Upgrades your scaffolded project to the latest Stackbase template.

pnpm dlx stackbase@latest upgrade [options]

This command must be run from the root of a project that was scaffolded with Stackbase or migrated from Build Elevate. It requires a .stackbase.json manifest. Follow the migration guide when the project contains only .build-elevate.json.

Options

FlagDescription
--dry-runPreview what would change without writing any files.
--forceAdvance to the latest commit, keeping your local edits and clearing current conflicts.
-y, --yesSkip confirmation prompts.

How upgrade works

The upgrade command uses a commit SHA + file hash strategy to determine what is safe to update automatically.

For each tracked file, it compares three values:

ValueDescription
savedHashSHA-256 of the file at scaffold time, stored in .stackbase.json
currentHashSHA-256 of the file as it exists on disk right now
newHashSHA-256 of the file fetched from the latest GitHub commit, after applying init-time transforms

The decision matrix:

SituationResult
currentHash === newHashAlready in sync - skip
currentHash === savedHash and newHash !== savedHashUntouched since scaffold - auto-update
newHash === savedHash and currentHash !== savedHashTemplate unchanged, user edited - skip (your changes are kept)
All three differBoth you and the template changed this file - conflict

Files that are conflicts are listed with a message directing you to stackbase diff <file>.

Init-time transforms

Before comparing or writing, upgrade applies the same transformations that init ran after downloading the template:

  • Project name replacement (all case formats)
  • Docker Hub registry username cleanup (Kubernetes manifests)
  • package.json - CLI fields removed, unselected feature scripts stripped, version reset to 1.0.0
  • Dockerfiles - package manager adjustments

This ensures that fetched template content is directly comparable to your post-init files, eliminating false conflicts on these files.

Files never upgraded

The following are always skipped regardless of changes:

  • .env, .env.local, .env.production, .env.development - secrets, user-owned
  • .env.example - intentionally upgradeable (see below)
  • README.md - rewritten by init with project-specific content
  • pnpm-lock.yaml, bun.lockb, package-lock.json - regenerated by package manager
  • .stackbase.json - the manifest itself
  • Internal repository files outside the template directory
  • Binary and generated files (images, fonts, .map files, etc.)

.env.example is upgraded when the template changes it - it contains no secrets and serves as documentation for required environment variables.

Template-aware filtering

Upgrade compares files against the exact template recorded in your manifest (templates/base, templates/web, or templates/api). Files belonging to optional features you opted out of (Docker, Kubernetes, Observability, Studio) are never added back:

FeatureExcluded when opted out
DockerProduction Dockerfiles, docker-compose.prod.yml, .dockerignore
Observabilitydocker-compose.observability.yml, deploy/observability/**
Kubernetesk8s/**, deploy.sh
Studioapps/studio/**

Manifest and conflict tracking

The .stackbase.json manifest commit pointer is only advanced when all conflicts are resolved. If conflicts remain after a run, the manifest keeps the old commit SHA so that stackbase diff can still show what needs to be applied.

Once you manually resolve all conflicts and re-run upgrade with no new conflicts, the commit pointer advances to the latest.

Forcing past conflicts with --force

If you've customized files that the template also changes, those files stay conflicts on every run and the commit pointer never advances. --force breaks out of that loop without losing your edits:

  • Your conflicting files on disk are left untouched, --force never overwrites them.
  • For each conflict, the manifest base hash is set to the template's latest newHash (the template content is not written to disk), and the commit pointer advances to the latest.
  • The current conflicts stop being reported. Because the recorded base now differs from your file (currentHash !== savedHash), the file is treated as edited-by-you and is protected from auto-update. It only re-appears as a conflict if the template changes that same file in a future release.

Crucially, the base is set to the template's hash, not a re-hash of your file. Recording your file's hash would make the next upgrade see the file as "untouched since scaffold" and silently auto-overwrite your edits, --force deliberately avoids that.

--force is non-destructive: it changes the manifest, never your files. Review what was force-advanced with git diff and re-apply any template changes you want by hand. Combine with --dry-run to preview first.

Examples

# Preview changes without writing
pnpm dlx stackbase upgrade  --dry-run

# Apply upgrade
pnpm dlx stackbase upgrade

# Apply upgrade, skip prompts
pnpm dlx stackbase upgrade  --yes

# Advance to latest past conflicts, keeping your local edits
pnpm dlx stackbase upgrade  --force

Example output

┌  stackbase upgrade
│
◇  Current: d55f5fa  →  Latest: 6669a80
│
◆  Auto-updated 8 file(s):
│    ✔ apps/web/next.config.ts
│    ✔ turbo.json
│    ✔ packages/auth/src/server.ts
│    ...
│
◆  Added 1 new file(s) from template:
│    + packages/auth/.env.example
│
▲  1 file(s) were modified by you and could not be upgraded automatically:
│
│    ⚠ apps/api/src/config/corsOptions.ts
│
│  Run `stackbase diff <file>` to see exactly what changed in the template.
│
└  Upgraded to 6669a80 with 1 conflict(s) to resolve manually.

diff

Shows a colored line-by-line diff of what changed in the Stackbase template for a specific file between your scaffolded commit and the latest.

pnpm dlx stackbase diff <file>

This command shows changes in the template, not in your local file. Use it to understand what you need to manually apply to a file that was listed as a conflict by upgrade.

Arguments

ArgumentDescription
filePath to the file relative to the project root. Accepts Windows (\) and Unix (/) separators.

How to read the diff

--- apps/api/src/config/corsOptions.ts (d55f5fa)
+++ apps/api/src/config/corsOptions.ts (6669a80)

    3 | import { env } from "../env";
-   4 | const allowedOrigins = [env.ALLOWED_ORIGINS];
+   4 | const allowedOrigins = env.ALLOWED_ORIGINS.split(",");
    5 |

1 insertions(+), 1 deletion(-)
  • Lines marked - were removed from the template
  • Lines marked + were added to the template
  • Context lines (dimmed) are unchanged
  • The summary line shows total insertions and deletions across the whole file, even if the displayed diff is truncated

When there are no template changes

If the template did not modify the file between your commit and the latest, the command tells you so:

No template changes to apps/api/src/config/corsOptions.ts between d55f5fa and 6669a80.
The template did not touch this file - your local changes are yours to keep.

This is expected behaviour, it means the file was listed as modified by you, but the template never changed it, so there is nothing to apply.

Examples

# Show what changed in the template for next.config.ts
pnpm dlx stackbase diff apps/web/next.config.ts

# Windows paths work too
pnpm dlx stackbase diff .\apps\web\next.config.ts

The .stackbase.json manifest

The manifest is written by init and read by upgrade and diff. It is committed to your repository and should never be added to .gitignore.

{
  "version": 2,
  "commit": "6669a80f3c2d1a4b5e6f7a8b9c0d1e2f3a4b5c6d",
  "template": "base",
  "projectName": "my-app",
  "scaffoldedAt": "2026-03-23T10:00:00.000Z",
  "features": {
    "docker": true,
    "kubernetes": true,
    "studio": true,
    "observability": true
  },
  "files": {
    "turbo.json": "a3f8c2d1b4e5",
    "package.json": "b7e4a10912f3",
    "apps/web/next.config.ts": "c1d2e3f4a5b6"
    ...
  }
}
FieldDescription
versionVersion of the manifest format.
commitThe exact GitHub commit SHA the project was cloned from. Used as the base for all upgrade comparisons.
templateThe canonical template used at scaffold time (base, web, or api). Used by upgrade and diff to resolve the template path.
projectNameYour project name in kebab-case. Used by upgrade to apply name replacements to fetched template content before comparison.
scaffoldedAtISO timestamp of when init was run. Informational only.
featuresThe optional feature flags (docker, kubernetes, studio, observability) selected during scaffolding.
filesA map of file paths to their SHA-256 hashes (first 12 characters) at scaffold time, after all init-time mutations. This is what upgrade compares against.

During an incomplete Build Elevate migration, the manifest also contains "source": "build-elevate". Stackbase removes this field after the commit pointer reaches a Stackbase commit.

If your manifest is missing the projectName field (projects scaffolded before v1.2.0), upgrade will exit with an error. Add "projectName": "your-project-name" manually to .stackbase.json to resolve this.


Upgrade workflow

The recommended flow for keeping your project up to date:

# 1. Check what would change
pnpm dlx stackbase upgrade  --dry-run

# 2. Apply the upgrade
pnpm dlx stackbase upgrade

# 3. For each conflict listed, inspect the template diff
pnpm dlx stackbase diff apps/api/src/config/corsOptions.ts

# 4. Manually apply the relevant changes to your file

# 5. Re-run upgrade - with conflicts resolved, the manifest advances
pnpm dlx stackbase upgrade

# 6. Install updated dependencies
pnpm install

Line endings on Windows

On Windows, Git may check out files with CRLF line endings while GitHub always serves LF. The CLI normalizes line endings to LF before hashing, so file comparisons are consistent across platforms.

On this page