jao 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
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 binary for Linux, macOS, or Windows from GitHub Releases.
On Linux and macOS, place the binary on your PATH and mark it executable if needed:
crates.io
Docker
License
Apache-2.0