mani: run one git command across every checkout you own
:robot: CLI tool to help you manage repositories
At a glance
- What is it?
- mani is a Go command line tool that treats a directory of git repositories as a single managed project set, so a command can be executed across all of them in parallel with consistent output, configured from one mani.yaml file.
- Who is it for?
- Adopt mani if your day to day work spans a directory of git checkouts and you keep repeating the same git command in each one, since a single mani.yaml plus mani exec covers that without a script. Do not adopt it for a single repository, for remote CI orchestration, or as a substitute for review tooling, because it operates on local checkouts only and offers only partial Windows support.
- 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 27 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 22, 2026, and from our analysis. They are not legal advice.
Editorial analysis
A directory of checkouts becomes one managed project set
mani lets you manage multiple repositories and run commands across them. That is the whole pitch, and it is aimed at a specific kind of developer: someone with a directory holding a dozen or more git working copies who repeats the same command in each of them, or who wants a task definition that travels with the configuration instead of living in a shell function.
The tool is written in Go and is distributed as a single static binary, built with CGO_ENABLED=0 and the netgo tag, so there is no runtime dependency to install on a work machine. The project ships a release page with prebuilt binaries, and the package is also published through Homebrew, MacPorts, Arch AUR, Nix and the Go module proxy.
What mani is not is a version control client. It does not replace git, and it does not fetch or merge anything on its own. It sits above the directory you already have and turns a set of individual commands into one invocation with a defined order, a defined output format and a record of what it ran. The project documentation keeps the distinction visible: configuration lives in docs/config.md, the command surface in docs/commands.md, and the filter, variable and output behaviour in docs/filtering-projects.md, docs/variables.md and docs/output.md.
mani init discovers the repositories and writes mani.yaml
The entry point is a single command run inside a directory that contains your git repositories:
mani initTwo things are generated. The first is mani.yaml, which contains projects and custom tasks. Any subdirectory that has a .git directory will be included, and the flag --auto-discovery=false turns that feature off, so you can pin the project list by hand instead of letting the tool infer it. The second is a .gitignore, written only when you are inside a git repository, which includes the projects specified in the mani.yaml file; --sync-gitignore=false opts out of that behaviour.
The .gitignore part is the detail worth understanding. If the parent directory is itself a git repository, the generated ignore file keeps the individual project directories out of the parent's history, so you can commit a single manifest of your project set and clone the group with one command. The documentation makes that explicit: it can be helpful to initialize the mani repository as a git repository so that anyone can download it and run mani sync to clone all repositories and get the same project setup as you.
So the intended workflow is a directory that is a git repo, a mani.yaml listing the projects and the tasks, and each child directory being an independent repository. A directory of checkouts that is not versioned still works, but the sync and ignore behaviour is where the extra value sits.
mani exec fans a command out and can run it in parallel
The daily verbs are list and exec. The examples in the project documentation are short:
# List all projects
mani list projects
# Run git status across all projects
mani exec --all git status
# Run git status across all projects in parallel with output in table format
mani exec --all --parallel --output table git statusThe mechanism is the same shape in each case: --all selects every project in the configuration, --parallel changes the execution model from sequential to concurrent, and --output selects the rendering, with table as one of the choices. The underlying command is passed through as arguments, so anything git can do, mani can do to every repository at once.
The project set can be narrowed rather than run wholesale. docs/filtering-projects.md documents how to select a subset of projects, and docs/variables.md documents variable handling, which is the mechanism for parameterising a task. The output side is separately documented in docs/output.md, and the terminal interface is a separate concern again, built on a TUI layer that the repository keeps under core/tui. The examples directory in the tree carries a frontend example and a template-generator example, so there is a documented way to look at a populated configuration before writing your own.
Five install routes and one build command
mani is available on Linux and Mac, with partial support for Windows. The install script route is the shortest, and the project publishes it for Linux and macOS:
curl -sfL https://raw.githubusercontent.com/alajmo/mani/main/install.sh | shPackage managers cover the rest. Homebrew, Arch AUR, MacPorts and Nix are all documented:
brew tap alajmo/mani
brew install maniyay -S maninix-env -iA nixos.manisudo port install maniIf you already have Go, the module path is installable directly:
go get -u github.com/alajmo/maniBuilding from source is a clone plus two steps, and the Makefile target writes the binary to the dist directory where the README expects it:
make build && ./dist/maniThe build injects the version, commit and date at link time, and the Makefile pins the current version string to v0.32.1. Two supporting commands are documented alongside the install steps: mani completion bash|zsh|fish|powershell sets up shell completion, and mani gen produces the man page. The Go module requires go 1.26.3, which matters if you are pinning an older toolchain on a corporate image.
A cobra command tree over yaml.v3, with tview for the interface
The dependency list in go.mod describes the architecture more honestly than the README does. The command layer is github.com/spf13/cobra with spf13/pflag for flags, and configuration is read with gopkg.in/yaml.v3, which matches the mani.yaml format. The terminal interface is built on github.com/rivo/tview and gdamore/tcell/v2, and table output comes from jedib0t/go-pretty/v6, with theckman/yacspin handling progress feedback during longer runs.
The repository layout follows the same split. cmd/ holds the cobra commands, core/ holds the engine, and inside core there are separate packages for dao, exec, print and tui. The dao layer is the one that gets its own test target, since it owns the persistence of the project and task data, and the Makefile runs unit tests over core/dao plus an integration suite through test/scripts/test with build, count and clean options. A bench target exists for the dao and core packages, and results can be written into the benchmarks/ directory for later comparison with benchstat.
Two other dependencies hint at behaviour. fsnotify is used for file system watching, and otiai10/copy plus jinzhu/copier handle file and struct copying, which is what makes the sync and template examples possible. The result is a tool with three cooperating layers: a configuration store, an execution engine that fans commands out, and a presentation layer that can render the same run as a table, plain output or a terminal interface.
The release trail runs behind the last commit
The repository is not archived, and the last push was on 2026-09-27. The tagged releases move more slowly. v0.31.2 was published on 2025-12-05, v0.32.0 on 2026-02-11 and v0.32.1 on 2026-05-15, so there is work in the tree that postdates the newest tag by several months. For a tool that people install from a release page rather than from source, that gap matters: the binary you download is not the code sitting in the main branch.
The version number also says something. It is still a 0.x series, which in Go convention signals that the API and behaviour may still change between minor versions. The project publishes a changelog at docs/changelog.md and a roadmap at docs/roadmap.md, and both are the right places to look before pinning a version in a script that other people will run.
Licensing is the simplest part of the picture. mani is released under the MIT License, with copyright held by Samir Alajmovic, and the LICENSE file sits at the root of the repository. The dependencies listed in go.mod carry their own licences, and a static binary you redistribute includes them, so the licence of your distribution is the combination of the MIT grant and whatever each dependency requires. That question belongs to whoever ships the binary, not to this article.
Where a shell loop or a different tool fits better
There is a case where mani is overhead. If you maintain one repository, a shell loop over directories is shorter than a configuration file, and no tool adds value. If your checkouts are spread across machines rather than one directory, the local-directory model of mani does not apply, since mani init works on a directory you already have. And if the repetition you need is about reviewing pull requests or gating merges, mani is the wrong layer, because it executes commands you ask for and does not decide anything for you.
For the same author's other project, the README points to sake for managing servers in a similar way, which is a useful way to read mani's scope: it stops at the repository boundary.
A more concrete alternative for a large team is to encode the repeated command in whatever CI or task runner you already use, because that gives you history, retries and per-repository status without a new local tool. mani's advantage over that route is that it is local, immediate and cheap, with a configuration file you can commit next to the projects it describes. The trade-off is that a local tool leaves no record on a server, which is exactly what a task runner is for.
Editorial conclusion
Adopt mani if your day to day work spans a directory of git checkouts and you keep repeating the same git command in each one, since a single mani.yaml plus mani exec covers that without a script. Do not adopt it for a single repository, for remote CI orchestration, or as a substitute for review tooling, because it operates on local checkouts only and offers only partial Windows support. Before rolling it out, run mani init in a scratch directory and read the generated mani.yaml, confirm your repositories are discovered as expected, and check the Go version requirement of 1.26.3 if you intend to build from source rather than install a release binary.
Frequently asked questions
How do I install mani?
The project documents a script install for Linux and macOS, package manager installs through Homebrew, MacPorts, the Arch AUR and Nix, a Go install with go get, and a source build using make build followed by ./dist/mani. Prebuilt binaries are also published on the release page.
What does mani init create in my directory?
It generates mani.yaml, which holds projects and custom tasks, and it includes every subdirectory that has a .git directory unless you pass --auto-discovery=false. It also writes a .gitignore containing the projects from mani.yaml, but only when the parent is itself a git repository, and --sync-gitignore=false turns that off.
How do I run a command in every repository at once?
Use mani exec --all with the command, as in mani exec --all git status. Adding --parallel runs the commands in parallel and --output table renders the results as a table. Docs on filtering projects, variables and output live in the docs directory of the repository.
Does mani work on Windows?
The project states that mani is available on Linux and Mac, with partial support for Windows, so a Windows user should expect gaps. Shell completion is offered for bash, zsh, fish and powershell through mani completion.
What is the latest mani release and how recent is the code?
The most recent release is v0.32.1, published on 2026-05-15, and the last push to the repository was on 2026-09-27. Because the newest tag is several months older than the last commit, a binary from the release page does not include all current work on the main branch.
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-mani)Was this useful?