CLI
The taskq CLI operates queues, jobs, workers, workflows, schedules, the
scheduler, migrations, maintenance, and optional IAM without a dashboard. It
uses TaskQ's typed SQL/HTTP transports and never falls back to privileged raw
queries.
Start with discovery
taskq commands -o json
taskq schema job.enqueue -o json
taskq capabilities --context staging -o json
taskq completion zsh
commands is generated from the command registry. Every leaf declares its
transport, capability/role, mutability, danger level, input/output JSON Schema,
examples, and exit behavior. This is the best integration point for coding
agents.
Contexts
Store a secret-free config in $XDG_CONFIG_HOME/taskq/config.toml or
~/.config/taskq/config.toml:
version = 1
[contexts.staging]
transport = "sql"
dsn_env = "TASKQ_STAGING_DSN"
expected_environment = "staging"
expected_installation_id = "018f0000-0000-7000-8000-000000000000"
actor = "operator:release-agent"
[contexts.remote]
transport = "http"
base_url = "https://api.example.com"
bearer_token_env = "TASKQ_STAGING_TOKEN"
expected_environment = "staging"
expected_installation_id = "018f0000-0000-7000-8000-000000000000"
Contexts store secret environment-variable names, never literal DSNs, tokens, passwords, or header values. There is no implicit current context.
taskq context validate
taskq context list
taskq --context staging doctor -o json
Every connected command requires --context or complete explicit connection
flags. SQL mutations require an actor from the context, TASKQ_ACTOR, or
--actor. HTTP mutations use the authenticated server principal and reject
actor spoofing. Explicit mutations also require --expected-environment;
ambient TASKQ_EXPECTED_* runtime settings are not operator target constraints.
For a supervisor or host-owned wrapper that does not need a context file, pass the name of the secret environment variable—never its value:
taskq --dsn-env TASKQ_STAGING_DSN \
--expected-environment staging \
--expected-installation-id "$TASKQ_EXPECTED_INSTALLATION_ID" \
--actor service:worker worker run \
--registry myapp.tasks:registry --queue mail --environment staging
Command surface
| Group | Commands |
|---|---|
| Discovery | version, doctor, capabilities, commands, schema, completion |
| Context | context list, show, validate |
| Database/target | `db plan |
| Queues | `queue list |
| Jobs | `job list |
| Workers | `worker run |
| Workflows | `workflow list |
| Schedules | `schedule list |
| Flow control | See Operations → Flow control for the breaker, rate limits, caps, ramps, TTL, smear, and aging |
| Runtime/admin | `scheduler run |
taskq-bench remains a separate report-only executable.
For scheduler topology, activation, monitoring, and rollback, continue with the Standalone Scheduler guide.
Stable machine output
-o table|json|yaml|jsonl|name is explicit; table is always the default. JSON
and YAML return a versioned taskq.cli/v1 envelope with command, kind,
ok, data, target/transport metadata, cursor, sensitivity marker, and
warnings.
Errors have stable codes, category, retryability, safe bounded details, request
ID, and remediation. JSON errors go only to stderr, leaving stdout empty.
Secrets, SQL, payloads, raw exceptions, and attempt fences are redacted.
The intentional fresh-database migration stop uses
CLI_TARGET_BINDING_REQUIRED; it is a safe instruction to inspect and bind the
target, not a retryable database outage.
| Exit | Meaning |
|---|---|
| 0 | Success |
| 1 | Non-retryable operation failure |
| 2 | Usage/configuration/safety refusal |
| 3 | Retryable/unavailable/runtime failure |
| 4 | Wait timeout |
| 5 | Partial/degraded result |
| 130 | Watch interrupted |
Bounded reads and waits
List commands use bounded server pages. --limit bounds the total result;
--all explicitly exhausts pages. Opaque cursors bind command, filters,
transport, and target installation.
taskq --context staging job list --queue mail --view failed --limit 50 -o json
taskq --context staging workflow list --view running --all -o jsonl
taskq --context staging job watch "$JOB_ID" -o jsonl
taskq --context staging job wait "$JOB_ID" --for succeeded \
--timeout 300 --poll-interval 2 -o json
Payload/result/progress/error/event details are opt-in and mark output as sensitive.
Enqueue from flags or stdin
taskq --context staging job enqueue \
--queue mail --type mail.send \
--payload '{"message_id":"m-42"}' \
--idempotency-key 'mail:m-42' -o json
taskq --context staging job enqueue --input - -o json <<'JSON'
{
"queue": "mail",
"job_type": "mail.send",
"payload": {"message_id": "m-43"},
"idempotency_key": "mail:m-43"
}
JSON
Full input and field flags cannot be mixed. Enqueue requires an idempotency key
or workflow identity unless --allow-unkeyed is explicit.
Plan/apply and safety gates
taskq --context staging db plan -o json
taskq --context staging --yes db migrate --plan-digest "$PLAN_DIGEST" -o json
taskq --context staging schedule manifest plan schedules.yaml -o json
taskq --context staging schedule manifest apply schedules.yaml \
--plan-digest "$PLAN_DIGEST" -o json
taskq --context staging auth plan --queues mail,exports -o json
taskq --context staging --yes auth apply --queues mail,exports \
--plan-digest "$PLAN_DIGEST" -o json
Apply recomputes the target-bound plan and rejects drift. Before every
mutation, the CLI compares actual and expected target identity. Destructive or
bulk operations require literal --yes everywhere. Production mutations also
require an exact installation UUID and literal --allow-production; config or
environment acknowledgements cannot satisfy these gates.
Worker
taskq --context staging worker run \
--registry myapp.tasks:registry \
--queue mail --queue courts \
--environment staging \
--concurrency 4 --batch 2
HTTP workers cannot use PostgreSQL LISTEN; add --no-listen. See
Configuration for runtime settings.
migrate became
db migrate, verify became db verify, worker became worker run, and
schedule source reconciliation moved under schedule manifest.