Skip to main content

flowsh-cli

flowsh-cli turns workflow YAML into executable shell scripts.

Use it when you want a small, reproducible way to encode a workflow once and rerun it locally or in CI.

Quick Start

uvx flowsh-cli path/to/workflows.yml

That reads the workflow YAML at the path you provide and writes harness scripts to the current working directory.

In this repository, the example workflow file lives at workflows.yml.

Useful flags:

uvx flowsh-cli path/to/workflows.yml --dry-run
uvx flowsh-cli path/to/workflows.yml --workflow wf_example
uvx flowsh-cli path/to/workflows.yml --force
uvx flowsh-cli path/to/workflows.yml --schema
uvx flowsh-cli --examples
uvx flowsh-cli --example simple

You can also run it locally with uv run flowsh-cli.

Use As A Library

flowsh-cli also works as a plain Python library, with no CLI dependencies (no typer, no terminal UI). This is the right choice if you want to parse or render workflows from your own Python code instead of shelling out to the CLI.

uv add flowsh-cli
from pathlib import Path
from flowsh_cli import parse_workflows, render_harness, harness_path

workflows = parse_workflows(Path("workflows.yml"))
for workflow in workflows:
    harness_path(workflow).write_text(render_harness(workflow))

Public API (re-exported from flowsh_cli):

Name Purpose
parse_workflows Parse and validate a workflow YAML file (given its Path) into Workflow objects.
Workflow Pydantic model of a single workflow.
WorkflowParseError Raised on invalid workflow YAML.
render_harness Render a Workflow into a shell harness script.
harness_path Compute the output path for a workflow's harness script.

If you also want the flowsh-cli command-line tool (built on typer), install the cli extra:

uv add "flowsh-cli[cli]"
# or, for one-off use without installing:
uvx flowsh-cli path/to/workflows.yml

Workflow Shape

The input file is a single mapping with a workflows list:

workflows:
  - id: wf_example
    name: Example
    params:
      - name: ISSUE_NUMBER
        description: Issue to inspect
        required: true
    steps:
      - type: vars
        values:
          TODAY: date -u +%F
      - type: bash
        run: printf 'today=%s\n' "$TODAY"
      - type: agent
        agent: general
        model: openai/gpt-5
        command: review
        expandPrompt: true
        prompt: |
          Review issue ${ISSUE_NUMBER} and summarize the repository state.
       - type: parallel
         steps:
           - type: bash
             run: echo "worker A"
           - type: bash
             run: echo "worker B"
       - type: for
         in: ITEMS
         item: ITEM
         steps:
           - type: bash
             run: echo "$ITEM"
       - type: while
         condition: '[ -n "$(ls doc/plan/steps/planned/ 2>/dev/null)" ]'
         steps:
           - type: bash
             run: echo "keep looping until the queue is empty"

Harness paths are derived from workflow ids. wf_example becomes example.sh in the current working directory.

Step Types

Type Purpose Notes
vars Execute shell commands and export their stdout into shell variables Variable names must be uppercase shell identifiers.
bash Run shell commands Runs with bash -euo pipefail.
agent Call the agent runtime Supports agent, model, command, capture, expandPrompt, and dangerouslySkipPermissions.
for Iterate over newline-delimited values from a previous vars step Flat iteration only; nested for steps are not supported.
while Re-evaluate a Bash condition before each iteration Use for dynamic queues or other stateful loops that must keep discovering new work.
parallel Run child steps concurrently Children run as separate branches and the parent waits for all of them. capture inside a branch is not visible to sibling branches or later steps — see Agent Behavior below.

Agent Behavior

agent prompts are literal by default. Use expandPrompt: true only when you want $VAR or ${VAR} tokens from earlier vars steps substituted at runtime.

expandPrompt: true does plain text replacement only. It does not evaluate shell expressions like $(...), backticks, or globs.

Set capture: VARIABLE_NAME on an agent step when you want the agent's final plain-text answer stored in a shell variable for later vars or bash steps. The captured value is the answer text (extracted from the underlying --format json event stream via jq), not the raw JSON stream — requires jq to be installed.

Set dangerouslySkipPermissions: true only when you want the generated harness to pass --dangerously-skip-permissions to the agent runtime. The YAML alias dangerously-skip-permissions is also accepted.

Inside a parallel step, each child branch runs in its own backgrounded subshell, so capture set in one branch is not visible to sibling branches and does not survive past the parallel block — there is no gather/join mechanism. To share results across branches (e.g. fan out N agents and merge their verdicts afterward), have each branch write its result to its own file (via a bash instruction in the agent prompt, or a bash child step), then read all the files back in a plain bash or vars step placed after the parallel block.

Validation And Safety

The parser is strict:

  • workflow YAML must be UTF-8, non-empty, and under 1 MiB
  • the root must be a mapping with a workflows key
  • duplicate mapping keys and YAML aliases are rejected
  • workflow ids must match wf_[A-Za-z0-9_-]+
  • workflow and step names must be non-empty single-line labels
  • unsafe control characters are rejected in executable fields
  • agent names may contain only letters, digits, _, and -

Generated harnesses are non-interactive, owner-executable, and refuse to overwrite existing outputs unless --force is set.

Logs go to .flowsh/logs by default. Set FLOWSH_LOG_DIR to use another relative log directory.

Development

uv sync
make install
make qa
make security
make clean

make qa runs linting, tests, a dependency security audit, and a local build. make security audits hash-pinned runtime, CLI-extra, and development dependencies exported from uv.lock against known vulnerability advisories. It requires network access and fails if the audit cannot complete. The isolated build backend and downloaded CI tools are outside this dependency scan.

GitHub Actions are pinned to immutable commits. CI installs OpenCode 1.14.40 from a versioned Linux release archive and verifies its SHA-256 before extraction. Workflow comments and prompts are passed as data, not interpolated into shell scripts; only repository-owner comments can request agent execution. Agent runs still have their job's declared GitHub permissions, so review untrusted issue content before authorizing write-capable work.

Release

make bump-patch

That bumps the patch version, runs QA, and publishes the package.

Limits

This repository intentionally stays focused on the Python CLI blueprint. It does not include the old TypeScript implementation, workflow templates, DSL explorer, plugin registry, or extra workflow node types.

Metadata

Release files for flowsh-cli 0.11.1

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for flowsh-cli 0.11.1
File Size Uploaded Provenance Actions
flowsh_cli-0.11.1.tar.gz 17.8 kB Without provenance Details for flowsh_cli-0.11.1.tar.gz

Built distribution (wheel)

Table of built distributions (wheels) for flowsh-cli 0.11.1
File Interpreter ABI Platform Actions
flowsh_cli-0.11.1-py3-none-any.whl Python 3 none any Details for flowsh_cli-0.11.1-py3-none-any.whl

Total release size: 38.5 kB

Release files / flowsh_cli-0.11.1.tar.gz

Download URL flowsh_cli-0.11.1.tar.gz
Size 17.8 kB
Tags Source
SHA-256 checksum
How to use checksums
d58a1a365a4ca0b4cbeb1dd9e84d5a418cb769e70885df3f26da7bbe1fc44f16
BLAKE2b-256 checksum
How to use checksums
a765dc24f1c81381ce32d05c6cb5f1394f6e7ce88becd29afe1b65e1951e59e3
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via uv/0.12.7 {"installer":{"name":"uv","version":"0.12.7","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}

Release files / flowsh_cli-0.11.1-py3-none-any.whl

Download URL flowsh_cli-0.11.1-py3-none-any.whl
Size 20.6 kB
Tags Python 3
SHA-256 checksum
How to use checksums
64f3245c4456aaa5e527a82a4eb5397ab3aaccbb232db638e185943ed044538e
BLAKE2b-256 checksum
How to use checksums
36f82283a9de18cada9b2d376792aedd981c0ee8e69d1fe544bfeb20bc6d63fa
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via uv/0.12.7 {"installer":{"name":"uv","version":"0.12.7","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}

Security for flowsh-cli 0.11.1

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

No provenance found

None of the files in this release were uploaded with provenance metadata.

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page