{"id":49220517,"url":"https://github.com/durable-workflow/cli","last_synced_at":"2026-05-24T11:02:59.519Z","repository":{"id":350804596,"uuid":"1208272390","full_name":"durable-workflow/cli","owner":"durable-workflow","description":null,"archived":false,"fork":false,"pushed_at":"2026-05-20T23:55:32.000Z","size":800,"stargazers_count":1,"open_issues_count":1,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-05-21T06:00:14.922Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"PHP","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/durable-workflow.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-04-12T03:46:13.000Z","updated_at":"2026-05-20T23:50:37.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/durable-workflow/cli","commit_stats":null,"previous_names":["durable-workflow/cli"],"tags_count":61,"template":false,"template_full_name":null,"purl":"pkg:github/durable-workflow/cli","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/durable-workflow%2Fcli","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/durable-workflow%2Fcli/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/durable-workflow%2Fcli/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/durable-workflow%2Fcli/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/durable-workflow","download_url":"https://codeload.github.com/durable-workflow/cli/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/durable-workflow%2Fcli/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":33431039,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-23T22:14:44.296Z","status":"online","status_checked_at":"2026-05-24T02:00:06.296Z","response_time":57,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2026-04-24T03:02:04.603Z","updated_at":"2026-05-24T11:02:59.513Z","avatar_url":"https://github.com/durable-workflow.png","language":"PHP","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Durable Workflow CLI\n\nCommand-line interface for running and interacting with the [Durable Workflow Server](https://github.com/durable-workflow/server).\n\n## Installation\n\nThree options depending on what you have installed:\n\n**1. Standalone binary (no PHP required).** The easiest path — a one-liner\ninstaller that detects your OS and arch:\n\n```bash\n# Linux and macOS\ncurl -fsSL https://durable-workflow.com/install.sh | sh\n```\n\n```powershell\n# Windows\nirm https://durable-workflow.com/install.ps1 | iex\n```\n\nThe installers download the release `SHA256SUMS` manifest and verify the\nbinary checksum before writing `dw` into the install directory. Installer\nscripts live in this repository under `scripts/` and are published with each\ntagged release so the one-line install path is versioned with the binaries it\ndownloads.\n\nSet `DURABLE_WORKFLOW_INSTALL_VERIFY_ATTESTATIONS=1` when the GitHub CLI is\ninstalled to make the installer also verify artifact attestations for the\ndownloaded binary and `SHA256SUMS` before installation.\n\nOr download a native binary directly from the [releases\npage](https://github.com/durable-workflow/cli/releases). Available assets:\n`dw-linux-x86_64`, `dw-linux-aarch64`,\n`dw-macos-aarch64`, `dw-windows-x86_64.exe`.\n\nTagged releases also include `dw.rb`, a generated Homebrew formula for the\nmacOS arm64 binary, with the release URL and SHA256 baked in. Until a public\ntap is live, two install paths are supported: install from the bundled formula\ndirectly with `brew install --formula ./dw.rb` after downloading it from the\nrelease, or vendor the same formula into a self-hosted tap so users can run\n`brew install \u003corg\u003e/\u003ctap\u003e/dw`. See [`docs/distribution.md`](docs/distribution.md)\nfor the full Homebrew install runbook.\n\nmacOS x86_64 standalone binaries are not currently produced because the\n`macos-13` runner label is not available to this org; Intel Mac users can\nrun the PHAR with a system PHP.\n\nTo verify a direct download, fetch the matching `SHA256SUMS` file from the\nsame release and check it before moving the binary into your PATH:\n\n```bash\nsha256sum -c SHA256SUMS --ignore-missing\nchmod +x dw-linux-x86_64\n./dw-linux-x86_64 --version\n```\n\nRelease assets, including the installer scripts, also carry GitHub artifact\nattestations generated by the tagged release workflow. To verify that an asset\nwas built by this repository's release workflow, install the GitHub CLI and run:\n\n```bash\ngh attestation verify dw-linux-x86_64 --repo durable-workflow/cli\ngh attestation verify SHA256SUMS --repo durable-workflow/cli\n```\n\nTagged releases include `verify-release.sh` for downloaded release\ndirectories. It verifies every local asset named in `SHA256SUMS`; pass\n`--attest` to also verify GitHub artifact attestations for the checked files:\n\n```bash\nsh verify-release.sh .\nsh verify-release.sh --attest .\n```\n\nWindows operators can verify the same manifest from PowerShell:\n\n```powershell\n$expected = Select-String -Path .\\SHA256SUMS -Pattern 'dw-windows-x86_64.exe'\n$actual = (Get-FileHash .\\dw-windows-x86_64.exe -Algorithm SHA256).Hash.ToLower()\nif (-not $expected.Line.StartsWith($actual)) { throw 'Checksum mismatch' }\n.\\dw-windows-x86_64.exe --version\n```\n\n**2. PHAR (requires PHP \u003e= 8.2).** Download `dw.phar` from the\n[releases page](https://github.com/durable-workflow/cli/releases) and run it\nwith `php dw.phar` (or `chmod +x` and call directly — the PHAR\nhas a `#!/usr/bin/env php` shebang).\n\n**3. Composer.**\n\n```bash\ncomposer global require durable-workflow/cli\n```\n\n### Building from source\n\n```bash\nmake phar      # Build the PHAR (requires PHP \u003e= 8.2 and Composer)\nmake binary    # Build the PHAR plus a standalone native binary for the\n               # current platform (downloads Box and static-php-cli on demand)\nmake clean     # Remove build artifacts\n```\n\nBuild artifacts land in `./build/`. See [scripts/build.sh](scripts/build.sh)\nfor the underlying steps; tools are cached under `build/.tools/`.\n\n### Release Policy\n\nRelease assets are published from the tagged source by GitHub Actions. Each\nrelease includes `SHA256SUMS` for `dw.phar` and every supported native binary\nfor that tag: Linux x86_64, Linux aarch64, macOS aarch64, and Windows x86_64.\nThe release workflow waits for all supported platform builders before\npublishing the manifest; a failed platform build blocks the release instead of\npublishing a partial standalone surface.\n\nThe release workflow also publishes artifact attestations for every release\nasset, including `SHA256SUMS`, the installer scripts, and the generated\nHomebrew formula, so operators can verify both checksum integrity and GitHub\nActions build provenance with `gh attestation verify` or the release-bundled\n`verify-release.sh --attest` helper. These attestations are the current\nmachine-verifiable provenance mechanism for the 0.1.x line. The one-line\ninstallers keep checksum verification as the baseline and add attestation\nverification when `DURABLE_WORKFLOW_INSTALL_VERIFY_ATTESTATIONS=1` is set.\n\nNative binaries and PHARs are not currently code-signed or notarized. Treat the\nGitHub release tag, artifact attestations, and `SHA256SUMS` as the current\nprovenance boundary. Signing and notarization are explicitly out of scope for\nthe 0.1.x line; see [`docs/distribution.md`](docs/distribution.md) for the\nrationale and the conditions under which that decision would be revisited.\n\n`dw` does not auto-update itself; the explicit `dw upgrade` command is the\nonly update path, and it never runs unsolicited. The CLI also does not collect\ntelemetry — there is no background network traffic beyond commands that\nexplicitly contact the configured Durable Workflow server. Telemetry is\npermanently out of scope for the 0.1.x line.\n\nThe PHAR is a reproducible build: given the same tag and the\n`SOURCE_DATE_EPOCH` recorded by the release workflow, locally rebuilding from\nsource produces a byte-identical `dw.phar`. Run `scripts/verify-reproducible-build.sh`\nto confirm the rebuild is deterministic on your machine, and see\n[`docs/distribution.md`](docs/distribution.md) for the cross-check against a\npublished release artifact.\n\n### Live Server Smoke Test\n\nUnit tests use mocked HTTP clients. To verify the packaged `dw` entrypoint\nagainst a real server, start a local Durable Workflow server first, then run:\n\n```bash\nmake smoke-server\n```\n\nBy default the smoke test targets `http://localhost:8080` with no token. Override\nthe target and credentials when needed:\n\n```bash\nDURABLE_WORKFLOW_CLI_SMOKE_SERVER_URL=http://localhost:18082 \\\nDURABLE_WORKFLOW_CLI_SMOKE_ADMIN_TOKEN=admin-token \\\nDURABLE_WORKFLOW_CLI_SMOKE_OPERATOR_TOKEN=operator-token \\\nDURABLE_WORKFLOW_CLI_SMOKE_WORKER_TOKEN=worker-token \\\nmake smoke-server\n```\n\nThe smoke path creates a disposable namespace, starts and inspects a workflow,\nreads its history, registers a diagnostic worker, polls and completes the\nworkflow task through the worker protocol, creates and deletes a paused\nschedule, and terminates a second cleanup workflow.\n\n## Configuration\n\nFor day-to-day work, create named environment profiles. Profiles keep the\nserver URL, namespace, token source, TLS verification mode, and default output\nformat together so commands do not drift between shell aliases:\n\n```bash\ndw env:set dev --server=http://localhost:8080 --namespace=default --make-default\ndw env:set prod --server=https://api.example.com --namespace=orders --token-env=PROD_DW_TOKEN --profile-output=json\ndw env:list\ndw env:show prod\n```\n\nProfiles are stored in `~/.config/dw/config.json` by default, or\n`$XDG_CONFIG_HOME/dw/config.json` when `XDG_CONFIG_HOME` is set. Set\n`DW_CONFIG_HOME` to point `dw` at a separate config directory.\n\nProfile selection is explicit and typo-safe:\n\n```bash\ndw env:use dev\nDW_ENV=prod dw workflow:list\ndw --env=prod workflow:list\n```\n\nUnknown names passed through `--env`, `DW_ENV`, or `dw env:use` fail instead\nof falling back to another target. Literal token values are redacted by\n`env:list` and `env:show` unless `--show-token` is passed; prefer\n`--token-env=NAME` so secrets stay out of the config file.\n\nFor one-off automation, set the server URL and auth token via environment\nvariables:\n\n```bash\nexport DURABLE_WORKFLOW_SERVER_URL=http://localhost:8080\nexport DURABLE_WORKFLOW_AUTH_TOKEN=your-token\nexport DURABLE_WORKFLOW_NAMESPACE=default\nexport DURABLE_WORKFLOW_TLS_VERIFY=true\n```\n\nOr pass them as options to any command:\n\n```bash\ndw --server=http://localhost:8080 --token=your-token --namespace=production --tls-verify=true workflow:list\n```\n\nConnection settings resolve with one stable precedence contract: command-line\nflags win over environment variables, environment variables win over the\nselected profile, and profiles win over built-in defaults. Profile selection\nresolves as `--env`, then `DW_ENV`, then the `current_env` set by\n`dw env:use`. `DURABLE_WORKFLOW_SERVER_URL`,\n`DURABLE_WORKFLOW_NAMESPACE`, `DURABLE_WORKFLOW_AUTH_TOKEN`, and\n`DURABLE_WORKFLOW_TLS_VERIFY` are the portable environment variable names for\ncarriers. `DURABLE_WORKFLOW_TLS_VERIFY` and `--tls-verify` accept `true`,\n`false`, `yes`, `no`, `on`, `off`, `1`, or `0`. Tokens are bearer-token\ncredentials today; mTLS and signed-header credentials are reserved extension\npoints and must be added as redacted references instead of echoed secret\nmaterial. External executor configs follow the same auth-composition contract:\n`auth_refs` may persist a profile name, environment variable name, token-file\npath, mTLS certificate path plus key reference, or signed-header key reference\nplus header allowlist. They must not persist bearer tokens, private keys, or\nsigning secrets inline.\n\nNamespace-scoped commands always send exactly one namespace to the server. When\n`--namespace` is omitted, `dw` resolves the namespace from\n`DURABLE_WORKFLOW_NAMESPACE`, the selected profile, or the built-in `default`\nnamespace; workflow, schedule, and search-attribute list commands do not fan\nout across all tenant namespaces. Namespace-scoped workflow, schedule, and\nsearch-attribute commands include the effective namespace in human and JSON\noutputs so operators can tell which scope was queried or mutated.\n\nInvocable activity handlers use the `invocable_http` carrier type in the same\nexternal executor config file. The CLI validates that these targets stay\nactivity-only, use `POST`, declare an absolute HTTPS URL, avoid embedded URL\ncredentials, and keep `timeout_seconds` within the server-published\ninvocable-carrier envelope. Loopback HTTP is accepted only for local\ndevelopment. `dw server:info` and `dw doctor --output=json` expose the\nserver-advertised `worker_protocol.invocable_carrier_contract` so operators can\nverify the request/response content types, task-kind scope, idempotency key\nsource, and retry-authority boundary before enabling a mapping.\n\nThe CLI targets control-plane contract version `2` automatically via\n`X-Durable-Workflow-Control-Plane-Version: 2` and expects canonical v2\nresponse fields such as `*_name` and `wait_for`. Non-canonical legacy aliases\nsuch as `signal` and `wait_policy` are rejected.\n\nThe server also emits a nested `control_plane.contract` document with schema\n`durable-workflow.v2.control-plane-response.contract`, version `1`, and\n`legacy_field_policy: reject_non_canonical`. The CLI validates that nested\nboundary before trusting the server-emitted `legacy_fields`,\n`required_fields`, and `success_fields` metadata.\n\nFor request fields such as `workflow:start --duplicate-policy` and\n`workflow:update --wait`, the CLI now reads the server-published\n`control_plane.request_contract` manifest from `GET /api/cluster/info` before\nsending the command. Supported servers publish schema\n`durable-workflow.v2.control-plane-request.contract`, version `1`, with an\n`operations` map. The CLI treats missing or unknown request-contract\nschema/version metadata as a compatibility error instead of silently guessing.\nUse `dw server:info` to inspect the current canonical values,\nrejected aliases, removed fields, and the server-advertised role-topology\ncontract for the current node, including shape, process class, matching-role\ndeployment knobs, current write boundaries, scaling/failure metadata, and the\nfleet-wide `coordination_health` manifest that summarizes rollout-safety\nwarning/error checks from `GET /api/cluster/info`.\nUse `dw doctor` when you need the full resolved local/remote diagnostic state:\nCLI build identity, selected server/namespace/profile, a redacted\n`connection.effective_config` block that names which source won for each\nsetting, normalized auth-composition source names, TLS verification mode,\nserver-advertised `auth_composition_contract` metadata, `/api/cluster/info`,\nand compatibility warnings derived from the protocol manifests and\n`client_compatibility` metadata.\nUse `dw debug workflow \u003cid\u003e` when support needs a single stuck-run capture:\nexecution state, pending workflow/activity tasks, task queue backlog and\npollers, recent failures, and compatibility metadata.\n\n## Shell Completion\n\nGenerate shell completion scripts with the built-in `completion` command:\n\n```bash\ndw completion bash\ndw completion zsh\ndw completion fish\n```\n\nFor ad-hoc use, evaluate the generated script in your current shell:\n\n```bash\neval \"$(dw completion bash)\"\n```\n\nFor persistent installation, write the script to a shell-specific completion\nlocation, or source it from your shell startup file. The completion endpoint\nsuggests command names, option names, and stable values for enum-like fields\nsuch as workflow status, duplicate policy, update wait policy, schedule overlap\npolicy, worker status, search attribute type, and local dev database driver.\n\n## Compatibility\n\nCLI version 0.1.x is compatible with servers that advertise\n`control_plane.version: \"2\"` and\n`control_plane.request_contract.schema: durable-workflow.v2.control-plane-request.contract`\nversion `1` from `GET /api/cluster/info`.\n\nThe top-level server `version` is build identity only. The CLI validates the\nprotocol manifests on first invocation and raises a clear error if incompatible:\n\n```bash\n$ dw workflow:list\nServer compatibility error: unsupported control_plane.version [3]; dw CLI 0.1.x requires control_plane.version 2.\nUpgrade the server or use a compatible CLI version.\n```\n\n`dw --version` prints local build identity. When `DURABLE_WORKFLOW_SERVER_URL`\nor `DW_ENV` explicitly selects a target, it also performs a short best-effort\ncompatibility probe and emits at most one warning from protocol/client metadata.\nThe first server-talking command in a CLI process uses the same warning source\nand points to `dw doctor` for the full resolved diagnostic payload.\n\nSee the [Version Compatibility](https://durable-workflow.github.io/docs/2.0/compatibility) documentation for the full compatibility matrix across all components.\n\n## Commands\n\n### Server\n\n```bash\n# Check server health\ndw server:health\n\n# Show server version, capabilities, role topology, and coordination health\ndw server:info\n\n# Diagnose the resolved connection and compatibility state\ndw doctor\ndw doctor --env=prod --output=json\n\n# Start a local development server\ndw server:start-dev\ndw server:start-dev --port=9090 --db=sqlite\n```\n\n### Workflows\n\n```bash\n# Start a workflow\ndw workflow:start --type=order.process --input='{\"order_id\":123}'\ndw workflow:start --type=order.process --input-file=payload.json\ndw workflow:start --type=order.process --input='b3BhcXVlLWlk' --input-encoding=base64\ndw workflow:start --type=order.process --workflow-id=order-123\ndw workflow:start --type=order.process --execution-timeout=3600 --run-timeout=600\n\n# List workflows\ndw workflow:list\ndw workflow:list --namespace=orders\ndw workflow:list --status=running\ndw workflow:list --type=order.process\n\n# Describe a workflow\ndw workflow:describe order-123\ndw workflow:describe order-123 --run-id=01HXYZ --json\n\n# Diagnose a stuck workflow in one command\ndw debug workflow order-123\ndw debug workflow order-123 --run-id=01HXYZ --output=json\n\n# Watch a long-running workflow and print state changes\ndw watch workflow order-123\ndw watch workflow order-123 --run-id=01HXYZ --interval=5 --max-polls=60\n\n# Send a signal\ndw workflow:signal order-123 payment-received --input='{\"amount\":99.99}'\ndw workflow:signal counter-1 increment --input='[\"not-an-int\"]' --output=json\n# {\"error\":\"Server error: Signal argument validation failed.\",\"exit_code\":2,\"status_code\":422,\"reason\":\"invalid_signal_arguments\",...}\n\n# Query workflow state\ndw workflow:query order-123 current-status\ndw workflow:query counter-1 current-at --input='[\"not-an-int\"]' --output=json\n# {\"error\":\"Server error: Query argument validation failed.\",\"exit_code\":2,\"status_code\":422,\"reason\":\"invalid_query_arguments\",...}\n\n# Send an update\ndw workflow:update order-123 approve --input='{\"approver\":\"admin\"}'\n\n# Send an integration event through a bounded bridge adapter\ndw bridge:webhook stripe --action=start_workflow --idempotency-key=stripe-event-1001 --target='{\"workflow_type\":\"orders.fulfillment\",\"task_queue\":\"external-workflows\",\"business_key\":\"order-1001\"}' --input='{\"order_id\":\"order-1001\"}'\ndw bridge:webhook pagerduty --action=signal_workflow --idempotency-key=pd-event-3003 --target='{\"workflow_id\":\"wf-remediation-42\",\"signal_name\":\"incident_escalated\"}' --input='{\"severity\":\"critical\"}' --json\n\n# Cancel a workflow (workflow code can observe and clean up)\ndw workflow:cancel order-123 --reason=\"Customer request\"\ndw workflow:cancel --all-matching='customer-42' --yes --reason=\"Customer request\"\n\n# Terminate a workflow (immediate, no cleanup)\ndw workflow:terminate order-123 --reason=\"Stuck workflow\"\n\n# View event history\ndw workflow:history order-123 01HXYZ\ndw workflow:history order-123 01HXYZ --follow\n```\n\n### Namespaces\n\n```bash\n# List namespaces\ndw namespace:list\n\n# Create a namespace\ndw namespace:create staging --description=\"Staging environment\" --retention=7\n\n# Describe a namespace\ndw namespace:describe staging\n\n# Update a namespace\ndw namespace:update staging --retention=14\n\n# Delete a namespace and its runtime state\ndw namespace:delete staging --json\n```\n\nConfigure external payload storage for a namespace:\n\n```bash\ndw namespace:set-storage-driver billing s3 --bucket=dw-payloads --prefix=billing/ --threshold-bytes=2097152\ndw namespace:set-storage-driver dev local --uri=file:///var/lib/durable-workflow/payloads --json\ndw storage:test --namespace=billing --large-bytes=2097152\ndw storage:test --driver=s3 --json\n```\n\n### Schedules\n\n```bash\n# Create a schedule\ndw schedule:create --workflow-type=reports.daily --cron=\"0 9 * * *\"\ndw schedule:create --workflow-type=reports.daily --cron=\"0 9 * * *\" --input-file=payload.json\ndw schedule:create --schedule-id=daily-report --workflow-type=reports.daily --cron=\"0 9 * * *\" --timezone=America/New_York\n\n# List schedules\ndw schedule:list\ndw schedule:list --namespace=orders\n\n# Describe a schedule\ndw schedule:describe daily-report\n\n# Pause/resume\ndw schedule:pause daily-report --note=\"Holiday freeze\"\ndw schedule:resume daily-report\n\n# Trigger immediately\ndw schedule:trigger daily-report\n\n# Backfill missed runs\ndw schedule:backfill daily-report --start-time=2024-01-01T00:00:00Z --end-time=2024-01-07T00:00:00Z\n\n# Delete a schedule\ndw schedule:delete daily-report\n```\n\n### Task Queues\n\n```bash\n# List task queues with admission status\ndw task-queue:list\n\n# Describe a task queue (pollers, backlog, queue, namespace, and downstream admission budgets)\ndw task-queue:describe default\n```\n\n### Worker Protocol Diagnostics\n\n```bash\n# Register a diagnostic worker identity\ndw worker:register cli-worker --task-queue=orders --workflow-type=orders.Checkout\n\n# Poll and lease one workflow task\ndw workflow-task:poll cli-worker --task-queue=orders --json\n\n# Complete the leased workflow task with a JSON workflow result\ndw workflow-task:complete TASK_ID ATTEMPT --lease-owner=cli-worker --complete-result='{\"ok\":true}'\n\n# Report a worker-side failure on a leased workflow-task attempt (workflow tasks are replayed, not retried against application logic)\ndw workflow-task:fail TASK_ID ATTEMPT --lease-owner=cli-worker --message=\"replay mismatch\"\n\n# Fetch the next history page for a leased workflow task\ndw workflow-task:history TASK_ID PAGE_TOKEN --lease-owner=cli-worker --attempt=ATTEMPT --json\n\n# Poll and answer a routed query task\ndw query-task:poll cli-worker --task-queue=orders --json\ndw query-task:complete QUERY_TASK_ID ATTEMPT --lease-owner=cli-worker --result='{\"ready\":true}'\ndw query-task:fail QUERY_TASK_ID ATTEMPT --lease-owner=cli-worker --message=\"unknown query\"\n```\n\n### Activities\n\n```bash\n# Complete an activity externally\ndw activity:complete TASK_ID ATTEMPT_ID --input='{\"status\":\"done\"}'\ndw activity:complete TASK_ID ATTEMPT_ID --input-file=result.json\n\n# Fail an activity externally\ndw activity:fail TASK_ID ATTEMPT_ID --message=\"External service unavailable\" --non-retryable\n```\n\nInput-accepting commands use the same payload flags everywhere:\n`--input` for inline values, `--input-file` for a file path or `-` for stdin,\nand `--input-encoding=json|raw|base64` with `json` as the default.\n\n### System Operations\n\n```bash\n# Show the rollout-safety coordination-health snapshot\ndw system:operator-metrics\n\n# Pipe the raw snapshot to jq for scripted checks\ndw system:operator-metrics --json | jq '.operator_metrics.workers.active_workers_supporting_required'\n\n# Show task repair diagnostics\ndw system:repair-status\n\n# Run a task repair sweep\ndw system:repair-pass\n\n# Show expired activity timeout diagnostics\ndw system:activity-timeout-status\n\n# Run activity timeout enforcement sweep\ndw system:activity-timeout-pass\n\n# Target specific execution IDs\ndw system:activity-timeout-pass --execution-id=EXEC_ID_1 --execution-id=EXEC_ID_2\n```\n\n## Global Options\n\n| Option | Description |\n|--------|-------------|\n| `--server`, `-s` | Server URL (default: `$DURABLE_WORKFLOW_SERVER_URL` or `http://localhost:8080`) |\n| `--env` | Named profile to use (overrides `$DW_ENV` and `dw env:use`; hard-fails if missing) |\n| `--namespace` | Target namespace (default: `$DURABLE_WORKFLOW_NAMESPACE` or `default`) |\n| `--token` | Auth token (default: `$DURABLE_WORKFLOW_AUTH_TOKEN`) |\n| `--tls-verify` | Verify TLS certificates (`true`/`false`; default: `$DURABLE_WORKFLOW_TLS_VERIFY`, profile setting, or `true`) |\n\n## Exit Codes\n\nThe CLI uses a stable exit-code policy so scripts and CI pipelines can react\nto specific failure modes without parsing stderr. Values follow Symfony\nConsole's canonical `0`/`1`/`2` for success / failure / usage, and extend\nfrom there:\n\n| Code | Name | Meaning |\n|------|------|---------|\n| 0 | `SUCCESS` | Operation completed successfully. |\n| 1 | `FAILURE` | Generic failure — command ran but did not succeed. |\n| 2 | `INVALID` | Invalid usage — bad arguments, unknown options, or local validation. Also returned for HTTP 4xx responses that are not covered below (e.g. 400, 422). |\n| 3 | `NETWORK` | Could not reach the server (connection refused, DNS failure, TLS handshake failure, transport error). |\n| 4 | `AUTH` | Authentication or authorization failure. Returned for HTTP `401` and `403`. |\n| 5 | `NOT_FOUND` | Resource not found. Returned for HTTP `404`. |\n| 6 | `SERVER` | Server error. Returned for HTTP `5xx`. |\n| 7 | `TIMEOUT` | Request timed out before the server responded. Also returned for HTTP `408`. |\n\nExample:\n\n```bash\ndw workflow:describe chk-does-not-exist\necho $?  # 5 (NOT_FOUND)\n\ndw server:health --server=http://unreachable:9999\necho $?  # 3 (NETWORK)\n```\n\nExit codes are defined in [`DurableWorkflow\\Cli\\Support\\ExitCode`](src/Support/ExitCode.php)\nand are covered by [`tests/Commands/ExitCodePolicyTest.php`](tests/Commands/ExitCodePolicyTest.php).\n\n## JSON Output\n\nEvery list, describe, read, and mutating command supports `--json` for\nmachine-readable output. JSON responses preserve server response fields and\nmay add CLI-resolved context, such as the effective `namespace` for\nnamespace-scoped commands, making them safe to pipe into `jq` or feed into\ndownstream tooling.\n\n```bash\n# Read surface — stable even when no --json flag is passed for list views.\ndw workflow:list --json | jq '.workflows[].workflow_id'\n\n# Mutating surface — capture command response for idempotent automation.\nwf_id=$(dw workflow:start --type=orders.Checkout --json | jq -r '.workflow_id')\ndw workflow:signal \"$wf_id\" approve --json | jq '.command_status'\n```\n\nThe CLI publishes patch-stable JSON Schema files for every `--json` response\nand for `workflow:history-export` replay bundles. PHAR and standalone binary\nbuilds bundle the schema catalog under `schemas/output/`; operators can inspect\nthe embedded catalog without unpacking the artifact:\n\n```bash\ndw schema:list\ndw schema:manifest | jq '.commands[\"workflow:list\"]'\ndw schema:show workflow:list \u003e workflow-list.schema.json\n```\n\nSchemas are additive across patch releases: new optional fields may appear, but\nrequired top-level fields and their basic types stay stable.\n\n## License\n\nMIT\n## Public Boundary Checks\n\nThis is a public repository. Do not add private tracker names, workspace-only absolute paths, or automation metadata to files or new commit metadata. Run `scripts/check-public-boundary.sh` before publishing changes; CI runs the same scan on pushes and pull requests.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdurable-workflow%2Fcli","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fdurable-workflow%2Fcli","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdurable-workflow%2Fcli/lists"}