Command reference
ndo <name> [args...]
The default invocation. Resolves name against the merged central+local
recipe set, binds args positionally to the recipe's declared params
(checking ndo var lookup tables along the way), and executes
the result. If the recipe has depends, those run first, in order, each
recipe running at most once even across a shared dependency — see
Dependencies for the full
rules (cycles, fail-fast, --dry-run/--verbose behavior).
ndo open ./file.txt
Args beyond the declared params are appended raw (quoted) to the end of the command — useful for passthrough:
ndo test -- -run TestFoo
ndo add
ndo add <name> "<command>" [--param <name>]... [--depends <name>]... [--local] [--desc "<text>"]
Adds a new recipe. Fails with an error (not a silent overwrite) if the
name already exists in the target file — use ndo edit to change an
existing recipe by hand.
ndo add deploy "./scripts/deploy.sh {{env}}" --param env --local --desc "Deploy to the given environment"
# build/lint run first, in order, every time deploy does
ndo add deploy "./scripts/deploy.sh {{env}}" --param env --depends build --depends lint --local
| Flag | Effect |
|---|---|
--param <name> | Declares a parameter, in positional order. Repeatable. |
--depends <name> | Recipe to run first, in order. Repeatable. See Dependencies. |
--local | Write to the nearest local .ndo.toml (creating one in the current directory if none is found upward) instead of the central file. |
--desc "<text>" | Description shown in ndo list. |
ndo list
ndo list [--local] [--central]
Prints resolved recipes. With no flags, shows the merged central+local
view. --local/--central restrict to just that file's contents,
unmerged.
ndo edit
ndo edit [--local] [--central]
Opens the relevant recipe file in $EDITOR (or config.toml's
settings.editor, which takes precedence). Defaults to the central file;
--local opens the nearest local file instead.
ndo remove
ndo remove <name> [--local]
Deletes a recipe from the target file. Errors if not found in that specific file — it doesn't cascade-search the other one.
ndo init
ndo init
Creates an empty .ndo.toml in the current directory. Errors if a local
recipe file already exists anywhere in the tree above the current
directory, so it never silently shadows one.
ndo var
Named lookup tables that expand a recipe's positional argument into a longer value, without any new recipe syntax — the lookup is keyed by param name. See Vars: named lookup tables for param shortcuts for the full mechanics and TOML schema.
ndo add o "code {{folder}}" --param folder --local
ndo var add folder work "C:\Users\dev\projects" --local
ndo var add folder ndo "C:\Users\dev\projects\ndo" --local
ndo o work # -> code C:\Users\dev\projects
ndo o D:\other\path # no match in vars.folder -> code D:\other\path (used literally)
| Subcommand | Effect |
|---|---|
ndo var add <group> <key> <value> [--local] | Add or overwrite one entry. |
ndo var remove <group> <key> [--local] | Remove one entry. |
ndo var remove <group> [--local] | Remove the entire group at once. |
ndo var list [group] [--local] [--central] | List resolved entries, optionally filtered to one group. |
ndo var list output:
folder:
ndo: C:\Users\dev\projects\ndo
work: C:\Users\dev\projects
Central and local vars merge at the key level — unlike recipes, which
replace wholesale on a name collision. A local .ndo.toml can add or
override individual keys without losing the rest of the central group.
ndo update
ndo update [--check]
Checks the latest GitHub release against the running version. What
happens next depends on how ndo was installed, detected from the
running binary's path:
| Detected as | Behavior |
|---|---|
Homebrew, Scoop, a .deb/.rpm install, or go install | Prints the right command for that channel (brew upgrade ndo, etc.) — never touches the binary, so that package manager's own records stay accurate. |
Anything else (raw binary via install.sh or a manual download) | Downloads the new release, verifies its checksum against checksums.txt, and atomically replaces the running binary in place. |
--check only reports whether an update is available (and the right
command to get it) without installing anything, regardless of which
channel is detected.
Shell completion
ndo <TAB> completes recipe names; ndo <recipe> <TAB> completes that
recipe's next declared param — offering the matching vars group's keys
(if any) alongside normal file completion, so you never have to memorize
what you named an entry.
The first time you run ndo in a real terminal, it asks once whether to
set this up for you — if you say yes, it wires the completion script into
your shell's startup file itself, so it just works in every new terminal
from then on. It never asks again (the answer is remembered in
config.toml), and it's a strict no-op in scripts/CI/pipes. To set it up
by hand instead:
# bash (current shell)
source <(ndo completion bash)
# zsh (current shell)
source <(ndo completion zsh)
# fish
ndo completion fish | source
# PowerShell — add to your profile ($PROFILE) to persist across sessions
ndo completion powershell | Out-String | Invoke-Expression
Or skip the one-time prompt and trigger the same auto-detect-and-install logic directly:
ndo completion install # detect your shell, wire it in
ndo completion uninstall # remove what install added
Run ndo completion --help for instructions on installing the script
permanently for your shell.
Global flags
| Flag | Effect |
|---|---|
--verbose | Print extra diagnostics, including which file a resolved recipe came from. |
--dry-run | Print the resolved, interpolated command without executing it. |
--version | Print the ndo version. |
--help | Show help for any command. |