Commands
boks is a single binary. Everything is driven by flags: the only positional argument is the tool to run.
Running a tool
boks [OPTIONS] TOOL [ARGS]...boks python --version
boks python@3.12 --version
boks rg "TODO" .
boks jq '.name' data.json
echo '{"x":1}' | boks jq '.x'
Flags must appear before the tool name. Anything after the tool is passed to the tool verbatim, so boks jq -e '.foo' correctly sends -e to jq (it is not boks's -e/--env).
Use -- to mark the end of boks flags explicitly:
boks --cap net -- rg -- --hidden patternVersion pinning
Append @tag to pin to a specific image tag:
boks python@3.11 --version
boks node@18 --version
boks node@22 --versionboks man <tool>
View a tool's real upstream man page. man is an ordinary composable tool — boks man <tool> composes it with <tool>'s own image and finds the page via a real man command inside the container:
boks man ls
boks man cp
boks honors $MANPAGER/$PAGER the same way a real man command does. Only tools whose images ship a staged man page (from the upstream package's own -doc subpackage) have one — this is a catalog-by-catalog migration, not yet every tool.
boks --info <tool>
Print a one-line synopsis of a tool, sourced from the global index and — if the image is pulled locally — enriched with labels from the image (sh.boks.description, sh.boks.version, sh.boks.provides, sh.boks.security.*):
boks --info curlboks --update
Fetch the latest global tool index from https://index.boks.sh/index.json and cache it locally:
boks --update
This refreshes the index used by --search, --info, and tool resolution. See Tool Index.
boks also refreshes the index and policy cache automatically in the background — no explicit --update needed for day-to-day use. Before running a tool, boks checks whether the cache is older than index_max_age_secs (default: 1 day, [global] in boks.toml) and, if so, kicks off a refresh that never delays the run: it's bounded to a few seconds and abandoned if it doesn't finish before the command completes, falling back to the cached data either way. Skipped entirely with --offline.
Installing a shim
boks --install rg
Creates ~/.local/bin/rg → boks. After that, rg works exactly as boks rg — boks reads argv[0] to learn the tool name.
Listing shims
boks --listRemoving a shim
Remove the symlink manually:
rm ~/.local/bin/rgSearching the tool index
boks --search dns
boks --search pythonReclaiming disk
boks --status # what boks is storing, by category
boks --clean # leaked scan scratch + boks-env-* images
boks --clean cache --dry-run # show what a cache clean would remove
boks --clean cache # every regenerable cache (asks first)
boks --clean [TARGET] takes a comma-separated target list:
| Target | Removes | Asks first |
|---|---|---|
scratch | leaked per-run scan scratch not owned by a running scan | no |
images | environment images built by boks (boks-env-*) | no |
| (default) | scratch + images | no |
cache | all of ~/.cache/boks — grype database, tool index, policy, scan verdicts, freshness stamps | yes |
all | cache + images + scratch | yes |
decisions | accepted scans, trusted projects | yes, always |
decisions is never part of all: reclaiming disk and revoking every security
decision you have made are different operations, and decisions occupy a few
kilobytes. Base images are never touched by any target.
Add --dry-run to print the plan and stop, or --yes to pre-answer the
confirmation. Under --non-interactive (or with CI set, or no terminal) a
target that would prompt fails closed rather than assuming yes — pass
--yes explicitly if a pipeline really means it.
Three things --clean refuses to remove, and reports instead: a symlinked
index.json (a deliberate developer setup pointing into a checkout), files boks
did not write, and scratch belonging to a scan running in another terminal.
Using environment files
boks -e @pip:requirements.txt python script.py
boks -e @uv python script.py
boks -e @npm:package.json node app.js
boks -e @pip:. python script.py # auto-detect
Watch a file and rebuild on change:
boks --watch -e @pip:requirements.txt python script.py
See Environments for details.
Kubernetes
boks --k8s python --version
boks --k8s --namespace production python script.py
boks --k8s --node worker-1 htop
See Kubernetes for what is and isn't supported in k8s mode.
kubectl plugin
When boks is invoked as kubectl-boks, it automatically uses Kubernetes mode:
ln -s ~/.local/bin/boks ~/.local/bin/kubectl-boks
kubectl boks python --version