ds CLIThe ds command-line interface is the entry point for working with DevStride's AWS infrastructure and databases from a developer machine. It wraps AWS authentication and SST (the framework that deploys the backend Lambda/API Gateway stack and the frontend static site) behind a small set of Commander-based subcommands.
ds Wrapsds run backend runs sst dev (SST's live-lambda mode) against the backend; the frontend ships as an SST StaticSite in the same deploy..env, and an agent machine's certificate identity.Postgres is hosted on Neon on every stage, and a few commands know that (ds golden push and import prefer the direct, non-pooled endpoint; ds data copy works around idle timeouts). Neon's copy-on-write branching is not exposed as a CLI operation: seeding goes through pg_dump/pg_restore and additive org copies instead. There is no infrastructure-as-code tool here beyond SST.
ds is not a single monolithic program — it's a thin bash dispatcher that compiles and runs one TypeScript file per invocation. The chain is:
./ds [-b] [-r] [-u] <command> [subcommand] [args]
│
├─ ./ds ← root bash script: parses -b/-r/-u, runs the SSO gate,
│ resolves/regenerates the stage+region bind cache
│
├─ ./cli/run_script.sh ← esbuild-bundles cli/commands/<command>.ts
│ to .ds/.tmp/<command>.mjs
│
└─ node .ds/.tmp/<command>.mjs "$@" ← the actual Commander program runs,
then the temp bundle is deleted
Concretely, running ds migrations run:
./ds parses wrapper flags, runs the SSO gate (unless -u), resolves the stage/region bind cache, then hands off everything after the flags to cli/run_script.sh.cli/run_script.sh takes $1 (migrations) and calls node ./cli/bin/build.js ./cli/commands/migrations.ts ./.ds/.tmp/migrations.mjs — an esbuild bundle, built fresh on every single run.run), which resolves to a Commander subcommand inside cli/commands/migrations.ts..mjs/.mjs.map and propagates the child process's exit code.Every top-level command is its own file under cli/commands/*.ts — there is no central command registry; each file builds its own Commander program and parses process.argv independently.
ds command pays a small esbuild cost before it starts doing real work.These three flags belong to the ./ds wrapper itself, not to any subcommand, and must come before the command name:
./ds [-b] [-r] [-u] <command> [subcommand] [args]
| Flag | Effect |
|---|---|
-b | Force a re-bind of the stage/region config, even if a cached .ds/bind/<stage>-<region>.env already exists. |
-r | Target remote: unsets IS_LOCAL and sets DEVSTRIDE_REMOTE=true. |
-u | Skip the AWS SSO auth check entirely for this invocation. |
For any AWS-bound command, ./ds runs an AWS auth check before your command's code ever executes:
DEVSTRIDE_DEV_PROFILE is set, it's exported as AWS_PROFILE.AWS_SDK_LOAD_CONFIG=1 is exported, so AWS SDK v2 (used by some Node-side scripts) reads SSO profiles from ~/.aws/config instead of only ~/.aws/credentials.aws sts get-caller-identity is run. If it succeeds, you'll see Already authenticated. If it fails, what happens next depends on who could finish a login:
No active session found. Logging in... and the browser login (aws sso login). This includes a person pushing from a terminal, whose git hooks still show stderr.aws sso login --profile <profile>, and ./ds exits 1 without running your command. It used to open the device-code login where nobody could see it and appear to hang for minutes.ds machine enroll) is never sent to a login, because a login cannot repair a certificate. ./ds says the identity was refused — the machine was revoked, its certificate expired, or its key is gone — and exits 1.AWS_PROFILE the shell carries — usually your dev profile. It says nothing about a production profile, a role profile, or another account you are about to touch. Check the profile the work actually needs.These invocations skip the gate and the stage bind automatically, with no -u needed, because they either run entirely on your machine or check the AWS account themselves when they need it:
ds run local and ds worktree — the fully-local docker stack, which needs neither AWS SSO nor SST resource binding (this is exactly what makes the no-AWS docker flow work).ds pool — reserving, resetting and handing back checkouts touches only local Docker. Its cloud mode checks your AWS login itself and never opens one.ds secrets — ds secrets pull must still be able to write from its offline cache when your login has lapsed.ds machine and ds fleet — every subcommand that reaches AWS checks the account with the profile it was given.ds agent, ds quickbooks and ds graph — they use the agent's own credentials file; only storing a credential the provider rotated reaches AWS, and a lapsed login must not block the read itself.ds work and ds merge-path — ds work reads DevStride with the agent's own key and otherwise touches only git; ds merge-path is a verdict computed from a branch name, labels and the config.ds verify — local type-checks, lint and tests against this checkout's own test containers.For every other command, -u is the way to bypass the check — useful for tight loops on commands that don't touch AWS, but since most ds run, ds migrations, ds data, and ds golden commands need live credentials, treat -u as the exception, not the default.
After the SSO gate, ./ds resolves which stage and region you're targeting and caches that resolution to disk:
.ds/bind/<DEVSTRIDE_STAGE>-<DEVSTRIDE_REGION>.env.-b, ./ds runs node ./cli/bin/store_bind.mjs $DEVSTRIDE_STAGE $DEVSTRIDE_REGION to (re)generate it..env file is exported into the shell environment before cli/run_script.sh is invoked, so every subcommand sees a consistent, already-resolved stage/region without re-deriving it itself.In practice this means the first ./ds command after switching DEVSTRIDE_STAGE or DEVSTRIDE_REGION pays a one-time bind cost, and every subsequent invocation reuses the cached file until you force a refresh with -b.
There are twenty top-level commands, one file each under cli/commands/. Each is its own Commander program — there's no shared subcommand namespace beyond these eighteen.
| Command | What it does | Covered in depth |
|---|---|---|
ds run | Runs the backend via sst dev (live-lambda mode), starts the frontend Vite dev server, or (ds run local) brings up the fully-local docker stack. | Local Development |
ds migrations | Runs Drizzle SQL migrations against the bound stage's PostgreSQL database. | Local Development |
ds data | Imports, exports, wipes, or org-scoped-copies SQL table data on the bound stage. | Local Development |
ds golden | Builds, publishes, imports, reanchors, and manages the Acme golden demo/test dataset. | Golden Dataset |
ds script | A grab-bag of one-off maintenance, diagnostic, and codegen scripts (config push, orphan cleanup, DB reset, and more). | Maintenance & Codebase Checks |
ds stripe | Exports a read-only billing inventory and runs test-mode proofs of the Stripe behaviour billing relies on. | Stripe Integration |
ds g | Scaffolds a new CQRS command or query into a backend module. | Local Development |
ds worktree | Manages sandboxed per-worktree docker instances (create/list/remove, run CLI commands against one). Like ds run local, it skips the SSO gate and bind entirely. | Dockerized Worktree Development |
ds pool | Reserves, resets and hands back the machine's fixed checkouts (main, wt1, wt2) with a lease; copies one customer organization in for a repro; or runs one checkout against this machine's own cloud stage. | Dockerized Worktree Development |
ds work | Starts one item on the branch it belongs to — its Epic's integration branch, else the support train — and lands it there after the local checks. Never merges to develop or master. | Dockerized Worktree Development |
ds merge-path | Says whether a branch may open a pull request into develop: the same ALLOWED / BLOCKED verdict the required merge-path check posts. | Command Reference |
ds verify | Runs the local mirror of CI: land, the check every Story and one-off passes before it merges, and full, everything cloud CI runs on a release pull request, which posts the local-ci status every pull request into develop needs. | Command Reference |
ds secrets | Writes every pool checkout's .env from the dev account's secrets bundles (and the agent's credentials to their own private file), and changes one value in a bundle. | Credentials and access |
ds machine | Takes a bare machine to ready (setup, which ./setup runs), proves it works (ready), keeps its checkouts current (doctor), and gives an unattended agent machine its own certificate-backed AWS identity, shut off with a single revoke. | Set up your machine |
ds fleet | Lists every agent machine and its checkouts: who holds each, its branch and whether it is healthy. | Command Reference |
ds agent | Wires an agent's DevStride MCP connection and GitHub access from the agent bundle. | AI Development |
ds quickbooks | Reads QuickBooks Online through the agent's own grants — every call names the company. | AI Development |
ds graph | Looks up Microsoft Entra accounts and rotates the agent app's own client secret. | AI Development |
ds seed | Asks Seed to redeploy one chosen commit to one stage, with the team's shared Seed token (it can deploy production). | Command Reference |
ds neon | Runs Neon's command-line tool with the team's shared Neon key and DevStride's organisation, never a person's own Neon sign-in. | Command Reference |
ds help fails to resolve a module, because each command is its own file. ds <command> --help prints that one command's Commander help, and the Command Reference lists every subcommand and flag across all eighteen.Getting Started
New here? Start with the Developer Guide. This page covers day-to-day use of what ./setup built: your machine's own AWS stage, its config and migrations, and the test suite.
Command Reference
Exhaustive, flag-by-flag reference for every real ds CLI command, verified directly against cli/commands/*.ts.