team hold

A hold is a note on the team's work: why it was placed, who placed it and when, and when it lapses. It lives in the team state (.agents/team.state.json), never in the team file: placing one edits no team file, and a hold that waits is no hold. A hold is the project's, not one session's. status prints it as its first note: and doctor as the last note line before the summary. A record whose until has passed reads as no hold at all, so a lapsed hold needs no writer to clear it: every reader stops showing it, and the next team hold replaces it. In this build nothing else consults a hold: no command, no launch and no watch changes what it does while one stands.

Synopsis

team hold <reason> [--until <time>] [--json]
team hold --release [--json]

What it reads and writes

Reads the team file in the current folder and the state beside it, and the pane the state records for the caller's seat when a seat runs it. Writes one hold record at the top level of the state:

{
  "format": 1,
  "hold": {
    "reason": "freeze deploys",
    "by": "owner",
    "at": "2026-10-04T09:00:00.000Z",
    "until": "2026-10-04T18:00:00.000Z"
  },
  "sessions": {}
}

until is absent when the hold names no end. Placing a hold under one that still stands writes nothing and is refused, naming the hold in force; a hold that has lapsed is replaced. --release removes the record and writes nothing else. A hand-edited value that is not the record this command writes — a reason with no text, a name or an instant that doesn't parse — is dropped when the state is read, so it is never printed by any reader.

Who may run it

The caller rule is the session walk's: the owner, or the team's orchestrator or operator running on its own seat.

CallerMay
the owner, from a terminal outside herdrplace and release
the orchestrator's or the operator's seat, on the pane the state records for itplace and release
a run with no terminalnothing: team hold: only the owner, the orchestrator or the operator runs this, from a terminal outside herdr or its own seat
any other seat, or an agent-run CLInothing: team hold: only the owner, the orchestrator or the operator holds the team; this call is <caller>
the orchestrator's or the operator's seat, when the state records no pane for itnothing: team hold: no pane is recorded for seat <name> in this session: a lead stops that seat and runs \team up``
the same seat on a pane the state doesn't record for itnothing: team hold: the state records pane <recorded> for seat <name> in this session, not the pane this call is on: a lead stops the team and starts it again (\team down`, then `team up`)`

Flags

FlagMeaning
<reason>the line stored as the reason; required unless --release
--until <time>a local <HH:MM>, the next time that clock comes (today, or tomorrow when today's has passed), or an ISO 8601 instant carrying Z or an offset
--releaseclears the hold that stands; takes no <reason> and no --until
--jsonemit a team.hold v1 JSON document (schema/hold.schema.json) on stdout
--help, -hthe usage, and exit 0

Refusals

MessageExit
team hold: a <reason> is required (with the usage)2
team hold: unexpected "<word>" (with the usage)2
team hold: --release takes no <reason> and no --until (with the usage)2
team hold: <why the team file did not load>2
team hold: --until is a local <HH:MM>, or an ISO 8601 instant with Z or an offset, and nothing else1
team hold: already held: <reason> — already held until <instant>: <reason> when the hold names an end1
team hold: not held1
team hold: only the owner, the orchestrator or the operator runs this, from a terminal outside herdr or its own seat1
team hold: only the owner, the orchestrator or the operator holds the team; this call is <caller>1
team hold: no pane is recorded for seat <name> in this session: a lead stops that seat and runs \team up``1
team hold: the state records pane <recorded> for seat <name> in this session, not the pane this call is on: a lead stops the team and starts it again (\team down`, then `team up`)`1
team hold: <why the state could not be read or written>1

Exit codes

  • 0 — the hold was placed, or released.
  • 1 — it was refused: the caller may not hold the team, a hold already stands, no hold stands, --until is neither shape, the state can't be read or written, or the run has no terminal.
  • 2 — the invocation can't be read, or the team file can't.

Example

.agents/team.yaml
format: 1
project: beacon
operator: claude-keeper

trust:
  - ~/.config/team/lobby
  - ~/Code/beacon

workspace:
  mode: shared
seats:
  - role: project coordinator
    name: claude-keeper
    leads: true
    cli: claude-code
    vendor: anthropic
    model: Claude Opus
    version: "5.5"
    launch: claude --model claude-opus-5-5

The owner holds the team until an instant, and a second hold is refused by name:

Terminal
 team hold "freeze deploys" --until 2026-10-04T18:00:00Z ; echo "exit $?"
hold until 2026-10-04T18:00:00.000Z: freeze deploys
exit 0
 team hold "keep the tree still" ; echo "exit $?"
team hold: already held until 2026-10-04T18:00:00.000Z: freeze deploys
exit 1

--release clears it, and a release with no hold is refused:

Terminal
 team hold --release ; echo "exit $?"
hold: released
exit 0
 team hold --release ; echo "exit $?"
team hold: not held
exit 1

--until takes a clock or an instant, and nothing else. A hold with no --until stands until it is released:

Terminal
 team hold "freeze deploys" --until tomorrow ; echo "exit $?"
team hold: --until is a local <HH:MM>, or an ISO 8601 instant with Z or an offset, and nothing else
exit 1
 team hold "freeze deploys" ; echo "exit $?"
hold: freeze deploys
exit 0

An agent-run CLI is refused, and so is the orchestrator's seat with no pane recorded for it — a team the state never brought up:

Terminal
 team hold "freeze deploys" ; echo "exit $?"
team hold: only the owner, the orchestrator or the operator holds the team; this call is unplaced (it is run by an agent (claude) outside herdr)
exit 1
Terminal
 team hold "freeze deploys" ; echo "exit $?"
team hold: no pane is recorded for seat claude-keeper in this session: a lead stops that seat and runs `team up`
exit 1