Skip to main content

Generate Bash harness scripts from workflow YAML files.

Project description

flowsh-cli

flowsh-cli is a small uv Python CLI that reads workflow YAML and writes executable Bash harness scripts for OpenCode.

Supported YAML

Only this top-level shape is supported:

workflows:
  - id: wf_example
    name: Example
    steps:
      - type: vars
        name: Capture date
        values:
          TODAY: date -u +%F
      - type: bash
        name: Print date
        run: |
          printf 'today=%s\n' "$TODAY"
      - type: agent
        name: Ask OpenCode
        agent: general
        model: openai/gpt-5
        command: review
        prompt: |
          Summarize the current repository state.

Supported step types are only vars, bash, and agent.

The input path must be a regular file no larger than 1 MiB. The input file must be valid UTF-8, non-empty YAML with a mapping root, no duplicate mapping keys, and no YAML aliases. Workflow and step names are single-line labels. Executable fields reject unsafe control bytes while allowing normal newlines and tabs. vars keys must be uppercase shell variable names, and agent names may contain only letters, digits, _, and -. Agent model values are passed through to OpenCode, so provider/model IDs such as openai/gpt-5 are valid. Agent command values map to OpenCode --command; the prompt remains the message/arguments after --.

Agent prompts are literal by default. Set expandPrompt: true on an agent step only when the prompt should be expanded by Bash at harness runtime, for example to insert values exported by earlier vars steps:

- type: agent
  name: Fix captured issue
  agent: general
  expandPrompt: true
  prompt: |
    Follow issue #$ISSUE_NUMBER.

expandPrompt: true is a security-sensitive opt-in: Bash also performs command substitution such as $(...) and backticks in the prompt body before OpenCode receives it. Keep it disabled for prompts that contain shell examples or untrusted content.

Set dangerouslySkipPermissions: true on an agent step only when the generated harness should pass OpenCode --dangerously-skip-permissions. The flag is false by default, accepts the YAML alias dangerously-skip-permissions, and auto-approves permissions that are not explicitly denied. Treat it as security-sensitive and avoid it for untrusted workflows.

Harness paths are derived from workflow ids. wf_example writes .harness/example.sh.

Commands

# Generate every workflow harness
uvx flowsh-cli .made/workflows.yml

# Generate one workflow by id
uvx flowsh-cli .made/workflows.yml --workflow wf_example

# Show planned outputs without writing files
uvx flowsh-cli .made/workflows.yml --dry-run

# Overwrite existing harness files
uvx flowsh-cli .made/workflows.yml --force

# Show version
uvx flowsh-cli --version

# Show the workflow YAML schema
uvx flowsh-cli --schema

You can also run it via uv run flowsh-cli if installed locally.

CLI Contract

flowsh-cli is non-interactive. It never prompts for missing information.

Current help output is plain text and deterministic across repeated runs:

Usage: flowsh-cli [OPTIONS] WORKFLOW_YAML

  Generate reproducible OpenCode Bash harness scripts from MADE workflow YAML.

Arguments:
  WORKFLOW_YAML  Path to .made/workflows.yml  \[required]

Options:
  --workflow TEXT  Optional workflow id to generate. Defaults to all workflows.
  --dry-run        Print planned output paths without writing scripts.
  --force          Overwrite existing files. Without this, existing files cause a failure.
  --version        Show the flowsh-cli version and exit.
  --schema         Show the workflow YAML schema and exit.
  --help           Show this message and exit.

The CLI pins its help formatter width so this contract does not vary with the caller terminal size or COLUMNS environment value.

Exit codes:

Case Exit stdout stderr
--help 0 Help text Empty
--version 0 flowsh-cli <version> Empty
--schema 0 Workflow schema as YAML-formatted JSON Schema Empty
Valid generation 0 One Wrote <path> line per harness Empty
Valid --dry-run 0 One DRY-RUN would write <path> line per selected workflow Empty
Missing required CLI argument 2 Empty Typer usage error
Malformed or unsupported workflow YAML 1 Empty ERROR: <reason>
Unknown --workflow id 1 Empty ERROR: No workflow id matched ... with known workflow ids
Existing harness without --force 1 Empty ERROR: Refusing to overwrite ...
Output directory/path safety failure 1 Empty ERROR: <path safety reason>

Generated harnesses are also non-interactive. harness.sh --dry-run exits 0 after logging planned steps to stderr and creating no log directory. A real harness run exits 0 only after every step succeeds. Failed bash, vars, or agent steps return the failing command status, log Step failed: <step> (exit=<code>) to stderr, and stop before later steps run. If an agent step runs without opencode on PATH, the harness exits 127 and prints opencode CLI not found in PATH to stderr.

Generated harnesses are written with owner-only executable permissions and refuse to overwrite existing paths unless --force is passed. Multi-workflow generation preflights overwrite conflicts before writing any harness. --force replaces regular harness files and harness-file symlinks, but never replaces a directory at a harness file path. The .harness output directory must be a real directory, not a symlink or file. Harness dry runs do not create log files or directories. Real harness logs go to .flowsh/logs by default with owner-private directory and file permissions. Set FLOWSH_LOG_DIR when running a harness to use another local relative log directory; absolute paths, .. path segments, symlinked path components, and non-directory log paths are refused. Logging setup and write failures fail the harness instead of being silently ignored.

Generated bash and vars bodies run with bash -euo pipefail, so command failures stop the workflow instead of being masked by later successful commands. Captured vars values are exported for later bash steps. agent prompt heredocs are quoted by default and unquoted only when expandPrompt: true is set. agent steps invoke only opencode run --format json with optional --agent <agent>, --model <provider/model>, --command <command>, and --dangerously-skip-permissions flags before -- <prompt>, so dash-prefixed prompts are message content rather than OpenCode flags. Agent steps fail with a clear error if opencode is not on PATH.

Development

uv sync
make install
make build
make qa
make hygiene
make clean

make install installs flowsh-cli into the user PATH with uv tool install --force .. make build creates reproducible source and wheel distributions under ignored dist/.

make qa runs Ruff, Python compile checks, and pytest with locked dependencies, then builds packages locally and in CI. The pytest suite also verifies python -m flowsh_cli, uvx flowsh-cli, and the direct scripts/workflow_to_harness.py entrypoint against the same help contract. make hygiene prints tracked, untracked, and ignored files with git status --short --ignored; review it before release to confirm only intended source changes are present and generated artifacts remain ignored. make clean removes local caches, build outputs, generated harnesses, and generated logs.

There is no TypeScript compiler, template system, DSL explorer, legacy node registry, or archived legacy workflow spec in this repository.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

flowsh_cli-0.6.0.tar.gz (12.6 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

flowsh_cli-0.6.0-py3-none-any.whl (15.0 kB view details)

Uploaded Python 3

File details

Details for the file flowsh_cli-0.6.0.tar.gz.

File metadata

  • Download URL: flowsh_cli-0.6.0.tar.gz
  • Upload date:
  • Size: 12.6 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.9.9 {"installer":{"name":"uv","version":"0.9.9"},"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}

File hashes

Hashes for flowsh_cli-0.6.0.tar.gz
Algorithm Hash digest
SHA256 736d46090ebb8119505a62a71b70f35aff0f03b1af3bff3732759f3ab4d32ff9
MD5 7371ef7c27ef64642d0f79b6f65c5909
BLAKE2b-256 5d06959dc07864b37271eeb6663229e92a702831fbf66ee193778aac57a4812f

See more details on using hashes here.

File details

Details for the file flowsh_cli-0.6.0-py3-none-any.whl.

File metadata

  • Download URL: flowsh_cli-0.6.0-py3-none-any.whl
  • Upload date:
  • Size: 15.0 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.9.9 {"installer":{"name":"uv","version":"0.9.9"},"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}

File hashes

Hashes for flowsh_cli-0.6.0-py3-none-any.whl
Algorithm Hash digest
SHA256 f77141838605ccc98fcafb6b3f4e6758c316b6acb6d2d3d7b90480f3d1676603
MD5 7d9908f21d42f6fe973cc3b878f24fa4
BLAKE2b-256 1c1922716bc1a67b2e332c273f36d09193bd44c21a420359acaf7d569c387f1e

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page