# π¦ Brigade β Your personal intelligence, built enterprise-grade
Built for enterprise scale. Open for everyone. · An ecosystem, not an app.
π No tokens to juggle. No drama. No copy-pasting secrets, no telemetry β
we handle them, not you . Your API keys stay on your own machine, never sent to a middleman.
π No API key? No problem. Sign in with your Claude , ChatGPT , or
Copilot subscription β or, if you're already signed into the Claude Code or
Codex CLI, reuse that login (no browser, no re-auth).
π©Έπ₯ BΒ³ β Brigade Bloody Benchmark π₯π©Έ
NEW in v1.9.0 Β· the one command that throws your crew to the wolves (lovingly)
Three B's. One bloody command. Your crew β loose on the open internet.
Brigade is your crew. Bloody is what you do to it β fling it into the open with no net, down a red-hot tunnel to the wild. Benchmark is the punchline: the only test that ever mattered isn't a lab, it's strangers poking your agents at 3 a.m. Survive that, and you've shipped.
Under the hood it's tame β HTTPS at the edge, no account, no setup. Cloudflare by default, or bring your own relay (bore Β· frp Β· sish, all open-source). A secret key rides along invisibly : you never see it, and gate-crashers just bleed out on a 401. Not feeling the name? It also answers to the buttoned-up brigade expose. π©Έ
brigade bloody benchmark Β· brigade expose Β· brigade expose stop π©Έ
**Brigade is your personal intelligence, built on enterprise-grade tech**: a crew of
AI agents on a real org chart that share one long-term memory, Tideline, so what one
agent learns, the rest can use. They delegate to each other, switch models mid-task
without losing the thread, and act inside the 1,000+ apps you already use. It's an
ecosystem you host yourself, with the controls and data sovereignty of enterprise
tech: no account to create, no SaaS in the middle.
The same crew runs on a Raspberry Pi or a server. By default it's a small filesystem
install; switch to a self-hosted Convex database when you want one. Bring any model:
Claude, GPT, Gemini, Llama, or a local Ollama. Privileged actions wait for your
approval, and your keys and data never leave your machine. No telemetry.
It's an ecosystem, not an app: one crew you reach from the terminal, WhatsApp, Telegram,
Slack, Discord, iMessage, and BlueBubbles, and from your watch, Meta smart glasses, and Meta Quest.
```bash
# macOS / Linux β installs Node if needed, then Brigade (no sudo)
curl -fsSL https://brigade.spinabot.com/install.sh | sh
brigade
```
Start it and you get a fast chat TUI. Keep going and you get isolated agents with
their own workspaces and credentials, persistent memory, a skill system, a cron
scheduler, sub-agent fan-out, an org hierarchy, messaging channels like WhatsApp and Telegram,
1,000+ app connectors, an MCP memory server, and an optional self-hosted Convex
backend β all under one `~/.brigade/` directory you fully own.
> One owner, a whole crew β many agents that coordinate through a real org chart,
> all on hardware and storage **you** control.
---
## Table of contents
- [Why Brigade](#why-brigade)
- [Install](#install)
- [Quick start](#quick-start)
- [How it works](#how-it-works)
- [Features](#features)
- [CLI reference](#cli-reference)
- [In-chat commands](#in-chat-commands)
- [Built-in tools](#built-in-tools)
- [Team Mode](#team-mode)
- [Multi-agent isolation](#multi-agent-isolation)
- [Providers & web search](#providers--web-search)
- [Configuration & storage](#configuration--storage)
- [Storage modes: filesystem vs. Convex](#storage-modes-filesystem-vs-convex)
- [MCP memory server](#mcp-memory-server)
- [Tideline (long-term memory)](#tideline-long-term-memory)
- [Extending Brigade](#extending-brigade)
- [Privacy](#privacy)
- [Develop from source](#develop-from-source)
- [Contributing](#contributing)
- [License](#license)
- [π¦ Brigadiers](#-brigadiers)
---
## Why Brigade
| | |
|---|---|
| π₯οΈ **Terminal-first** | A flicker-free chat TUI by default. No browser, no Electron. |
| π§ **Memory that lasts** | Facts persist across sessions with origin scoping, decay, and hybrid (keyword + vector) recall β the **Tideline** engine. |
| π₯ **A real crew** | Spawn isolated agents with their own personas, credentials, and memory; wire them into an **org chart** that governs who can talk to whom. |
| π **Bring any model** | Anthropic, OpenAI, Gemini, OpenRouter, OrcaRouter, Token Market, Groq, Cerebras, xAI, DeepSeek, Mistral, local Ollama, or any OpenAI-compatible endpoint. Switch mid-conversation. |
| π
**Always-on** | Run as a headless WebSocket gateway with a crash supervisor, cron jobs, and OS service install. |
| π¬ **Channels** | Talk to your crew from WhatsApp, Telegram, Slack, Discord, iMessage, and BlueBubbles today; the adapter contract is built for more. |
| π **1,000+ connectors** | Gmail, Slack, GitHub, Notion, Calendar, Linearβ¦ via the built-in Composio tool. |
| π **Reads & writes documents** | Send a PDF, Office doc, image, audio, or video and your crew *understands* it β then have it **create or edit** Word, Excel, PowerPoint, and PDF files and hand them back. |
| π§© **MCP** | Expose your long-term memory to any MCP client (`brigade mcp`), or connect MCP servers in. |
| ποΈ **Your storage** | Default filesystem mode, or an optional **fully self-hosted Convex** backend with at-rest encryption. |
| π **Yours** | Everything lives under `~/.brigade/`. Keys are stored locally at mode `0600`. `rm -rf ~/.brigade` wipes it clean. |
---
## Install
**Fastest β handles Node for you** (installs Node 22.12+ if you don't have it, then Brigade):
```bash
# macOS / Linux
curl -fsSL https://brigade.spinabot.com/install.sh | sh
# β¦or straight from GitHub:
curl -fsSL https://raw.githubusercontent.com/spinabot/brigade/main/packaging/install/install.sh | sh
```
```powershell
# Windows (PowerShell)
irm https://brigade.spinabot.com/install.ps1 | iex
# β¦or straight from GitHub:
irm https://raw.githubusercontent.com/spinabot/brigade/main/packaging/install/install.ps1 | iex
```
**Already on Node 22.12+?** Install straight from npm:
```bash
npm i -g @spinabot/brigade
```
> **Hitting `EACCES` / permission denied?** Your Node's global folder needs admin rights. **Don't `sudo`** β either use the `curl β¦ | sh` installer above (it sets up a private, user-owned runtime, no root needed), or point npm at a user-writable prefix: `npm config set prefix ~/.npm-global`, then add `~/.npm-global/bin` to your `PATH`.
Then launch onboarding:
```bash
brigade
```
---
## Quick start
```bash
# 1. Set up β pick a provider, paste an API key (or scan local Ollama), choose a model
brigade onboard
# 2. Start the always-on gateway β your crew, channels, and cron jobs live here
brigade gateway run
# 3. Chat with your crew
brigade tui
```
The onboarding wizard walks you through **five steps**: **(0) storage mode**
(filesystem or self-hosted Convex), **(1) pick a provider** (Anthropic, OpenAI, Gemini,
OpenRouter, OrcaRouter, Token Market, Ollama, and more), **(2) connect it** (paste an API key, **sign in with a
Claude/ChatGPT/Copilot subscription**, reuse your Claude Code or Codex CLI login, or
connect local Ollama), **(3) choose a default model**, and **(4) web search** (pick a
search backend; keyless options work out of the box). Subsequent launches resume right
where you left off.
`brigade tui` (or just `brigade`) auto-starts the gateway if it isn't already running,
so for a quick local session you can skip step 2. To keep the gateway alive across
reboots, run `brigade gateway install` (installs a launchd / systemd / Task Scheduler
service).
Other handy entry points:
```bash
brigade agent -m "summarize ~/today.md" # one-shot turn, no TUI
brigade connect # attach a client to a running gateway
brigade doctor # health-check your install
```
---
## How it works
Brigade is one binary that can act as a **gateway** (the long-lived process that
holds all state and runs agents) or as a **thin client** that attaches to it.
```
ββββββββββββββββββββββββββββ ~/.brigade/ ββββββββββββββββββββββββββββ
β config Β· per-agent workspaces Β· sessions (JSONL) Β· memory Β· cron β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β²
β reads/writes (filesystem OR Convex)
βββββββββββββββββββ΄ββββββββββββββββββ
brigade tui ββwsβββΆ β GATEWAY :7777 β βββwsββ brigade connect
brigade chat β per-turn agent loop Β· routing β
WhatsAppΒ·Telegram βββΆβ tools Β· sub-agents Β· supervisor ββββββββββ cron jobs
MCP client βstdioβββΆ β (brigade mcp β memory server) β
βββββββββββββββββββββββββββββββββββββ
```
- **Clients are thin.** The TUI (`brigade`/`brigade tui`), `brigade connect`, and
channel adapters are all WebSocket clients of the gateway. State lives only in
the gateway; clients mirror it. Disconnect, walk away, reconnect later β your
agents keep running.
- **One turn at a time.** Each message runs through a resilient agent loop: resolve
the session, assemble the system prompt (persona + skills + org context), stream
the model, run tool calls through approval and ownership guards, persist the
transcript, reply.
- **Inbound from anywhere.** A WhatsApp message and a TUI keystroke flow through the
same routing pipeline that resolves them to an `(agent, session)` pair, so a peer
on one channel never bleeds into another's context.
- **It stays up.** A heartbeat file plus an out-of-process supervisor restart the
gateway if its event loop wedges; per-OS service installers bring it up at login.
---
## Features
### π§ Memory (Tideline)
File-backed facts (`facts.jsonl`) tagged with an **origin** (owner vs. channel peer)
so a peer's facts never leak into your context. Facts **decay** on three tiers and
are deduped at write time, behind a **provenance write-gate** that stops untrusted
sources from overwriting your identity/preferences. The **Tideline** engine adds
**hybrid recall** (BM25 keyword + model-free vector lane), a typed link graph, and a
nightly reflect/consolidate pass. Auto-recall injects only origin-matched facts
before each turn. Tools: `recall_memory`, `read_memory`, `write_memory`,
`manage_memory`. β **[docs/tideline.md](docs/tideline.md)**
### πͺͺ Skills
Drop a folder with a `SKILL.md` into your workspace and Brigade discovers it next
turn. Skills are **prompt-resident** (name + description injected; the model reads
the body on demand). Six discovery roots merge in precedence order with eligibility
filters for OS, required binaries, env vars, and config. 56 skills ship bundled.
Manage with `manage_skill`.
### π₯ Sub-agents
Delegate work to child agents: `spawn_agent` (single) and `spawn_agents` (parallel
fan-out). Depth-capped (default 3) and child-count-capped (default 5), with an
**abort cascade** and a completion bridge that wakes the parent when children settle.
### π’ Org / Pride hierarchy
Define a crew as a real org chart (`cfg.org`): members, departments, reporting
lines. An **A2A (agent-to-agent) policy** derives from the graph and governs which
agents may message which. Inspect it with `brigade org show` / `explain` / `doctor`,
or render a π¦ Pride chart with the `org` tool.
### π¬ Channels
A typed channel-adapter contract with a shared inbound pipeline (access control,
dedupe, abort triggers, approval routing). **WhatsApp** (Baileys, QR/code pairing,
multi-account, reconnect backoff), **Telegram** (Bot API token, inline-button
approvals, owner bootstrapped on the gateway), **Slack** (Socket Mode, bot + app
tokens, channel/thread chat), **Discord** (bot token, DM/server/thread chat),
**iMessage** (via the `imsg` CLI, plain-text only), and **BlueBubbles** (macOS
server, REST-out + webhook-in, reactions/edit/unsend) ship today; the contract is
built for more. See [Telegram setup](#telegram-setup-end-to-end) for the full
walkthrough.
### β° Cron
Schedule recurring or one-shot work: cron expressions (with IANA timezones and
stagger), fixed intervals, or one-shot timestamps. Payloads can be a system event
into your main session, a full agent turn in an isolated session, or a shell script.
Jobs survive restarts.
### π Connectors (Composio)
An owner-only `composio` tool brings **1,000+ app connectors** (Gmail, Slack, GitHub,
Notion, Calendar, Linear, β¦) with managed OAuth. Set a key once, then just ask your
crew in plain language: *"connect my Gmail"*, *"post to #team"*.
**Getting the key:** Brigade uses the Composio **SDK**, so it needs a **PLATFORM** key
(starts with `ak_`), *not* the "FOR YOU" consumer key (`ck_`) that Brigade rejects. At
[dashboard.composio.dev](https://dashboard.composio.dev), set the top-left mode toggle
to **PLATFORM**, open **Settings β API Keys**, and copy the `ak_β¦` key. Hand it to
Brigade once (*"set my Composio key to `ak_β¦`"*) and it's verified and stored encrypted.
Full guide: **[docs/composio.md](docs/composio.md)**.
### π Documents & media
Send your crew a file and it actually **reads** it: the `analyze_media` tool
understands PDFs (text or scanned), Word / Excel / PowerPoint (including the images
embedded inside them), plain images, audio, and video β auto-selecting the right
provider and caching the result. The write side, `make_document` and
`edit_document`, **creates and edits** Word / Excel / PowerPoint / PDF in place:
fill templates and form fields, set cells and formulas, add charts, and
merge / split / stamp / watermark PDFs β all with pure-JS libraries, no sandbox.
Drop a document into a channel and Brigade sees it; ask for a report and it hands
one back with `send_media`.
### π Attach files in the terminal
Send your crew an image, a PDF, a screenshot, a video β from the chat TUI, with
no ceremony. Four ways in, and they all land as a real attachment:
- **Drag a file onto the window** β the path turns into a `[filename]` chip the
instant it lands, before you press anything.
- **`Ctrl+V`** β paste an image and it attaches; paste text and it types, exactly
as before. Brigade reads the clipboard on the paste event your terminal sends,
so a copied screenshot just works.
- **`@path`** β an autocompleting file picker; type `@` and fuzzy-find.
- **`/attach `**, **`/paste`**, **`/detach`** β the explicit backbone, plus
`/clipboard` to see what's on your clipboard and which build is running.
An **image** on a vision-capable model rides the turn inline β the model actually
*sees* it. A **text or source file** is read and its contents are inlined
directly. **PDFs, Office docs, video and audio** go through `analyze_media` (see
above). A persistent clipboard worker keeps a paste to a few milliseconds on every
platform, and a `π attached` bar shows what will ride your next message. Works
against a local gateway (files travel as paths, so a 400 MB video costs nothing on
the wire).
### π¬ Motion-graphics video (HyperFrames)
`render_video` turns an HTML composition into a **deterministic MP4** β animated
charts and dashboards, data explainers, quote/announcement cards, kinetic
typography, branded short-form social clips. Your crew writes a self-contained
GSAP-timeline composition (the `hyperframes` skill teaches the conventions) and
Brigade renders it frame-by-frame in an **isolated worker** (headless Chrome +
FFmpeg), then hands back the file with `send_media`. It's the deterministic,
data-driven counterpart to `generate_video` (generative AI footage). The engine is
an **optional** dependency β the tool stays dormant until you install it with
`brigade video install`, so it adds nothing to a lean setup. (Install it that way,
not with a bare `npm i`: Brigade keeps engine dependencies in its own directory, and
npm run from your shell would put it somewhere Brigade never looks.)
### π§© MCP
Run `brigade mcp` to expose your long-term memory to any MCP client (Claude Desktop,
editors, etc.) as add/search/context tools over stdio, owner-bound.
Brigade is also an MCP **server for its own agent**. See below.
### π Subscription backends β your Claude login, Brigade's tools
Already signed into **Claude Code**? Pick `claude-cli` as your provider and Brigade
drives that binary directly, on your existing subscription. No API key, no per-token
bill.
Most tools that wrap a CLI give the model whatever the CLI already had. Brigade does
the opposite: it **denies the binary's own filesystem, shell, network and sub-agent
tools**, and serves it Brigade's entire guarded surface β all 30+ native tools plus
`read`/`write`/`edit`/`bash`/`grep`/`ls` β over a loopback MCP endpoint scoped to that
single turn.
The consequence is the point: every call the binary makes runs through the *same*
objects a normal turn uses. The same ownership gate, the same exec approval prompt,
the same path-write and config-write guards, the same memory origin, bound to your
real working directory. It cannot reach anything a normal turn could not, because it
is holding the same tools. Tool calls appear live in the TUI, land in the session
transcript, and are remembered on the next turn.
```
[mcp/tool-plane] tool-plane connected agentId=main tools=39
[mcp/tool-plane] tool call tool=bash ms=63
```
The per-turn credential is a 256-bit token, is never logged, and dies with the turn.
### π‘οΈ Safety & ownership
Privileged tools use either a **per-call ownership gate** (`cron list` is visible to
peers; `cron add` is not) or a blanket owner-only refusal. The `bash` tool is gated
by a per-agent approval allowlist (`brigade exec`). Secrets in config use `${VAR}`
references that resolve at read time and are never persisted resolved. Optional
**AES-256-GCM at-rest encryption** in Convex mode (`brigade encrypt`).
**Optional gateway tokens.** The gateway is unauthenticated and localhost-only by
default β ideal for a single machine. Want more? Add one or more access tokens
(`brigade gateway token new`) and every connection must then present a valid one
(`Authorization: Bearer`, `x-brigade-token`, or `?token=`). **Multiple tokens** are
supported, so you can hand a distinct token to each device and revoke one without
disturbing the rest, and the same tokens secure `brigade expose`. Entirely opt-in:
with no tokens configured, nothing changes.
### π Carrow β cross-model continuity
Switch models mid-conversation **without losing context**. Carrow carries the full
transcript onto the new model (it's the same session), **re-anchors your thinking
level** to what the target supports (preserved when it can reason, forced off for a
non-reasoning model, bumped for a reasoning-only one), and sanitizes provider-specific
reasoning blocks the next provider would reject. It works **mid-turn** (abort the
in-flight run and replay your last message on the new model) or **next-turn**. This is
what makes `/model` and `/provider` switches seamless.
### π Autonomous loops
A **loop-runner** drives an agent (or a planner/executor stage) step-by-step under hard
guards β token / iteration / time **budget**, plus **no-progress** and **repetition**
detection β and stops only when **independent done-checks** pass or a guard fires,
*never on the agent's own say-so*. Each step's output is gated through the slop
detector with a bounded repair retry.
### π§Ή Anti-slop quality gate
A deterministic, zero-dependency **AI-slop detector** scans generated text in four
passes (vocabulary crutches, clichΓ© phrases, formulaic openers, structural patterns)
and flags **density, not single words**. When output trips the threshold it triggers
**one bounded repair retry**, wired as a post-generation hook β an objective check, not
the model grading itself.
### π Self-improvement (human-gated)
Tideline ships a **human-gated** self-improvement loop: propose changes from telemetry
β **gate on evaluation** β human approve β apply β revert if needed. Brigade also
reviews its own behavior and curates/reviews skills from usage. Nothing that affects
recall changes without passing the eval bar **and** a human approval. Throughout, the
principle is the same: *independent verification, never the agent judging itself.*
---
## CLI reference
`brigade` on its own is shorthand for `brigade tui`. Run `brigade --help` or
`brigade --help` for full flags.
### Core
| Command | What it does |
|---|---|
| `brigade` Β· `brigade tui` | Start the chat TUI (auto-starts the gateway if needed) |
| `brigade connect` | Attach a thin TUI to an already-running gateway (`--host`, `--port`) |
| `brigade agent ` | Drive a single turn through the agent pipeline (`--provider`, `--model`, `-m`) |
| `brigade onboard` | Run the provider/model setup wizard |
| `brigade status` | Snapshot config, sessions, and gateway state (`--json`) |
| `brigade doctor` | Health-check Node, config, providers, prompts, logs, gateway (`--json`, `--strict`, `--gateway `) |
| `brigade logs` | Tail today's gateway log (`--follow`) |
| `brigade update` Β· `upgrade` | Update Brigade to the latest code and restart the gateway (`--check`, `--no-restart`) |
### Gateway
| Command | What it does |
|---|---|
| `brigade gateway run` | Run the headless WebSocket gateway (`--port`, `--host`, `--verbose`, `--quiet`, `--log-level`) |
| `brigade gateway status` Β· `stop` Β· `restart` | Inspect / stop / restart the running gateway |
| `brigade gateway install` Β· `uninstall` | Install/remove as a system service (launchd / systemd / Task Scheduler) |
| `brigade gateway supervise` | Out-of-process crash watchdog (respawns a wedged gateway) |
| `brigade expose` Β· `expose stop` | Publish the gateway to the public internet via a secure, token-gated tunnel (alias: `bloody benchmark`) |
| `brigade gateway token new` Β· `list` Β· `add` Β· `revoke` | Manage **optional** access tokens (multiple supported). No tokens β the gateway stays unauthenticated + localhost-only |
### Agents
| Command | What it does |
|---|---|
| `brigade agents` Β· `agents list` | List every configured agent (`--json`, `--bindings`) |
| `brigade agents add [name]` | Create an isolated agent (`--workspace`, `--model`, `--provider`, `--bind`, `--non-interactive`) |
| `brigade agents delete ` | Delete an agent + its workspace/sessions (`--force`) |
| `brigade agents bind` Β· `unbind` | Claim / release channel-account routing slots (`--agent`, `--bind`, `--all`) |
| `brigade agents bindings` | List routing bindings (`--agent`) |
| `brigade agents set-identity` | Set name / theme / emoji / avatar (`--agent`, `--from-identity`) |
### Org / Pride
| Command | What it does |
|---|---|
| `brigade org init` | Write a starter `cfg.org` block (`--template solo\|family\|company\|custom`, `--skip-editor`) |
| `brigade org show` | Print an ASCII tree of the current org |
| `brigade org explain ` | Show whether `from` can message `to`, and the derivation/denial reason |
| `brigade org doctor` | Run org lints (single-member dept, dangling overrides, depth > 5, β¦) |
### Channels & pairing
| Command | What it does |
|---|---|
| `brigade channels list` Β· `status` Β· `add` | List channels, probe status, add an account |
| `brigade channels link` Β· `unlink` | Pair / unpair a channel (e.g. WhatsApp QR) |
| `brigade channels enable` Β· `disable` | Toggle a channel |
| `brigade channels allow list\|add\|remove` | Manage the per-channel allowlist |
| `brigade pairing list\|approve\|revoke` | Review / approve / revoke pending pairing codes |
### Cron
| Command | What it does |
|---|---|
| `brigade cron list` Β· `status` Β· `runs ` | List jobs, service status, per-job run history |
| `brigade cron add` | Create a job (`--cron`/`--every`/`--at`, `--tz`, `--message`/`--system-event`, `--model`, `--tools`, `--channel`/`--to`) |
| `brigade cron edit ` Β· `rm ` | Modify / remove a job |
| `brigade cron enable\|disable\|run ` | Toggle or run a job on demand |
### Storage, encryption & data
| Command | What it does |
|---|---|
| `brigade store mode show` | Print the active storage mode (filesystem / convex) |
| `brigade store mode set ` | Pin the mode (`--convex-url` for convex) |
| `brigade store migrate --to ` | Copy data between backends (`--convex-url`, `--dry-run`, `--keep-source`) |
| `brigade store reset` | Factory-reset the Convex backend (`--yes`, `--purge-local`) |
| `brigade convex dev` Β· `start` | Run the **bundled** self-hosted Convex backend + dashboard in the foreground (`brigade convex:dev` also works) |
| `brigade convex status` Β· `stop` | Probe whether the backend is running / how to stop it (Ctrl-C) |
| `brigade convex push` Β· `codegen` | Deploy the bundled Convex functions to the backend / regenerate the client |
| `brigade encrypt status` Β· `init` Β· `test` | Manage the AES-256-GCM at-rest key |
| `brigade backup create` Β· `verify` Β· `restore` | Snapshot / verify / restore your install as a `.tar.gz` |
| `brigade secrets audit` | Find suspected leaked credentials in your install |
### Config, skills, sessions, exec, MCP
| Command | What it does |
|---|---|
| `brigade config list\|get\|set\|unset\|file\|schema\|validate` | Read & write configuration |
| `brigade skills list\|info ` | Inspect installed skills |
| `brigade sessions list\|cleanup` | List + clean up session transcripts |
| `brigade exec list\|allow\|allow-pattern\|remove\|deny-test\|file` | Manage the `bash`-tool approval allowlist |
| `brigade mcp` | Serve your long-term memory as an MCP server over stdio (`--agent `) |
### `brigade gateway`
Runs Brigade as a WebSocket server with no terminal UI of its own β the long-lived
process that channel adapters, cron jobs, and sub-agent spawns all need running.
```bash
brigade gateway run --port 7777 --host 127.0.0.1 --verbose
brigade gateway status
brigade gateway stop
brigade gateway restart
brigade gateway install # install as a system service (launchd / systemd / Task Scheduler)
brigade gateway supervise # out-of-process crash watchdog
brigade gateway token new # generate + store an access token (printed once)
brigade gateway token list # show configured tokens (masked) + whether auth is on
brigade gateway token revoke 1 # remove a token by its number (or its exact value)
```
| Flag | Default | Notes |
|---|---|---|
| `--port N` | `7777` | Listen port (also `BRIGADE_PORT`) |
| `--host A` | `127.0.0.1` | Bind address (loopback by design) |
| `--verbose` | off | Stream a one-line summary of every event |
| `--quiet` | off | Suppress the live console stream |
| `--log-level X` | `info` | `debug` / `info` / `warn` / `error` |
**Optional authentication.** By default the gateway is unauthenticated and refuses to
bind anywhere but loopback. To require a token, run `brigade gateway token new` (repeat
for multiple tokens) and restart the gateway. On the same machine, clients read the
token from config automatically; elsewhere pass `--token ` or set
`BRIGADE_GATEWAY_TOKEN`. `BRIGADE_GATEWAY_TOKENS` (comma-separated) adds tokens via the
environment. Remove every token to return to open, localhost-only mode.
### `brigade connect`
Attaches a TUI to a running gateway. Same chat experience as `brigade`, but the
agent runs in the gateway process β so you can disconnect, walk away, reconnect
later, and pick up where you left off while channel adapters and cron jobs keep
running.
```bash
brigade connect --host 127.0.0.1 --port 7777
```
### `brigade agents`
Brigade ships with a default agent called `main`. Add more β each agent has its own
workspace (persona files), auth profiles, exec allowlist, sessions, and optional
channel/account routing bindings.
```bash
brigade agents # list every agent (default)
brigade agents list [--json] [--bindings]
brigade agents bindings [--agent ] [--json]
brigade agents bind --agent --bind [--bind β¦] [--json]
brigade agents unbind --agent (--bind β¦ | --all) [--json]
brigade agents add [name] [--workspace ] [--model ] [--provider ]
[--agent-dir ] [--bind β¦] [--non-interactive] [--json]
brigade agents set-identity --agent [--from-identity]
[--name <β¦>] [--theme <β¦>] [--emoji <β¦>] [--avatar <β¦>] [--json]
brigade agents delete --force [--json]
```
`agents add` without `--workspace` defaults to `~/.brigade/agents//workspace/`.
A binding `` is `""` or `":"`. Delete requires
`--force`.
### `brigade doctor`
Health-checks Node version, your `~/.brigade/` directory, config, configured
providers, log sink, prompt files, and (optionally) a running gateway. Exits 0 on
pass, 1 on failure.
```bash
brigade doctor
brigade doctor --gateway ws://127.0.0.1:7777
brigade doctor --json # machine-readable
brigade doctor --strict # exit 1 on warnings (CI mode)
```
### `brigade update`
Bring Brigade up to date and reload the gateway. It auto-detects how Brigade is
installed and does the right thing:
- **npm global** β `npm i -g @spinabot/brigade@latest`, then restart.
- **source checkout** β `git pull` (fast-forward, only when your tree is clean and
behind upstream β a dirty tree is left untouched and rebuilt as-is), then
`npm install`, `npm run build`, then restart.
```bash
brigade update # update + restart the gateway
brigade upgrade # alias of update
brigade update --check # report whether newer code is available; change nothing
brigade update --no-restart
```
If Brigade is installed as a background service (`brigade gateway install`) the
restart is automatic; if you run the gateway in the foreground, restart it yourself
to load the new code. Same behavior on macOS, Linux, and Windows.
### `brigade config`
Read and write the local config without opening the TUI.
```bash
brigade config list
brigade config get agents.defaults.provider
brigade config set agents.defaults.provider openrouter
brigade config unset agents.defaults.thinking
brigade config file # print the resolved config path
brigade config validate # schema-check the current config
```
### `brigade cron`
Schedule recurring or one-shot agent turns. Pick exactly one of `--cron`, `--every`,
or `--at`; pair `--cron` with an IANA `--tz`.
```bash
brigade cron list
brigade cron add --cron "0 9 * * *" --tz "Asia/Kolkata" --message "good morning"
brigade cron add --at "2026-06-04T09:00:00+05:30" --message "stand-up reminder"
brigade cron run # fire it now
brigade cron enable # / disable / rm
```
A payload can be a `--message` (system event into your main session), an isolated
agent turn (`--model`, `--tools`, `--light-context`), and an optional delivery
target (`--channel`, `--to`).
### `brigade channels`
Connect external messaging channels β WhatsApp, Telegram, Slack, Discord, iMessage,
and BlueBubbles ship today.
```bash
brigade channels list
brigade channels link --channel whatsapp # WhatsApp: pair via QR / code
brigade channels add --channel telegram # Telegram: set up a bot token
brigade channels status --channel telegram
brigade channels allow list --channel telegram # add / remove allowed senders
brigade pairing approve --channel telegram # approve a waiting sender
brigade channels disable --channel whatsapp
```
### Telegram setup (end to end)
A Telegram bot is a separate account from you, so Brigade establishes ownership on
the **gateway** β never by whoever texts the bot first.
1. **Create the bot.** In Telegram, message [@BotFather](https://t.me/BotFather),
send `/newbot`, and copy the API token it returns.
2. **Add it to Brigade** (on the gateway machine), then start the gateway:
```bash
brigade channels add --channel telegram # paste the bot token when prompted
brigade gateway restart # load the channel
```
3. **Claim ownership.** DM your bot anything β it replies with a one-time code and
asks an admin to approve it. Approve it once, from the gateway:
```bash
brigade pairing approve --channel telegram
```
The **first** approval on a Telegram bot makes you the owner. Because approving
requires access to the gateway machine, that access *is* the proof it's really
you β nobody becomes owner just by sending `/start`.
4. **Run it from the chat.** As owner you're never challenged again, and you manage
everyone else from Telegram itself:
| Command | Who | What |
|---|---|---|
| `/start` Β· `/help` | admitted | welcome + command list |
| `/pending` | owner | list people waiting for approval |
| `/approve ` | owner | admit a waiting person β takes effect immediately, no restart |
| `/deny ` | owner | reject a pending request |
| `/allowlist add\|remove ` | owner | manage approved senders directly |
| `/whoami` Β· `/agent ` | admitted | see / pin which agent answers you |
Everyone else who messages the bot gets a pairing challenge; only you (in chat) or
the gateway CLI can let them in. Multiple bots or accounts each track their own owner.
---
## In-chat commands
When you're in the chat TUI (`brigade` or `brigade connect`):
| Command | What it does |
|---|---|
| `/agent []` | Show or switch the agent this connection is bound to |
| `/agents` | List every agent the gateway knows about |
| `/sessions`, `/session ` | List or switch sessions for the current agent |
| `/model []`, `/provider` | Switch model (picker or by id), or add a provider mid-session |
| `/thinking ` | Reasoning effort (off, minimal, low, medium, high) |
| `/reasoning [on\|off]` | Toggle whether thinking blocks render |
| `/compact` | Force a context compaction now |
| `/abort`, `/steer ""` | Stop the current turn, or inject mid-turn guidance |
| `/attach `, `/paste`, `/detach [\|all]` | Stage a file, pull from the clipboard, or unstage |
| `/clipboard` | What's on your clipboard, plus the running build + worker health |
| `/usage` | Token + cost usage for this session |
| `/help`, `/exit` | Show all commands / quit |
Keyboard: **Enter** sends Β· **Ctrl+C** stops the current response Β· **Ctrl+D**
quits Β· **β/β** history Β· **Ctrl+V** pastes an image as an attachment Β· drag a
file onto the window to attach it.
---
## Built-in tools
Every agent gets a curated toolset. Mutating/privileged tools are owner-gated
(either per-call or owner-only).
- **Coding (pi SDK):** `read`, `write`, `edit`, `bash`, `grep`, `find`, `ls`
- **Memory:** `recall_memory`, `read_memory`, `write_memory`, `manage_memory`
- **Sub-agents:** `spawn_agent` (sync), `spawn_agents` (parallel fan-out)
- **Team Mode:** `team` (owner orchestration); leased workers get only coding
tools plus the attempt-scoped `team_task` capability
- **Cross-session:** `sessions_send`, `sessions_spawn`, `sessions_list`,
`sessions_history` (gated by visibility + A2A policy)
- **Crew management:** `agents_list`, `manage_agent`, `manage_skill`,
`manage_provider`, `manage_access`, `manage_channel_access`, `org` (when
`cfg.org` is set)
- **Scheduling:** `cron` (schedule jobs from inside a turn)
- **Web:** `web_search`, `fetch_url`, `browser` (when a provider is configured)
- **Connectors:** `composio` (1,000+ apps), `oauth_authorize`
- **Generation:** `generate_image`, `generate_video`, `generate_speech`, `generate_music`, `render_video` (HTMLβMP4 motion graphics, optional engine)
- **Documents & media:** `analyze_media` (read/understand PDF Β· Office Β· image Β· audio Β· video), `make_document` Β· `edit_document` (create & edit Word/Excel/PowerPoint/PDF)
- **Channels:** `send_message`, `send_media` (when a channel is linked)
---
## Team Mode
Team Mode adds durable rooms and multi-agent task graphs on top of Brigade's
existing agent loop. It supports dependency joins (`all`, `any`, quorum),
retries, leases and fencing, cancellation and timeouts, run budgets, approvals,
handoffs, artifacts, restart recovery, and a room-scoped streaming protocol for
UIs. A room is a durable group/channel: its public conversation supports
threads, replies, explicit agent mentions, attachment references, search,
reactions, pins, edits, soft deletion, reconnect history, and authoritative
metrics. Mentions communicate but never silently launch work; delegation,
consultation, and ownership handoff remain explicit operations. Worker attempts
have isolated transcripts, results return durably to the room coordinator, and
the owner can launch a validated graph with one `team.delegate` call. The same
tool can update configured room membership or archive an idle room without
bypassing the store's membership and active-run guards. It works in both default filesystem mode and optional
Convex mode; it does not require Tideline or a SaaS control plane. The current
Convex collaboration adapter is a single-owner Phase-1 scale profile whose
retained core state must stay below its documented 16 MiB hydration boundary;
filesystem mode does not have that Convex transaction limit.
See **[docs/team-mode.md](docs/team-mode.md)** for the execution model, agent
tools, storage guarantees, and versioned WebSocket API. Brigade ships Team Mode
as a headless backend so products can build their own web, desktop, or mobile
room experience without coupling UI code to the runtime package.
---
## Multi-agent isolation
Every agent has its own workspace, persona, credentials, memory, sessions, exec
approvals, and routing bindings. By design:
- Agent A cannot read agent B's session transcripts (unless visibility β `self`).
- Agent A cannot send to agent B's session unless `cfg.session.agentToAgent` (the
A2A policy) permits it.
- Memory facts are per-agent and origin-scoped β they don't bleed between agents.
- Provider credentials are per-agent β e.g. `support` and `prod-bot` can use
different accounts.
The default policy is `visibility: "self"` (an agent only sees its own sessions);
switch to `"tree"` to let a parent see sub-agents it spawned.
---
## Providers & web search
**Models out of the box:** Anthropic, OpenAI, Google Gemini, OpenRouter, OrcaRouter, Token Market,
Groq, Cerebras, xAI, DeepSeek, Mistral, **Ollama** (local), and **Custom**
OpenAI-compatible endpoints (Together, Fireworks, vLLM, LM Studio, on-prem gateways
β anything that speaks `/v1/chat/completions`). Connect several at once, switch with
`/model`, and Brigade keeps your context across the switch.
**Sign in with a subscription β no API key.** Don't want to manage keys, consoles,
and billing? Use the subscription you already pay for. Two ways, both keyless:
- **Browser sign-in** β `brigade login` signs in to **Claude Pro/Max**, **ChatGPT
Plus/Pro**, or **GitHub Copilot** over OAuth (also offered inside `brigade onboard`).
- **Reuse a CLI login** β already signed into the **Claude Code** or **Codex** CLI on
this machine? `brigade onboard` offers *"Reuse this machine's login"* β one keystroke,
no browser, no re-auth.
Keys still work if you prefer them; either way the credential is sealed on your own
machine (auto-refreshed when the provider supports it).
The `claude-cli` provider goes one step further: it runs the `claude` binary as
Brigade's engine, with the binary's own tools denied and **Brigade's guarded toolset
served back to it** over a per-turn loopback MCP endpoint. Your crew, your memory,
your approval prompts β on a subscription, at no marginal token cost. See
[Subscription backends](#-subscription-backends--your-claude-login-brigades-tools).
**Web search** is pluggable and auto-selected by what you've configured: Tavily,
Brave, Exa, Perplexity, Firecrawl, SearXNG (keyed) and DuckDuckGo, Wikipedia, Hacker
News, arXiv, GitHub, npm, local Ollama (keyless).
---
## Configuration & storage
Brigade keeps every byte of state under `~/.brigade/` β `rm -rf ~/.brigade` truly
wipes everything it knows.
```
~/.brigade/
βββ brigade.json # main config (JSON5; ${VAR} secret refs preserved on write)
βββ brigade.json.bak{,.1..4} # rotating forensic backups (mode 0600)
βββ models.json # custom provider catalog (Ollama / custom endpoints)
βββ workspace/ # default agent (main): SOUL/IDENTITY/AGENTS/USER/TOOLS/
β β # BOOTSTRAP/HEARTBEAT.md persona files
β βββ memory/facts.jsonl # write_memory / recall_memory
β βββ skills/ # drop-a-folder skills
βββ agents// # per-agent isolation
β βββ workspace/ # same shape, per agent
β βββ sessions/.jsonl # transcripts (one file per session)
β βββ agent/ # auth-profiles.json, models.json (mode 0600)
βββ channels/// # channel state (auth, allow-from, pairings)
βββ cron/runs/.jsonl # cron state + per-run logs
βββ logs/ # daily rolling logs + config audit
βββ gateway.{pid,lock,heartbeat}
```
**Useful environment overrides:**
| Var | Purpose |
|---|---|
| `BRIGADE_STATE_DIR` | Alternate state directory (default `~/.brigade`) |
| `BRIGADE_CONFIG_PATH` | Alternate config file path |
| `BRIGADE_PORT` | Gateway port (default `7777`) |
| `BRIGADE_PROFILE` | Named profile (`workspace-/`) |
| `BRIGADE_MODE` | `filesystem` or `convex` |
| `BRIGADE_CONVEX_URL` | Convex deployment URL (implies convex mode) |
| `BRIGADE_ENCRYPTION_KEY` | At-rest encryption master key (hex) |
| `BRIGADE_ENABLE_INBOX_PERSIST` | Persist the sub-agent inbox to JSONL (auto-on at gateway boot) |
| `BRIGADE_HOST_ENV` | Override the host-environment tag in the system prompt's runtime line |
---
## Storage modes: filesystem vs. Convex
Brigade defaults to **filesystem** mode (everything under `~/.brigade/`). It also
ships an optional **Convex** backend you can run **fully self-hosted** β no cloud
account, no telemetry. The mode resolves from a sticky sentinel and **freezes once
at boot**.
```bash
brigade store mode show # what mode am I in?
brigade store mode set convex --convex-url http://127.0.0.1:3210
brigade store migrate --to convex --dry-run # preview a migration
brigade store migrate --to filesystem # copy data back
```
Run the **bundled** self-hosted Convex backend β no Convex account, no separate
install. The backend binary + functions ship inside Brigade, so this works from
anywhere once `brigade` is installed, not just a repo checkout:
```bash
brigade convex dev # download the backend if needed, then run it + dashboard (foreground)
brigade convex status # is the backend up? (probes :3210)
brigade convex push # deploy the bundled Convex functions to the backend
brigade convex codegen # regenerate convex/_generated/ against the local backend
```
`brigade convex dev` runs the backend on `:3210`, the site proxy on `:3211`, and
the dashboard on `:6791`, with binaries + data under `~/.brigade/convex/`. Ctrl-C
to stop; the `brigade convex:dev` colon form works too. Then point Brigade at it
with `brigade store mode set convex --convex-url http://127.0.0.1:3210` (above).
> Running from a repo checkout? The `npm run convex:install` / `convex:dev` /
> `convex:codegen` scripts still work and write into the repo's `bin/` + `.convex-data/`.
Turn on **at-rest encryption** for Convex byte columns (credentials, persona,
memory, cron payloads, transcripts) with `BRIGADE_ENCRYPTION_KEY`:
```bash
brigade encrypt init # generate a 32-byte key
brigade encrypt status # is a key configured? self-check
brigade encrypt test # round-trip seal/open
```
See [docs/convex-mode.md](docs/convex-mode.md) for the full runbook.
---
## MCP memory server
Brigade can expose your long-term memory to any MCP client over stdio:
```bash
brigade mcp # serves the `main` agent's memory
brigade mcp --agent support # a specific agent
```
It surfaces add / search / context tools, owner-bound. Point an MCP client (an
editor, a desktop assistant, etc.) at the command `brigade mcp`.
---
## Tideline (long-term memory)
Tideline is the **model-agnostic long-term memory engine** that backs Brigade.
Where a transcript is what an agent *just said*, Tideline is what it *knows* β
durable facts about you and your work, written under a trust gate, recalled by
meaning, decayed when stale, and reconciled over time. It's structured to be lifted
out as its own package (`brigade-tideline`).
It's built to survive the three ways naive "vector store" memory breaks:
| Pillar | What it does |
|---|---|
| π‘οΈ **Provenance write-gate** | An untrusted source (a web page, a tool result) can't author or overwrite your identity/preferences/corrections. Poisoning writes are rejected. |
| π **Per-origin isolation** | Owner facts and per-channel/peer facts are scoped so one principal's memory never surfaces in another's recall. |
| π **Hybrid recall, no model needed** | BM25 keyword search + a **model-free** HRR vector recovery lane, so semantically-close phrasings match offline. Plug in a learned embedder to upgrade. |
| β³ **Bi-temporal decay + trust** | Recency/usage decay and source-trust fold into one effective ranking score; `permanent` facts never decay. |
| π **Typed link graph** | `supersedes` / `corrects` / `relates` / `supports` / `contradicts` edges power graph-recall and contradiction handling. |
| π **Reflect / consolidate** | A nightly pass confirms repeated beliefs, merges duplicates, writes association edges, and evicts decayed noise. |
**The flow, end to end:**
```
WRITE add() β write-gate (trusted vs untrusted Γ protected segment) β dedup β store
RECALL query β BM25 + HRR vector β graph walk β decayΓtrust score β origin filter β budgeted block
MAINTAIN decay GC β nightly dream (consolidate/relate) β contradiction detection
```
Each record carries a `segment` (identity / preference / correction / relationship /
project / knowledge / context), a `tier` (short / long / permanent), an `importance`,
and an `origin`.
```ts
import { Tideline } from "brigade-tideline";
const memory = Tideline.open("/path/to/workspace");
memory.add({ content: "I keep a strict vegetarian diet.", segment: "preference" });
const block = memory.context("dietary restrictions", { maxChars: 800 });
```
In Brigade you reach it through the `recall_memory` / `read_memory` / `write_memory` /
`manage_memory` tools and via auto-recall (which **fails closed** for unknown peers,
so operator memory never leaks). An evaluation harness (`brigade-tideline/eval`)
measures recall@k / MRR / nDCG@k on deterministic gold sets β run `npm run bench`.
π Full write-up: **[docs/tideline.md](docs/tideline.md)** Β·
package surface: [`src/tideline/`](src/tideline/)
---
## Extending Brigade
Brigade ships a typed extension SDK. Drop a module into `~/.brigade/extensions/` and
register against a slot:
```ts
import { defineModule } from "@spinabot/brigade/extension-sdk";
export default defineModule((b) => {
b.tool({ /* a custom agent tool */ });
b.webSearch({ /* a search provider */ });
b.channel({ /* a messaging adapter */ });
b.gatewayMethod({ /* a gateway RPC */ });
});
```
Shipped slots include `tool`, `hook`, `command`, `modelProvider`, `channel`,
`webSearch`, `webFetch`, `integration`, `service`, `httpRoute`, and `gatewayMethod`.
Voice/media slots (`tts`, `stt`, `mediaGen`) and pluggable `memory` backends have
locked contracts with implementations on the roadmap. See [AGENTS.md](AGENTS.md) for
how to add a tool, channel, skill, or provider.
---
## Privacy
Brigade is a local CLI. Your API keys never leave your computer; they're stored in
your home directory at mode `0600` and used only to talk to the providers you
connect. **No telemetry, no analytics, no cloud component.** For Ollama and custom
endpoints, requests stay on your network. The gateway binds to `127.0.0.1` by
default.
---
## Develop from source
```bash
git clone https://github.com/spinabot/brigade.git
cd brigade
npm install
npm run build # tsc β dist/
```
**Run from your checkout** (npm scripts wrap the binary so you don't type `node`):
```bash
npm run dev # smart runner: rebuilds dist/ if src/ is newer, then runs
npm run dev:tsx # run TypeScript directly via tsx (no build, slower per call)
npm run watch # tsx --watch: auto-restart on edit
npm link # make `brigade` available globally β this checkout
```
**Surface shortcuts** (all wrap `scripts/run-brigade.mjs`):
```bash
npm run onboard # brigade onboard
npm run tui # brigade tui
npm run gateway # brigade gateway run (also gateway:status / gateway:stop)
npm run connect # brigade connect
npm run agent -- -m hi # brigade agent -m hi
npm run agents:list # brigade agents list (agents:add / agents:bind / β¦)
npm run status # brigade status (status:json)
npm run doctor # brigade doctor (doctor:json / doctor:strict)
npm run channels:list # brigade channels list (wa:link / pairing:list / β¦)
npm run skills:list # brigade skills list
npm run logs # brigade logs (logs:follow)
```
**Checks** (CI runs the same three):
```bash
npm run typecheck # tsc --noEmit, strict
npm test # node:test, tempdir-isolated (281 test files)
npm run build # ensure the production build compiles
npm run bench # memory / recall evaluation benchmarks
```
**Storage / Convex dev:** `npm run store:mode:show`, `npm run convex:install`,
`npm run convex:dev`, `npm run convex:codegen`.
Full contributor guide, repo layout, and conventions live in **[AGENTS.md](AGENTS.md)**.
---
## Contributing
Contributions are welcome! Read **[CONTRIBUTING.md](CONTRIBUTING.md)** for dev setup,
coding conventions, and the Conventional-Commits release flow. For security issues, see
**[SECURITY.md](SECURITY.md)** β please report privately. Releases are automated with
release-please; see **[docs/RELEASING.md](docs/RELEASING.md)**.
Questions or ideas? Open a
[discussion](https://github.com/spinabot/brigade/discussions) or email
**hello@brigade-agent.ai** (security β **security@brigade-agent.ai**).
---
## License
[MIT](LICENSE) Β© Spinabot
## π¦ Brigadiers
A pride of contributors who make Brigade better. Thank you to everyone who has
joined the crew!
Want to join the pride? See [CONTRIBUTING.md](CONTRIBUTING.md).