---
title: The CLI
description: "be <type> <verb> <name>. The command is the name. Built for an agent to call."
---

`be` reads the naming scheme left to right:

```text
  be-wiki-zoom-etl          the thing
  be  wiki  new  zoom-etl   the command that makes it
```

```bash
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

```text
  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

```text
  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:

```text
  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.
