Toast
Contributor

Toast Dev CLI (td)

Inspection, scaffolding, and development lifecycle management for the Toast codebase.

td is the Toast developer CLI. It solves two problems that make development friction worse over time:

  1. Agent blindness — agents and developers can't see the database schema without reading source files, can't inspect errors without hunting logs, and can't verify PR previews without manual curl commands.
  2. The scaffolding gap (pre-td) — before generators, every new feature required manual route/service/repo/test scaffolding, and it was easy to miss the siteId multi-tenancy requirement.

td is the Toast equivalent of Laravel's Artisan. It lives in packages/td and is never published — it's internal dev tooling only.

# Quick start
td status          # What's running, what port, what environment
td schema          # Live database schema: tables, columns, types, FKs
td generate feature newsletters   # Scaffold a complete feature in seconds

Generators

This is the most important td capability. Generators scaffold most of the API boilerplate in the right directories with correct imports pre-wired and the multi-tenancy requirement baked in.

td generate feature <name>

Generates a full API feature scaffold: contract stub, repository, service, controller, route definitions, schemas, and tests.

td generate feature newsletters

Creates:

shared/contracts/src/newsletters.ts          # Contract stub
apps/api/src/repositories/newsletters.repository.ts
apps/api/src/services/newsletters.service.ts
apps/api/src/routes/newsletters/
├── routes.ts
├── newsletters.controller.ts
├── schemas.ts
└── index.ts

Also:

  • Wires barrel exports in apps/api/src/routes/index.ts, apps/api/src/services/index.ts, and apps/api/src/repositories/index.ts
  • Updates shared/contracts/package.json exports
  • Prints a checklist of what still needs filling in

The repository template includes siteId scoping. You still need to add any table changes in shared/db/src/schema.ts and wire the new stack through container.ts, index.ts, and app.ts.

td generate migration <name>

Creates a migration SQL stub with a timestamp-based prefix:

td generate migration add-newsletters-table
# → shared/db/migrations/20260323230155_add-newsletters-table.sql

td generate event <name>

Scaffolds a typed domain event and handler stub:

td generate event newsletter-created
# → updates apps/api/src/events/domain-events.ts

td generate driver <type> <name>

Scaffolds an implementation skeleton for a Toast driver interface:

td generate driver email resend
# → drivers/email-resend/src/index.ts

Inspection

Some inspection commands support remote environment or PR preview flags. Check td <command> --help for the exact surface area of each command.

td status

What's running, on which port, in which environment. Solves the worktree port problem — agents and developers shouldn't need to guess.

td status
# ✓ API         http://localhost:3101  (worktree: frameworkisation)
# ✓ Admin       http://localhost:5175
# ✓ PostgreSQL  localhost:5433
# ✓ MinIO       localhost:9002

td schema

Live database schema: tables, columns, types, foreign keys, and indexes. Reads directly from information_schema — always reflects reality, not the source files.

td schema
td schema --env staging
td schema --pr current

td routes

All registered API routes from the live OpenAPI spec — method, path, tags, request/response schemas.

td routes
td routes --env staging

td migrations

Applied versus pending migrations. Critical for diagnosing PR preview environments.

td migrations
td migrations --pr 472

td config

Resolved configuration values from the Zod env schema. Secrets are masked.

td config
# DATABASE_URL    postgresql://...@localhost:5433/toast  ✓
# BETTER_AUTH_SECRET  ••••••••••••••••  ✓
# EMAIL_DRIVER    toast-driver-email-mailgun  ✓
# MAILGUN_API_KEY  ••••••••••••••••  ✓

td drivers

Driver configuration and package discovery — shows which email and storage drivers are installed and configured.

td drivers
# email    toast-driver-email-mailgun  ✓  configured
# storage  toast-driver-storage-s3     ✓  configured

td logs

Pino JSON logs from the running server, with filtering:

td logs                    # All logs, streaming
td logs --level error      # Errors only
td logs --last 50          # Last 50 entries
td logs --service api      # Filter by compose service

td errors

Shorthand for the most common debugging command — the last 5 error-level log entries with full stack traces:

td errors
td errors --last 10

td query "<sql>"

Read-only SQL against any environment. 100-row limit, 5-second timeout, production-safe:

td query "SELECT id, name FROM newsletters WHERE site_id = '...' LIMIT 10"
td query "SELECT COUNT(*) FROM content" --env staging

td seed:status

Row counts per table — confirms whether the database is seeded:

td seed:status
# sites         1
# users         1
# content       12
# newsletters   0

td info

Monorepo structure, package versions, Node/pnpm versions, and API health check:

td info

PR preview inspection

Use --pr on commands that explicitly support it (check td <command> --help):

td pr status                        # Current PR info + inferred preview URLs
td schema --pr current              # Live schema in the PR environment

Shorthand commands:

td pr status                        # PR info + inferred preview URLs, with optional Railway enrichment
td pr open                          # Open inferred PR admin preview URL in browser
td pr logs                          # Recent errors from PR preview
td pr compare schema --pr current   # Schema diff: PR vs main
td pr compare routes --pr current   # Routes diff: PR vs main

td pr status does not require Railway for the basic happy path. It always shows the inferred admin/API/docs preview URLs for the PR, then adds Railway environment details when the Railway CLI is installed, authenticated, and linked.

td staging

Staging follows the same inferred-URL-first model:

td staging status                   # Canonical staging URLs + optional Railway enrichment
td staging open                     # Open the staging admin URL in browser

td pr compare schema answers "did my migration actually run in the preview environment?" instantly — no manual curl commands needed.


Development lifecycle

td provides a single interface for the full development lifecycle:

td dx              # Start everything (databases, migrations, dev servers)
td check           # Lint, format, typecheck, test, build
td test            # Run unit tests
td typecheck       # Run type checker

td db generate <name>  # Generate migration from schema changes
td db migrate          # Apply pending migrations
td db push             # Push schema directly (no migration file)
td db reset            # Drop and recreate database, then seed
td db seed             # Seed the database with fixture data
td db studio           # Open Drizzle Studio (database GUI)

td db runs commands directly in the shared/db package. The root pnpm db:* scripts still exist for CI and production deployments where td is not available.

td watch

Runs pnpm check (or pnpm check:strict) directly. Useful when you want to use the td command surface consistently during development:

td watch           # runs pnpm check
td watch --strict  # uses check:strict (no auto-fixes, coverage enforcement)

Provider authentication

td auth manages credentials for external providers (Railway, Fly.io, etc.) so inspection commands can reach remote environments:

td auth add railway --token <token>
td auth login railway
td auth list
td auth remove railway
td auth status          # Check all configured providers are reachable

For Railway-backed commands, prefer td auth login railway when you want td to launch Railway's native login flow for you. After that, td can reuse Railway CLI state to enrich commands like td pr status, td pr logs, and td staging status.

Credentials are stored in ~/.config/toast/credentials.json. Secrets are never committed to the repository.


CI status

td ci

Check GitHub CI status for a branch. Useful for verifying whether a failure is local or already broken on main:

td ci                  # Check main branch
td ci --branch my-pr   # Check a specific branch

td test:status

Show the last test run results from Vitest JSON reports without re-running tests. Shows per-package pass/fail counts and report age:

td test:status

Package location

td lives in packages/td/ and is never published to npm. It's a local dev dependency wired via the pnpm workspace:

# From anywhere in the monorepo
td status

On this page