Skip to content

Command reference

Root commands for development, databases, Rackspace schemas, and verification

Run these aliases from the repository root. Operator aliases run the CLI directly, and each command runs its own prerequisites. For example, pnpm db:seed applies migrations before it adds seed data. Prompts read from your terminal. Run pnpm cli --help to list every CLI command, and add --help after a command to see its flags. Each executable loads its own environment.

Getting started describes owner-local files. Operator commands live in the CLI. Use NODE_ENV=production pnpm db:migrate to read only supplied variables. Explicit NODE_ENV wins; otherwise CI selects production and local use selects development. The CLI README defines the complete mode and file policy.

Setup and development

CommandPurpose
pnpm installInstall the workspace dependencies
pnpm dev:setupApply migrations, add seed data, and create the local accounts
pnpm rsdb:seedLoad the local Rackspace databases with synthetic data
pnpm auth:bootstrap-developmentCreate or repair the local administrator and impersonation users
pnpm auth:bootstrap-previewCreate the preview administrator from PREVIEW_ADMIN_* values
pnpm auth:create-adminCreate a system administrator; prompts ask for missing values
pnpm devStart every app, Drizzle Studio, and foreground Maildev
pnpm maildev:startStart background Maildev without the apps
pnpm maildev:stopStop the repository-owned background Maildev process
pnpm add:componentAdd a Shadcn component to the shared interface package
pnpm api:list-projectsList one organization's Projects through the HTTP API and SDK

pnpm dev:setup is for a new development environment. It runs db:migrate, db:seed, and auth:bootstrap-development in order, and it runs rsdb:seed. The local administrator values are in the tracked apps/cli/.env.development file. Do not use them outside local development.

pnpm dev:setup runs rsdb:seed only after the other setup steps pass.

[!CAUTION] pnpm rsdb:seed drops the local mi_property_value and tredis_global_dynamic databases and the concourse_local account, and then creates them again. Local changes to that data are lost.

pnpm rsdb:seed needs MySQL 8.0 or 8.4 on this machine. It loads their committed tables, creates the concourse_local runtime account for connections from this machine only, and adds synthetic Global Dynamic users and property value projects through the Services. Running it again gives the same result. The RSDB checks describe the root connection settings.

Before it changes data, the seed makes these checks:

  • The root connection uses a loopback address.
  • The server reports this machine's host name. A tunnel or proxy on a loopback address to another server fails this check.
  • The server is the one that MIDOT reads: RACKSPACE_MYSQL_HOST and RACKSPACE_MYSQL_PORT in apps/cli and apps/midot. If RSDB_TEST_MYSQL_* selects another server, set the same host and port in apps/cli/.env.local and apps/midot/.env.local.

The seed creates these Global Dynamic accounts:

User namePasswordAccount
local-adminlocal-admin-passwordSuper user. The same password is its administrator password.
local-userlocal-user-passwordMichigan user with full TREDIS access. Can sign in to MIDOT.
local-legacylocal-legacy-passwordUser whose profile dates are legacy zero dates

Each user has one calculated and one new property value project.

pnpm auth:bootstrap-preview is for the preview database workflow. It reads PREVIEW_ADMIN_EMAIL, PREVIEW_ADMIN_NAME, and PREVIEW_ADMIN_PASSWORD from the environment. The deployment runbook says where those values come from.

pnpm api:list-projects reads CONCOURSE_BASE_URL and CONCOURSE_SESSION_TOKEN and takes an optional --organization <id> and --status archived. The SDK guide says how to get a session token.

Before you run pnpm dev, stop background Maildev. The development command owns its own foreground Maildev process.

Database operations

CommandPurpose
pnpm db:migrateApply the committed migrations to the development database
pnpm db:generateWrite a migration for a schema change
pnpm db:diffReport a schema change that has no migration
pnpm db:seedApply migrations, then add seed data or reuse it
pnpm db:resetRecreate the development database after a typed confirmation
pnpm db:clearErase the rows in the tables that the seed command manages

CAUTION: pnpm db:reset erases the complete development database. Type reset only when you intend to erase its data.

CAUTION: pnpm db:clear erases the tables that the seed command manages. Make sure that TURSO_DATABASE_URL points at the intended database before you run it.

The database package guide describes the migration workflow.

Rackspace schemas

CommandPurpose
pnpm rackspace:schema generate --config <config-path>Generate Rackspace schema snapshots through the VPN
pnpm rackspace:schema verifyCheck the committed snapshots without a database connection

Run generate from an interactive terminal on the approved VPN. Add --database <name> once for each database to skip the database list. The Rackspace operations page has the protected configuration shape and the review steps.

Checks and tests

CommandPurpose
pnpm checkRun lint rules and compiler checks for every workspace
pnpm lint:fixApply the safe Oxlint corrections
pnpm lint:boundariesCheck the package boundaries and relative import depth
pnpm lint:deadReport unused files, dependencies, and exports with Knip
pnpm formatFormat the workspace
pnpm format:checkCheck the formatting
pnpm testRun the cacheable unit tests
pnpm test:integrationRun the SQLite and MySQL integration tests
pnpm e2eRun or restore the complete acceptance lifecycle
pnpm e2e:fullIgnore the E2E cache and run the complete lifecycle
pnpm buildBuild every app with Turbopack
pnpm verifyRun the complete merge gate
pnpm ci:localRun the CI workflow under act and sign off the commit (Local CI)

After a small change, run the focused command for the files that you changed. Before a merge, or after a change that crosses several areas, run pnpm verify. Turbo restores each completed task from the local or remote cache.

pnpm verify schedules two Turbo runs. Each task loads only its owner’s applicable files. The first run includes combined checks, package boundaries, dead code, and formatting. The second run starts only when the first run passes. It includes unit tests, migration diff, builds, SQLite and MySQL integrations, and acceptance tests. The virtual verify:build task selects ordinary builds except for Concourse, where it selects build:test. Concourse tests use .next-test; its production build uses .next.

Verification selects the DB, Auth, Services, API, CLI, RSDB, and application integration suites as separate tasks. They form a serial chain and cache successful results from isolated fixtures. pnpm test:integration --force reruns them. pnpm e2e does not repeat integration coverage. Repository test scopes own isolated database files. The browser lifecycle uses its fixed acceptance database. The MySQL suites use isolated databases on local MySQL, so they can run alongside the acceptance lifecycle.

The root package.json script verify defines this task selection.

The acceptance suite uses one fixed SQLite file in each checkout. It also uses fixed ports on the machine: Next 3100, Maildev 1125 and 1180, OIDC 8180, and SAML 8280. The Vitest global setup starts scripts/e2e-server.ts. That script removes leftover SQLite files, migrates the fixed database, serves Next, and removes the database when it stops. Do not run two acceptance suites at the same time on one machine, even from separate worktrees. The @concourse/auth and @concourse/email unit tests use the same ports. If a forced stop leaves SQLite files behind, the next run removes them before migration.

Remote cache

Developers can share cache results through the Conveyal Vercel Remote Cache. Authenticate and link this checkout from the repository root:

turbo login
turbo link --scope=conveyal

Turbo stores the login and the link outside the tracked source files. Do not commit Turbo credentials or .turbo/config.json.

CI exchanges its GitHub OIDC token for short-lived cache access. It does not use a Vercel personal access token or a cache-signature secret.

Combined checks

pnpm check runs the lint rules and compiler checks. The first step of the CI checks job also checks package boundaries, dead code, and formatting. To get the same result as that step, also run pnpm lint:boundaries, pnpm lint:dead, and pnpm format:check, or run pnpm verify.

To check one workspace, use pnpm exec turbo run check --filter=<package-name>. Turbo also runs route generation and retained compiler tasks. A direct workspace check script runs only Oxlint and does not run these dependencies.

Oxlint checks source types and lint rules together. Next.js apps retain full compiler checks for generated route validators. Concourse also retains its separate server and E2E compiler projects. The root, sdk, and midot also run a check:types compiler task. It compiles their imported configuration modules together with their own files. These tasks use the check:types prefix. Turbo invalidates a workspace check when imported workspace source changes. Root checks include workspace inputs because root tests import workspace modules.

Next.js builds retain framework type checks and route generation ordering without a lint prerequisite. The virtual DB and RSDB build gates retain their complete checks. pnpm verify finishes the source checks before it starts the builds. next build removes its output folder, including the generated route types that the compiler checks read. The Oxlint guide owns the lint scope. The TypeScript guide owns compiler configuration.