CLI

Compatibility Rules

Understanding compatibility rules and restrictions between different CLI options

Overview

The CLI validates option combinations to ensure generated projects are coherent. Validation happens in two places:

  1. Per-language value checks — framework, orm, migrations, and frontend must belong to the selected language's option set.
  2. Resolved-config checks — after prompts (or with --yes), the fully-resolved stack is validated again.

--yolo skips the compatibility checks entirely.

Per-language option sets

Each language has its own option sets (packages/types), so a Go/Rust value can never leak into a Python stack:

CategoryPythonGoRust
frameworkfastapi, litestar, django, flaskgin, fiber, echo, chi, stdlibaxum, actix-web, rocket, warp, salvo, loco
frontendhtmx, nonehtmx, nonehtmx, none
ormsqlmodel, sqlalchemy, tortoise, nonesqlc, gorm, sqlx, noneseaorm, diesel, sqlx-rust, none
migrationsalembic, nonegoose, golang-migrate, nonenone
databasesqlite, postgres, mysql, nonesamesame
packageManageruv, poetry, pipgocargo
addonsdocker, ruff, mypy, pytest, github-actions, nonedocker, air, golangci-lint, github-actions, nonedocker, cargo-watch, clippy, github-actions, none

Status: Python, Go, and Rust scaffolds are all generated today.

What gets validated today

  • framework not in the language's set → error, e.g. --language python --framework gin
  • frontend not in the language's set → error
  • frontend htmx with framework none → error (HTMX needs a backend to serve the rendered pages)
  • frontend htmx with framework loco (Rust) → error (Loco doesn't support HTMX yet)
  • orm not in the language's set → error, e.g. --language python --orm seaorm
  • migrations not in the language's set → error, e.g. --language python --migrations goose
  • addons passed as a list must be valid enum values; none is normalized away
  • database must be one of sqlite, postgres, mysql, none
# ❌ Invalid - Gin is not a Python framework
uvx tristack --language python --framework gin

# ✅ Valid
uvx tristack --language python --framework fastapi

# ❌ Invalid - SeaORM is a Rust ORM
uvx tristack --language python --orm seaorm

# ✅ Valid
uvx tristack --language python --orm sqlmodel

# ✅ Valid - Rust stack (standalone binary)
tristack my-api --language rust --framework axum --orm seaorm

Validation order

The CLI validates resolved configs in this order:

  1. Flag input validation: valid enum values, project-name rules (see below)
  2. Per-language value checks: framework/orm/migrations/frontend belong to the language
  3. Path checks: target directory must be within the current directory and not a symlink (unless --directory-conflict increment)

Project name rules

  • Cannot be empty or longer than 255 characters
  • Cannot start with . (except . itself) or -
  • Cannot contain <, >, :, ", |, ?, *
  • node_modules is reserved

Roadmap

Cross-option rules are planned alongside each language's rollout — for example Django bundling its own ORM and migrations (hiding those prompts entirely), Loco narrowing Rust ORM choices, and Chi/stdlib surfacing assemble-it-yourself addons more prominently.

Understanding these rules helps you create valid configurations and troubleshoot issues when the CLI reports compatibility errors.

On this page