jao runs scripts as if you made your own, repo specific CLI
The name jao comes from the Hindi "जाओ" meaning "Go!" :D
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
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.
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
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
License
Apache-2.0