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 pattern

Version pinning

Append @tag to pin to a specific image tag:

boks python@3.11 --version
boks node@18 --version
boks node@22 --version

boks 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 curl

boks --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/rgboks. After that, rg works exactly as boks rg — boks reads argv[0] to learn the tool name.

Listing shims

boks --list

Removing a shim

Remove the symlink manually:

rm ~/.local/bin/rg

Searching the tool index

boks --search dns
boks --search python

Reclaiming 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:

TargetRemovesAsks first
scratchleaked per-run scan scratch not owned by a running scanno
imagesenvironment images built by boks (boks-env-*)no
(default)scratch + imagesno
cacheall of ~/.cache/boks — grype database, tool index, policy, scan verdicts, freshness stampsyes
allcache + images + scratchyes
decisionsaccepted scans, trusted projectsyes, 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