Skip to content
Rubin Bhandari edited this page Sep 30, 2026 · 3 revisions

Usage

Commands at a glance

shelf init [--shell bash|zsh]
shelf lock [--update | --reinstall] [--concurrency N] [--force]
shelf source [--relock | --update | --reinstall] [--concurrency N] [--force]
shelf reload
shelf update [--lock] [--concurrency N] [--force]
shelf path
shelf status
shelf doctor
shelf clean
shelf list
shelf info NAME
shelf add NAME [source flags]
shelf edit
shelf remove [NAME] | shelf remove --interactive
shelf completion SHELL
shelf self-update [--version TAG] [--yes] [--force]
shelf --version

--update and --reinstall are mutually exclusive on every command that has them. --force only makes sense together with one of them, and shelf rejects it alone with error: --force requires --update or --reinstall.

Global options

Every command accepts these:

Flag Env equivalent Meaning
--quiet SHELF_QUIET=1 Drop diagnostics, including plugin build output.
--non-interactive SHELF_NON_INTERACTIVE=1 Never prompt. Commands that would ask fail instead of waiting.
--verbose SHELF_VERBOSE=1 Add Unlocked, Rendered, Inlined, and Removed lines to stderr.
--color auto|always|never SHELF_COLOR auto colors only a TTY.
--config-dir PATH SHELF_CONFIG_DIR Configuration directory.
--data-dir PATH SHELF_DATA_DIR Data directory.
--config-file PATH SHELF_CONFIG_FILE Configuration file. Its parent becomes the config directory unless --config-dir is set.
--profile NAME SHELF_PROFILE Load only plugins whose profiles include NAME.

Boolean env vars are on when they hold 1 or true.

Environment variables

Variable Default Notes
SHELF_CONFIG_DIR ~/.config/shelf
SHELF_DATA_DIR ~/.local/share/shelf
SHELF_CONFIG_FILE <config-dir>/config.toml
SHELF_PROFILE empty Same as --profile.
SHELF_SHELL empty bash or zsh. Any other value is an error, not a fallback. Ignored when the config sets shell.
SHELF_EDITOR empty Used by shelf edit. Falls back to VISUAL, then EDITOR.
SHELF_QUIET, SHELF_NON_INTERACTIVE, SHELF_VERBOSE, SHELF_COLOR Env forms of the global flags.

XDG_CONFIG_HOME and XDG_DATA_HOME pick the base directories when no shelf flag is set.

Output contract and exit codes

Shelf code goes to stdout. Everything else, headers, statuses, warnings, and errors, goes to stderr. That is why eval "$(shelf source)" works: the script is the only thing on stdout, so diagnostics never end up inside the eval.

A failed command prints a blank line then error: <message> on stderr and exits 2. Success exits 0. This holds for scripts and CI, so shelf source || exit does what you expect.

Shell startup

First run, empty config to a working shell:

shelf init --shell zsh --non-interactive   # no prompts, default file
$EDITOR ~/.config/shelf/config.toml
shelf lock                                 # installs everything, writes both locks

Add one line to .zshrc, or .bashrc for bash:

eval "$(shelf source)"

Open a new terminal. The first start relocks if the config changed, later starts take the warm path and only read the lock.

After editing the config in the shell you are already in:

shelf lock
 eval "$(shelf reload)"   # exec's the shell, startup files rerun

Completions:

# zsh, save the script, then add fpath+=(~/.zfunc) before compinit in .zshrc
mkdir -p ~/.zfunc && shelf completion zsh > ~/.zfunc/_shelf

# bash, source it from .bashrc
source <(shelf completion bash)

# fish, drop it in the completions directory, no rc changes
shelf completion fish > ~/.config/fish/completions/shelf.fish

In scripts and cron, add --quiet --non-interactive. The exit code is 0 or 2 and nothing prompts.

Clone this wiki locally