Makefiles are for boomers. The future is Runny.
Every project accumulates a pile of shell commands. Build scripts, test runners, deploy steps, dependency wrangling. Runny gives them a home in a clean .runny.yaml file and gets out of your way.
Syntax inspired by GitHub Actions. If you've written a workflow file, you already know how Runny works.
Full JSON schema means your editor can autocomplete keys, validate structure, and catch typos as you type.
Chain commands with needs and then. Run steps conditionally with if. No more copy-pasting sequences.
Pass arguments to commands with argnames. No quoting gymnastics or positional parameter headaches.
Mark helper commands as internal to keep your command list focused. Add description for quick reference.
A single Go binary. No runtime, no dependencies. Installs in seconds, runs instantly.
One Homebrew command. Also available via go install or GitHub releases.
Create a .runny.yaml in your project root. Or run runny --init to generate one.
Type runny <command>. Tab completion works out of the box for bash, zsh, and fish.
$ runny build go build -o dist/myapp ./... deploy Deploy to production lint golangci-lint run ./... test go test ./... test-coverage go test -coverprofile=c.out ./... $ runny test ok myapp/api 0.42s ok myapp/core 0.31s ok myapp/web 0.18s
Real configs for real workflows. Drop one of these into your project and go.
shell: /bin/bash
commands:
install-uv:
internal: true # hidden from command list
if: "! command -v uv"
run: pip install uv
pip-sync:
description: Sync dependencies from requirements.txt
needs:
- install-uv
run: uv pip sync requirements.txt
pip-install:
argnames:
- packagespec
run: echo $packagespec >> requirements.in
then:
- pip-compile-and-sync
commands:
clean:
run: |
go clean ./...
rm -rf dist
test:
run: go test ./...
release:
needs:
- clean
- install-goreleaser
run: |
export GITHUB_TOKEN=$(gh auth token)
goreleaser
commands:
up:
run: docker compose up -d
down:
run: docker compose down
logs:
argnames:
- service
run: docker compose logs $service
shell:
argnames:
- service
run: docker compose exec $service sh