# jan-cli
Rust CLI that loads a **YAML command tree**: each node can expose nested subcommands (progressive disclosure via `--help`) or run a real program (`exec`). Successful and failed child processes can be recorded in **SQLite**, keyed by the current **git branch** (or `--branch` / `JAN_BRANCH`) so each agent branch has a separate audit trail.
## Usage
```bash
cargo build --release
# Built-in tree when no jan.yaml or JAN_SPEC:
./target/release/jan --no-log
./target/release/jan --no-log git s
./target/release/jan --no-log disk df
./target/release/jan --no-log gradle tasks
./target/release/jan --spec examples/demo.spec.yaml --no-log
./target/release/jan --spec examples/demo.spec.yaml --no-log android skills list
./target/release/jan --spec examples/demo.spec.yaml --no-log android skills search -- extra args
```
- **Default commands**: if there is no `--spec`, no `JAN_SPEC`, and no `jan.yaml` / `jan.spec.yaml` under `--cwd`, `jan` loads a bundled YAML tree covering **git** (including richer log/blame/reflog helpers), **disk**, **net**, **proc**, **gradle**, **rust**, **android**, **docker**, and Linux **sys** tools (see `default.spec.yaml`).
- `--spec` / `JAN_SPEC`, or `jan.yaml` / `jan.spec.yaml` in `--cwd` to use your own spec instead.
- **`--extra-spec FILE`** (repeatable) and **`JAN_EXTRA_SPEC`** (comma-separated paths): merge YAML fragments into the loaded tree after load (later fragments override earlier keys). **`--stdin-spec`**: same merge from stdin (stored in a temp file for parsing; empty stdin merges an empty overlay).
- **`--verbose` / `-v`**: print spec identity, cwd, and merged fragment paths (stderr).
- **`jan --help`**: framework flags (`--cwd`, `--db`, `--no-log`, …). **`jan <prefix> --help`**: nested commands for that prefix. Subcommands use their own `--help` when forwarded to tools with `exec.passthrough`.
- `--db` / `JAN_DB` (default: OS data dir / `jan-cli/audit.db`), or `--no-log`
- `--cwd` working directory for `git` and spawned programs
- **`jan bundle`** — zip all YAML specs under the spec anchor plus `env.sh` and `manifest.json` (portable export)
- **`jan alias`** — emit shell aliases for script `run` leaves (includes `--spec-dir` / `--spec-root` by default)
### Portable scripts
See [`docs/PORTABLE_SCRIPTS.md`](docs/PORTABLE_SCRIPTS.md) for moving the incubator `scripts` collection between machines:
```bash
python3 jan-cli/scripts/generate_scripts_jan_spec.py
cd jan-cli && cargo build --release
./target/release/jan --spec-dir . --spec-root scripts.spec.yaml bundle -o ~/scripts-jan.zip
# on target: unzip, source env.sh, run jan scripts …
```
## Spec format
See `examples/demo.spec.yaml` for a minimal tutorial tree, and `default.spec.yaml` for the full bundled command set. Each command has optional `about`, nested `commands`, and/or `exec` with `argv` (first element is the program). `exec.passthrough: true` forwards remaining CLI tokens after the matched path.
Script-style entries can also declare:
- **`path`**: directory prepended to `PATH` when the script (or a `run` leaf under it) executes
- **`dependencies`**: other script names in the spec whose `path` directories are prepended first (transitive, cycle-checked)
- **`requires`**: external binaries (e.g. `fzf`, `jq`) that must be discoverable on `PATH` before the leaf runs
- **`env`**: map of environment variables passed to the child process (deeper nodes in the chain override keys from ancestors)
Relative `path` values resolve against `--cwd`, the spec directory, its parent, or `JAN_SCRIPTS_ROOT`. The `scripts.spec.yaml` tree is generated from `scripts/source/*/script.meta.yaml` (see `scripts/generate_scripts_jan_spec.py`).
## License
MIT — see `LICENSE.md`.