The CLI
be <type> <verb> <name>. The command is the name. Built for an agent to call.
be reads the naming scheme left to right:
be-wiki-zoom-etl the thing
be wiki new zoom-etl the command that makes it
be wiki new zoom-etl # github repo from be-wiki-template, cloned to ~/be-wiki-zoom-etl, stamped, pushed
be wiki pull zoom-etl # a teammate gets it
be wiki list # every be-wiki-* in the org
be doctor # tools, auth, config, every repo's harness
be upgrade # refresh the harness in this repo
Every type, the same four verbs
new <name> create from be-<type>-template, land in it
pull <name> clone or update, land in it
go <name> pull if absent, land in it
list what exists
A type may add verbs (wiki archive). It may not rename these.
One file per type
be-cli/
├── bin/be dispatcher: be <x> … → libexec/be-<x>. Knows nothing.
├── libexec/be-wiki a type: TYPE=wiki; the four verbs come from lib/types.sh
├── libexec/be-cli another type — twenty lines
├── libexec/be-doctor a tool
├── libexec/be-upgrade a tool
└── lib/types.sh new · pull · go · list, once
Adding a type is adding one file and publishing be-<type>-template.
It shows up in be help and tab completion with no other change.
Built for an agent
The employee says what they want in ~; Claude runs be. So the CLI
holds to standards that suit that caller, and be-cli-template enforces
them on every CLI we make:
never prompt flags in, message out — no questions
exit codes 0 ok · 1 error · 2 usage · 127 missing tool
the contract every command answers --summary --verbs --help
one item per line stdout is the answer, stderr is commentary
POSIX sh runs on the box and on a laptop, nothing to install
config precedence environment > ~/.config/be/config > defaults
sh .be/scripts/validate.sh in a CLI repo parses every script and calls
every command with all three contract flags. A command that skips one
cannot be pushed.
The cd trick
A process cannot change its parent shell’s directory. be … new writes
cd '~/be-wiki-x' && claude to a file; the function from
eval "$(be shell-init)" sources it after be exits. Without the wrapper,
be prints the line. BE_NO_LAUNCH=1 lands without starting the agent —
that is what Claude uses, since it is already running.
It is an instance too
be-cli was created from be-cli-template the same way be cli new deploy would create be-cli-deploy. The template that standardises CLIs
standardised the CLI.