CLI Usage
The @duckflux/runner package ships a quack binary that lets you run, lint, and validate workflows from the command line.
quack <command> <workflow.yaml> [flags]Installation
Section titled “Installation”Auto-detects your package manager (apt, brew, bun, npm) and installs accordingly. Falls back to downloading a standalone binary.
curl -fsSL https://duckflux.github.io/apt-repo/install.sh | bashInstall via Homebrew:
brew install duckflux/tap/quackInstall via apt:
curl -fsSL https://duckflux.github.io/apt-repo/install.sh | bashInstall globally so quack is available everywhere on your machine.
# npmnpm install -g duckflux
# Bunbun add -g duckfluxVerify:
quack versionRun without installing — always uses the latest published version.
# Node.jsnpx duckflux run workflow.yaml
# Bunbunx duckflux run workflow.yamlDownload a self-contained binary (no Node.js or Bun required) from the GitHub Releases page.
| Platform | File |
|---|---|
| macOS ARM64 (Apple Silicon) | quack-darwin-arm64 |
| macOS x64 (Intel) | quack-darwin-x64 |
| Linux x64 | quack-linux-x64 |
| Linux ARM64 | quack-linux-arm64 |
| Windows x64 | quack-windows-x64.exe |
macOS / Linux:
# Example for macOS ARM64 — replace the filename for your platformcurl -fsSL https://github.com/duckflux/runtime-js/releases/latest/download/quack-darwin-arm64 \ -o /usr/local/bin/quackchmod +x /usr/local/bin/quackquack versionWindows: download the .exe, place it somewhere on your %PATH%, and run it directly.
Commands
Section titled “Commands”| Command | Description |
|---|---|
run | Execute a workflow |
lint | Validate schema and detect common issues (no execution) |
validate | Full validation including input schema |
server | Start the web server UI for visual workflow observation |
version | Print the CLI version |
Executes a workflow from a YAML file and prints the result to stdout.
quack run <workflow.yaml> [flags]run is the default command — if the first positional argument is a .yaml file and no subcommand is given, it is implied:
quack workflow.yaml # same as: quack run workflow.yaml| Flag | Short | Type | Default | Description |
|---|---|---|---|---|
--input | -i | string | — | Input as key=value. Repeatable. Values are JSON-parsed, falling back to strings. |
--input-file | — | string | — | Path to a JSON file containing workflow inputs. |
--cwd | — | string | — | Working directory for exec participants. See Working directory. |
--event-backend | — | string | memory | Event hub backend: memory, nats, or redis. |
--nats-url | — | string | — | NATS server URL. Required when --event-backend=nats. |
--nats-stream | — | string | duckflux-events | JetStream stream name. |
--redis-addr | — | string | localhost:6379 | Redis server address (host:port). |
--redis-db | — | string | 0 | Redis database number. |
--trace-dir | — | string | — | Directory to write execution trace files. One file per run, named <executionId>.<ext>. |
--trace-format | — | string | json | Trace output format: json, txt, or sqlite. |
--verbose | -v | boolean | false | Print error stack traces to stderr. |
--quiet | — | boolean | false | Suppress stdout output. |
Input sources
Section titled “Input sources”Inputs are merged from multiple sources. Higher entries take priority:
--inputflags (highest)--input-filecontents- JSON piped via
stdin(when no other input source is provided)
--input value parsing
Section titled “--input value parsing”Values are JSON-parsed first, falling back to plain strings:
--input name=World # {name: "World"}--input count=3 # {count: 3}--input active=true # {active: true}--input data='{"x":1}' # {data: {x: 1}}--input items='[1,2,3]' # {items: [1, 2, 3]}--input flag # {flag: true} (no "=" → boolean true)Output
Section titled “Output”stringoutput → printed as-is (no trailing newline added)- Object/array output → printed as formatted JSON (2-space indent)
null/undefinedoutput → nothing printed
Exit codes
Section titled “Exit codes”| Code | Meaning |
|---|---|
0 | Workflow succeeded |
1 | Execution error (file not found, parse error, unhandled exception) |
2 | Workflow ran but returned success: false |
Examples
Section titled “Examples”# Basic executionquack run workflow.yaml
# Pass inputsquack run workflow.yaml --input name=World --input count=3
# Inputs from filequack run workflow.yaml --input-file inputs.json
# Piped inputscat inputs.json | quack run workflow.yaml
# Custom working directory with verbose errorsquack run workflow.yaml --cwd /workspace --verbose
# NATS event backendquack run workflow.yaml \ --event-backend=nats \ --nats-url=nats://localhost:4222
# Redis event backendquack run workflow.yaml \ --event-backend=redis \ --redis-addr=localhost:6379
# Write a JSON trace for each runquack run workflow.yaml --trace-dir ./traces
# Write a SQLite trace (all runs in separate DB files)quack run workflow.yaml --trace-dir ./traces --trace-format sqliteTracing
Section titled “Tracing”Use --trace-dir to capture a structured execution record for each run. See Execution tracing for full details.
Validates a workflow file without executing it. Checks schema correctness, semantic consistency, and common authoring issues.
quack lint <workflow.yaml>Checks performed
Section titled “Checks performed”- Schema validation — the file must conform to the duckflux JSON schema.
- Semantic validation — participant references, variable bindings, and imports are verified.
- Lint warnings (non-blocking) — the following patterns are flagged:
- Loops without both
untilandmaxconditions (infinite-loop risk) - Parallel branches writing to the same context variable (race condition risk)
- Inline participants without an
asname (output unreachable by name)
- Loops without both
If all checks pass, valid is printed to stdout. Errors and warnings go to stderr.
Exit codes
Section titled “Exit codes”| Code | Meaning |
|---|---|
0 | Workflow is valid |
1 | Validation failed or file could not be read |
Example
Section titled “Example”quack lint workflow.yaml
# CI-friendly: capture all outputquack lint workflow.yaml 2>&1
# Check exit codeif quack lint workflow.yaml; then echo "Ready to run"fivalidate
Section titled “validate”Performs the same checks as lint, and additionally validates provided inputs against the workflow’s declared inputs schema.
quack validate <workflow.yaml> [flags]| Flag | Short | Type | Default | Description |
|---|---|---|---|---|
--input | -i | string | — | Input as key=value. Repeatable. |
--input-file | — | string | — | Path to a JSON file containing inputs. |
stdin is also accepted (same rules as run).
Checks performed
Section titled “Checks performed”- Schema validation
- Semantic validation
- Input schema validation — types,
enum,min,max,pattern,format, and required fields are all checked against the values you provide.
Exit codes
Section titled “Exit codes”| Code | Meaning |
|---|---|
0 | All validations passed |
1 | Validation failed |
Examples
Section titled “Examples”# Validate structure onlyquack validate workflow.yaml
# Validate structure + inputsquack validate workflow.yaml --input name=World --input count=3
# Inputs from filequack validate workflow.yaml --input-file test-inputs.json
# Piped inputsecho '{"name":"World"}' | quack validate workflow.yamlserver
Section titled “server”Starts the duckflux web server UI — a local dev tool for executing and observing workflows visually. See Web Server UI for a full feature walkthrough with screenshots.
quack server [flags]| Flag | Type | Default | Description |
|---|---|---|---|
--trace-dir | string | — | Required. Directory to watch for execution trace JSON files. |
--workflow-dir | string | cwd | Directory to scan for .yaml / .yml workflow files. |
--port | string | 3000 | HTTP port for the web UI. |
Auto-install
Section titled “Auto-install”If @duckflux/server is not installed in the current project, the CLI prompts to install it automatically:
@duckflux/server is not installed. Install it now? [Y/n]Answering Y runs bun add @duckflux/server -D (falling back to npm install if Bun is not available).
Examples
Section titled “Examples”# Start with trace output directoryquack server --trace-dir ./traces
# Custom workflow directory and portquack server --trace-dir ./traces --workflow-dir ./workflows --port 8080version
Section titled “version”Prints the CLI version to stdout.
quack version# 0.7.0Always exits with code 0.
Event hub backends
Section titled “Event hub backends”The --event-backend flag (used with run) selects the pub/sub layer for emit and wait participants.
| Backend | Flag value | Infrastructure | Replay | Cross-process |
|---|---|---|---|---|
| In-memory | memory (default) | None | Yes | No |
| NATS JetStream | nats | NATS server | No | Yes |
| Redis Streams | redis | Redis server | Yes | Yes |
For detailed configuration of each backend see Event hub providers.
Error handling
Section titled “Error handling”Unknown command — prints available commands and exits with code 1.
Missing file argument — prints the command’s usage string to stderr and exits with code 1.
Backend not installed — if @duckflux/hub-nats or @duckflux/hub-redis is missing, the CLI prints an installation hint and exits with code 1:
Error: NATS backend requires @duckflux/hub-nats — install it with: bun add @duckflux/hub-nats--nats-url missing — required when --event-backend=nats; exits with code 1 if omitted.
--verbose / -v — appends the full stack trace to stderr for any error, regardless of command.