Reference manual

5dive CLI

v0.19.11

The 5dive CLI is an MIT-licensed Bash binary that runs on any Linux host with systemd. It manages coding agents as Linux users + systemd units, handles non-TTY auth flows, installs Claude/OpenAI/Google CLIs on demand, and pairs each agent with a Telegram or Discord channel. The same binary runs every agent on 5dive.ai — no open-core split. Source: github.com/5dive-ai/5dive.

Docs verified against CLI v0.19.11 on August 10, 2026. Check your install with 5dive --version; update with sudo 5dive self-update.

01

Overview

5dive is a single Bash entry point installed at /usr/local/bin/5diveon any Linux+systemd host. It is the canonical way to create, inspect, and tear down agents — and it's the same binary that runs every agent on the managed 5dive.com VMs (no open-core split). The CLI is intentionally narrow and emits structured JSON whenever --json is passed, so it is safe to script against from a dashboard, a webhook, or another agent.

Each agent is one Linux user (agent-<name>) in the claude group, one systemd unit (5dive-agent@<name>.service), and one tmux session (agent-<name>). The unit runs the chosen CLI binary inside a tmux restart loop with the agent type's shared credentials injected via EnvironmentFile.

This page is the reference manual. It is written so an LLM can use the CLI without trial-and-error: every flag, every exit code, and every state path is listed below.

02

Quickstart

Install on any Linux host with systemd (requires sudo):

bash
curl -fsSL https://install.5dive.com | sudo bash

Then run the interactive first-run wizard — it walks you through picking an agent type, signing in, optionally pairing a Telegram bot, and creating your first agent:

bash
5dive init

If you'd rather script the agent create step (CI, reproducible setup), here's the explicit path to a running Claude agent paired to Telegram:

bash
# 1. Authenticate the Claude CLI once (covers every claude-typed agent)
sudo 5dive agent auth login claude

# 2. Spawn an agent named "scout" wired to Telegram
sudo 5dive agent create scout \
  --type=claude \
  --channels=telegram \
  --telegram-token=123456:ABC...

# 3. Pair the bot to your chat (DM the bot, then paste the code it replies)
sudo 5dive agent pair scout --code=AB12CD

# 4. Inspect — should print state=running
sudo 5dive agent stats scout

All commands exit non-zero on failure with an exit code drawn from the table at the bottom of this page. Add --json to any of them to get a parseable envelope on stdout. For declarative many-agent setups, see Compose.

03

Company wizard

5dive company is onboarding sugar over project add + objective add (+ optionally goal add) — one call stands up a whole self-steering project namespace instead of three separate ones.

bash
sudo 5dive company --yes \
  --name=<company> [--key=<slug>] [--prefix=<UPPER>] \
  --objective="<outcome>" --metric-cmd="<read-only cmd>" \
  --target=<n> --direction=up|down [--unit=<u>] \
  [--planner=<agent>] [--review="<cron>"] [--max-new-per-cycle=<n>] \
  [--goal="<outcome>"]

# Bare (TTY, no flags) walks an interactive wizard instead
sudo 5dive company

Bare invocation on a TTY walks an interactive wizard. Non-interactive runs require --yes plus --name, --objective, and --metric-cmd — everything else falls back to flags or defaults, and the command fails outright if neither a TTY nor --yes is present. See Objectives for what --metric-cmd / --direction mean.

04

Concepts

Agents

An agent is a long-running tmux session running one of the supported coding CLIs (Claude Code, Codex, Antigravity, Grok, openclaw, hermes, opencode). It owns its own Linux user, its own home directory, and — when paired — its own bot/app token. Two agents of the same type can coexist on one host.

Accounts (named auth profiles)

By default every agent of a given type shares one set of credentials, stored under /etc/5dive/connectors/<type>.env. To run two agents of the same type against different accounts, create a named account once and bind agents to it: 5dive account add personal, 5dive account login personal --type=claude, then --auth-profile=personal on agent create (or 5dive agent set-account <agent> personal after the fact). See Accounts for the full surface. The lower-level auth set --auth-profile=<name> and auth login --auth-profile=<name>verbs still work and back the dashboard's device-code flow.

Channels

A channel is the inbound message surface the agent listens on. Today: telegram, discord, dashboard, or none (comma-listable). Every agent type supports Telegram — natively where the CLI ships an MCP plugin contract (claude, openclaw, hermes), and via a bundled 5dive bridge for the rest (codex, grok, antigravity, opencode). Discord is currently claude / openclaw / hermes only. dashboard is a claude-only, token-free web-dashboard chat surface that is folded into every claude create by default — --channels=none opts out.

Workdir

The tmux session starts in the agent's workdir. Default is /home/claude/projects. Override at create time with --workdir=..., or change later with 5dive agent config <name> set workdir=....

05

JSON output

Pass --json as a global flag (anywhere on the command line) to switch stdout to a stable envelope. Progress lines (==>) keep going to stderr so the JSON on stdout is always parseable. The exit code matches error.code on failure.

success envelope
{
  "ok": true,
  "data": {
    "name": "scout",
    "type": "claude",
    "channels": "telegram",
    "workdir": "/home/claude/projects",
    "created": true
  }
}
error envelope
{
  "ok": false,
  "error": {
    "code": 6,
    "class": "auth_required",
    "message": "claude is not authenticated (missing) — run: sudo 5dive agent auth login claude"
  }
}

Branch on error.class for stable program flow — the human-readable message changes, the class does not.

06

Agent types

5dive agent types lists every supported CLI on the host along with auth state and an installed boolean. Types missing from disk are installed on demand the first time you agent create them.

TypeChannelsAuth flowNotes
claudetelegram, discordsetup-token / API keyAnthropic Claude Code. Default for new agents.
codextelegramOpenAI device flow / API keyOpenAI Codex CLI.
antigravitytelegramGoogle OAuthGoogle Antigravity CLI.
groktelegramxAI device-auth / API keyxAI Grok CLI.
hermestelegram, discordOpenAI device flow / API keyNous Research hermes harness.
openclawtelegram, discordOpenAI device flow / API keyThird-party Claude harness, OpenAI-backed.
opencodetelegramnone / optional API keyopencode.ai. Free models, no signup required.
07

Isolation tiers

Every agent runs as its own Linux user, but the blast radius of that user is configurable. Pick a tier at create time with --isolation=<tier> — default is standard (zero sudo).

TierAccess
standardShared read, limited write. In the claude group (so cross-agent reads work) but no sudo. Default for every new agent.
adminScoped root. Granted only to the first agent on a fresh box, or one explicitly created with --isolation=admin — a narrow sudoers grant limited to the 5dive CLI itself plus non-paging systemctl start|stop|restart of 5dive-* units, not NOPASSWD:ALL. Needed to run the root surfaces (agent create/config/pair, heartbeat on/off, doctor --fix, fleet add/rm, self-update).
sandboxedOwn home only. No claude group, no sudo, systemd resource limits. Use for untrusted prompts or work that must not see your other agents. Also refuses --can-push (see Delegated push).

The no-sudo surfaces (task, org, memory search/doctor, usage, market, agent list/info) run from any agent regardless of tier — only the root surfaces above need an admin-tier agent.

bash
sudo 5dive agent create scout --type=claude --isolation=sandboxed
08

Authentication

Auth is decoupled from agents. You authenticate a typeonce (optionally under a named profile) and every agent of that type inherits the credentials via systemd's EnvironmentFile.

Interactive login (TTY)

bash
sudo 5dive agent auth login claude

Hands this process off to the upstream CLI's interactive flow. Don't use this from a dashboard; use the device-code variant below instead.

API key

bash
# Direct
sudo 5dive agent auth set claude --api-key=sk-ant-...

# From stdin (recommended — keeps the key out of shell history)
echo "$KEY" | sudo 5dive agent auth set claude --api-key=-

Anthropic sk-ant-oat01-* tokens are routed to CLAUDE_CODE_OAUTH_TOKEN; everything else becomes ANTHROPIC_API_KEY.

Non-TTY device-code flow

The dashboard uses this flow because it runs without a PTY. Each call is async — start, poll until you get a URL, show the URL to the user, then submit the callback code the upstream login redirects to.

bash
# 1. Start a session — returns a session id
sudo 5dive agent auth start claude --json
# -> {"ok":true,"data":{"session":"01HXX..","state":"awaiting_url"}}

# 2. Poll until state=awaiting_code; data.url is what the user opens
sudo 5dive agent auth poll 01HXX.. --json

# 3. User pastes the callback code from the redirect URL back to you
sudo 5dive agent auth submit 01HXX.. --code=anthropic#abc123

# 4. (optional) cancel a pending session
sudo 5dive agent auth cancel 01HXX..

Status

bash
# Sentinel-only (fast)
sudo 5dive agent auth status

# Live probe — actually calls the API
sudo 5dive agent auth status --probe

# One type only
sudo 5dive agent auth status --type=claude --probe

Identity (whoami)

bash
5dive whoami [--json]

Prints who is acting, under whose authority, and at what tier — with the source of each. Identity resolution is uid-first: $EUID (or sudo's $SUDO_UID at real root) resolved against /etc/passwd, never argv/--from, $USER, $SUDO_USER, or id/getent(both PATH-resolved and therefore spoofable). An actor that can't be measured this way exits 6 (auth_required) rather than printing unknown with a success status.

Actor-routed gh

bash
5dive gh <gh args...>                  # writes -> machine account; admin + reads -> your own credential
5dive gh --as=bot|caller <gh args...>  # force one identity
5dive gh --explain <gh args...>        # print the routing decision, run nothing
5dive gh whoami                        # resolve BOTH identities

Routes every ghcall by operation instead of by caller: writes go out under a shared machine account so a compromised agent can't act as a specific human, while admin calls and reads stay on your own credential — a plain read leaves no actor field to attribute, and the machine account sees fewer repos than a signed-in human does. The PAT backing the machine account never leaves /etc/5dive/connectors/github-bot.env (root only); an agent gh write authenticates as that shared account, not as the human operating the box, so the audit trail can tell a bot write from a human one.

09

Accounts

An account is a named bundle of credentials that one or more agents can share. Accounts are the user-facing surface over the lower-level auth profile primitive: the same on-disk storage, friendlier verbs.

Use accounts when you want two agents of the same type to authenticate against different sign-ins (e.g. personal + work Anthropic accounts), or when you want a single sign-in to feed many agents — re-authing the account heals every agent bound to it in one shot.

Create and sign in

bash
# 1. Create an empty account
sudo 5dive account add personal

# 2. Sign in interactively (TTY hand-off)
sudo 5dive account login personal --type=claude

# Or, set an API key non-interactively
echo "$KEY" | sudo 5dive agent auth set claude \
  --api-key=- --auth-profile=personal

Names: lowercase letters, digits, _, and -; must start with a letter; max 32 characters. The literal name defaultis reserved (it's the magic value agent set-account <agent> default uses to clear a binding).

Inspect

bash
sudo 5dive account list           # name, types signed in, # agents bound
sudo 5dive account show personal  # detail incl. env keys present
sudo 5dive account usage          # per-account 5h/7d rate-limit usage
account list --json
{
  "ok": true,
  "data": [
    { "name": "personal", "types": ["claude"], "agents": ["scout","builder"] },
    { "name": "work",     "types": ["claude","codex"], "agents": ["work-bot"] }
  ]
}

Bind agents

bash
# At create time
sudo 5dive agent create scout --type=claude --auth-profile=personal

# After the fact (rebinds + restarts the agent to pick up the new env)
sudo 5dive agent set-account scout work

# Clear the binding (agent falls back to the shared default credentials)
sudo 5dive agent set-account scout default

Rename and remove

bash
# Rename — repoints every bound agent's symlink and restarts the units
sudo 5dive account rename personal primary

# Remove — refuses if any agents still bind to it
sudo 5dive account remove primary

account remove is a safety net: if any agent has its authProfile set to the account, the command fails with class conflict (exit 5) and prints the agent names. Rebind or delete those agents first.

Account vs `agent auth` (lower-level)

The legacy agent auth set/login/start/poll/submit/cancel verbs still work — they take an --auth-profile=<name>flag and back the dashboard's device-code flow. Prefer account for human-driven flows; reach for agent auth start|poll|submit when you need the non-TTY device-code lifecycle from a programmatic caller.

10

Agent lifecycle

Create

5dive hire <name> is ergonomic sugar over agent create: it defaults --type=claude, forwards every other create flag verbatim, and peels off --role / --title to record the agent in the org chart once it exists (sudo 5dive hire cto --role="CTO"). agent create stays the canonical form and is what the rest of this section documents.

bash
sudo 5dive agent create <name> --type=<type> \
  [--channels=none|telegram|discord|dashboard[,ch...]] \
  [--telegram-token=<bot-token>] [--discord-token=<token>] \
  [--workdir=<absolute-path>] \
  [--auth-profile=<name>] \
  [--isolation=standard|admin|sandboxed] \
  [--provider=<id> --api-key=<key|->] [--model=<slug>] \
  [--telegram-home-channel=<chat-id>] [--telegram-allowed-users=<csv>] \
  [--with-skills=<spec>[,<spec>...]] [--inherit-memory=<scope>] \
  [--yolo | --autonomy=standard|yolo] \
  [--no-skills] [--no-team-bot] [--defer-auth] [--can-push]

Names: lowercase letters / digits / hyphens, must start with a letter, max 16 characters. The CLI installs the type binary on demand if it's missing, then refuses to create the agent unless the type is authenticated.

--with-skills preinstalls one or more skills on the new agent. Spec is either a bare id (defaults to 5dive-ai/skills) or <owner/repo>:<id>. Multiple specs are comma-separated. When the create call is made by another agent on a claude-typed agent, the flag defaults to --with-skills=5dive-cli so spawned children inherit inter-agent comms knowledge automatically. Use --no-skills to opt out. A failed skill install warns but does not roll back the agent — rerun 5dive agent skill <name> add ... to retry.

--defer-authskips the auth gate so the agent can be created before credentials exist (useful when the agent's own first-run UI handles sign-in). --provider=<id> --api-key=<key|-> is for hermes/openclaw only — BYO key for one of openrouter, google, minimax, moonshot, huggingface, anthropic, deepseek, qwen, nous, openai, zai (mutually exclusive with --defer-auth). When the host has a shared team bot configured, new no-bot agents auto-attach to it (own forum topic, send-only on the shared token) — --no-team-bot opts out.

--model=<slug> sets the runtime model at create time instead of a follow-up agent config set model=.... For a BYO-provider claude agent it accepts any slug the provider serves, overriding the CLI's safe per-tier defaults. --telegram-home-channel=<chat-id> (hermes only) and --telegram-allowed-users=<csv> seed the channel config at create time instead of a separate agent config call afterward. --inherit-memory=<scope>seeds the new hire's recall store from shared knowledge so it boots knowing the company — scope is a comma-list of wiki, a sibling <agent-name> (its shareable facts only), or all/team.

--can-push grants the agent delegated 5dive push (a scoped sudoers entry for the push helper) — refused on --isolation=sandboxed, a no-op with a warning on --isolation=admin (already covered by its broader sudo).

--yolo (alias --autonomy=yolo) sets the agent's autonomy mode. claude-only: it appends a standing “act on your own recommendations, still honor hard gates” directive to the system prompt (via --append-system-prompt, so it survives a /clear) — the agent stops asking for permission on reversible work but still parks secrets/approvals on a human. Default is standard; change it later with agent config <name> set autonomy=....

List & inspect

bash
sudo 5dive agent list                # text or --json (carries model + effort per agent)
sudo 5dive agent info <name>         # type, CLI version, model, channel + state
sudo 5dive agent stats <name>        # state, restart count, last exit
sudo 5dive agent logs <name> --lines=200 [--follow] [--tmux]

--tmux dumps the tmux scrollback (what the user sees in the TUI). Without it, logs come from systemd / journalctl. agent list and agent info are no-sudo surfaces — any agent can run them regardless of isolation tier.

Install a type binary

bash
sudo 5dive agent install <type>              # install if missing (no-op if present)
sudo 5dive agent install <type> --upgrade    # reinstall @latest (aliases: --force, -u)

agent create already installs a missing type binary on demand — reach for agent install directly to pre-warm a type before the first create, or to force a stale binary back to latest without touching the agent itself.

Start, stop, restart, remove

bash
sudo 5dive agent start   <name>
sudo 5dive agent stop    <name>
sudo 5dive agent restart <name> [--defer]   # --defer = internal deferred self-restart
sudo 5dive agent rm      <name>   # removes user, unit, tmux session, env

Reconfigure

bash
sudo 5dive agent config <name> set channels=<none|telegram|discord>
sudo 5dive agent config <name> set workdir=<path>           # "default" clears
sudo 5dive agent config <name> set auth-profile=<name>      # "default" clears
sudo 5dive agent config <name> set telegram.token=<token>
sudo 5dive agent config <name> set discord.token=<token>
sudo 5dive agent config <name> set telegram.allowed-users=<id1,id2,...>
                                                            # seed access.json allowlist (no pair-code gate)
sudo 5dive agent config <name> set telegram.home-channel=<chat-id>
                                                            # hermes only — chat the gateway posts to unsolicited
sudo 5dive agent config <name> set model=<id>               # claude/codex/grok/antigravity;
                                                            # claude: opus|sonnet|haiku|fable
sudo 5dive agent config <name> set effort=<low|medium|high|xhigh|max>
                                                            # claude only — reasoning effort;
                                                            # xhigh/max are Opus-tier
sudo 5dive agent config <name> set autonomy=<standard|yolo>
                                                            # claude only — yolo appends the "act on
                                                            # your recs, still honor hard gates" directive

# Shorter alias for the auth-profile case
sudo 5dive agent set-account <agent> <account|default>

Send input / attach

bash
# Inject a message into the running tmux session (sends keys + Enter)
sudo 5dive agent send <name> "implement the dashboard skeleton"

# Hand off a chat request: tells the receiver to answer in that
# Telegram/Discord chat via its OWN bot instead of relaying back
sudo 5dive agent send <name> "user asks ..." --reply-to-chat=<id> [--reply-to-msg=<id>]

# Attach your terminal to the session — Ctrl-b d to detach
sudo 5dive agent <name> tui

When called from another agent, send auto-wraps the payload with a [5dive-msg from=<sender> id=<id>] envelope so the receiver knows who pinged it. Use --from=<label> to override and --raw to skip wrapping. See Inter-agent comms for the full protocol and the synchronous agent ask wrapper.

Clone

bash
sudo 5dive agent clone <src> <dst> [--channels=...] \
  [--telegram-token=...] [--discord-token=...] [--workdir=...]

Clones type, workdir, and auth profile from <src>. Channel + tokens must be passed fresh — two agents cannot share a Telegram bot.

11

Delegated push

An agent created with --can-push (see Agent lifecycle; requires --isolation=standard, the default) can push ONE named feature branch for PR review once its task's gate is cleared and bound to that branch. The agent's own process never touches a GitHub token.

bash
# One-time per box: scaffold the GitHub App config
# (never pass the private key itself on argv)
sudo 5dive push setup [--author="Name <email>"]

# From the --can-push agent, once its task's gate is cleared and
# bound to the branch being pushed:
5dive push <id|DIVE-N> [--branch=<b>] [--repo=<url>] [--dry-run]

Never pushes main/master/HEAD, and never a merge. A root-only helper mints a GitHub-App-installation token scoped to just that repo, pushes, and discards it immediately — so a compromised or over-eager agent can leak at most one throwaway, single-repo token, never a durable credential.

Deploy (INST-5)

bash
5dive deploy <id|DIVE-N> [--target=<project@ref>] \
  [--env=production|preview] [--dry-run]

Same delegated-credential shape as 5dive push — it deploys ONLY the project@refthe task declares, ONLY once that task's gate is cleared. --target can also come from a Target: <project@ref> line in the task body, mirroring how push reads Branch:.

12

Proof (zero-human badge)

5dive proofpublishes a daily public “zero-human” status badge and scorecard to a repo, answering “how much of what shipped needed a human?” from real task-outcome data rather than self-report.

bash
sudo 5dive proof on --repo=<url> [--branch=status] [--at=<0-23>] [--user=<u>] \
  [--as-name=<name> --as-email=<email>]
sudo 5dive proof off
5dive proof status [--json]
5dive proof scorecard [--json] [--7d] [--by=tier|class]
sudo 5dive proof publish [--dry-run] [--repo=<url>] [--branch=<b>]
5dive proof tick                     # cron driver, gated on the on/off pref

on installs an idempotent daily cron gated by a per-box preference; off removes it. scorecard is the read-only local metrics view — both --by=tier and --by=class are wired to their own grouping (class = project/priority); class coverage is complete while tier coverage is partial.

publish/on refuse without a resolved git identity (exit code 4, distinct from the healthy no-op exit 3). Identity resolves in order: (1) ZH_GIT_NAME/ZH_GIT_EMAIL env, per-invocation; (2) proof.json's .identity.{name,email}, set via proof on --as-name= --as-email=(both required together, email format-validated); (3) the publishing user's own git config. The very first publishis gated behind an explicit human approval (it emits a public brand/comms artifact), cached once approved via a verifiable human-tap nonce — a plain gate answer does not satisfy it. Every refusal path prints its own reason rather than degrading to a stale “last published: never”.

13

Compose (declarative)

Standing up many agents at once? Declare them in 5dive.yaml and bring the whole stack up in one command. Re-running 5dive up is idempotent — agents that already exist are left alone; only missing ones are created.

5dive.yaml
agents:
  coder:
    type: claude
    workdir: ./repo
    channels: telegram
    telegram_token: ${TELEGRAM_TOKEN_CODER}
    isolation: standard
    skills: [5dive-cli]
  reviewer:
    type: codex
    workdir: ./repo
    isolation: sandboxed
  pm:
    type: claude
    channels: telegram
    telegram_token: ${TELEGRAM_TOKEN_PM}
bash
sudo 5dive up         # bring everything up (idempotent)
sudo 5dive ps         # status of each agent in the file
sudo 5dive down       # stop + remove everything declared
sudo 5dive export     # dump the LIVE fleet to a 5dive.yaml (reverse direction)

# Default file: 5dive.yaml or 5dive.yml in cwd; override with -f <file>

${VAR} placeholders are strictly expanded from the environment — unset references fail loudly (exit 3) rather than silently inserting an empty string. Relative workdir paths resolve against the directory holding the spec file (Docker-Compose convention). Spec keys per agent: type, channels, telegram_token, discord_token, workdir, skills, no_skills, defer_auth, isolation, auth_profile, provider, api_key, and pack — set pack: <slug> to build the agent from a published character pack instead of a bare type (the pack supplies the persona; the spec supplies the name + token).

Team templates

Bundled multi-agent company structures — provision a whole team in one call. team import wraps up, so it is idempotent too.

bash
sudo 5dive team ls                                  # list bundled templates
sudo 5dive team import <slug|path> [--auth-profile=<name>]
14

Packs & marketplace

An agent pack is a portable .tar.gzof an agent's identity — instructions, skill refs, and a sanitized subset of its settings. Packs carry no secrets: tokens, API keys, sessions, and transcripts are hard-excluded. Use a pack to share an agent across users or hosts; agent clone remains the same-host, full-fidelity duplicate path.

Export

bash
# Config-only pack (default — safe to share)
sudo 5dive agent export <name> --out=./mybot.tar.gz

# With persona memory — a two-phase, deny-by-default review gate
sudo 5dive agent export <name> --with-memory          # 1. writes a redacted DRAFT to review/edit
sudo 5dive agent export <name> --approve-memory=<dir> # 2. seals the reviewed memory into the pack

--with-memory never ships memory blind: phase one distills only reference/project knowledge facts (private user/feedback facts are excluded) into a draft directory for you to read and edit; nothing is packed until you re-run with --approve-memory=<draft dir>.

Marketplace & import

The character-pack registry (<org>/character-packs on GitHub) is a public catalogue of ready-made agent personas. Browse it, then import any entry by its bare slug into a fresh agent name:

bash
# Browse the registry
sudo 5dive agent marketplace ls

# Import a published persona under a new name + your own bot
sudo 5dive agent import lilbro --as=scout \
  --channels=telegram --telegram-token=123456:ABC...

# Import from a local .tar.gz you were handed
sudo 5dive agent import ./mybot.tar.gz --as=scout

# Provision a live agent from an OpenAgent persona.yaml
sudo 5dive agent import --from-persona=./dario.persona.yaml --as=scout \
  --type=claude --channels=telegram --telegram-token=123456:ABC...

--from-persona turns the OpenAgent self-author flow into self-provision: the persona supplies identity (name, role, look, voice, behavior) and the CLI synthesizes a character pack from it — a generated identity doc, the portrait from face.ref as the avatar, and a manifest seeding find-skills / 5dive-cli / compile-knowledge / openagent — then runs the normal import. Runtime config (--type, --isolation, --model, --effort, --channels) comes from flags.

import takes either a registry slug or a local pack file and recreates the agent under --as=<name>. Because packs carry no secrets, you supply the new agent's own token / auth-profile / workdir at import time. Skills are re-added from their recorded refs (any skill not in a published repo is skipped and reported). The dashboard's Marketplace modal drives this same path.

15

Agent market

The agent market is the searchable, rarity-first face of the character-pack registry above — browse and hire a ready-made persona instead of building an identity from scratch.

bash
sudo 5dive market                          # browse every pack, rarity-first
sudo 5dive market <keyword> [--role=<r>] [--rarity=<tier>] [--seasoned]
sudo 5dive market search <keyword>         # explicit alias for the keyword form
sudo 5dive market show <slug>              # preview: tier, model, skills, card, DID

sudo 5dive hire <role> --from-market --dry-run --json           # resolve + disclosure, create NOTHING
sudo 5dive hire <role> --from-market [--as=<name>] --yes --json # provision the top match

--rarity is one of mythical / legendary / epic / rare; --seasoned filters to packs that ship pre-trained memory. hire --from-market provisions a real teammate and is gated: --dry-run creates nothing, a TTY requires an interactive y/N, and a non-interactive caller needs an explicit --yes or it aborts after showing the disclosure. It runs agent import under the hood — agent inspect <slug> first for the full hooks/skills disclosure on an untrusted pack.

16

Channels & pairing

A new agent created with --channels=telegram writes the bot token under /etc/5dive/connectors/telegram-<name>.env and starts an MCP plugin process inside the agent. The plugin is locked down by default — it ignores every chat until you pair one.

Pairing

bash
# Option A — give the user a 6-character code, they DM the bot, paste it back
sudo 5dive agent pair <name>                    # prints/returns code

# Option B — paste the bot's reply directly (dashboard flow)
sudo 5dive agent pair <name> --code=AB12CD

# Option C — seed access.json directly with a known Telegram user id
# (pairs with agent telegram-discover, which long-polls getUpdates and
# returns {userId, chatId, username} on the first inbound DM)
sudo 5dive agent pair <name> --user-id=<id> [--chat-id=<id>]

Allow-list

The plugin's allow-list lives at ~/.claude/channels/<channel>/access.json inside the agent's home. Pairing appends to allowFrom; rotate the bot token via 5dive agent config <name> set telegram.token=....

17

Skills

Skills are the skills.sh prompt-bundle format. A skill is a directory with a SKILL.mdat its root. Installing a skill on an agent drops it into the agent type's skills dir (~/.claude/skills/ for claude, ~/.hermes/skills/ for hermes, ~/.agents/skills/ for codex / opencode, ~/skills/ for openclaw) and makes it loadable on next prompt.

bash
# Install a skill on an agent
sudo 5dive agent skill <name> add \
  --source=<owner/repo> \
  --skill=<skill-id>

# List installed skills
sudo 5dive agent skill <name> list

# Remove a skill
sudo 5dive agent skill <name> rm <skill-id>

Tip: install the 5dive-cli skill from github.com/5dive-ai/skills on any agent to teach it the 5dive command surface — agent lifecycle, JSON envelope, recovery on exit codes, and the --json orchestration loop:

bash
sudo 5dive agent skill <name> add \
  --source=5dive-ai/skills \
  --skill=5dive-cli

With it installed, an agent can spawn its own subagents on the same host — see Spawning subagents.

18

Spawning subagents

Any agent on a 5dive VM can call 5diveto spawn more agents on the same host — that's how recursion works. The agent user (agent-<name>) is in the claude group and has sudo 5dive ... in its sudoers, so:

bash
# From inside one agent's tmux session — spawn a worker for a side task
sudo 5dive agent create worker-1 \
  --type=claude \
  --workdir=/home/claude/projects/myrepo \
  --json

# Send it a task
sudo 5dive agent send worker-1 "audit auth middleware for OWASP A01"

# Watch its output
sudo 5dive agent logs worker-1 --tmux --lines=50

# Tear it down when done
sudo 5dive agent rm worker-1

For LLM-driven orchestration, prefer --jsonon every call and branch on error.class rather than parsing the human stderr. The 5dive-cli skill packages this loop as a reusable prompt — install it on the parent agent and ask for “a worker that does X”.

19

Inter-agent comms

agent send and agent askform a tiny message bus between agents on the same host. There is no separate channel — messages land in the receiver's running CLI as if a human had typed them, but with an envelope that lets the receiver tell who is pinging it.

Auto-attributed sends

When the caller is an agent-* Linux user (i.e. one agent shelling out to talk to another), the CLI auto-detects the sender from $SUDO_USER and wraps the payload as:

bash
[5dive-msg from=<you> id=<8-hex>] <your text>

Humans calling sudo 5dive agent send directly are unaffected — only sends from agent users get the envelope. Override with --from=<label> or skip wrapping entirely with --raw.

Replying

A receiver that sees a wrapped message replies the same way it would talk to anything else — by name. The [re=<id>] prefix is convention, not enforced; it lets the sender match replies when juggling several outstanding asks.

bash
# Inside the receiver's session, after seeing
# [5dive-msg from=scout id=ab12cd34] please summarise the audit

sudo 5dive agent send scout "[re=ab12cd34] auth middleware looks clean except ..."

Synchronous request/response: agent ask

bash
sudo 5dive agent ask <name> "<prompt>" \
  [--from=<sender>] \
  [--timeout=120] \
  [--idle-secs=5] \
  [--poll-secs=2] \
  [--json]

Sends the wrapped envelope, then watches tmux capture-pane after the marker line until the slice has been quiet for --idle-secs (default 5s) — at which point it returns the reply body. Times out with class timeout (exit 11) if the receiver never goes idle within --timeout.

JSON envelope
{
  "ok": true,
  "data": {
    "name": "scout",
    "from": "coordinator",
    "msg_id": "ab12cd34",
    "reply": "auth middleware looks clean except for ..."
  }
}

Caveats

Idle-by-stability is heuristic. A receiver that streams progress continuously will keep ask awake until --timeout fires. For long agentic work, prompt the receiver for a terse final summary, or use plain send + logs and poll on your own schedule.

The reply is whatever was on screen. It includes any chrome the receiver CLI prints (cursor lines, status hints) — don't expect a clean JSON body unless the prompt explicitly asks for one.

No retries, no delivery confirmation. If the receiver crashed mid-reply you'll get a partial slice or a timeout, nothing in between.

When to use what

Fire-and-forget delegation: agent send, then poll agent logs --tmux at your own convenience. Need an answer before continuing: agent ask. Fan-out across N workers: loop agent send, or run several agent ask calls in parallel via & + wait.

20

Task queue

A host-shared work queue (sqlite at /var/lib/5dive/tasks/tasks.db) that any agent in the claude group can use without sudo. Tasks have priorities, assignees, parent/subtask links, and blocking edges — the substrate for delegating work across a fleet.

bash
5dive task add <title...> [--body=<text>] [--priority=low|medium|high|urgent] \
  [--assignee=<agent>] [--parent=<id>] [--project=<key>] [--recurring="<cron>"] \
  [--task-budget=<tokens|$cost>]   # per-run spend cap for the on-host loop
  [--branch=<name>]                # seed a delegated-push branch binding (see merge-gate below)
5dive task ls [--mine] [--status=<s>] [--all] [--project=<key>] [--recurring]
5dive task show <id|PREFIX-N>        # full detail + subtasks + blockers
5dive task set-body <id|PREFIX-N> <text...> [--append]   # edit body after creation (overwrites by default)
5dive task start <id|PREFIX-N>       # -> in_progress
5dive task done <id|PREFIX-N> [--result=<text>] [--force-merge-gate] [--keep-worktree]
5dive task deliver <id|PREFIX-N> --pr=<url> [--result=<text>]   # record the shipping PR, hand off, don't close
5dive task cancel <id|PREFIX-N> [--result=<text>] [--keep-worktree]
5dive task assign <id|PREFIX-N> <agent>
5dive task escalate <id|PREFIX-N>    # flag for attention: bump priority a tier + ping owner & human
5dive task block <id|PREFIX-N> --by=<id|PREFIX-N>   # + unblock to clear
5dive task reclaim <id|PREFIX-N>|--all [--dry-run]   # sweep node_modules from a closed task's worktree
5dive task merge-audit [--limit=N] [--json]          # read-only: DONE tasks whose named PR never merged
5dive task rm <id|PREFIX-N>          # delete (cascades subtasks + edges)

Statuses: todoin_progress done / cancelled, plus blocked while a blocking edge or human gate is open. --recurring="<cron>" (5-field cron) makes a template that re-instantiates on schedule. Task ids are PREFIX-N — the default dive project numbers DIVE-1, DIVE-2…; see Projects to carve out your own namespace.

Verify loops (maker → verifier)

A task can carry a declarative acceptance loop so “done” is proven, not just claimed. Attach acceptance criteria, a verify command, and (optionally) a separate verifier agent at create time:

bash
5dive task add "ship the export endpoint" \
  --accept="returns 200 + a .tar.gz" \
  --verify="curl -fsS localhost:3000/export -o /tmp/o && file /tmp/o | grep gzip" \
  --verifier=reviewer --max-iters=3
bash
5dive task verify <id|PREFIX-N> [--cmd="<command>"] [--no-done]
                                     # run the check; exit 0 => proven-done (flips to done)
5dive task reject <id|PREFIX-N> [--feedback="<what to fix>"]
                                     # verifier's FAIL verdict — bounce back to the maker
5dive task loops [--stuck] [--all] [--escalate-stuck]
                                     # board of active loops: iteration/cap + ⚠ stuck flag

With a --verifier(which must differ from the assignee), the maker's task done does not close the task — it hands off to the verifier, who grades against the criteria / runs task verify, then closes it on PASS or task reject --feedback= on FAIL (bounce back to the maker, or escalate to a human at --max-iters). The writer never grades itself. task loops is the observability view — --escalate-stuck pings the owning agent + the human on loops that have stalled.

Verification is on by default: a non-trivial task add auto-derives acceptance criteria and assigns a grader distinct from the assignee, so a plain task done hands off to grade instead of closing. Trivial bodyless chores, low-priority tasks, and recurring templates auto-skip it; --no-verify is the explicit opt-out, and FIVE_VERIFY_DEFAULT=0 is a fleet-wide kill switch. A task filed without the rail can still get one later: 5dive task verifier <id> <agent> [--accept=<criteria>] [--max-iters=<n>] attaches it after the fact (grader must differ from the assignee), or re-points an already-in-review handoff to a different grader.

A delivered loop is durable against its own maker. Once a task is handed to its verifier, task done from anyone but that verifier is refused outright — even a second task done from the maker itself. Send a correction to the verifier and let them fold it in rather than re-running done; real exits mid-review are task reject (bounce back), task verify --cmd= (evidence-backed close), or task cancel.

Delivery & the merge-gate

If work ships as a pull request, use task deliver <id> --pr=<url> [--result=<text>] instead of task done— it hands off to the verifier without closing, the maker's own act of declaring “this is what I shipped.”

donemeans merged-to-main, not “PR opened.” Once a task carries a declared delivery binding — a task deliver --pr= reference, or a Branch: <name> body line from task set-branch / task add --branch=task done refuses to close until gh confirms that PR is merged and its checks are not red. Even with no declared binding, a second, mandatory auto-detect gate still runs on every close: it scans open PRs across the known repos for a title/branch naming the task's ident, and separately checks the close's own result text for a shipping claim (“merged as #6”, a Delivered: line — a PR merely cited in passing is deliberately not checked). --force-merge-gateis the audited override for false positives (a flaky post-merge CI run); the leftover unmerged PR still surfaces in the weekly branch-hygiene digest. When the gate can't reach a verdict at all (no gh token, a broken scan), the close still proceeds but the result is stamped [merge-gate: UNVERIFIED — …] rather than looking silently clean.

task set-branch <id> <branch> binds a task to a git branch for delegated push, writing or updating that Branch: body line. task merge-audit is the read-only retrospective version of the merge-gate check, run over already-done tasks — it only reports, never reopens. done/cancel also reclaim disk on close: node_modulesis deleted from the task's worktree (gitignored, npm ci-regenerable) unless you pass --keep-worktree; the worktree directory itself is never deleted since it may hold unpushed commits. task reclaim <id>|--all [--dry-run] runs that same sweep manually.

Human task inbox

When an agent needs a decision, approval, secret, or a manual step only a person can do, it parks the task on a human instead of guessing:

bash
5dive task need <id> --type=decision|secret|approval|manual|access \
  --ask="<one crisp question>" [--options=A|B] [--recommend="A"] [--tier=0|1|2] \
  [--probe=<cmd>]                    # type=access only
5dive task need <id> --withdraw      # cancel a still-pending gate that's now moot
5dive task inbox                     # list ONLY human-gated tasks
5dive task inbox --send [--channel-proof=<chat>]
                                     # root-only: DM the owner ONE tap-button digest
                                     # of up to 10 pending gates (fresh per-gate nonce,
                                     # never exposed via --json)
5dive task answer <id> --value="..."   # record answer, unblock, ping the agent
5dive task clear-recs --channel-proof=<chat_id> [--only=<id>]
                                     # bulk-clear every eligible low-risk gate (tier<2,
                                     # has a --recommend, not lead-routed) as the paired human

The gate pings the owner (Telegram inline buttons when paired); answer clears it and wakes the owning agent to resume.

--type=accessis for “I'm blocked on a permission/grant I don't have.” Pair it with --probe=<cmd> — a self-check that must currently fail; if it succeeds the gate is refused (“you already have this access”) instead of pinging a human for nothing. Omitting --probe still files the gate, just with a warning to confirm you actually tested the block. 5dive task coordinator [--json]prints the resolved org coordinator — the one agent a surface should pin a needs-you banner to; empty output means an ambiguous or missing org, which callers should treat as “nobody pins.”

--withdrawcancels a gate that's still pending — the antidote to filing an access/secret/approval gate that turned out to be moot. It is nota grant: it never records an answer, so no secret or approval is ever recorded as provided — which is why it's safe to allow without a human tap. Authorized callers are the gate's filer, the filer's routed lead/coordinator, or a genuine human; a real grant-clear still goes exclusively through task answer.

--tier=0|1|2 sets how hard the gate blocks. Tier 0 auto-clears — the --recommendvalue applies immediately with no ping (the daily digest's “auto-cleared gates” section is the record). Tier 1 pings normally, but if unanswered for 48h the recommendation is auto-applied and the owner notified (the default for decision). Tier 2 is a hard human gate that never auto-applies (the default for approval / secret / manual). Money, public comms, secrets, destructive, and brand asks are floored to tier 2 by the CLI regardless of the flag — reserve tier 0/1 for low-stakes reversible calls.

approval and secret gates are human-only: an agent-* caller is refused, and once gate-proof enforcement is on, clearing one requires human evidence: either a per-gate nonce that only a real Telegram approve tap carries, or a non-agent SUDO_UID(an operating-system user that isn't an agent). A sudo-capable agent has neither, so it can't silently clear its own approval gate. Trusted UI paths clear it for you: the dashboard and drop links run as a real (non-agent) user, and the Telegram approve button carries the gate's nonce.

Parking & escalation

Not every wait is a human gate. task park puts a task to sleep without parking it in the human inbox — for revisit-later work or a task waiting on an external date — and auto-wakes it back to todo at --wake. task escalate raises urgency without filing a gate: it bumps priority one tier (capped at urgent) and pings the owning agent plus the paired human.

bash
5dive task park <id|PREFIX-N> --reason="revisit after launch" --wake=+3d
                                     # --wake=<YYYY-MM-DD[ HH:MM]|+Nd|+Nh> — REQUIRED,
                                     # --reason is REQUIRED too (fail-closed)
5dive task unpark <id|PREFIX-N>      # wake it early, back to todo
5dive task escalate <id|PREFIX-N>    # +1 priority tier + ping owner & human

Both --reason and --wake are required — no more block-graveyard with no revisit date. park also refuses to run over a task that already has a live, unanswered task need gate — answer the gate first, or parking would silently destroy it with no audit trail.

Gate-proof (tamper-evident approvals)

Because tasks.db is group-writable, gate closures are made tamper-evident: task answer stamps the real pre-sudo invoker and an HMAC (signed with a root-only key) over the closure facts, so a raw-sqlite3 bypass or an after-the-fact edit is detectable. When enforcement is on fleet-wide, an agent-path answer to an approval/secret gate with no human evidence (a per-gate nonce or a non-agent SUDO_UID) is rejected.

bash
# Verify a stored closure signature: signed=? valid=?
sudo 5dive gate-proof verify <id|PREFIX-N>

# Toggle enforcement for this box (reject vs audit-only)
sudo 5dive gate-proof enforce on|off|status
21

Goals (task DAGs)

5dive goal add turns a one-line outcome into a validated, guardrailed task DAG — tasks, blocking edges, and assignees under a project — instead of you hand-authoring every subtask. A planner agent proposes the plan; it's checked for DAG acyclicity, size/depth caps, tier-floor, and assignability before anything is created.

bash
5dive goal add "<outcome>" --dry-run --json   # plan + render, create NOTHING

5dive goal add "<outcome>" --json \
  [--project=<key>] [--planner=<agent>] [--max-tasks=12] [--depth-cap=5] \
  [--checkpoint=6] [--ceiling=40000] [--yes] [--plan=<json>]

5dive goal add --from-gate=<id> --json   # materialize a plan a HUMAN answered 'approve'

Over the --checkpoint task-count threshold, or carrying any Tier-2 task, ONE decision gate holds the plan and nothing materializes until a human approves — --yes waives only the count checkpoint. --from-gate=<id> is the only path that creates a Tier-2 plan (a human already approved it on that gate). Always --dry-run first to eyeball the plan; the real add is the only thing that creates work.

22

Objectives (self-steering)

5dive objective is different from goal: not a one-shot task DAG but a standing target bound to a read-only metric command that gets re-measured every tick. Use it to track a number you want to move (conversion %, warm-pool size, error rate) rather than to decompose a fixed body of work.

bash
5dive objective add "<outcome>" --metric-cmd="<read-only cmd>" --target=<n> \
  --direction=up|down [--unit=<u>] [--public] [--planner=<agent>] \
  [--review="<cron>"] [--max-new-per-cycle=<n>]

5dive objective ls | show <name> | tick [<name>]
5dive objective pause  <name>                # stop measurement/replanning (always allowed)
5dive objective resume <name> [--force]      # --force bypasses a preflight refusal
                                             # (e.g. the planner role can't currently do the work)
5dive objective rm <name>

--metric-cmd must be read-only — it runs every tick. --direction says whether higher or lower is better; --public surfaces it on the public scoreboard.

Self-steer it: objective replan

objective replan <name> drives one cycle: a planner proposes a diff (new / reprioritized / cancelled tasks) toward the target, validated the same way a goal add plan is.

bash
5dive objective replan <name> --dry-run --json     # see the proposed diff, create nothing

5dive objective replan <name> --json \
  [--max-new-per-cycle=3] [--no-progress-limit=3] [--yes] [--force] [--from-gate=<id>]

--yes waives only the count-over-checkpoint gate — a Tier-2 task in the diff still hard-gates, and nothing under a shadow/propose-only run is waivable. --no-progress-limit=<n> auto-pauses the objective after N flat/adverse cycles. Always --dry-run a replan first, same discipline as goal add.

23

Loop orchestration

5dive loop is agent-native multi-agent orchestration built over the task queue and a loop_runs table. Every verb takes JSON in and emits JSON out, and every verb honors a per-loop token --ceiling — at the limit the loop self-halts and escalates with proof rather than running up a surprise bill. Humans watch and kill loops via 5dive task loops [--kill <loopId>]; they never author one.

bash
loop spawn  --role=maker|verifier|worker --agent=<type|name> --prompt="…" \
            [--schema=<json>] [--ceiling=<tokens>] [--wait[=<sec>]]
loop verify --target=<id> --verifier=<agent> [--accept="…"]
loop grade  --target=<id> --verifier=<agent> [--accept="…"] [--threshold=<0-100>] [--wait]
loop panel  --n=<k> --lens="correctness,security,repro" --claim="…" --quorum=<m>
loop map    --over=<json-array> --do=<spawn-spec> [--max-concurrency=<n>]
loop until-dry --round=<spawn-spec> --stop-after=<K> --dedup-key="…"
loop collect --handles=<id,id,…>
loop status  --handle=<loopId>

The verbs mirror the common orchestration shapes: spawn is the atom (a backing task + heartbeat), verify/grade are the maker→verifier wrapper (grade emits a numeric scorecard against the acceptance criteria), panel runs N diverse-lens graders to a quorum vote, map is index-aligned fan-out with bounded concurrency, until-dry is K-empty-round discovery with a seen-set dedup, and collect is the barrier gather. Token spend rolls up per topology via 5dive usage loops.

Loop packs (marketplace)

A loop pack is a published recurring agentic workflow — a persona + skills + cadence — you install onto an existing agent. It sets the agent up to run that workflow on a schedule.

bash
sudo 5dive loop show <slug>                       # peek at a marketplace loop pack
sudo 5dive loop install <slug> --onto=<agent> \
  [--cron="<5-field>"] [--ceiling=<tokens>] [--dry-run]

Relay loops & scorecards

5dive task loop startis the higher-level relay that backs the dashboard loop builder: a chain of steps where each agent's task done hands off to the next, with optional human gate steps. Because it's just the task queue underneath, you can build and edit a running loop conversationally (the dashboard can't safely edit a live one).

bash
5dive task loop start --title="Content pipeline" --steps='[
  {"agent":"olivia","label":"Pick topic + brief","handoff":"briefs"},
  {"agent":"theo","label":"Draft the post"},
  {"gate":"approval","label":"You approve before publish"},
  {"agent":"theo","label":"Publish and close"}
]'
5dive task loop ls                   # board of relay runs: per-step progress + status

Each row on task loop ls carries the latest grade scorecard for the run — a score column (e.g. 84/100) on the text board and the full scorecard_json (banded criteria) in --json, empty until a verifier grades it. The maker→verifier control window lives under task loops:

bash
5dive task loops --runs              # loop_runs control window: topology / stage /
                                     # iteration / token-ceiling / status
5dive task loops --runs --watch      # live repaint
5dive task loops --kill <loopId>     # request a deferred-safe stop
24

Crew (CrewAI runtime)

5dive crew makes the box an always-on runtime for CrewAI crews. CrewAI is a Python library: you write Agent/Task/Crew and call crew.kickoff(), which runs to completion and exits. A crew is a finite triggered job; the “24/7” is the box, the scheduler, and the durable state around it. 5dive supplies what a bare crew lacks: a persistent install, durable memory across kickoffs (CrewAI's memory dir mounted on the box's persistent disk via CREWAI_STORAGE_DIR), a did:key identity, and a co-signed work receipt per run that feeds the ZeroHuman work-history net.

LLM auth is BYO customer key (litellm env), never a Claude subscription — supplied via crew secret set into a root/owner-600 env file that is injected only at kickoff, never group-readable.

bash
# Install a CrewAI project from git, isolated in its own venv
sudo 5dive crew install <git-url> --as=<name> [--entry=<module:Crew>] [--branch=<b>]

# Set the BYO LLM key(s) — owner-600, injected at kickoff only
sudo 5dive crew secret set <name> OPENAI_API_KEY=sk-...

# Run one kickoff (schedule it via a recurring task / heartbeat for "always-on")
sudo 5dive crew run <name> [--input='{"topic":"..."}'] [--no-receipt]

sudo 5dive crew show <name>
sudo 5dive crew list
sudo 5dive crew uninstall <name> [--purge]

Memory persists across runs in <name>/storage; each run emits a co-signed receipt to the ZeroHuman feed unless you pass --no-receipt. Schedule crew run with a recurring task or trigger it from Telegram for the always-on shape.

25

Projects

A project carves the shared task queue into its own identifier namespace. Every host starts with the built-in dive project (prefix DIVE-, so tasks number DIVE-1, DIVE-2…). Add your own so unrelated streams of work get their own readable ids (FROG-1, POST-1) instead of sharing one counter.

bash
sudo 5dive project add frogs --prefix=FROG \
  [--name="Frog app"] [--goal="<one-liner>"] \
  [--folder=/home/claude/projects/frogs] [--lead-agent=<agent>]
5dive project ls                     # key, prefix, task count, lead, status
5dive project show <key>             # detail

# Then file work into it — ids auto-number per project:
5dive task add "build the pond view" --project=frogs   # -> FROG-1
5dive task ls --project=frogs

A prefix is UPPERCASE letters only. Tasks filed with --project=<key> number independently within that project; everything else in the task queue (assignees, blockers, gates, loops) works identically across projects.

26

Usage & budgets

5dive usagereports per-agent and per-task token burn — the subscription tokens an agent consumed, not dollars. Use it to see which agents and which tasks are eating the shared account's budget.

bash
5dive usage [--7d]                   # board: top agents + top tasks by tokens (24h default)
5dive usage <agent> [--7d]           # one agent: per-model + per-task breakdown
5dive usage loops                    # token spend rolled up per loop topology / per loop

# Soft daily budgets — a board warning, not a throttle
sudo 5dive usage budget set <agent> --daily=<tokens>
5dive usage budget ls
sudo 5dive usage budget clear <agent>

A budget is advisory: crossing it flags the agent with on the usage board — nothing is throttled or stopped. Pair it with account usage (Accounts) for the 5h/7d rate-limit picture per sign-in.

27

Standup digest

5dive digest is a deterministic per-fleet standup built from data every fleet already has — the task queue (shipped in the last 24h / in-progress / open human gates), usage (token burn + share-of-limit), and heartbeat health. Zero agent reasoning, zero tokens — it works on a solo-agent box and never depends on a coordinator agent.

bash
5dive digest [--7d]                  # human/Telegram-ready standup (24h default; --7d widens)
5dive digest --json                  # { window, done, inProgress, blocked, usage, health }
5dive digest --send                  # deliver it to the paired Telegram chat now

# Auto-delivery is opt-in, OFF by default (per-box pref survives CLI updates)
sudo 5dive digest on [--at=<0-23>]   # enable daily delivery at hour HH (box-local)
5dive digest off | status

Auto-delivery is opt-in: the per-box cron runs hourly but sends nothing until digest on is set, at most once per day at the configured hour. Backs the Telegram /digest command.

28

Team memory

5dive memory searchis a read-only query into the accumulated markdown memory on the box — every agent's ~/.claude/projects/*/memory store plus the shared team wiki when one is present. It returns BM25-ranked snippets with file + heading provenance, capped at a token ceiling. No sudo, and nothing leaves the box.

bash
5dive memory search "hetzner capacity gotchas" --json
5dive memory search "deploy rollback" --limit=4 --max-tokens=800
5dive memory search "auth" --roots=/path/a,/path/b   # override the default roots

Reach for it before re-deriving a past decision or debugging something a teammate already hit — retrieval beats re-reading whole memory files into context.

29

Supervisor

5dive supervisor is an observe-only fleet-health board: per-agent state, a classification (stuck / crashloop / idle / healthy), the likely cause, and last activity. It detects and classifies but never auto-acts — restarting an agent is always your call.

bash
sudo 5dive supervisor            # one-shot board
sudo 5dive supervisor --watch    # live repaint (default 5s)

Check it before restarting an agent on a hunch. Pair it with usage (token burn) and doctor (dependency + auth health) for the full picture.

30

Fleet (multi-box)

When an operation spans more than this VM, a fleet registry maps box names to SSH targets — references only (host / user / port + a path to a key, never key material). It gives you one view and one command surface over every box.

bash
sudo 5dive fleet add prod-2 --host=1.2.3.4 --key=/home/claude/.ssh/id_ed25519
5dive fleet ls
5dive fleet status --json          # per-box reachability + agent counts (parallel SSH)
5dive fleet agents --json          # every agent across the fleet, one view
5dive fleet send scout@prod-2 "status report please"
5dive fleet restart scout@prod-2

Agents are addressed as <agent>@<box>. One unreachable box never fails the whole view. add / rmneed root; the read surfaces don't.

31

Org chart & heartbeat

Org chart

A lightweight reporting structure over the agents on a host — who manages whom, and what each agent's role is. Dashboards and coordinator agents read it to route work.

bash
5dive org set <agent> --manager=<agent> [--role=<text>] [--title=<text>]
5dive org tree                       # render the hierarchy
5dive org show <agent> | ls | rm <agent>

Heartbeat (wake-on-work)

Enrolled agents are woken only when they have queued tasks — one task per tick — instead of idling in a hot loop. The root cron driver is heartbeat tick.

bash
sudo 5dive heartbeat on <name> [--every=<dur>] [--no-fresh]   # default 30m;
                                                              # /clear before each task unless --no-fresh
sudo 5dive heartbeat off <name>
sudo 5dive heartbeat ls              # enrolled agents + next wake + queued count
sudo 5dive heartbeat tick            # cron driver (root); wakes due agents with work
32

Council (governance)

For decisions that should be a recorded vote rather than one agent's call — membership motions, constitutional amendments, or routing an open gate to deliberation — use 5dive council. This is a governance primitive: reach for it deliberately, not as a substitute for a normal task need gate. Writes (init, promote/demote/expel, bench add/rm) are sudo-gated; reads (roster, log, verify) are not.

Setup & roster

bash
sudo 5dive council init --seats=<a:chair,b,c,...> --threshold=<majority|all|N|a/b> --veto=<principal>
                                             # human-seed the primary Council ONCE
                                             # (fail-closed if already init'd; --force re-seeds,
                                             # logged in lineage)

5dive council roster                    # live seats, threshold/quorum, veto holder, lineage head
5dive council log [--limit=N]           # sealed verdict history (genesis + every motion + veto)
5dive council record [--json]           # per-seat track record: votes scored vs REAL task outcomes
5dive council lineage [verify|ls]       # verify the sealed hash-chain, or list it
5dive council verify [<receipt-digest>] # whole-lineage integrity + constitution-drift check

Convening a vote

bash
5dive council convene "<question>" --subject="<what this decides>" \
  [--seats=a,b,c] [--mode=quick|deliberate|adversarial] \
  [--bench=<name>] [--class=<decisionClass>] [--threshold=<n>] \
  [--timeout=120] [--idle-secs=5] [--poll-secs=2] [--standalone]

By default convene dispatches to the real seated agents — each votes via its own harness over agent ask, blind on the first round — and seals an auditable, tamper-evident verdict. --standalone uses a single-key modelCall seam instead (needs COUNCIL_API_KEY/COUNCIL_BASE_URL; COUNCIL_MOCK=1 runs a deterministic offline council for tests/smoke). A PASS from the primary Council offers the founder a one-time, non-blocking veto tap.

Membership motions & veto

bash
sudo 5dive council {promote|demote|expel} --subject=<seat> [--lens="..."] [--mode=...] [--dry-run]

5dive council sign-vote --seat=<id> --vote=approve|reject|escalate|abstain --convene=<id> \
  (--qdigest=<hex>|--question=<text>) --key-file=<PEM|-> [--rationale=...] [--emit=line|json]
5dive council verify-votes --votes=<json|@file> --roster=<json|@file> --convene=<id> \
  (--qdigest=<hex>|--question=<text>)

5dive council veto exercise --receipt=<digest> --nonce=<tap nonce> [--tier=hold|posthoc] [--reason=...]

A membership motion recuses the subject and auto-derives its decision class (promote = majority, demote/expel = 2/3). sign-vote lets a seat sign its own vote at source, emitting the COUNCIL-SIG: line pasted after COUNCIL-VOTE; verify-votes re-checks every co-signed vote against the roster's public keys and revocation list. A veto can never be asserted from a bare CLI string — convene --veto-by=... is a detected forge-attempt, refused with exit 9; veto exercise is the only authenticated path, gated on the receipt digest plus a real tap nonce.

Benches & gate routing

bash
5dive council bench ls | show <name>
sudo 5dive council bench add <name> --seats=a:lens|b:lens [--mode=] [--threshold=] [--desc=]
sudo 5dive council bench rm <name>

5dive council gate-clear <task|DIVE-N> [--mode=deliberate] [--seats=a,b,c] [--dry-run]
5dive council rot-triage [<task|DIVE-N>|--all] [--older-than-hours=48] [--dry-run]

sudo 5dive council amend --file=<new 5dive.md> [--dry-run]

Built-in benches: council, ship, brand, security (the council bench itself is refused — its seats change only via promote/demote). gate-clear routes an open tier-1 gate to the council instead of a human — a tier-2 or human-only-type gate is never self-cleared, always bumped up. rot-triage re-briefs a stale unanswered tier-2 gate sharper for the human but never clears it (tier-2 stays human-only). amend is the constitutional-class motion — 2/3 + full quorum + veto — and only swaps 5dive.md on a PASS.

Scheduled convenes

bash
sudo 5dive council schedule add <name> --question="<template>" --cron="<m h dom mon dow>" \
  [--bench=<name>] [--mode=quick|deliberate|adversarial] [--class=<c>] \
  [--max-actions=N] [--ballot-deadline=<secs>] [--context-cmd="<sh>"] [--no-cron]
5dive council schedule ls | show <name>
sudo 5dive council schedule rm <name>
5dive council schedule run <name> [--dry]     # what cron actually invokes

schedule add productizes a recurring convene: it binds a named question template to a cron expression and installs a managed crontab line keyed by a # 5dive-council-schedule:<name> marker, so re-running add updates it in place and rm only ever touches that one line — never a duplicate, never a clobber of an unrelated entry. The template may embed {{date}}/{{context}}; --context-cmd is a shell snippet run at each fire whose bounded stdout fills {{context}}. add/rm write the root-owned schedule config, so they run under sudo; ls/show/run don't.

run <name> gathers context, convenes on the default ballot rail, then files up to --max-actions ACTION:-prefixed board tasks from seat rationales, each stamped with the sealed receipt digest. An inquorate or failed run is logged but never fatal (exit 0) — only a quorate PASS files tasks. --dry prints the would-be task add calls instead of running them.

33

Trace (task history)

5dive trace <id|DIVE-N>reconstructs one task's story goal → ship, read-only and lock-free — same posture as usage/digest/memory search. Debug a task's history with this rather than reconstructing it by hand.

bash
5dive trace <id|DIVE-N> [--json] [--no-audit]

Text mode prints an origin block, a chronological timeline (created_atstarted_at → handoff/need/shipped/done, with a pending gate shown inline as (pending)), its project/goal/parent chain, audit-log lines mentioning its ident, and a final verdict: line.

The verdict is the zero-human proof story compiled into one line — it reads gate provenance, not effort: human_touchpoints only counts a need_answered_at whose need_answered_by is prefixed human: (a decision gate an agent answered itself does not count, even though the row exists). zero-human = done with 0 counted human touchpoints; otherwise human-in-the-loop names the count, or cancelled, or for an open task, “in progress — blocked on a pending <type> gate” / “in progress — N human touchpoint(s) so far.”

Audit-log references are supplementary, never authoritative — two structural gaps mean absence from the log is not proof an action didn't happen: rows written before CLI v0.15.26 systematically omit non-root agents' own task/task need sub-events, and a row whose append once failed leaves a marker (audit_drops) rather than vanishing silently. --no-auditskips reading the log (and the caveat) entirely. Tracing a cancelled or stuck task is not itself a failure — exit is 0 regardless of the task's status.

34

Selfcheck (self-test)

Where doctorasks “is the box healthy,” selfcheckasks “can our own instruments still tell?” Before trusting the fleet's own rails, run this — it runs each critical rail for real against throwaway, isolated state and asserts the effect it's supposed to have, not the string it printed.

bash
5dive selfcheck [--json] [--only=<probe,...>] [--full] [--assume-clean] \
                [--strict] [--allow=<probe,...>] [--report=<file>] [--label=<env>] [--list]

--list prints the probe corpus: gate-delivery, audit-root, audit-nonroot, harness-verdicts, bundle-integrity, snapshot-rails, scorecard-honesty. Each reports pass | fail | not-reached | error not-reached is first-class, never folded into pass: a probe whose precondition is absent (e.g. audit-rootrun as non-root) hasn't shown its rail works, and needs a machine-readable reason or it counts unexplained and fails the run. audit-root/audit-nonroot are deliberately never reachable together in one run, so full coverage needs a root job and a non-root job unioned via --report=<file> + --label=<env>.

--full runs the harness-verdict mutation sweep over the whole test corpus (~164-168 harnesses — budget ~10min with --assume-clean, ~22min bare) instead of a 3-harness sample; never put this on an interactive path. --strict treats any not-reached (even with a reason) as failure — only sound in an environment known to be fully complete. --allow=<probe,...>declares probes this deployment structurally can never reach — recorded for the union checker, but doesn't change this run's own exit code.

Exit codes differ from doctor: doctor --json always exits 0 and expects callers to branch on data.summary; selfcheck --json exits non-zero on failure — 0 only if every probe passed or was a reasoned not-reached.

35

Models

5dive models [--json] prints the current Claude model id for each short alias (opus, sonnet, fable, haiku), read-only, no sudo. This is the single source of truth that both agent create/agent config set model= alias-resolution and the Telegram /model picker read against — a model release is meant to be a one-line edit to that source and nothing else. Check it rather than assuming a hardcoded model id is still current; the alias and the underlying id drift apart across releases.

36

Doctor & health

5dive doctor walks every dependency (tmux/jq/bun/python3/nvm/node/npm), every type binary, every live auth probe, the creds heal (renames a stale ~/.claude/.credentials.json that would shadow an env-injected token), registry integrity, channel-plugin wiring, and shelld reachability.

bash
# Read-only check
sudo 5dive doctor --json

# Fix what's fixable (apt installs, type installer recipes, registry reseed)
sudo 5dive doctor --repair

# Narrow the scope
sudo 5dive doctor --category=deps   # or types | auth | creds | registry | shelld | channels

Envelope is always {ok: true, data: {summary, checks}} with exit 0 — branch on data.summary.errors > 0 in CI.

37

Updating & uninstall

bash
5dive --version                  # what's installed
5dive update --check             # read-only: is the CLI behind/stale? (no root)
sudo 5dive self-update           # update CLI + plugins, then restart agents
                                 # (alias: sudo 5dive update)
sudo 5dive watch [--interval=N]  # htop-style live view of every agent;
                                 # ↑↓ select, ↵ attach, r refresh, q quit
sudo 5dive uninstall [--purge] [--yes]   # remove 5dive; --purge also wipes
                                         # state + agent users

Managed 5dive.com boxes update nightly on their own; self-update is the on-demand path for self-hosted installs.

38

Exit codes

Both shell exit code and error.code in the JSON envelope. Branch on error.class for human-stable matching.

CodeClassMeaning
0okSuccess
1genericCatch-all / internal error
2usageUnknown flag, missing arg, bad subcommand
3validationFormat check failed (name, workdir, token, lines)
4not_foundAgent/type/session doesn't exist
5conflictAlready exists (name collision)
6auth_requiredType not authenticated, bot token missing
7not_installedCLI binary missing, no installer recipe
8not_runningtmux session / systemd unit not active
9pairingPair code not pending or invalid
10permissionMust run as root
11timeoutPlugin didn't materialize within waitloop
39

State & paths

Useful only when debugging — every path below is managed by the CLI. Don't edit by hand.

/var/lib/5dive/agents.jsonAgent registry (versioned). Source of truth for `agent list`.
/var/lib/5dive/agents.d/<name>.envPer-agent systemd EnvironmentFile.
/var/lib/5dive/auth-profiles/<name>/Named auth profile env files + captured CLI config.
/var/lib/5dive/auth-sessions/<id>/Live device-code session state.
/etc/5dive/connectors/<type>.envShared auth env (default profile).
/etc/5dive/connectors/telegram-<name>.envPer-agent bot token.
/etc/systemd/system/5dive-agent@.serviceTemplated systemd unit. One instance per agent.
/var/lib/5dive/tasks/tasks.dbShared task queue (sqlite). Group-writable — agents use it without sudo.
/var/log/5dive/agent-audit.logNDJSON audit trail of every mutating command.