---
name: setup
description: >-
  How a HUMAN creates or joins a Brigade team — `team create` from a terminal, `$join <path>` (or `brigade team
  join --secret-file <path>` in a terminal) to join — and how to leave and uninstall: the Supabase project prerequisites,
  `team create` (which writes the project's committed `.brigade.json`), the one-line join, and
  the removal order. Use when someone asks how to set Brigade up, join a team, add a teammate, leave, or remove
  the plugin. It never asks anyone to paste a join secret into the chat.
---

# Setting Brigade up

A Brigade team belongs to a **project**: a committed file, `.brigade.json`, at the repository's top level names the
team every session in that checkout talks to. It carries only public values, so it is safe in version control; the
join secret is never in it. The administrator writes the file once; each member runs one command in their checkout.
The file may carry optional members the project commits by hand: `sync` (folders to keep in step), `gateway` (how
people without a session reach the team) and `polling` (how often sessions check in with the backend, to stay
inside a plan's request budget, and how long a session the VS Code extension started may stay idle before it
closes itself). `docs/team-admin/configure/team-file.md` in the Brigade repository describes each.

Every command below is the **person's** to run, in their own terminal, through the package's bootstrap: the
`bin/brigade` under Codex's plugin cache for `brigade` (the session-start line names its path), and a symlink such
as `ln -sf <that path> ~/.local/bin/brigade` gives the terminal and this session the bare word. This is a Codex
CLI session: when the person wants to run one of these, give them the command to paste into their terminal. The
join secret is a bearer capability: **never paste it into a Codex chat**, a commit, an issue or a log — it lives in the file `team create` wrote,
saved outside the repository, and `--secret-file` names that file (its mode and owner are never checked). Two team commands run in a terminal only — `team revoke-member`
and `team transfer` — and so does the release of a held message (`docs/team-member/use/held-messages.md`).

## 1. Administrator: create a team

For a first Supabase setup, `docs/project-owner/install/README.md` in the Brigade repository is the project
owner's ordered procedure, and `docs/team-admin/create/create-the-team.md` the administrator's. The publishable key is under Project Settings → API Keys and starts with `sb_publishable_`;
the `sb_secret_` key on the same page is never used. The short form follows.

The bundled adapter keeps a team in a Supabase project, so create a **single-purpose** project for it first:
enable anonymous sign-ins under Authentication > Sign In / Providers; leave CAPTCHA off (a command-line client
cannot solve a browser challenge); do not enable the Pro session time-box or inactivity limits (they silently kill
idle principals); turn "Allow public access" off in the Realtime settings; and apply the migrations from this
repository's `supabase/` directory to the project. Members ever receive only two values, and both are non-secret:
the **project URL** and the **publishable key** — and the committed file already carries both. A project that
already holds a Brigade team can hold another: run `team create` with the same URL and key and skip this setup.
Anyone who can read the project's database can read every team in it.

Run this **in the project checkout**, in a terminal:

```sh
brigade team create --url https://<ref>.supabase.co --key sb_publishable_… \
  --name <team> --secret-file ~/brigade-<team>.secret
```

then `git add .brigade.json && git commit && git push`. `team create` writes `.brigade.json` at the repository top
level and stores your credential locally so your sessions attach at once. `--secret-file` is required and must be
an absolute path outside the repository; it holds the join secret at mode 0600 instead of your terminal scrollback
or the conversation.

`team create` runs only inside a git checkout, because that is where sessions look for the file. With no checkout
of the project on this machine, run it in an empty `git init` directory and copy the `.brigade.json` it writes into
each repository. One team can span several repositories: commit the same file in each (section 2).

To keep folders in step between the members' checkouts, add a `sync` member to `.brigade.json` by hand and commit
it:

```json
"sync": { "folders": [".brigade"] }
```

`team create --force` carries it into the file it rewrites. Add each listed folder to `.gitignore`, or a teammate's
edit shows in your `git status` as a change of yours. Every member's plugin must be 0.16.0 or later before the
project commits the member. `docs/team-admin/configure/sync-folders.md` in the Brigade repository has the rules.

Then send each member the join secret **over a password-grade channel** — a password manager share, not chat and
not email. The secret is a bearer capability: anyone holding it can join and pick any label.

By default a member's label is **the email address of the Claude account their install is signed in to**, so the
roster you and every other member see will hold those addresses — and so will the backend you run. A member who
would rather not can set the `label` plugin option to `none` or to any text before joining; tell them so when you
send the secret if that matters to your team. The same default applies to you: `team create` sends your account
email as your own label and names it in its output (`sent your display label: …`, the line after `created team …`),
so you can see what it published. A label is unverified free text either way: the principal reference beside it is
the identity.

Your credential directory (`~/.config/brigade/teams/<key>`, or under the `config_dir` plugin option) is the
team's only administrative credential. Keep a 0700 backup of it somewhere you control; without it nobody can
rotate the secret or administer the team. Rotating the join secret runs in a session or a terminal
(`brigade team rotate-secret --secret-file <path>`, the file outside the repository); revoking a member and
transferring the team are terminal-only administrative commands that refuse inside a session. The procedure is in
`docs/team-admin/members/README.md` in the Brigade repository.

## 2. Member: join

Clone the project, save the secret file your administrator sent you outside the repository, open a Codex
session in the checkout, and ask it to join with `$join`, naming the file:

```
$join ~/brigade-<team>.secret
```

That runs `brigade team join --secret-file ~/brigade-<team>.secret` and relays the output. `team join` reads the
project's `.brigade.json`, prints the team and backend host it is joining (invoking it is the consent), reads the
secret from the file and joins; its output never carries the secret, and this session attaches at your next prompt
(one already attached to another team stays there until a new session). Delete the file once every machine
that needs it has joined.

**The join sends a display label**: in a Codex CLI session there is no Claude account to read an email address
from, so unless the `label` option in `~/.config/brigade/codex-options.json` names a text (or `none`), your
sessions are listed by their principal reference alone. Set it **before you join** if you want a label; any text
is used as your label, and every member of the team, and whoever runs its backend, will see it. `--label <text>` on the command overrides the option for
that one join. It is not prompted for, so choose it first.

In your own terminal,
`brigade team join` alone shows what the file names, asks you to confirm, then reads the secret without echo.
Either way the secret never reaches your scrollback, your shell history or a chat. There is no `--profile`, no
`--url` and no `--key`: the project file supplies all of that.

- The URL in the file must be `https://`; the adapter refuses anything else except a loopback host.
- Under Codex's default profile the model's shell runs in a sandbox with the network off, so a `brigade`
  command that reaches the backend (`send`, `sessions`, `join`) asks for your approval; under
  `--dangerously-bypass-approvals-and-sandbox` nothing is asked. Brigade's hooks and its watcher run outside the
  sandbox either way, so team messages arrive under both.
- Joined from a terminal, start a Codex session in the checkout and type one prompt — Codex runs Brigade's
  session start at the first prompt; joined from a session, it attaches at your next prompt. The session-start
  line names your team, this session's name and id, and the inbound policy, and says where the `brigade` command
  is; from then on every team message arrives as a turn of its own.
- A second checkout of the same project on this machine needs `team join` once too, but no secret. One team can
  span several repositories: commit the same `.brigade.json` in each and join each checkout once; a different
  `.brigade.json` is a different team. Either way, `cd` between checkouts — nothing is shared or switched.
- A project that syncs folders (its `.brigade.json` has a `sync` member) needs Syncthing on your `PATH`:
  `brew install syncthing` on macOS, `sudo apt install syncthing` on Debian or Ubuntu. Without it the session
  joins all the same and says file sync is off.
- A backend other than the bundled Supabase adapter is named in the project file's `adapter` field, and the name
  resolves to a command through your own `adapters.json` (an absolute path or a JSON array);
  `docs/adapter-authors.md` in the Brigade repository explains the forms. `brigade team status`, run in the
  checkout, names the team and its adapter.

## 3. Leaving and uninstalling

The order matters. Every step is optional except step 3 when the goal is to remove the plugin.

1. `brigade team leave` (with `!` in a session) closes your open sessions in that team and revokes the
   membership; teammates stop seeing your sessions immediately. Skip it and the membership stays active
   indefinitely while your sessions merely go offline after the lease expires.
2. `brigade team reset` revokes the credential family on the backend and deletes the
   local credential. **Run step 1 first:** after a reset the membership and its sessions can no longer be closed
   from this machine, and a later rejoin mints a new principal that teammates see as a new person.
3. `codex plugin remove brigade@brigade` removes the plugin itself (`codex plugin marketplace remove brigade`
   removes the marketplace too).
4. `rm -rf ~/.local/state/brigade ~/.local/share/brigade` (or the `XDG_STATE_HOME`/`XDG_DATA_HOME` equivalents)
   removes the session maps, pidfiles, logs and the cached binaries. Keep
   `~/.local/state/brigade/sessions/by-native` if a later reinstall should resume your old Brigade sessions.
5. `rm -rf ~/.config/brigade` (or the directory named by the `config_dir` option) removes every team's credential.
   Do this only after step 2 for each team: a deleted credential whose family was never revoked stays usable by
   any copy of it.

If you **created** the team, step 2 ends secret rotation, revocation and transfer for it, permanently (step 1 alone
does not: a rejoin with the current secret restores administration). Transfer the team to another active member
*before* step 1, and keep that 0700 backup of the credential directory either way.
