jao (from the Hindi "जाओ" meaning "Go!" :D) runs scripts as if you made your own, repo specific CLI
Compared with tools like make, just, or npm run, jao is a better fit when:
- you don't want to commit to a full task runner, and want something both seamlessly added and seamlessly removed from your workflow
- the scripts already exist and you do not want to rewrite them
- the same script names appear in multiple subprojects
- you want commands to get shorter as you move deeper into the repo (as in, jao is aware of your current working directory)
- you want changes in scripts to enforce detectable changes in anything depending on them, with the fingerprinting system
Installation
Prebuilt binaries
Download the latest archive for Linux, macOS, or Windows from GitHub Releases.
Each release from v0.3.7+ includes platform-specific archives plus a SHA256SUMS file.
On Linux and macOS, place the binary on your PATH and mark it executable if needed:
On Windows, extract the .zip archive and place jao.exe somewhere on your PATH.
crates.io
Docker
Quick Start
Repo:
scripts/
check.sh
test.integration.sh
db.reset.local.sh
Commands:
This is the default model: command parts map to script stems like check, test.integration, and db.reset.local.
Script arguments can follow the resolved command directly:
No special separator is required. jao resolves the longest matching script name first, then forwards any remaining words to the script as arguments.
For example, if db.reset.local.sh exists, jao db reset local runs that script. If only db.reset.sh exists, the same command runs db.reset.sh with local as its first argument.
What It Does
- Finds runnable scripts under the directory you start from
- Matches
.shon Unix and.baton Windows - Lets you run scripts by command parts instead of file paths
- Respects
.gitignoreduring discovery - Supports
.jaofolderto expose directory names in commands - Supports recursive
.jaoignorefiles to hide scripts or whole areas - Supports trust prompts for local use and fingerprints for CI
- Prints shell completion scripts for Bash and Zsh
jao runs scripts from the script's own directory, so existing scripts that rely on relative paths keep working.
Shell Completion
Bash:
Zsh:
Then jao can complete discovered script parts from the current directory:
jao m<TAB> -> myapp
jao myapp <TAB> -> backend frontend
jao myapp backend b<TAB> -> build
Obviously you can add this to e.g. your .bashrc to enable completions always.
Example 2: .jaofolder In A Multi-Project Repo
Repo:
apps/
.jaofolder
frontend/
.jaofolder
scripts/
build.sh
dev.sh
backend/
.jaofolder
scripts/
build.sh
dev.sh
From the repo root:
From inside apps/:
From inside apps/backend/:
Use this when multiple projects have the same script names and you want commands to get shorter as you move deeper into the repo.
Example 3: .jaoignore For Internal Or Throwaway Scripts
Repo:
.jaoignore
scripts/
check.sh
scratch/
scripts/
one-off-fix.sh
services/
api/
.jaofolder
.jaoignore
scripts/
migrate.dev.sh
seed.dev.sh
Root .jaoignore:
scratch/
services/api/.jaoignore:
seed.dev.sh
Result:
scratch/is not walked at allseed.dev.shis hidden fromjao --listmigrate.dev.shstill resolves normally
Use this when a repo contains one-off maintenance scripts, experiments, or internal scripts that should not be part of the public command surface.
Example 4: Fingerprinting In CI
Print the fingerprint for a script:
Use that value in CI:
That gives CI an exact content check instead of trusting whatever script happens to be present.
For local interactive use, jao keeps a trust manifest under ~/.jao/:
- unknown scripts ask before running
- modified scripts ask again
License
Apache-2.0
AI Usage
Both GPT-5.3-Codex and Qwen3-coder-next were used in this project for scaffolding, refactoring work and test generation