Reference

CLI

Every ductor subcommand and its flags — serve, dev, migrate, schema, health, validate-config, workflow, and more.

The ductor binary is a single executable with subcommands. With no arguments, it defaults to serve; a flag-only invocation (ductor --http-addr :9000) is also treated as serve.

ductor <command> [flags]

Global behavior

  • --config <path> — path to a config file. Accepted by every subcommand; also parsed from raw args (--config path or --config=path).
  • Config precedence: env vars > inline YAML in DUCTOR_CONFIG > config file > defaults. See the Configuration reference.
  • -h / --help / help prints usage; -v / --version prints the version.
  • A ./.env file is auto-loaded only when DUCTOR_ENVIRONMENT=development or DUCTOR_LOAD_DOTENV=true; otherwise it is ignored. Don't rely on it in production — set env vars directly.

Command overview

CommandPurpose
serve (default)Boot the full runtime via fx; optional startup auto-migrate; graceful shutdown
devBoot with embedded miniredis (Postgres still required) and development defaults
migrateRun database migrations — up / down / status
schemaschema status — verify the database schema is ready
healthHTTP health check against a running server
validate-configValidate resolved config and print a value/source table
versionPrint version and build_time
seed-demoSeed demo tenants
workflowvalidate / export / bootstrap-routing for workflow definitions
pipeline-modepipeline-mode set — flip a pool/tenant pipeline mode
audit-shadowAudit shadow-mode partition drift
migrate-shadowDrain/migrate shadow-partition items
scim-tokenscim-token mint — mint a SCIM bearer token
saml-idpsaml-idp set/get/disable — manage a tenant's SAML IdP config

serve

Boots every subsystem through the fx composition root, honoring server.role (all/api/worker/executor). If database.auto_migrate is true it migrates first; regardless, it logs a warning at startup if pending migrations exist. Shuts down gracefully on SIGINT/SIGTERM.

ductor serve --http-addr :8080 --metrics-addr :9090

Every serve flag binds to a config key, so a flag is just an inline override of the corresponding DUCTOR_* variable. The most useful:

FlagConfig keyNotes
--log-levellog.leveldebug/info/warn/error
--log-formatlog.formatjson/text
--http-addrserver.http_addrHTTP (REST + Connect) listener
--metrics-addrserver.metrics_addrPrometheus listener
--database-urldatabase.urlPostgres DSN
--cache-urlcache.urlRedis/Dragonfly URL
--auth-enabledauth.enabledToggle authentication
--api-enabledapi.enabledToggle the Connect/gRPC listener
--api-addrapi.addrConnect/gRPC address
--api-oidc-issuerapi.oidc_issuerOIDC issuer
--api-oidc-audienceapi.oidc_audienceOIDC audience
--workflows-dirworkflows.dirDir scanned for workflow-definition YAML at startup
--routing-filerouting.definition_fileOverride embedded routing topology
--roleserver.roleComma role set

Additional flag groups: archival (--archival-enabled, --archival-backend, --archival-s3-bucket, …), tracing (--tracing-enabled, --tracing-endpoint, --tracing-grpc, --tracing-insecure, --tracing-sample-rate), rules/events (--hot-reload, --events-enabled, --rule-cache-size, --rule-cache-ttl), and the executor plane (--exec-addr, --exec-target, --exec-shared-secret, --exec-runner-kind, --exec-isolation-required, --exec-task-timeout).

dev

Boots a development instance with an in-process Redis (miniredis) so you only need Postgres. It forces development defaults: auth.enabled=false, auth.allow_anonymous=true, archival.enabled=false, tracing.enabled=false, database.auto_migrate=true, environment=development.

export DUCTOR_DATABASE_URL="postgres://ductor:ductor@localhost:5432/ductor?sslmode=disable"
ductor dev

Flags: --log-level (default debug), --log-format, --http-addr, --metrics-addr, --database-url, --api-addr.

migrate

Runs goose migrations. Positional subcommand, no flags:

ductor migrate up       # apply all pending (default)
ductor migrate status   # show applied/pending
ductor migrate down     # roll back one

Uses database.url / DUCTOR_DATABASE_URL. See Database migrations.

schema status

Verifies the database schema is ready (all migrations applied) and prints schema=ready. Useful as a readiness gate in CI/CD before rolling a new version.

ductor schema status --database-url "$DUCTOR_DATABASE_URL" --timeout 15s
FlagDefaultNotes
--database-urldatabase.urlFalls back to DUCTOR_DATABASE_URL
--timeout15sSchema-check timeout

health

Performs an HTTP GET /health against a running server and prints OK (or the error). Defaults the address to :8080.

ductor health --http-addr :8080

validate-config

Validates the fully-resolved configuration and prints a table of each key, its resolved value, and its source ([env: …], [config: …], or [default]), with DSNs redacted.

ductor validate-config

workflow

Offline and management operations on workflow definitions:

ductor workflow validate ./definition.yaml      # offline lint; non-zero on any issue
ductor workflow export <family-slug>             # write latest published YAML to stdout
ductor workflow bootstrap-routing [--verify] [--repair]

validate resolves every action, strategy, hook, and interface reference without touching the database. bootstrap-routing defaults to --verify when neither flag is given.

Operational subcommands

CommandKey flagsWhat it does
seed-demo--tenant, --reset, --no-migrate, --database-urlSeed demo tenants (also seeds an acme tenant)
pipeline-mode set--pool | --tenant, --mode (inherit/linear/shadow/dag), --timeoutFlip a pool's or tenant's pipeline mode + fan out
audit-shadow--drift-threshold, --max-partitions, --fail-on-driftReport shadow-partition drift
migrate-shadow--dry-run, --max-items-per-poolDrain shadow-partition items
scim-token mint--tenant, --nameMint a SCIM bearer token. The plaintext token is printed once — it is not recoverable afterward
saml-idp set/get/disable--tenant, --metadata-file, --attribute-mapping, --allow-idp-initiatedManage a tenant's SAML IdP config. get truncates metadata_xml; disable flips enabled=false

Exit codes

Subcommands exit non-zero on failure — workflow validate on any validation issue, schema status when the schema isn't ready, audit-shadow --fail-on-drift when drift is detected, and serve when a required dependency is unreachable. This makes them safe to wire into CI/CD gates.