7 releases
Uses new Rust 2024
| 0.3.8 | May 11, 2026 |
|---|---|
| 0.3.7 | Apr 14, 2026 |
| 0.3.3 | Mar 25, 2026 |
| 0.2.4 | Mar 24, 2026 |
#239 in Command line utilities
88KB
1.5K
SLoC
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:
tar -xzf jao-*.tar.gz
chmod +x ./jao
mv ./jao /usr/local/bin/jao
On Windows, extract the .zip archive and place jao.exe somewhere on your PATH.
crates.io
cargo install jao
Docker
docker pull royprinsgh/jao:latest
Quick Start
Repo:
scripts/
check.sh
test.integration.sh
db.reset.local.sh
Commands:
jao --list
jao check
jao test integration
jao db reset local
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:
jao format --nightly
jao test integration --filter api
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:
source <(jao --completions bash)
Zsh:
source <(jao --completions 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:
jao apps frontend dev
jao apps backend build
From inside apps/:
jao frontend dev
jao backend build
From inside apps/backend/:
jao dev
jao build
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:
jao --fingerprint db reset local
Use that value in CI:
jao --ci --require-fingerprint <FINGERPRINT> db reset local
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
Dependencies
~5–9MB
~173K SLoC