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
| Argument | Description |
|---|---|
project-name | Optional. The name of the project to create. If omitted, you will be prompted. |
Options
| Flag | Description |
|---|---|
-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-git | Skip Git repository initialization. |
--skip-install | Skip dependency installation. |
--docker / --no-docker | Explicitly include or skip Docker container setup and Compose files. |
--k8s, --kubernetes / --no-k8s, --no-kubernetes | Explicitly 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-studio | Explicitly include or skip Prisma Studio GUI for database management. |
-y, --yes | Skip all prompts and use defaults (base template, best available package manager, Docker included, Prisma Studio included). |
-v, --verbose | Print detailed output for each step. |
Templates
Stackbase provides separate, dedicated standalone templates for each architecture:
| Template | Best For | Includes |
|---|---|---|
base | Complete application starter | Web (apps/web), API (apps/api), email preview (apps/email), Prisma Studio (apps/studio), all shared packages, Docker, Observability, and Kubernetes manifests |
web | Frontend-led products | Web app (apps/web), Prisma Studio (apps/studio), UI, auth, db, email, storage packages, and Docker |
api | Backend services | API (apps/api), Prisma Studio (apps/studio), db, auth, storage, contracts, rate-limit packages, Docker, and Observability |
fullstackis supported as a backwards-compatible alias forbase.
What init does internally
- Resolves the latest commit SHA on
mainfrom the GitHub API - this SHA becomes the baseline for future upgrades. - Downloads the selected template from
templates/<template>via archive download into a temporary directory (no.githistory). - Interactively presents template-aware optional feature prompts (Kubernetes and Observability are only offered for templates that contain those resources).
- Replaces Stackbase project identifiers with your project name across all relevant files.
- Cleans up CLI-specific fields from
package.json(bin,files,homepage,repository, etc.), strips unsupported optional scripts, and resetsversionto1.0.0. - Configures the chosen package manager (replaces catalog versions and
workspace:protocols if needed, updatespackageManagerfield, adjusts Dockerfiles). - Copies
.env.examplefiles to.env.local/.env.productionwith a shared generatedBETTER_AUTH_SECRET. - Deletes internal repository content and unselected optional feature files (e.g. Docker, Kubernetes, Observability, Studio).
- Writes a
.stackbase.jsonmanifest recording the commit SHA, canonical template (base,web, orapi), project name, optional feature selections, and a SHA-256 hash of every tracked file in its final post-mutation state. - Initialises a Git repository and creates the initial commit (unless
--no-gitis 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-installmigrate
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.
| Flag | Description |
|---|---|
--dry-run | Preview updates and conflicts without writing files or converting the manifest. |
--force | Use the latest Stackbase hashes as the baseline while keeping conflicting local files. |
-y, --yes | Skip 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
| Flag | Description |
|---|---|
--dry-run | Preview what would change without writing any files. |
--force | Advance to the latest commit, keeping your local edits and clearing current conflicts. |
-y, --yes | Skip 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:
| Value | Description |
|---|---|
savedHash | SHA-256 of the file at scaffold time, stored in .stackbase.json |
currentHash | SHA-256 of the file as it exists on disk right now |
newHash | SHA-256 of the file fetched from the latest GitHub commit, after applying init-time transforms |
The decision matrix:
| Situation | Result |
|---|---|
currentHash === newHash | Already in sync - skip |
currentHash === savedHash and newHash !== savedHash | Untouched since scaffold - auto-update |
newHash === savedHash and currentHash !== savedHash | Template unchanged, user edited - skip (your changes are kept) |
| All three differ | Both 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 to1.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 byinitwith project-specific contentpnpm-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,
.mapfiles, 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:
| Feature | Excluded when opted out |
|---|---|
| Docker | Production Dockerfiles, docker-compose.prod.yml, .dockerignore |
| Observability | docker-compose.observability.yml, deploy/observability/** |
| Kubernetes | k8s/**, deploy.sh |
| Studio | apps/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,
--forcenever 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 --forceExample 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
| Argument | Description |
|---|---|
file | Path 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.tsThe .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"
...
}
}| Field | Description |
|---|---|
version | Version of the manifest format. |
commit | The exact GitHub commit SHA the project was cloned from. Used as the base for all upgrade comparisons. |
template | The canonical template used at scaffold time (base, web, or api). Used by upgrade and diff to resolve the template path. |
projectName | Your project name in kebab-case. Used by upgrade to apply name replacements to fetched template content before comparison. |
scaffoldedAt | ISO timestamp of when init was run. Informational only. |
features | The optional feature flags (docker, kubernetes, studio, observability) selected during scaffolding. |
files | A 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 installLine 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.