Skip to main content

A minimal shell script orchestrator with SSH support

Project description

ShellFlow

DeepWiki Context7 Python 3.12+ License: Apache-2.0 PyPI

shellflow

ShellFlow is a minimal shell script orchestrator for mixed local and remote execution. You write one shell script, mark execution boundaries with comments, and ShellFlow runs each block in order while resolving remote targets from your SSH configuration.

shellflow-run

What It Does

  • Split a shell script into @LOCAL and @REMOTE execution blocks.
  • Run each block fail-fast, in order.
  • Reuse the shared prelude before the first marker for every block.
  • Pass the previous block output forward as SHELLFLOW_LAST_OUTPUT.
  • Resolve remote targets from ~/.ssh/config or a custom SSH config path.

Quick Start

git clone https://github.com/longcipher/shellflow.git
cd shellflow
uv sync --all-groups # uv sync --refresh --reinstall --no-cache
uv tool install --force --reinstall --refresh --no-cache .

shellflow run playbooks/hello.sh

If you do not want a global tool install, use uv run shellflow run playbooks/hello.sh.

Installation

Development checkout

git clone https://github.com/longcipher/shellflow.git
cd shellflow
uv sync --all-groups # uv sync --refresh --reinstall --no-cache

Install as a local tool

uv tool install --force .
shellflow --version

Install into the active environment

uv pip install -e .
shellflow --version

Script Format

Shellflow recognizes two markers:

  • # @LOCAL
  • # @REMOTE <ssh-host>

<ssh-host> must match a Host entry in your SSH config. Shellflow then connects using that SSH host definition, which means the actual machine can be resolved through the configured HostName, User, Port, and IdentityFile values.

Example:

#!/bin/bash
set -euo pipefail

# @LOCAL
echo "runs locally"

# @REMOTE sui
uname -a

# @LOCAL
echo "remote output: $SHELLFLOW_LAST_OUTPUT"

SSH Configuration

Example ~/.ssh/config entry:

Host sui
    HostName 192.168.1.100
    User deploy
    Port 22
    IdentityFile ~/.ssh/id_ed25519

With that config, this block is valid:

# @REMOTE sui
hostname

This is intentional:

  • Shellflow accepts configured SSH host names, not arbitrary free-form targets.
  • Unknown remote targets fail early with a clear error before spawning ssh.
  • You can override the default config path with --ssh-config.

Execution Model

Each block runs in a fresh shell.

  • Shell options from the prelude are copied into every block.
  • Shell state like cd, shell variables, aliases, and export commands does not persist across blocks.
  • Explicit context values are passed forward through environment variables.

Example:

# @LOCAL
echo "build-123"

# @LOCAL
echo "last output = $SHELLFLOW_LAST_OUTPUT"

Lines before the first marker are treated as a shared prelude and prepended to every executable block:

#!/bin/bash
set -euo pipefail

# @LOCAL
echo "prelude is active"

# @REMOTE sui
echo "prelude is also active here"

CLI

shellflow run <script>
shellflow run <script> --verbose
shellflow run <script> --ssh-config ./ssh_config
shellflow --version

Examples:

shellflow run playbooks/hello.sh
shellflow run playbooks/hello.sh -v
shellflow run playbooks/hello.sh --ssh-config ~/.ssh/config.work

Development

Useful commands:

just sync
just test
just bdd
just test-all
just typecheck
just build
just publish

Direct verification commands:

uv run pytest -q
uv run behave features
uv run ruff check .
uv run ty check src tests
uv build

Release Process

Shellflow supports both local publishing and GitHub Actions release publishing.

Local publish

just publish

uv publish uses standard uv authentication mechanisms such as UV_PUBLISH_TOKEN, or PyPI trusted publishing when supported by the environment.

GitHub Actions publish on tag push

The repository includes:

  • .github/workflows/ci.yml for lint, type-check, test, and build verification.
  • .github/workflows/release.yml for publishing to PyPI when a tag like v0.1.0 is pushed.

Recommended release flow:

git tag v0.1.0
git push origin v0.1.0

To use trusted publishing with PyPI:

  1. Create a pypi environment in GitHub repository settings.
  2. Add this repository as a trusted publisher in the PyPI project settings.
  3. Push a v* tag.

The release workflow then runs verification, builds distributions with uv build, and uploads them with uv publish.

Project Layout

shellflow/
├── src/shellflow.py
├── tests/
├── features/
├── playbooks/
├── pyproject.toml
├── Justfile
└── README.md

License

Apache-2.0

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

shellflow-0.1.0.tar.gz (332.1 kB view details)

Uploaded Source

Built Distribution

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

shellflow-0.1.0-py3-none-any.whl (9.6 kB view details)

Uploaded Python 3

File details

Details for the file shellflow-0.1.0.tar.gz.

File metadata

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

File hashes

Hashes for shellflow-0.1.0.tar.gz
Algorithm Hash digest
SHA256 747173c7dac6d08b292c367fe5c8ae57efe607865234d773997236c92c27e952
MD5 e367e0d655a61c243364db2dce82ac1d
BLAKE2b-256 1b0fc67d3e86b06eb22d29010439f5396f3f6595fb47c55a523519d0f15790f4

See more details on using hashes here.

File details

Details for the file shellflow-0.1.0-py3-none-any.whl.

File metadata

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

File hashes

Hashes for shellflow-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 d203d877f0990f96c46ccb8c7318d04b9453fb2ad63be558c6e4b67fc62e4a91
MD5 20b609e84e757368dedb0ee386a961d8
BLAKE2b-256 9bbf683cd2089dd5f4b601e25d53775035b1499c10848e8ffb62323b09b0b54c

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