sake: a Go task runner that keeps hosts and tasks in one sake.yaml
:robot: task runner for local and remote hosts
At a glance
- What is it?
- sake is a command line task runner written in Go that runs the same task across local and remote hosts defined in a single sake.yaml file. It gives you a server inventory, SSH execution, parallel strategies and table output in a small binary, and it is MIT licensed, though the last tagged release was v0.15.1 in 2023.
- Who is it for?
- Adopt sake if you keep a handful of servers you run the same commands against and want a declarative inventory plus parallel execution without writing a shell loop, and build it with a Go toolchain matching the go directive in go.mod. Skip it if you need Windows support, since the project is stated to be available on Linux and Mac, or if you want orchestration features that live in a separate tool.
- Can I use it commercially?
- Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Yes. The repository last received commits 144 days ago.
- What is it written in?
- Mainly Go, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on October 23, 2026, and from our analysis. They are not legal advice.
Editorial analysis
sake.yaml holds the server inventory and the task definitions
The whole model fits in one sentence from the README: you define servers and tasks in a sake.yaml file and then run the tasks on the servers. That is the entire architecture, and it is worth contrasting with the usual arrangement. A Makefile describes commands for one machine. A set of shell scripts with a hosts list spread across several files duplicates that list every time you add a server. sake keeps both halves in a single YAML document, parsed with gopkg.in/yaml.v3, so the inventory of hosts and the commands that run against them stay side by side. The project is built in Go, with the command surface handled by github.com/spf13/cobra and flags by github.com/spf13/pflag, and the rendered tables come from github.com/jedib0t/go-pretty/v6. The result is a single binary with no daemon, no agent and no server side state, which is a meaningful difference from the orchestration tools people often reach for when a fleet grows.
Running the same task everywhere with --all and a free strategy
The command set is where the value shows. sake list servers prints the inventory, sake list tasks prints the task list with descriptions, and sake run names a task to execute. The flag that matters is --all, which runs the task on every server in the inventory, and sake exec lets you pass an arbitrary shell command rather than a named task. The README shows the two together with a parallel strategy:
$ sake exec --all --output table --strategy=free 'find . -type f | wc -l'The --strategy=free option is the interesting part. It asks the runner to keep the work in flight rather than process servers in turn, which matters when you are counting files on twenty hosts. The --output table option renders results as a compact table instead of a stream of raw output, so a run that touches many machines is readable rather than a wall of interleaved text. Output formatting is not a cosmetic afterthought here. The same --output flag appears in the feature list for sake run, and the project carries a dedicated docs/output.md, which suggests the format choices are treated as part of the interface.
Installing sake on Linux and Mac
sake is stated to be available on Linux and Mac, and there are several installation routes. Binaries are published on the release page, and the repository also carries an install script:
curl -sfL https://raw.githubusercontent.com/alajmo/sake/main/install.sh | shPackage managers are covered too. Homebrew needs a tap before the install, while MacPorts, Arch and FreeBSD pkg each take a single command:
brew tap alajmo/sake
brew install sakeFor people who already work in Go, the module path is public and can be installed directly:
go install github.com/alajmo/sake@latestShell completion is available for bash, zsh and fish through sake completion, and man pages are generated by sake gen, which the Makefile backs with a gen-man target that builds the binary in a special buildMode. The first thing to do after installing is create a config, and sake init does that for you:
$ sake initThe output tells you it created sake.yaml and added a server. The default entry is localhost pointing at 0.0.0.0, which is a placeholder rather than a useful target, and a task named ping that returns Pong. That is enough to confirm the tool runs on your machine before you add a real host.
The go.mod directive asks for more than the README does
Here is a discrepancy worth catching before you try to build. The README says building from source requires go 1.19 or above, and lists the clone and build steps:
make build && ./dist/sakeThe module file in the repository declares a different floor:
module github.com/alajmo/sake
go 1.26.3A go directive of 1.26.3 is a language version requirement, and a toolchain older than that will refuse to build the module rather than merely warn. So the 1.19 figure in the README is out of date relative to the module, and the two disagree. If you are building from source, trust go.mod over the prose. The build itself is handled by the Makefile, which compiles with CGO_ENABLED=0 and the netgo tag, strips the binary with -s -w, and stamps the version, commit and date into the cmd package through ldflags. The target output lands in dist/sake. A second target, make build-all, drives goreleaser with --skip-publish to produce binaries for all target platforms, which means the release pipeline expects goreleaser to be installed locally.
SSH behaviour comes from two Go dependencies
How sake reaches a remote host is visible in the dependency list rather than in prose, and two entries stand out. github.com/kevinburke/ssh_config provides reading of the standard SSH configuration, which is why an existing ~/.ssh/config can plausibly inform how hosts are reached without sake reimplementing host aliases, key paths and port settings. golang.org/x/crypto supplies the underlying SSH primitives. The transport also depends on github.com/gobwas/glob for pattern matching, which is how server names and tags can be selected as groups rather than one at a time, and the topic list of the repository includes config, cli, server and ssh, which lines up with that design. Tags are one of the completion targets, so a tag is a first class way of addressing a subset of your inventory. Two more dependencies shape the interface: github.com/theckman/yacspin provides the spinner, and the indirect dependencies pull in github.com/rivo/tview with tcell, which is a terminal user interface toolkit. That combination is the reason the binary can offer a rich, non-scrolling terminal experience rather than plain lines of text.
The test suite needs Docker, not just Go
The Makefile separates two kinds of testing and the second one has infrastructure requirements. The unit tests are pure Go:
go test -v ./core/...The integration tests are not. They need mock SSH servers, and the way the project provides them is a Docker Compose stack: the test target brings the stack up with docker compose up -d, runs the integration suite five times with the -clean flag, and then tears the stack down. Separate targets exist for the mock SSH service on its own and for a mock performance SSH service using docker-compose-performance.yaml, and there is a target that regenerates the golden files used for output assertions. The test directory also holds a benchmark script invoked by the benchmark and benchmark-save targets. For a contributor this is the practical cost of the project: you cannot verify a change to the SSH or output layers with go test alone, you need a container runtime running the mock servers. The repository also carries a docs/performance.md page, and the existence of a separate performance mock suggests that the same harness is used to look at how the runner behaves under load.
MIT licensed, with the last tagged release in 2023
Licensing is simple. The project is MIT licensed, with the notice attributed to Samir Alajmovic, and the README says the project has ongoing development. The dates tell a more cautious story. The last push was on 2026-05-31, so the source moves, but the recent releases are v0.15.1 from 2023-09-25, v0.15.0 from 2023-06-10 and v0.14.0 from 2023-01-04, and the Makefile still pins VERSION := v0.15.1. So the code has changed since the last tag without a new tag to show for it. If you install from a package manager you get a tagged build, while go install with @latest pulls the current main branch, and those two are not the same thing. The README itself points sideways for a similar problem, recommending mani for managing git repositories in a comparable way. The docs directory is unusually thorough for a small project, with pages for background, roadmap, Ansible and performance, which is a reasonable guide to what the author considers the boundaries of the tool, and it also flags where a larger orchestration approach takes over. For an evaluation, the practical line is that sake is a command runner with an inventory, not a configuration management system.
Editorial conclusion
Adopt sake if you keep a handful of servers you run the same commands against and want a declarative inventory plus parallel execution without writing a shell loop, and build it with a Go toolchain matching the go directive in go.mod. Skip it if you need Windows support, since the project is stated to be available on Linux and Mac, or if you want orchestration features that live in a separate tool. Verify first that your Go version satisfies the go 1.26.3 directive in go.mod rather than the 1.19 figure in the README, and read docs/config-reference.md before writing anything beyond the localhost entry that sake init creates.
Frequently asked questions
What configuration file does sake use?
sake uses a sake.yaml file where you define both the servers and the tasks. Running sake init creates that file and adds a default localhost entry, and the project can also import other sake.yaml configs.
How do I run a task on every server at once?
Use the --all flag, for example sake run ping --all to run a named task everywhere, or sake exec --all with --strategy=free and an arbitrary command. The --strategy=free option keeps the work in flight across servers rather than processing them one at a time.
Which operating systems does sake support?
The README states that sake is available on Linux and Mac. Binaries are published on the release page, and there are install routes through cURL, Homebrew, MacPorts, Arch, pkg and go install.
Do I need Docker to run the sake test suite?
For the integration tests, yes. The Makefile test target brings up mock SSH servers with docker compose before running the integration suite and tears the stack down afterwards, while the unit tests under core run with go test alone.
How does sake connect to remote hosts over SSH?
The dependency list includes github.com/kevinburke/ssh_config for reading SSH configuration and golang.org/x/crypto for the SSH primitives, with a mock SSH server used for tests. sake also offers a sake ssh <server> command to open a session on a host or docker container.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/alajmo-sake)Was this useful?