Developer Docs

Command Reference

Exhaustive, flag-by-flag reference for every real ds CLI command, verified directly against cli/commands/*.ts.

Command Reference

This is the complete reference for every ds command that actually exists in the codebase today. Every command and flag below was verified directly against cli/commands/*.ts — nothing here is aspirational or planned.

The ds CLI has exactly 7 top-level commands: run, migrations, data, golden, script, stripe, and g. There is no ds setup, ds deploy, ds db, ds local, ds api, ds integrations, ds utils, ds aws, or ds help — those command surfaces do not exist in this CLI.

The Global Wrapper

Every invocation goes through the root ./ds bash script before Commander ever sees your subcommand. It does three things, in order: an AWS SSO auth gate, a stage/region "bind" step, then execution of your actual command.

./ds [-b] [-r] [-u] <command> [subcommand] [args]
FlagDescription
-bForce re-bind stage/region config, even if a cached .ds/bind/<stage>-<region>.env already exists
-rTarget the remote stage — unsets IS_LOCAL, sets DEVSTRIDE_REMOTE=true
-uSkip the AWS SSO auth check entirely (aws sts get-caller-identity / aws sso login)

Every command in this reference is invoked as ./ds <command> <subcommand> [flags] — the run.ts, migrations.ts, data.ts, golden.ts, script.ts, stripe.ts, and g.ts files under cli/commands/ are each their own Commander program, resolved by name from the second CLI argument.


ds run

Defined in cli/commands/run.ts, delegating to cli/commands/sst/run.ts. Two subcommands, no flags on either.

ds run backend

Starts the backend: an SST live-lambda dev session against the Hono API.

ds run backend

Runs, in order: pnpm install, then deleteOrphanStacks() (cleans up orphaned CloudFormation stacks left behind by earlier sst.config.ts changes), then pnpm exec sst dev.

ds run ui

Starts the Vite frontend dev server.

ds run ui

Spawns pnpm run dev inside frontend/, injecting VITE_* environment variables derived from the bound stage (API/auth/media/importer root URLs, Pusher key/cluster, Stripe public key, GitHub app name, Giphy key, SMTP settings, plugin host allowlist, etc.).


ds migrations

Defined in cli/commands/migrations.ts. Runs Drizzle ORM SQL migrations against the bound database.

ds migrations run

ds migrations run

Runs all pending Drizzle SQL migrations (migratemigrateSqlmigrateToLatest).

ds migrations run-sql

ds migrations run-sql

Also runs all pending SQL migrations. As of the current source, this is an identical alias of ds migrations run — both ultimately call migrateToLatest. The split into two subcommands is a leftover from a historical separation between SQL and non-SQL migrations; today they do the same thing. run-sql is the one invoked by the Seed deploy pipeline's after_deploy hook (see the Deployment guide).

Neither subcommand takes any flags.


ds data

Defined in cli/commands/data.ts. Bulk SQL table import/export/wipe, plus single-organization copy, against the bound database.

ds data import

ds data import <path> [-t <tables>]

Bulk-restores SQL tables from a directory previously produced by ds data export.

FlagDescription
<path>(required, positional) Directory to import from
-t, --tables <tables>Comma-separated list of table names to import (default: all tables)

ds data export

ds data export [path] [-t <tables>]

Dumps SQL tables to disk as chunked JSON files, one directory per table.

FlagDescription
[path](optional, positional) Output directory. Default: .ds/data/<DEVSTRIDE_STAGE>
-t, --tables <tables>Comma-separated list of table names to export (default: all tables)

Output lands under <path>/sql/<tableName>/0.json, 1.json, … (1000 rows per chunk). The workflowRuns table is always excluded.

ds data wipe

ds data wipe [-t <tables>]

Deletes all rows from the selected (or all) SQL tables. Temporarily sets session_replication_role = 'replica' to bypass FK constraint ordering while deleting.

FlagDescription
-t, --tables <tables>Comma-separated list of table names to wipe (default: all tables)

ds data copy

ds data copy [-o <organization>] [-s <source>]

Org-scoped copy: pulls one organization's data from a source database into the bound database.

FlagDescription
-o, --organization <organization>Organization ID to copy. Default: 970b8dea-c8b4-44d8-8aaf-febf3f25138a (the demo org used by ds script reset-db)
-s, --source <keyOrUrl>Source DB: either the name of an env var (e.g. GOLDEN_DB_CONNECTION_STRING) or a full connection string. Omitted in an interactive terminal, you get a picker over the *_CONNECTION_STRING vars in .env; omitted non-interactively, it defaults to SOURCE_DB_CONNECTION_STRING

ds golden

Defined in cli/commands/golden.ts. Manages the golden demo/test dataset (currently the Acme persona org) on the bound stage. Twelve subcommands, all lazy-imported so only the one you invoke loads the heavy backend graph.

Every mutating subcommand is guarded by assertGoldenStageWritable: all mutating golden subcommands refuse to run against prod. The guard is stricter than just push on devbuild, reset, enrich, and lifecycle are also refused on dev (only import, reanchor, refresh-stage, aichat, and cognito are permitted there, since those are additive/non-destructive to the rest of a shared stage). push is a whole-DB replace and is refused on both prod and dev — only safe on fresh/disposable stages.

ds golden build (alias: load)

ds golden build [--no-reset] [--no-verify] [--org <name>]

Rebuilds the golden Acme org, in the bound DB, from the generator spec (real CommandBus calls). Scoped — only the Acme org's rows are reset/rebuilt; everything else on the stage is untouched. load is a Commander alias of build, not a separate implementation.

FlagDescription
--no-resetLayer onto existing Acme rows instead of resetting them first
--no-verifySkip the §16 assertion gate after building
--org <name>Rebuild a specific golden org in place (currently only acme)

ds golden push

ds golden push --force-full-reset [--allow-any-scale] [--skip-aichat] [--skip-cognito] [--dry-run] [--target-db <connectionString>]

Fast whole-database seed: pg_dumps the locally vitest-built golden template DB and pg_restores it straight into the bound stage's Postgres, then re-seeds the DynamoDB AI chats and Cognito logins. This is a whole-DB replace, intended only for fresh/disposable stages — it is refused by the stage guard on both prod and dev.

FlagDescription
--force-full-resetRequired to proceed — drops the stage's public + drizzle schemas and replaces all stage data with the golden template
--allow-any-scaleSkip the full-scale floor check (allows pushing a dev-scale template)
--skip-aichatSkip the DynamoDB AI-chat leg
--skip-cognitoSkip the Cognito login leg
--dry-runRun preflight checks (container/template/scale) and print the target + template + row counts, but drop/restore nothing
--target-db <connectionString>Push to an explicit Postgres connection string instead of the bound stage — used to publish the gated template into the dedicated golden source DB and for CI. Relaxes the stage journal guard and skips the AWS-bound aichat/Cognito legs

ds golden import

ds golden import [--org <name>] [--skip-aichat] [--source <envVarName|connectionString>] [--dry-run]

Additive, org-scoped seed: copies the golden persona org(s) from the canonical golden source (GOLDEN_DB_CONNECTION_STRING — distinct from the generic SOURCE_DB_CONNECTION_STRING used by ds data copy / ds script reset-db) into the bound stage without wiping it. This is the safe path for shared/populated stages such as app.devstride.dev. Cognito logins are created as part of the copy.

FlagDescription
--org <name>Import one persona org instead of all. Currently acme is the only golden persona org — the CLI's own help text still lists bright/indie/brightTrial as options, but ORG_IDS in the golden spec is Acme-only, so those other names are rejected at runtime
--skip-aichatSkip the DynamoDB AI-chat leg
--source <envVarName|connectionString>Golden source override — a connection string, or the name of an env var. Defaults to GOLDEN_DB_CONNECTION_STRING, then an interactive picker at a TTY
--dry-runRun the parity/provenance checks and print the planned orgs, but make no changes

ds golden reanchor

ds golden reanchor [--to <YYYY-MM-DD|today>] [--shift <±days>] [--org <name>] [--target-db <connectionString>] [--dry-run]

Shifts an already-built stage's entire temporal dataset (item dates, transactions, activity logs, timeboxes, roadmaps, custom-field dates, …) by a uniform delta without rebuilding — re-anchors the demo to a new "today". Transactional, with a post-shift sanity probe.

FlagDescription
--to <YYYY-MM-DD|today>Re-anchor to an absolute target date (delta = target − stored anchor). Default when no flag is given: today (real wall-clock UTC)
--shift <±days>Relative shift in whole days (mutually exclusive with --to)
--org <name>Reanchor one persona org instead of all. Currently acme-only in practice — see the note on ds golden import above
--target-db <connectionString>Shift an explicit Postgres DB (e.g. the local golden template) instead of the bound stage — for testing; skips the AWS AI-chat leg
--dry-runRead the stored anchor, compute the delta, print the plan + row counts, mutate nothing

ds golden status

ds golden status [--target-db <connectionString>] [--skip-source]

Read-only health report: are the persona orgs present, is the dataset anchored at today, is it in sync with the canonical source, does Acme carry the full 5-lane cumulative-flow staircase. Mutates nothing; exits non-zero when missing/stale/out-of-sync.

FlagDescription
--target-db <connectionString>Inspect an explicit Postgres connection string instead of the bound stage
--skip-sourceSkip the comparison against the canonical golden source

ds golden refresh-stage

ds golden refresh-stage [--org <name>] [--skip-aichat]

One-shot recovery command: additive importreanchor --to today → verify. Use this when a dev stage was reset and the golden orgs disappeared. Rebuilds nothing (pulls the intact gated source); safe to re-run; leaves other tenants untouched.

FlagDescription
--org <name>Refresh one persona org instead of all. Currently acme-only in practice — see the note on ds golden import above
--skip-aichatSkip the DynamoDB AI-chat leg of the import

ds golden aichat

ds golden aichat [--org <name>] [--force]

Seeds the golden AI-assistant chats in DynamoDB. Run after push or build if the Dynamo leg was skipped or failed.

FlagDescription
--org <name>Only seed one org's chat. Currently acme-only in practice — see the note on ds golden import above
--forceDelete each persona's existing chat(s) before seeding, so an updated transcript is written instead of the stale one being kept

ds golden enrich

ds golden enrich [--org <name>] [--aspect <names...>]

Additively patches an existing golden org in place — descriptions, activity, and similar polish — without a rebuild. Idempotent, never truncates. Distinct from build, which rebuilds from scratch.

FlagDescription
--org <name>The org to enrich. Default: acme (currently the only scaled org with an enrich profile)
--aspect <names...>Which data point(s) to patch: descriptions, archive-example, feature-planning, admin-governance, pi-objectives, activity, comments, time-entries. Default: all aspects

ds golden lifecycle

ds golden lifecycle [--workers <n>] [--target-db <connectionString>]

Intended purpose: parallel lane walk that gives every scaled Acme item a back-dated PUBLISHED lane/status history across N worker processes. No-op at representative scale; idempotent and deterministic when it does run.

FlagDescription
--workers <n>Number of worker processes. Default: min(8, cores) or GOLDEN_LIFECYCLE_WORKERS
--target-db <connectionString>Run the walk against an explicit Postgres DB instead of the bound stage — canonical use is the local Docker golden template

ds golden reset

ds golden reset [--org <name>]

Deletes the golden Acme org's rows in the bound DB. Scoped — only the Acme org is removed; all other data on the stage is left intact (never a whole-DB truncate).

FlagDescription
--org <name>Reset a specific golden org (currently only acme)

ds golden cognito

ds golden cognito [--org <name>]

Seeds Cognito logins (password Demo@123) for the golden persona users. Run after build.

FlagDescription
--org <name>Only seed one org's users. Currently acme-only in practice — see the note on ds golden import above

ds golden preview

ds golden preview

Renders the golden spec to text — pure spec-to-text dump, no DB access at all. No flags.


ds script

Defined in cli/commands/script.ts. A grab-bag of one-off scripts and everyday maintenance commands — most take no flags at all.

ds script find-missing-inits

ds script find-missing-inits

Codebase scan for Command/Query handlers that aren't wired up in their module's init file. No flags.

ds script find-missing-set-correlation-ids

ds script find-missing-set-correlation-ids

Codebase scan for handlers missing correlation-ID propagation. No flags.

ds script find-missing-events-registration

ds script find-missing-events-registration

Codebase scan for domain/integration events that aren't registered. No flags.

ds script find-missing-events-in-stack

ds script find-missing-events-in-stack

Codebase scan for event handlers missing from the infrastructure stack. No flags.

ds script generate-api-docs

ds script generate-api-docs

Generates the public-facing OpenAPI spec with embedded documentation. No flags.

ds script generate-api-client

ds script generate-api-client

Generates the typed frontend TypeScript API client SDK from backend Hono routes (also writes the canonical .ds/tmp/openapi.json). No flags.

ds script generate-api-mcp

ds script generate-api-mcp

Orchestrates the full MCP-SDK refresh, in order: generate-api-clientgenerate-api-docs → regenerates packages/mcp/src/devstride/gen/* (sdk, types, schemas, operations, components) by running packages/mcp/scripts/generate.ts. Run this after any backend OpenAPI change — the generated packages/mcp files are committed to git. No flags.

ds script delete-orphaned-items

ds script delete-orphaned-items

Deletes orphaned folders, work items, activity, comments, and assets from the database. No flags.

ds script set-config

ds script set-config

Validates 22 unconditionally-required environment variables (DB connection strings including the read-only replica, Stripe keys, OpenAI key, Azure DevOps + Jira app credentials, all four Pusher vars, GitHub app credentials, and more), plus 5 more that are required only if SMTP is configured, then pushes them up as sst secrets set DEVSTRIDE_CONFIG (base64-encoded JSON). No flags.

ds script check-orphan-stacks

ds script check-orphan-stacks

Reports orphaned CloudFormation stacks left behind by earlier sst.config.ts changes. No flags.

ds script delete-orphan-stacks

ds script delete-orphan-stacks

Deletes the orphaned CloudFormation stacks found by the check above. Also invoked internally by ds run backend and ds script reset-db. No flags.

ds script assistant

ds script assistant

No flags.

ds script get-active-emails

ds script get-active-emails

Dumps active users' emails across organizations. No flags.

ds script maintenance-on

ds script maintenance-on

Enables maintenance mode by toggling a Lambda environment variable. No flags.

ds script maintenance-off

ds script maintenance-off

Disables maintenance mode. No flags.

ds script backfill-access-permissions

ds script backfill-access-permissions

Idempotent SQL backfill of baseline module-access permission keys. No flags.

ds script inspect-user-permissions

ds script inspect-user-permissions <username>

Diagnostic dump of every organization membership for a username, including the role's permissions and is_system_owner flag — useful for telling a stale DB role apart from a stale frontend session. The username is read positionally from process.argv, not a Commander-declared argument; omitting it prints a usage message and exits non-zero. No flags.

ds script reset-db

ds script reset-db

Full local reset: terminates other DB connections, drops and recreates the public schema (and drops drizzle), deletes every Cognito user, re-runs SQL migrations, re-adds Stripe products, copies the demo organization (970b8dea-c8b4-44d8-8aaf-febf3f25138a) from SOURCE_DB_CONNECTION_STRING, and cleans up orphan stacks. No flags.

ds script maintenance-on / ds script maintenance-off

Covered above — both toggle the same Lambda env var, no flags on either.

ds script remove-org

ds script remove-org [-o <organization>]

Deletes all rows for one organization.

FlagDescription
-o, --organization <organization>Organization ID to remove

Dev-only guard applies (not safe to run on prod).

ds script create-slack-workflows

ds script create-slack-workflows

One-off historical migration: provisions Slack notification workflows for existing users. No flags.

ds script migrate-workitem-timespent-to-timeentry

ds script migrate-workitem-timespent-to-timeentry

One-off historical migration: converts legacy work-item time-spent data into time-entry records. No flags.

ds script add-default-sidebar-form-group

ds script add-default-sidebar-form-group

One-off historical migration: backfills a default sidebar form group. No flags.


ds stripe

Defined in cli/commands/stripe.ts. Three subcommands for managing Stripe products, customers, and subscription quantities.

ds stripe add-products

ds stripe add-products

Creates Stripe products/prices via CreateProductCommand. No flags.

ds stripe create-customers

ds stripe create-customers [-o <organization>]

Creates Stripe customers for organizations.

FlagDescription
-o, --organization <organization>Organization ID. Omit to create customers for all organizations

ds stripe find-subscription-quantity

ds stripe find-subscription-quantity [-o <organization>]

Reports subscription seat quantity for organization(s).

FlagDescription
-o, --organization <organization>Organization ID. Omit to report for all organizations

ds g

Defined in cli/commands/g.ts. CQRS codegen — scaffolds a new command or query into a backend module.

ds g command (alias: c)

ds g command <name> -m <module> [-f]

Scaffolds a new CQRS command (command artifact, init, service handler, Lambda handler) in the given module.

FlagDescription
<name>(required, positional) Command name
-m, --module <module>(required) Module to generate the command in — throws if omitted
-f, --forceOverwrite existing files. Default: false

ds g query (alias: q)

ds g query <name> -m <module> [-f]

Scaffolds a new CQRS query in the given module.

FlagDescription
<name>(required, positional) Query name
-m, --module <module>(required) Module to generate the query in — throws if omitted
-f, --forceOverwrite existing files. Default: false

Next Steps