One front-end for every task runner. "karo" is Hindi for "do it" (करो).
Go to any repo and run karo — it lists every runnable task from whatever
runners the project uses. Then karo <task> runs it by delegating to the
real tool.
$ karo
just · justfile
build compile everything
test <filter>
bun · package.json
dev vite dev
build vite build
$ karo dev # -> exec `bun run dev`
$ karo just:build # qualified form when two runners define `build`
$ karo dev --port 3000 # extra args are forwarded
| Runner | Manifest | List via | Run via |
|---|---|---|---|
| just | justfile |
just --dump --dump-format json |
just <task> |
| bun / npm / pnpm / yarn | package.json scripts |
manifest | <pm> run <task> |
| deno | deno.json(c) tasks |
manifest | deno task <task> |
| go-task | Taskfile.yml |
task --list-all --json |
task <task> |
| make | Makefile |
make -pRrq database |
make -C <dir> <task> |
| uv | pyproject.toml [project.scripts] |
manifest | uv run <task> |
The package manager for package.json is picked from the packageManager
field if present, otherwise the lockfile (bun.lock > pnpm-lock.yaml >
yarn.lock > package-lock.json), defaulting to bun.
Manifests are discovered by walking up from the current directory until the
git repo root or mount root (nearest one wins, per runner). All parsing and
execution semantics stay in the underlying tools — karo only routes; it never
re-implements a runner. The chosen tool replaces the karo process via exec,
so exit codes, signals and TTY behavior are the real tool's.
- Ambiguity is explicit: if two runners define
build,karo builderrors and tells you to runkaro just:buildorkaro bun:build. - If a name is unknown but the project has exactly one runner, karo passes it through anyway so you get the real tool's own error/suggestions.
- Runner binaries (
just,task, ...) are looked up onPATHat runtime and are not build dependencies; a missing one only disables that runner.
Dynamic completions for Fish, Bash, and Zsh are built directly into karo. Task names are produced at completion time by karo --complete-tasks, which delegates discovery to your project's task runners.
Run:
karo --install-completionsThis automatically puts completions into:
- Fish:
~/.config/fish/completions/karo.fish - Bash:
~/.local/share/bash-completion/completions/karo - Zsh:
~/.local/share/zsh/site-functions/_karo(and~/.zfunc/_karo)
You can also print the completions directly:
# Fish
karo --completions fish > ~/.config/fish/completions/karo.fish
# Bash
karo --completions bash > ~/.local/share/bash-completion/completions/karo
# Zsh
karo --completions zsh > ~/.zfunc/_karocurl -fsSL https://raw.githubusercontent.com/nkitsaini/karo/main/install.sh | sh# The package is named `karo-task-runner`; the installed command is `karo`.
cargo install karo-task-runner# Build the release binary
nix build
# Install into current profile
nix profile install .cargo test # unit tests (make db parsing, jsonc, pm selection)
nix flake check # includes fish completion tests