CLI

The Strav CLI (strav) provides commands for migrations, code generation, package management, and database management.

Running commands

bun strav <command> [options]
The CLI entry point is strav.ts at the project root.

Available commands

generate:migration

Generates migration files by diffing your schemas against the live database.

bun strav generate:migration
bun strav generate:migration -m "add user roles"
bun strav generate:migration --scope public -m "add public schema tables"
Options:
  • -m, --message <message> — Migration description (default: 'migration').
  • -s, --scope <scope> — Domain to target (default: 'public'). Supports multi-domain database architectures.
What it does:
  • Loads all schemas from database/schemas/.
  • Introspects the live database.
  • Computes the diff (new tables, altered columns, new indexes, etc.).
  • Writes migration files to database/migrations/<timestamp>_<message>/.

migrate

Applies all pending (unapplied) migrations.

bun strav migrate
bun strav migrate --scope public
Migrations are applied in order and grouped into a batch. Each run creates a new batch number. Options:
  • -s, --scope <scope> — Domain to migrate (default: 'public').

rollback

Reverts migrations by batch.

bun strav rollback              # roll back the last batch
bun strav rollback --batch 3    # roll back batch 3 specifically
bun strav rollback --scope public
Options:
  • --batch <number> — Target a specific batch.
  • -s, --scope <scope> — Domain to rollback (default: 'public').

compare

Prints a read-only diff between your schemas and the live database. Does not modify anything.

bun strav compare

Output is color-coded:

  • Green — new items to create.
  • Red — items to drop.
  • Yellow — items to modify.

fresh

Destructive reset — drops everything and rebuilds from scratch.

bun strav fresh
Safety checks:
  • Requires APP_ENV=local.
  • Prompts for a random 6-digit confirmation code.
What it does:
  • Drops all tables (DROP TABLE ... CASCADE).
  • Drops all enum types.
  • Deletes all migration files.
  • Generates a fresh migration from current schemas.
  • Runs the new migration.

generate:models

Generates TypeScript model classes and enum files from your schema definitions. Does not require a database connection.

bun strav generate:models
Output directories are configured via config/generators.ts (see the Generators guide). What it produces:
  • app/models/<entity>.ts — Model class extending BaseModel with decorators, typed properties, and relationships.
  • app/enums/<entity>.ts — TypeScript enum definitions extracted from schema enum fields.
  • app/models/index.ts — Barrel export for all model classes.
  • app/enums/index.ts — Barrel export for all enum types.
Generated files are marked // Generated by Strav -- DO NOT EDIT.

generate:api

Generates the full application layer from your schema definitions: event constants, validators, policies, services, and controllers. Does not require a database connection.

bun strav generate:api
Output directories are configured via config/generators.ts (see the Generators guide). What it produces (per non-association schema):
  • app/events/<entity>.ts — Event constant object (e.g., UserEvents.CREATED).
  • app/validators/<entity>_validator.ts — Validation rule sets for store and update.
  • app/policies/<entity>_policy.ts — Policy class skeleton with archetype-specific methods.
  • app/services/<entity>_service.ts — Service class wrapping model CRUD + event dispatch.
  • app/http/controllers/<entity>_controller.ts — Controller with route handlers (validate → service → response).
  • start/api_routes.ts — Route file wiring all controllers to the router.
  • Barrel index.ts files for each output directory.
Generated files are archetype-aware — event schemas get append instead of create, component schemas omit store/destroy, etc.

generate:key

Generates a cryptographic application key and writes it to your .env file.
bun strav generate:key
bun strav generate:key --force
Options:
  • -f, --force — Overwrite an existing APP_KEY value.
If .env doesn't exist, it creates the file. If APP_KEY is already set, the command warns and exits unless --force is passed.

install

Copies config and schema stubs from a @strav/* package into your project.
bun strav install social
bun strav install @strav/social   # full name also works
bun strav install social --force       # overwrite existing files
Options:
  • -f, --force — Overwrite existing files instead of skipping them.
What it does:
  • Resolves the package root (checks node_modules/ first, then Bun workspace resolution).
  • Looks for a stubs/ directory inside the package.
  • Copies stubs/config/*.ts./config/.
  • Copies stubs/schemas/*.ts./database/schemas/.
  • Skips files that already exist (yellow warning) unless --force is passed.
Any @strav/* package can ship stubs by including a stubs/ directory with config/ and/or schemas/ subdirectories. No manifest or registration is needed.

seed

Seeds the database with records using seeder classes from database/seeders/.
bun strav seed
bun strav seed --class UserSeeder
bun strav seed --fresh
Options:
  • -c, --class <name> — Run a specific seeder instead of the default DatabaseSeeder.
  • --fresh — Drop all tables and re-migrate before seeding (requires APP_ENV=local).
What it does:
  • Bootstraps config, database, and wires the ORM.
  • If --fresh, runs the full fresh pipeline (without the interactive challenge).
  • Resolves the seeder file (default: database/seeders/database_seeder.ts).
  • Instantiates and runs the seeder.
The default seeder is DatabaseSeeder, which typically chains sub-seeders via this.call(). See the Database guide for full documentation.

generate:seeder

Scaffolds a database seeder class.

bun strav generate:seeder DatabaseSeeder
bun strav generate:seeder UserSeeder
bun strav generate:seeder User             # also works — "Seeder" suffix is added
Options:
  • -f, --force — Overwrite an existing file.
Output: database/seeders/<snake_case>_seeder.ts with a Seeder subclass skeleton.

queue:work

Start a worker process to pick up and run queued jobs.

bun strav queue:work
bun strav queue:work --queue emails --sleep 500
Options:
  • --queue <name> — Queue to process (default: 'default').
  • --sleep <ms> — Poll interval in milliseconds (default: 1000).

Press Ctrl+C to stop the worker gracefully (finishes current job before exiting).

queue:retry

Move failed jobs back to the queue for reprocessing.

bun strav queue:retry
bun strav queue:retry --queue emails
Options:
  • --queue <name> — Only retry failed jobs from this queue.

queue:flush

Delete pending jobs from a queue.

bun strav queue:flush
bun strav queue:flush --queue emails
bun strav queue:flush --failed
Options:
  • --queue <name> — Queue to flush (default: 'default').
  • --failed — Also clear failed jobs.

Custom commands

Create your own CLI commands by adding .ts files to a commands/ directory at the project root. Each file must export a register(program) function:
// commands/deploy.ts
import type { Command } from 'commander'

export function register(program: Command): void {
  program
    .command('deploy')
    .description('Deploy the application')
    .option('-e, --env <environment>', 'Target environment', 'production')
    .action(async ({ env }) => {
      console.log(`Deploying to ${env}...`)
      // your deployment logic
    })
}
bun strav deploy --env staging

Commands are auto-discovered on startup — no registration needed.

Package commands

Installed @strav/* packages can provide their own CLI commands. A package declares its commands directory in package.json:
{
  "name": "@strav/search",
  "strav": {
    "commands": "src/commands"
  }
}
Each .ts file in that directory must export a register(program) function, following the same convention as user commands. The CLI discovers these automatically from node_modules/ and Bun workspace packages. For example, @strav/search provides search:import and search:flush commands. See the Search guide for details.

Bootstrap

CLI commands that need a database connection use a shared bootstrap function:

import { bootstrap, shutdown } from '@strav/cli'

export function register(program: Command): void {
  program.command('my:command').action(async () => {
    let db
    try {
      const { db: database, config, registry, introspector } = await bootstrap()
      db = database

      // ... command logic ...
    } finally {
      if (db) await shutdown(db)
    }
  })
}

The bootstrap:

  • Loads configuration from ./config.
  • Connects to the database.
  • Discovers and validates schemas.
  • Creates the database introspector.

Typical workflow

# 1. Define or modify schemas in database/schemas/
# 2. Compare against the database
bun strav compare

# 3. Generate migration files
bun strav generate:migration -m "add teams"

# 4. Apply the migration
bun strav migrate

# 5. Regenerate model classes
bun strav generate:models

# 6. Generate the application layer (services, controllers, policies, validators, events)
bun strav generate:api

# 7. Seed dev data (optional)
bun strav seed

# Full reset: drop + migrate + seed in one command
bun strav seed --fresh