CLI Reference#
Both Python and Rust implementations share the same CLI interface with identical subcommands and flags.
Basic Commands#
# Run a workflow
tea run workflow.yaml --input '{"query": "hello"}'
tea run workflow.yaml --input @state.json
# Run with secrets
tea run workflow.yaml --secrets '{"api_key": "sk-123"}'
tea run workflow.yaml --secrets @secrets.json
tea run workflow.yaml --secrets-env TEA_SECRET_
# Streaming NDJSON output (for pipelines)
tea run workflow.yaml --stream
Interrupt Control#
# CLI interrupt control
tea run workflow.yaml --interrupt-before node1,node2
tea run workflow.yaml --interrupt-after classify
tea run workflow.yaml --auto-continue
See Human-in-the-Loop Guide for detailed interrupt workflow documentation.
Custom Actions (Python Only)#
# Load custom actions
tea run workflow.yaml --actions-module my_package.actions
tea run workflow.yaml --actions-file ./custom_actions.py
See Custom Actions Guide for creating custom action modules.
Resume from Checkpoint#
# Resume from checkpoint
tea resume checkpoint.pkl --workflow workflow.yaml
tea resume checkpoint.pkl --workflow workflow.yaml --input '{"update": "value"}'
Validation and Inspection#
# Validate workflow (without execution)
tea validate workflow.yaml
tea validate workflow.yaml --detailed
# Inspect workflow structure
tea inspect workflow.yaml
tea inspect workflow.yaml --format json
tea inspect workflow.yaml --format dot # Graphviz output
Verbosity Control#
tea run workflow.yaml -v # info
tea run workflow.yaml -vv # debug
tea run workflow.yaml -vvv # trace
tea run workflow.yaml -q # quiet (errors only)
Progress Heartbeat (TEA-DX-001.7)#
# Emit one progress line on stderr per node completion (default off)
tea run workflow.yaml --heartbeat
tea run workflow.yaml --quiet --heartbeat # silent stdout, heartbeat-only stderr
The --heartbeat flag is the recommended middle ground between --quiet
(no output) and --stream (full NDJSON). It prints exactly one line to
stderr per node completion:
Success:
[<node_name> done in <duration>]Failure:
[<node_name> FAILED in <duration>]Parallel branches:
[parallel:<branch_name> done in <duration>]
Notes:
Default off; combine with any other run flag.
Output goes to stderr so stdout pipelines and
--outputredirects remain byte-identical to a non-heartbeat run.Durations are wall-clock deltas between consecutive engine events (
50ms/1.2s/2m 18s/1h 1m 40s).Pair with
--quietfor long workflows where you want progress signal without the verbosity of--stream.--heartbeattogether with--streamworks but is redundant — prefer one or the other.
Intermediate State Dumps for Debug (TEA-DX-001.3)#
# Write per-node JSON state snapshots to <dir> as the workflow runs (default off)
tea run workflow.yaml --debug-state ./dumps/
The --debug-state <dir> flag captures the state after every node so you
can inspect the failure point post-mortem when a multi-node workflow
raises before reaching __end__ and the --output file would otherwise
be empty.
File naming:
Success:
<NN>-after-<node_name>.json(e.g.01-after-classify.json)Failure:
<NN>-FAILED-<node_name>.json— payload includes atracebackfield<NN>is a zero-padded sequence counter for the run
Notes:
The dump dir is created if missing; pre-existing files in the dir are preserved (you can
rm -rfbetween runs).A
WARNING:line is emitted to stderr at startup whenever--debug-stateis set, surviving--quiet. The flag is intended for development; do not enable it in production / CI.Node-name path components are sanitized: characters outside
[A-Za-z0-9_-]are replaced with_so a YAML node name like../../etc/passwdcannot escape the dump directory.Compatible with
--quiet,--stream,--show-graph, and--checkpoint— combine freely.For parallel /
dynamic_parallelblocks, only the parent fan-out and fan-in nodes are dumped; per-branch events (parallel_state,parallel_error,branch_complete) do not produce extra files.Redaction scope (Option B):
--debug-statedoes not redact state fields. Whatever lives in state is written to disk as-is, and exception messages appear verbatim in the FAILED dump’stracebackfield. Keep secrets in the secrets backend (tea run --secrets .../secrets.get), not in state. The startupWARNINGexists precisely to make this scope explicit at every invocation.Dump-write failures (e.g. read-only / full-disk dump dir) are swallowed and logged at DEBUG level — they never replace the user’s actual node exception.
No size cap in v1; on very long workflows with large states this can fill disk fast — use a dedicated directory and clean up afterwards.
Troubleshooting: empty --output after a mid-run failure#
If a node raises before reaching __end__, the --output file is
empty/missing because the engine never reaches the terminal final
event. Re-run with --debug-state ./dumps/ to capture per-node JSON
snapshots; the last <NN>-after-... file is the state right before the
failure, and <NN>-FAILED-... contains both the pre-node state and the
exception traceback.
Trace File Override (TEA-DX-001.2)#
# Override settings.trace_file for a single run
tea run workflow.yaml --trace-file ./traces/run-1.jsonl
tea run workflow.yaml --trace-file '${TRACE_DIR}/run.jsonl' # ${ENV_VAR} expansion
The --trace-file flag wires a JSON-lines FileExporter for the run
without requiring YAML edits or temp YAML rendering. Useful for external
runners that re-execute the same YAML many times with per-run trace paths.
Precedence and implicit behavior:
CLI
--trace-fileoverridessettings.trace_file. When set, the YAML’s trace path is ignored.Implicitly enables
auto_trace=trueeven if YAML hassettings.auto_trace: false— the user’s intent is clear when they ask for a trace path on the command line.Implicitly switches
trace_exporterto"file"if it is unset or"console". If the YAML already specifiestrace_exporter: file, only the path is overridden (exporter type unchanged).The path supports
${ENV_VAR}and${ENV_VAR:-default}expansion via the same helper used bysettings.trace_file(parity with TEA-DX-001.1).A bad path (e.g. parent-not-a-directory) exits with a
typer.BadParametererror referencing--trace-file, not a raw Python traceback.
Exit Condition Control (TEA-CLI-008)#
# Exit with code 1 if final state matches condition
tea run workflow.yaml --fail-on-state 'final_status=failed'
tea run workflow.yaml --fail-on-state 'final_status=failed' --fail-on-state 'error=true'
# Useful for CI/CD pipelines to detect workflow failures
tea run workflow.yaml --fail-on-state 'validation_status=incomplete' && echo "Success" || echo "Failed"
The --fail-on-state option checks the final workflow state against key=value conditions:
Specify multiple conditions (any match triggers exit 1)
Comparison is string-based (numeric values are compared as strings)
Works with
--stream,--show-graph, and default output modes
DOT File Execution (Python Only, TEA-GAME-001)#
# Execute DOT files with tmux (phases respect dependencies)
tea run --from-dot workflow.dot
tea run --from-dot workflow.dot --dot-session my-session
tea run --from-dot workflow.dot --dot-max-parallel 4
tea run --from-dot workflow.dot --dot-dry-run
# Workflow mode: run a YAML for each DOT node
tea run --from-dot stories.dot --dot-workflow bmad-validation.yaml
tea run --from-dot stories.dot --dot-workflow dev.yaml --dot-input '{"mode": "quick"}'
# Stop-on-failure control (TEA-CLI-008)
tea run --from-dot stories.dot --dot-stop-on-failure # Default: stop after phase if any node fails
tea run --from-dot stories.dot --no-dot-stop-on-failure # Continue all phases regardless of failures
# Resume from specific wave/step (TEA-CLI-009)
tea run --from-dot workflow.dot --dot-start-wave 3 # Skip waves 1-2, start from wave 3
tea run --from-dot workflow.dot --dot-start-step 2 # Skip step 1 in wave 1
tea run --from-dot workflow.dot --dot-start-wave 2 --dot-start-step 3 # Skip wave 1, skip steps 1-2 in wave 2
tea run --from-dot workflow.dot --dot-start-from "Build" # Start from node "Build" (finds wave/step)
tea run --from-dot workflow.dot --dot-start-wave 2 --dot-dry-run # Preview skipped/executed nodes
Exit code behavior for --from-dot:
Exit code 0: All nodes completed successfully
Exit code 1: One or more nodes failed (actual exit codes captured)
Wave/step selection options (TEA-CLI-009):
--dot-start-wave N: Skip waves 1 to N-1, start from wave N (1-based)--dot-start-step M: Skip steps 1 to M-1 in the starting wave (1-based)--dot-start-from <label>: Start from node with this label (mutually exclusive with wave/step options)
Version and Implementation Info#
tea --version # tea 0.1.0
tea --impl # python or rust
tea --version --impl # tea 0.1.0 (python)
# Show help
tea --help
tea run --help
Example Output#
================================================================================
Running agent from: examples/yaml_agent_example.yaml
================================================================================
Initial state: {
"query": "artificial intelligence"
}
[check] search
[check] validate_results
[check] summarize
[check] format_output
[check] save_report
================================================================================
[check] Completed
================================================================================
Final state: {...}
Actions Loading Priority#
When multiple action sources are specified, they are loaded in this order (later sources override earlier):
Built-in actions (lowest priority)
CLI
--actions-moduleflags (in order specified)CLI
--actions-fileflags (in order specified)YAML
imports:section (highest priority - overrides CLI actions)
Security Warning#
The --actions-module and --actions-file flags execute Python code from the specified modules. Only load actions from trusted sources. For production use, prefer installed packages over local files.