jao 0.3.6

Discover and run workspace scripts from a simple CLI
jao-0.3.6 is not a library.

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:

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.

What It Does

  • Finds runnable scripts under the directory you start from
  • Matches .sh on Unix and .bat on Windows
  • Lets you run scripts by command parts instead of file paths
  • Respects .gitignore during discovery
  • Supports .jaofolder to expose directory names in commands
  • Supports recursive .jaoignore files 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 all
  • seed.dev.sh is hidden from jao --list
  • migrate.dev.sh still 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

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:

chmod +x ./jao
mv ./jao /usr/local/bin/jao

crates.io

cargo install jao

Docker

docker pull royprinsgh/jao:latest

License

Apache-2.0