Skip to main content

Ready-to-run automations with a Python escape hatch

Project description

Stepyard

Stepyard

YAML pipelines. Python plugins. Runs on your machine - no server to set up, no cloud account needed.

CI Coverage PyPI Python License: MIT Issues

Stepyard demo

pip install stepyard
stepyard init my-automations && cd my-automations
stepyard run hello

Quick example

Build a container, smoke-test it, summarise the result with an LLM, and post to Slack. One YAML file, no glue scripts.

name: deploy
description: Build the image, smoke-test it, and post an AI summary to Slack.

steps:
  - id: build
    uses: shell.run
    with:
      command: docker build -t myapp:${{ env.GIT_SHA }} .

  - id: smoke_test
    uses: http.request
    with:
      method: GET
      url: https://staging.myapp.com/healthz

  - id: summary
    uses: llm.generate            # built-in - reads OPENAI_API_KEY from the env
    with:
      model: gpt-4o-mini
      prompt: |
        Write a one-line Slack message about this deploy.
        Build exit code: ${{ steps.build.output.code }}
        Health check HTTP status: ${{ steps.smoke_test.output.status }}

  - id: notify
    uses: http.request
    with:
      method: POST
      url: ${{ env.SLACK_WEBHOOK }}
      json_body:
        text: ${{ steps.summary.output.output }}

Run it:

GIT_SHA=$(git rev-parse --short HEAD) stepyard run deploy
✓  build         12.4s
✓  smoke_test     0.3s
✓  summary        0.9s
✓  notify         0.2s

Flow completed in 13.8s

Reading step outputs. Each node has a documented output shape, referenced as ${{ steps.<id>.output... }}:

Node output shape
shell.run { stdout, stderr, code }
http.request { status, headers, body }
llm.generate { output, usage, model, provider } (use ${{ steps.<id>.output.output }} for text)

Full reference: docs/nodes/builtin.md.


Why Stepyard?

  • Flows are YAML files in your repo. Steps, conditions, loops, and retries are plain keys. Version-control them alongside your code; no proprietary DSL to learn.
  • Extend with plain Python. One @node decorator turns any function into a reusable step. Inputs are type-validated automatically; plugin dependencies run in an isolated virtualenv, so they never clash with Stepyard's own.
  • Nothing leaves your machine. State is stored in a local SQLite database. Data only goes out if a step in your flow explicitly sends it.
  • Every run is its own process. Each flow executes in a dedicated OS subprocess, so a crash, timeout, or sys.exit in one run cannot take down the scheduler or a sibling run. See Execution model.
  • Built-in scheduler, no hosted service. Add a trigger: block with cron, interval, or startup, run stepyard service start, and flows execute on schedule without a control plane.

Install

# from PyPI
pip install stepyard

# or, for development, with uv
git clone https://github.com/rorlikowski/stepyard && cd stepyard
uv pip install -e ".[dev,docs]"
uv run stepyard doctor      # verify the install

Requires Python 3.10+. Works on macOS, Linux, and Windows (WSL).


The 60-second tour

stepyard init my-automations   # scaffold flows/ + .gitignore + .stepyard/
cd my-automations

stepyard run hello             # run a flow now (in its own subprocess)
stepyard status               # see every flow and its latest run
stepyard show <run-id>        # drill into the steps of one run
stepyard logs <run-id>        # stream the captured logs
stepyard validate --all       # type-check your YAML without running it

Schedule it instead of running by hand - add a trigger and start the daemon:

name: nightly_backup
trigger:
  uses: cron
  with:
    schedule: "0 3 * * *"      # every day at 03:00

steps:
  - id: dump
    uses: shell.run
    with:
      command: pg_dump ${{ env.DATABASE_URL }} | gzip > /tmp/backup.sql.gz
stepyard service start          # run the scheduler in the background
stepyard service status

Execution model

Stepyard is deliberately process-isolated:

  1. stepyard run <flow> spawns a fresh subprocess (python -m stepyard.engine.runner) for that single run. Its stdout/stderr are captured to .stepyard/logs/.
  2. The scheduler daemon (stepyard service start) runs separately. It evaluates triggers, enqueues runs in SQLite, and a worker spawns one subprocess per run (bounded by STEPYARD_MAX_CONCURRENT_FLOWS, default 4).
  3. Inside a run, steps execute sequentially. Built-in nodes run in-process; plugin nodes installed into an isolated virtualenv run in a second short-lived subprocess that talks JSON over stdin/stdout - so a plugin's dependencies can never clash with Stepyard's own.

The practical upshot: one misbehaving flow or plugin cannot corrupt the scheduler or sibling runs.


Write your own step

# my_plugin/nodes.py
from stepyard.sdk import node, NodeResult, NodeStatus

@node(name="math.add")
def add(a: int, b: int) -> int:
    return a + b

@node(name="files.archive")
def archive(path: str) -> NodeResult:
    if not path:
        return NodeResult(status=NodeStatus.FAILED, error="path is required")
    # ... do the work ...
    return NodeResult(status=NodeStatus.SUCCESS, output={"archived": path})

Register it via an entry point and it becomes available as uses: math.add in every flow. See docs/plugins/creating.md.


Documentation

Section What's inside
Getting Started Install, quickstart, two tutorials
Core Concepts Flows, expressions, control flow, triggers, errors
How-to Guides Scheduling, secrets, approvals, debugging
Built-in Nodes Every node that ships with Stepyard
Plugin Development Write, test, and publish plugins
CLI Reference Every command and flag

The full documentation is published at rorlikowski.github.io/stepyard.

Browse the docs locally with uv run mkdocs serve.


License

MIT - see LICENSE.

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

stepyard-0.1.1.tar.gz (1.5 MB view details)

Uploaded Source

Built Distribution

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

stepyard-0.1.1-py3-none-any.whl (127.9 kB view details)

Uploaded Python 3

File details

Details for the file stepyard-0.1.1.tar.gz.

File metadata

  • Download URL: stepyard-0.1.1.tar.gz
  • Upload date:
  • Size: 1.5 MB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for stepyard-0.1.1.tar.gz
Algorithm Hash digest
SHA256 47713599676b0ad4c8eca4ba0607df3b887d6559559250cc7795196b0d91dba5
MD5 93dc5babd50dc24d143d9ebef0754ee1
BLAKE2b-256 edf27543ac52f26ee97987b2364b78c92d21642c73f6598bc02af64ef6c2d90a

See more details on using hashes here.

Provenance

The following attestation bundles were made for stepyard-0.1.1.tar.gz:

Publisher: release.yml on rorlikowski/stepyard

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file stepyard-0.1.1-py3-none-any.whl.

File metadata

  • Download URL: stepyard-0.1.1-py3-none-any.whl
  • Upload date:
  • Size: 127.9 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for stepyard-0.1.1-py3-none-any.whl
Algorithm Hash digest
SHA256 f3b7c3d2e07ad55581cd5fc27e6ac52f82ffbcd96a8d0366084af446d178d546
MD5 3185e1244f31bf43c54e474ead069323
BLAKE2b-256 1d5abd56c45e76f1a479cb454da732a233181d6f6cbb453f25a29673a5a01018

See more details on using hashes here.

Provenance

The following attestation bundles were made for stepyard-0.1.1-py3-none-any.whl:

Publisher: release.yml on rorlikowski/stepyard

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

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