create-turbo-stack

Project Config

Customize the CLI per-project with create-turbo-stack.json

CLI config — defaults, policy, plugins, registries, conflict policy — lives in one place per project: the config block of .turbo-stack.json. So a project needs a single file. An out-of-project create-turbo-stack.json (walked up from cwd) or the global ~/.create-turbo-stack/config.json is optional, for org/team defaults shared across repos; the project's config block wins on overlap.

WhereOwnerPurpose
.turbo-stack.json configYou (in the project)This project's config — the common case
create-turbo-stack.jsonYou (team/external)Org defaults shared across repos (optional)
~/.create-turbo-stack/config.jsonYou (machine global)Personal defaults (optional)

The rest of .turbo-stack.json (resolved preset, catalog, …) is CLI-managed — don't hand-edit it; the config block is yours to edit.

Shape

The same UserConfigSchema applies whether it's the config block of .turbo-stack.json or a standalone create-turbo-stack.json:

{
  "$schema": "https://create-turbo-stack.dev/schema/user-config.json",
  "defaults":       { /* ... */ },
  "policy":         { /* ... */ },
  "plugins":        ["@scope/cts-plugin"],
  "registries":     { "@acme": { /* ... */ } },
  "conflictPolicy": "prompt"
}

defaults

Pre-fill prompt initial values. Anything not set falls back to the schema default.

{
  "defaults": {
    "basics": {
      "scope": "@acme",
      "packageManager": "pnpm",
      "linter": "biome",
      "typescript": "strict",
      "gitInit": true
    },
    "database":   { "strategy": "drizzle" },
    "api":        { "strategy": "trpc" },
    "auth":       { "provider": "better-auth" },
    "css":        { "framework": "tailwind4", "ui": "shadcn" },
    "integrations": {
      "errorTracking": "sentry",
      "envValidation": true
    }
  }
}

policy

Three-mode constraint: allow whitelists, forbid blacklists, require locks the value entirely (no prompt).

{
  "policy": {
    "allow":   { "auth": ["clerk", "better-auth"] },
    "forbid":  { "css":  ["vanilla", "css-modules"] },
    "require": {
      "typescript": "strict",
      "envValidation": true,
      "packageManager": "pnpm",
      "database": "drizzle"
    }
  }
}

allow + forbid apply to the same enum at prompt time (forbid wins on overlap). require removes the prompt and forces the value — useful for compliance ("typescript strict everywhere", "we use Drizzle, period").

After a preset is fully assembled — interactive, --preset, or add/remove/switch — it's checked against policy a second time. Violations abort the operation.

plugins

npm package names whose default export contributes registry entries.

{ "plugins": ["cts-plugin-nuxt", "@acme/cts-internal"] }

The CLI imports each plugin at startup and registers its default export. See Plugins.

registries

Namespaced package registries for cts add @ns/<name> (see Registry Packages). A bare string is the URL template; the object form adds auth headers / query params and an Ed25519 publicKey to verify signatures. ${VAR} placeholders resolve from the environment (and the project's .env / .env.local) at request time, so tokens never live in the file.

{
  "registries": {
    "@acme": {
      "url": "https://store.acme.com/r/{name}",
      "headers": { "Authorization": "Bearer ${ACME_TOKEN}" },
      "publicKey": "<base64 SPKI>"
    }
  }
}

conflictPolicy

How applyDiff handles files you've hand-edited since the last scaffold: prompt (default, interactive), keep, overwrite, or abort. Set it so CI / MCP / scripted runs don't deadlock on the prompt.

{ "conflictPolicy": "keep" }

Global config

Optional. ~/.create-turbo-stack/config.json has the same shape; project values override on overlap. Useful for "always use my org's scope" preferences without committing them to every repo.

Discovery

create-turbo-stack list shows everything that's currently registered, including plugin-provided entries. Use it to confirm a plugin loaded after editing create-turbo-stack.json.

On this page