`cotal` CLI reference
Reference: describes the TypeScript reference implementation (the
cotalCLI), not the wire contract. · For: operators · Wire contract: SPEC
cotal is the operator command line for the reference implementation: bring a mesh up, mint
identities, launch agents, watch what they do, and tear it all down. It is a thin client over the
wire contract: the normative subjects and schemas live in the SPEC; this page is
lookup material for the commands, not a walkthrough; if you are new, start with
Getting started.
Running it
Section titled “Running it”npm install -g cotal-ai # puts `cotal` on your PATH (needs Node 20+)cotal --help # every command, groupedcotal <command> --help # one command's flags and usagenpx cotal-ai <command> runs it without a global install; in a dev clone, pnpm cotal <command>
runs it through tsx with no build step. Bare cotal prints help. Every command generates its own
--help, usage, and shell completion from its declared flags.
Commands come from the surfaces the binary composes: the base mesh CLI, the manager
(supervise), and the delivery daemon (deliver), plus any operator-installed extensions.
cotal ext add <npm-package> adds a package’s commands to this same surface (the web dashboard
ships this way; see web).
Commands
Section titled “Commands”| Area | Command | Purpose |
|---|---|---|
| Set up & lifecycle | setup |
Guided, configure-only setup (installs, seeds personas; launches nothing) |
| Set up & lifecycle | up |
Start a local mesh (nats-server + JetStream), or boot a whole manifest with -f |
| Set up & lifecycle | down |
Stop a background mesh, or tear down a manifest / spawn -f deploy |
| Set up & lifecycle | meshes |
List the running meshes on this machine |
| Set up & lifecycle | use |
Set the default mesh a bare cotal spawn joins |
| Set up & lifecycle | status |
Read-only diagnostics for setup, processes, and the selected mesh |
| Agents & personas | spawn |
Launch an agent from a persona (foreground, or --detach via the manager) |
| Agents & personas | models |
List connector model catalogs and variants from the manager |
| Agents & personas | ps |
List managed agents and their mesh status |
| Agents & personas | stop |
Ask the manager to stop a managed agent |
| Agents & personas | attach |
Stream and drive a managed agent’s terminal (pty runtime) |
| Agents & personas | personas |
List, show, edit, create, or remove local personas |
| Agents & personas | supervise |
Run a manager daemon (the agent supervisor / control plane) |
| Messaging & watching | send |
Send one message, then exit: DM a peer, post a channel, or ask a role |
| Messaging & watching | channels |
Inspect or set the channel registry (replay, description, instructions) |
| Messaging & watching | history |
Clear retained message history |
| Messaging & watching | console |
Live protocol view for a space (TUI, or --plain line stream) |
| Messaging & watching | web |
Browser dashboard (installed as the cotal-web extension) |
| Auth & meshes | mint |
Mint a creds file for a space (auth mode) |
| Auth & meshes | join |
Join a space as your own presence (interactive) |
| Manifest | topology |
Validate and view a mesh manifest’s access graph (read-only) |
| Extensions & misc | ext |
Install / remove operator CLI extensions |
| Extensions & misc | completion |
Print or install shell completion |
| Extensions & misc | feedback |
Send feedback to the Cotal developers |
| Extensions & misc | deliver |
Run the server-side Plane-3 delivery daemon |
| Extensions & misc | feedback-intake |
Run a self-hosted feedback intake server |
The manifest modes of up, spawn, and down (-f <cotal.yaml>) plus topology are covered
together under Manifest deploys.
cotal setup [--full] [--demo] [--yes]| Flag | Default | Meaning |
|---|---|---|
--full |
off | Redo the full guided flow (implies --demo) |
--demo |
off | Also seed the guided expert team (david, sven, me) |
--yes, -y |
off | Non-interactive accept-all (for agents / CI) |
Guided setup is configure-only: it checks prerequisites, installs the Claude Code plugin, and
seeds persona files, and it launches nothing (no mesh, no web, no manager). First run gets the
narrated flow; later runs print a status card. By default it seeds one default persona; the
david/sven/me team is opt-in via --demo. See Getting started and, for
maintainers, setup internals.
cotal up [--detach] [--open] [--space <s>] [--server <url>] [--channels <path>]cotal up -f <cotal.yaml> [--dry-run] [--runtime <pty|tmux|cmux>]| Flag | Default | Meaning |
|---|---|---|
--server <url> |
auto (free local port) | Listen URL override |
--host <host> |
— | Bind host override |
--space <s> |
the folder’s name | Space name |
--store-dir <dir> |
— | JetStream store directory |
--channels <path> |
.cotal/channels.json if present |
Channel-registry seed file (JSON). An explicit path that is missing is an error |
--open |
off (auth) | Unauthenticated dev mesh: no JWT, no ACLs |
--detach |
off | Run in the background (stop with cotal down) |
--file <cotal.yaml>, -f |
— | Launch a whole mesh from a manifest |
--dry-run |
off | With -f: print the plan, mutate nothing |
--runtime <pty|tmux|cmux> |
manifest’s | With -f: override the manifest’s runtime |
cotal up boots a local nats-server with JetStream and, in auth mode (the default), JWT auth and
per-agent ACLs; --detach records the mesh so cotal spawn from any directory can find it. With no
--server, it auto-selects a free port if the default address is taken; an explicit --server
stays fail-loud on collision. --detach also brings up the control plane (delivery daemon in auth
mode, then the manager). The -f form is a manifest deploy; see
Run a mesh.
cotal downcotal down -f <cotal.yaml> | --run <id> [--dry-run]| Flag | Default | Meaning |
|---|---|---|
--file <cotal.yaml>, -f |
— | Tear down this manifest’s deploy |
--run <id> |
— | Tear down one spawn -f run by id |
--dry-run |
off | Print the plan, mutate nothing |
Bare cotal down stops a background mesh started with cotal up --detach. The -f / --run forms
tear down a manifest deploy without stopping the whole mesh.
meshes, use, status
Section titled “meshes, use, status”cotal meshescotal use <space>cotal status [--space <s>] [--server <url>]meshes lists the running meshes on this machine; a * marks the current default a bare
cotal spawn joins. use <space> sets that default when several are running. status is a
read-only report across four sections: machine prerequisites, this folder’s .cotal/, the
recorded meshes, and a live snapshot of the selected mesh (roster, channels, membership feed).
status takes only --space / --server to pick the mesh to inspect; it starts nothing.
cotal spawn [<persona>] [--detach] [--name <n>] [--agent <a>] [--model <m>] [--variant <v>] [--prompt <text>] [--cwd <dir>]cotal spawn -f <cotal.yaml> [--dry-run]| Flag | Default | Meaning |
|---|---|---|
--space <s> |
resolved mesh | Target space |
--server <url> |
registry entry | Broker URL override |
--creds <path> |
— | Control-caller creds for an off-registry manager (--detach only) |
--name <n> |
persona’s name: |
Presence-name override (does not choose the persona) |
--config <persona-or-path> |
— | Persona catalog name or file path; wins over the positional |
--agent <a> |
COTAL_DEFAULT_AGENT, else claude |
Connector type (claude, opencode, hermes, …) |
--role <r> |
persona’s role: |
Role override |
--model <m> |
persona’s model: |
Model override |
--variant <v> |
persona’s variant: |
Model variant override (connector-defined; e.g. OpenCode reasoning tiers) |
--cwd <dir> |
this cwd | Working directory to root the agent at |
--prompt <text> |
— | Initial prompt auto-submitted at start |
--resume <id> |
— | Fork an existing session id into the mesh (claude only) |
--transcript / --no-transcript |
off | Mirror the session transcript to tr-<name> |
--share-tools <sel> |
none | Share named operator MCP servers with the agent |
--subscribe <a,b> |
persona’s | Channel read-set override |
--allow-subscribe <a,b> |
= subscribe | Read-ACL override |
--allow-publish <a,b> |
deny | Post-ACL override |
--detach, -d |
off | Launch via the manager into a detached PTY (reattach with cotal attach) |
--file <cotal.yaml>, -f |
— | Deploy a manifest onto the running mesh |
--dry-run |
off | With -f: print the plan, mutate nothing |
--allow-stale <a,b> |
— | With -f: waive named stale agents (apply-only) |
--runtime <pty|tmux|cmux> |
manifest’s | With -f: override the manifest’s runtime |
The persona (--config > positional > COTAL_DEFAULT_PERSONA > default) is loaded from the
target mesh’s .cotal/agents/; the launch flags override the file. Foreground runs the agent
attached to your terminal; --detach hands the launch to the running manager. --detach is the
only mode that registers a durable delivery membership; a foreground spawn reads live only. See
Connect Claude Code and Agent files; -f is a
manifest deploy. (cotal start was merged into cotal spawn --detach.)
models
Section titled “models”cotal models [--agent <connector>] [--refresh]| Flag | Default | Meaning |
|---|---|---|
--space <s> / --server <url> / --creds <path> |
resolved mesh | Which manager to reach |
--agent <connector> |
all registered connectors | Connector whose catalog to list |
--refresh |
off | Ask the connector to refresh its provider cache |
Asks the running manager for each connector’s model catalog (model ids plus their variants)
for connectors that expose one (OpenCode today; a connector without a catalog says so). Pick a
result with cotal spawn --model <provider/model> --variant <v>.
ps, stop, attach
Section titled “ps, stop, attach”cotal ps [--space <s>]cotal stop --name <n> [--space <s>]cotal attach --name <n> [--space <s>]| Flag | Default | Meaning |
|---|---|---|
--space <s> / --server <url> / --creds <path> |
resolved mesh | Which manager to reach |
--name <n> |
— | Managed agent to stop / attach (required) |
These are operator clients over the running manager’s control plane. ps lists managed agents with
their mesh status (starting… / working / waiting / offline). attach streams and drives an
agent’s terminal on the pty runtime; detach with the escape key (Ctrl-] by default; see
COTAL_DETACH_KEY). stop and attach are cross-agent admin operations, so they need
a manager to talk to; launch detached agents with spawn --detach.
personas
Section titled “personas”cotal personas list [-v] [--running]cotal personas show <name>cotal personas edit <name>cotal personas new <name> (--prompt <t> | --from <f>) [--role <r>] [--model <m>]cotal personas rm <name> --force| Flag | Default | Meaning |
|---|---|---|
--space <s> / --server <url> / --creds <path> |
resolved mesh | Which mesh’s persona catalog |
--role <r> |
— | new: the persona’s role |
--model <m> |
— | new: the persona’s model |
--prompt <t> |
— | new: the persona’s prompt text |
--from <f> |
— | new: seed the prompt from a file |
--verbose, -v |
off | list: include role / model / description |
--running |
off | list: mark personas live on the mesh |
--force |
— | rm: required, delete without prompting |
Personas are the local agent files under .cotal/agents/ that cotal spawn launches. See
Agent files for the file format.
supervise
Section titled “supervise”cotal supervise [--runtime <pty|tmux|cmux>] [--space <s>] [--server <url>] [--spawn <names>]| Flag | Default | Meaning |
|---|---|---|
--space <s> |
this folder’s auth space | Space to supervise |
--server <url> |
the local mesh | Broker URL |
--runtime <pty|tmux|cmux> |
pty |
Agent runtime (tmux/cmux are explicit-only) |
--console-port <n> |
— | Protocol-console port |
--roster <file> |
— | Declarative roster to boot at startup |
--launch <spec> |
— | Resolved manifest launch spec (from up -f / spawn -f) |
--spawn <names> |
— | Comma-separated personas to pre-spawn at startup |
The manager is the agent supervisor and control plane: it answers spawn --detach, stop, ps,
attach, and the cotal_* manager tools. cotal up --detach starts one for you; run supervise
directly to recover a dead manager or drive a custom runtime. Default runtime is pty; tmux/cmux
require their extensions and are never selected implicitly. See Deploy.
cotal send dm <agent> "<text>" [--space <s>] [--server <url>] [--creds <path>]cotal send msg <channel> "<text>"cotal send ask <role> "<text>"| Flag | Default | Meaning |
|---|---|---|
--space <s> / --server <url> / --creds <path> |
resolved mesh | Which mesh, and (off-registry) which credential |
One-shot messaging: connect, send a single direct message (dm), channel post (msg), or role
ask/anycast (ask), then exit. For a running conversation, agents use the mesh tools instead
(MCP tools).
channels
Section titled “channels”cotal channels listcotal channels set <name> [--replay | --no-replay] [--window <n>] [--desc <s>] [--instructions <s>]cotal channels default --replay | --no-replay| Flag | Default | Meaning |
|---|---|---|
--space <s> / --server <url> / --creds <path> |
resolved mesh | Target mesh |
--replay / --no-replay |
— | set/default: replay history to new joiners, or not |
--window <n> |
— | set: replay window size |
--desc <s> |
— | set: one-line channel description |
--instructions <s> |
— | set: instructions shown to joiners |
Inspects and edits the channel registry: replay policy, description, and joiner instructions. ACL semantics (who may read or post) are set at mint / provision time, not here; see Channels and permissions.
history
Section titled “history”cotal history clear --force [--dms] [--space <s>]| Flag | Default | Meaning |
|---|---|---|
--space <s> / --server <url> / --creds <path> |
resolved mesh | Target mesh |
--dms |
off | Also clear DM history |
--force |
— | Required: clear without prompting |
Purges retained channel history; --dms extends it to direct-message history.
console
Section titled “console”cotal console [--plain] [--space <s>]| Flag | Default | Meaning |
|---|---|---|
--space <s> / --server <url> / --creds <path> |
resolved mesh | Space to watch |
--plain |
off | Line stream instead of the TUI |
A live protocol view for a space: a lazygit-style TUI, or a plain line stream on --plain. See
Watch a mesh.
cotal ext add cotal-web # install oncecotal web [--port <n>] [--no-open] [--space <s>]| Flag | Default | Meaning |
|---|---|---|
--space <s> / --server <url> / --creds <path> |
resolved mesh | Space to serve |
--port <n> |
7799 |
HTTP port |
--no-open |
off | Don’t open the browser |
The browser observability dashboard: presence, channels, and a live feed. It is not part of
cotal up: it ships as the cotal-web extension (cotal setup installs it automatically; otherwise
cotal ext add cotal-web). It self-registers cotal web into this surface and serves
http://cotal.localhost:7799 (loopback; *.localhost resolves in Chrome/Firefox/Edge; Safari may
need http://127.0.0.1:7799). See Watch a mesh.
cotal mint <name> [--profile <agent|observer|admin>] [--out <path>] [--signer]| Flag | Default | Meaning |
|---|---|---|
--profile <agent|observer|admin> |
agent |
Credential profile |
--out <path> |
.cotal/auth/creds/<name>.creds |
Output path |
--signer |
off | Emit a stripped account-signing file instead |
--force |
off | With --signer: overwrite an existing file |
--allow-subscribe <a,b> |
profile default | Read-ACL override |
--allow-publish <a,b> |
profile default | Post-ACL override |
Mints a NATS creds file for a space in auth mode, scoped to a profile and (optionally) explicit
read/post ACLs. --signer emits an account-signing file for delegating minting to another host. See
Identity and auth.
cotal join --space <s> --name <n> [--role <r>] [--channel <c>]cotal join --link <url> | --token <t>| Flag | Default | Meaning |
|---|---|---|
--space <s> / --server <url> / --creds <path> |
resolved mesh | Which mesh, and which credential |
--name <n> |
— | Your presence name |
--role <r> |
— | Your role |
--channel <c> |
— | Channel to join |
--kind <k> |
agent |
Endpoint kind |
--link <url> |
— | Join link (cotal://…) |
--token <t> |
— | Join token |
--tls |
off | Connect over TLS |
An interactive presence: join a space under your own name and role, without launching an agent
harness. A --link or --token supplies the where and the auth in one value. See
Spaces and Identity and auth.
Manifest deploys
Section titled “Manifest deploys”A cotal.yaml manifest declares a whole mesh (channels, personas, roles, and ACLs) in one file.
Three commands consume it, plus a read-only validator:
cotal up -f cotal.yaml # boot a fresh mesh from the manifestcotal spawn -f cotal.yaml # deploy the manifest additively onto a running meshcotal down -f cotal.yaml # tear that deploy down (or --run <id> for one run)cotal topology view -f cotal.yaml # validate + view the access graph, change nothingup -f and spawn -f differ in target: up -f brings up a new broker and applies the manifest;
spawn -f requires an already-reachable mesh and applies additively (ownership-scoped). Both take
--dry-run to print the plan without mutating anything. topology validates the manifest and
renders its channel / role / ACL graph. See Define a team and the
manifest reference.
cotal ext add <npm-package>cotal ext remove <name>cotal ext listOperator-installed CLI extensions: add installs an npm package into a cotal-owned prefix and makes
its commands appear in help, completion, and dispatch; remove and list manage them. The
cotal-web dashboard is the canonical example. Installed packages and their location are described
in config.
completion
Section titled “completion”cotal completion <bash|zsh|fish|powershell> # print a stub to eval / sourcecotal completion install [shell] # install it persistentlyPrints or installs shell completion. Completion candidates come from each command’s declared flags and, where useful, live mesh state (spaces, personas, managed agents) resolved offline.
feedback
Section titled “feedback”cotal feedback "<summary>" [--type <t>] [--email <e>] [--details <text>]| Flag | Default | Meaning |
|---|---|---|
--type <t> |
— | bug | idea | friction | praise | other |
--details <text> |
— | Longer free-form details |
--severity <s> |
— | low | medium | high |
--area <a> |
— | The part of Cotal this concerns |
--email <e> |
git email | Contact email (required on the keyless public path) |
--name <n> |
— | Your name (optional) |
--url <url> |
keyed / public intake | Intake URL override |
--key <k> |
COTAL_FEEDBACK_KEY |
Feedback key |
Sends feedback to the Cotal developers. With a key (--key / COTAL_FEEDBACK_KEY) it routes to the
keyed beta intake; without one it goes to the public cotal.ai intake and requires a contact email
(--email / COTAL_FEEDBACK_EMAIL, else your git email). Run a self-hosted intake with
feedback-intake.
Server daemons
Section titled “Server daemons”Two long-lived infra roles ship with the CLI. They are not part of everyday operation; the delivery
daemon comes up automatically with cotal up --detach in auth mode.
cotal deliver --space <s> [--server <url>] [--creds <file>]cotal feedback-intake --keys <keys.json> [--port <n>] [--creds <file>]deliver runs the server-side Plane-3 delivery daemon: the durable backstop and membership/ACL
authority. It is auth-mode-only and single-instance (--shard/--shards accept only N=1);
--dev-mint mints a scoped cred from the local signer for standalone dev. See the
delivery daemon. feedback-intake runs a self-hosted feedback server
(requires --keys and a scoped --creds), announcing submissions into a space channel; flags
include --host/--port, --store, --space/--channel, --max-bytes, and --rate-limit.
Plumbing
Section titled “Plumbing”cotal __complete <words…> is the internal entry the shell-completion stubs call to emit candidates
for the current command line; you never run it directly. (cotal start is a removed tombstone: it
errors and points you to cotal spawn --detach.)