team approve
The owner approves the team file: reads it, shows what changed since the last approval, asks for the
number of seats, and writes the record this machine holds it to. Every command that starts, moves or
changes a team checks that record first, so an edit to the file needs a new approval before it can
run. --show prints the same comparison and stops, writing nothing.
Synopsis
team approve [--show] [--file <path>]
What it reads and writes
Reads the team file (or the one --file names), its validation, and, when there is one, the approved
copy this machine holds. It also reads overrides.yaml in that same store, when the owner has one.
Writes the approval record — the team file and the override file, as approved — and the ledger of
every seat the team has had here — both in the store, ~/.config/team/<project>-<hash> — and one
line in .agents/team.log. --show writes nothing.
Who may run it
The owner, from a terminal outside herdr: no seat approves a file, not even the coordinator's.
--show may be run by anyone, in any terminal.
Flags
| Flag | Meaning |
|---|---|
--show | print the comparison, ceilings and seats, and stop; change nothing |
--file <path> | the team file, instead of .agents/team.yaml |
--help, -h | the usage, and exit 0 |
What it prints
With no record on this machine, the whole file, numbered, so the owner reads exactly what is being approved. With a record, a line per changed section or seat against the approved copy:
+ 6: trust:
+ 7: - .
Needs a new approval: `trust` changed.
Nothing at all changed is said plainly:
./.agents/team.yaml: the same text as the copy approved on 2026-10-04T09:00:00.000Z.
Nothing in it needs a new approval.
Then the ceilings the approval would fix — 3 seats at most, 2 temporary — and the
seat names, and then the question. The seat ceiling defaults to the seats the file declares plus the
temporary ones, so adding a seat widens it, and that shows up as limits changed too. What needs a
new approval is a change to an owner section
(trust, limits, machine, rules, identity, workspace, coordinator, operator,
session, visibility, tools, budgets, watch — its timings included, down to watch.checks,
whose turn-offs are their own line) or to a seat's own fields. A seat taken out does not.
Parking or stopping one does, except that remove --keep and add record the new digest
themselves, so those commands do not send the owner back to approve. Until an edit is
approved its section changes nothing: the watch, the budget reports, the check cadence, up's and
add's launch gate and status's table run with the approved values, or with the defaults when
nothing was approved. A stored copy that no longer validates: budgets falls back to no accounts (no
budget reports, no check runs) and the difference is reported until the next approve; up and add
refuse a drifted file before the gate.
Refusals
| Message | Exit |
|---|---|
team approve: unexpected "x" (with the usage) | 2 |
team approve: line <n>: <message> / team approve: <message> | 2 |
team approve: the approval store <store> is inside <folder>, where seats work | 1 |
team approve: only the owner approves a team file, from a terminal outside herdr; this call is <caller> | 1 |
team approve: not approved; nothing was written | 1 |
A file that loads with warnings prints them on stderr as
team approve: warning, line <n>: <message> and goes on. The last refusal is what an answer that is
not the number of seats gets: a blank answer, a wrong one, and a closed terminal are all the same
answer.
Exit codes
0— approved, or--showprinted the comparison and stopped before the question.1— refused: a seat ran it, the store sits where seats work, or the answer was not the number of seats. Nothing is written.2— the invocation, the team file or the file's validation is bad.
Examples
format: 1
project: beacon
coordinator: claude-keeper
operator: claude-keeper
workspace:
mode: shared
seats:
- role: coordinator
name: claude-keeper
label: coordinator
cli: claude-code
vendor: anthropic
model: Claude Opus
version: "5.5"
launch: claude --model claude-opus-5-5The first run shows the whole file, because this machine has no copy of it to compare against:
team approve --show ; echo "exit $?"
./.agents/team.yaml: never approved on this machine. The whole file:
1: format: 1
2: project: beacon
3: coordinator: claude-keeper
4: operator: claude-keeper
5:
6: workspace:
7: mode: shared
8:
9: seats:
10: - role: coordinator
11: name: claude-keeper
12: label: coordinator
13: cli: claude-code
14: vendor: anthropic
15: model: Claude Opus
16: version: "5.5"
17: launch: claude --model claude-opus-5-5
Ceilings this approval fixes: 3 seats at most, 2 temporary.
Seats: 1 (claude-keeper).
exit 0The owner approves it, typing the number of seats:
team approve
./.agents/team.yaml: never approved on this machine. The whole file:
1: format: 1
2: project: beacon
3: coordinator: claude-keeper
4: operator: claude-keeper
5:
6: workspace:
7: mode: shared
8:
9: seats:
10: - role: coordinator
11: name: claude-keeper
12: label: coordinator
13: cli: claude-code
14: vendor: anthropic
15: model: Claude Opus
16: version: "5.5"
17: launch: claude --model claude-opus-5-5
Ceilings this approval fixes: 3 seats at most, 2 temporary.
Seats: 1 (claude-keeper).
Type the number of seats (1) to approve this file, and its commands and rules, to run: 1
Approved. The record is in ~/.config/team/beacon-<hash>; check the rest with `team doctor`.A seat can read the comparison — even the coordinator's — but a seat is not the owner, and nothing is written for it:
team approve ; echo "exit $?"
./.agents/team.yaml: the same text as the copy approved on 2026-10-04T09:00:00.000Z.
Nothing in it needs a new approval.
Ceilings this approval fixes: 3 seats at most, 2 temporary.
Seats: 1 (claude-keeper).
team approve: only the owner approves a team file, from a terminal outside herdr; this call is claude-keeper
exit 1An owner section is the owner's to change, and the comparison says so before the question:
format: 1
project: beacon
coordinator: claude-keeper
operator: claude-keeper
trust:
- .
workspace:
mode: shared
seats:
- role: coordinator
name: claude-keeper
label: coordinator
cli: claude-code
vendor: anthropic
model: Claude Opus
version: "5.5"
launch: claude --model claude-opus-5-5 team approve --show ; echo "exit $?"
./.agents/team.yaml: against the copy approved on 2026-10-04T09:00:00.000Z:
+ 6: trust:
+ 7: - .
Needs a new approval: `trust` changed.
Ceilings this approval fixes: 3 seats at most, 2 temporary.
Seats: 1 (claude-keeper).
exit 0A new seat needs one too — a seat already approved may be taken out without bothering the owner.
Parking or stopping one needs an approval, unless remove --keep or add wrote the mark and
recorded the digest. A seat the file never had is not approved:
format: 1
project: beacon
coordinator: claude-keeper
operator: claude-keeper
trust:
- .
workspace:
mode: shared
seats:
- role: coordinator
name: claude-keeper
label: coordinator
cli: claude-code
vendor: anthropic
model: Claude Opus
version: "5.5"
launch: claude --model claude-opus-5-5
- role: implementer
name: claude-beacon
label: implementer
cli: claude-code
vendor: anthropic
model: Claude Opus
version: "5.5"
launch: claude --model claude-opus-5-5 team approve ; echo "exit $?"
./.agents/team.yaml: against the copy approved on 2026-10-04T09:00:00.000Z:
+ 6: trust:
+ 7: - .
+ 20: - role: implementer
+ 21: name: claude-beacon
+ 22: label: implementer
+ 23: cli: claude-code
+ 24: vendor: anthropic
+ 25: model: Claude Opus
+ 26: version: "5.5"
+ 27: launch: claude --model claude-opus-5-5
Needs a new approval: `trust` changed; `limits` changed; seat claude-beacon is not in the approved file.
Ceilings approved: 3 seats at most, 2 temporary.
Ceilings this approval fixes: 4 seats at most, 2 temporary.
Seats: 2 (claude-keeper, claude-beacon).
Type the number of seats (2) to approve this file, and its commands and rules, to run: 1
team approve: not approved; nothing was written
exit 1The answer is the number of seats, and nothing else — here, two:
team approve
./.agents/team.yaml: against the copy approved on 2026-10-04T09:00:00.000Z:
+ 6: trust:
+ 7: - .
+ 20: - role: implementer
+ 21: name: claude-beacon
+ 22: label: implementer
+ 23: cli: claude-code
+ 24: vendor: anthropic
+ 25: model: Claude Opus
+ 26: version: "5.5"
+ 27: launch: claude --model claude-opus-5-5
Needs a new approval: `trust` changed; `limits` changed; seat claude-beacon is not in the approved file.
Ceilings approved: 3 seats at most, 2 temporary.
Ceilings this approval fixes: 4 seats at most, 2 temporary.
Seats: 2 (claude-keeper, claude-beacon).
Type the number of seats (2) to approve this file, and its commands and rules, to run: 2
Approved. The record is in ~/.config/team/beacon-<hash>; check the rest with `team doctor`.The same file again is the same text as the approved copy, and the approval stands:
team approve --show ; echo "exit $?"
./.agents/team.yaml: the same text as the copy approved on 2026-10-04T09:00:00.000Z.
Nothing in it needs a new approval.
Ceilings this approval fixes: 4 seats at most, 2 temporary.
Seats: 2 (claude-keeper, claude-beacon).
exit 0The overrides file
overrides.yaml lives in the approval store, beside the record. It may add dialog patterns
(unknown, trust, permission, question) and quota patterns to a profile this version
ships, and nothing else: not a composer, a prompt, a footer, a launch line, a stage order, a
case flag, a fold, or a code module. A pattern is added after the shipped ones. It cannot take
a shipped pattern out, and it cannot make a screen read idle or unsent that does not
already, nor stop a shipped permission, trust or question pattern from matching.
approve records the file's text with the team file. Until it does, the approved copy stays
in force — or the shipped profiles alone, when there is no copy, or the copy cannot be read.
doctor and status name the difference. A file that does not parse is refused here, with
its path and its line, and the other commands report that line instead of failing on it.
format: 1
profiles:
codex:
quota:
- account: anthropic
match: '\bL: ([0-9]+)% \(([0-9hm]+)\)'
used: '{1}%'
resets: '{2}'
window: session team approve --show ; echo "exit $?"
./.agents/team.yaml: the same text as the copy approved on 2026-10-04T09:00:00.000Z.
overrides.yaml: against the copy approved on 2026-10-04T09:00:00.000Z:
+ 1: format: 1
+ 2: profiles:
+ 3: codex:
+ 4: quota:
+ 5: - account: anthropic
+ 6: match: '\bL: ([0-9]+)% \(([0-9hm]+)\)'
+ 7: used: '{1}%'
+ 8: resets: '{2}'
+ 9: window: session
Needs a new approval: `overrides` changed.
Ceilings this approval fixes: 4 seats at most, 2 temporary.
Seats: 2 (claude-keeper, claude-beacon).
exit 0