Standing review pools
A standing review pool is a team of reviewer agents that stays running between reviews. Start one with start-review-team/synthex:start-review-team, and every review-code/synthex:review-code or performance-audit/synthex:performance-audit that matches its roster hands the work to reviewers that are already warm — no per-review spawn.
Why it exists
By default, every review-code/synthex:review-code spawns its reviewers fresh, runs them, and throws them away. That's the right trade for occasional reviews. When you review many times an hour — a fast-moving branch, a pre-commit flow where you're waiting on the result — the spawn cost on every run adds up.
A pool pays that cost once. The reviewers sit idle until a review arrives, an idle reviewer claims the task, and you get the same consolidated report the normal path produces.
For a few reviews a day, skip pools. The default path is simpler and the idle pool isn't worth it.
Requirements
Pools are built on Claude Code's Agent Teams feature, so they only work on Claude Code:
- The Agent Teams flag. Set
CLAUDE_CODE_EXPERIMENTAL_AGENT_TEAMS=1and restart Claude Code. start-review-team/synthex:start-review-team checks for it before doing anything else. - The Agent Teams tools. The pool commands check that
SendMessageandListAgentsare in the session's tool list. On a host without them, start-review-team/synthex:start-review-team, stop-review-team/synthex:stop-review-team, and list-teams/synthex:list-teams print a one-line notice and stop. review-code/synthex:review-code and performance-audit/synthex:performance-audit keep working there with their normal reviewers. - Routing turned on. Commands only look for a pool when
standing_pools.enabled: true. It's off by default.
configure-teams/synthex:configure-teams is the exception: it only writes config, so it runs on any host. That lets a team on mixed tools set up the shared config from wherever they are.
Quick start
# 1. Turn on routing (writes standing_pools to .synthex/config.yaml)
/synthex:configure-teams
# 2. Start a pool with the default roster (code-reviewer, security-reviewer)
/synthex:start-review-team
# 3. Review as usual — the command finds the pool on its own
/synthex:review-code
# 4. Stop the pool when you're done
/synthex:stop-review-team --name review-poolWhen a review routes to a pool, the command says so:
Routing to standing pool 'review-pool' (multi-model: no).and the report header starts with Review path: standing pool 'review-pool' (multi-model: no).
Lifecycle
A pool moves through four states, which list-teams/synthex:list-teams shows:
| State | Meaning |
|---|---|
idle | Nothing pending or in progress. Available for routing. |
active | One or more reviews pending or in progress. Still available for routing. |
draining | Finishing in-flight reviews before shutdown. Not accepting new work. |
stopping | Shutdown signal sent, waiting for confirmation. Disappears from the list soon. |
Start. start-review-team/synthex:start-review-team validates the name and roster, spawns a
Pool Lead plus one teammate per reviewer, and records the pool in a shared index at
~/.claude/teams/standing/index.json. Pools live under your home directory, so a pool is
visible to every session on the machine — but only routes reviews whose roster it matches.
Route. A matching command submits its review as tasks to the pool, waits up to
lifecycle.submission_timeout_seconds (default 300) for the result, and presents the pool's
consolidated report as its own. A pool can only serve reviews while the Claude Code session
that started it is still open.
Idle and TTL. A pool that sits idle past ttl_minutes (default 60) becomes eligible for
shutdown. TTL is enforced lazily: nothing watches the clock. The next time something looks
for pools — a list-teams/synthex:list-teams call or a routed review — it notices the
expired pool and treats it as gone. Set ttl_minutes: 0 to turn off TTL reaping entirely.
Stale pools. Pools don't outlive the Claude Code session that started them. When a pool's metadata directory is missing, or it's been inactive longer than the TTL or 24 hours (whichever is longer), the next routed review cleans it up, prints a one-time warning, and carries on without it.
Stop. stop-review-team/synthex:stop-review-team asks the Pool Lead to shut down, lets in-flight reviews finish, and removes the pool from the index.
How routing works
review-code/synthex:review-code and performance-audit/synthex:performance-audit check for a pool
first, before resolving the diff or spawning anyone. A pool matches when it is a standing pool,
isn't draining or stopping, hasn't passed its TTL, and its roster fits the reviewers the command
needs:
- review-code/synthex:review-code needs the reviewers from its
--reviewersflag, orcode_review.reviewersin config, orcode-reviewer+security-reviewerif neither is set. Prompt-file reviewers are dropped from that set — a pool can only hold agents — and they don't run when a pool handles the review. If every configured reviewer is a prompt file, the command skips pool routing. - performance-audit/synthex:performance-audit always needs
performance-engineer, so only a pool that includes it will match.
matching_mode decides what "fits" means:
covers(default) — the pool's roster includes every required reviewer. A pool withcode-reviewer,security-reviewer, andperformance-engineerserves both commands.exact— the pool's roster is exactly the required set, nothing more.
If several pools match, the first by name wins.
routing_mode decides what happens when nothing matches, or a routed review times out:
prefer-with-fallback(default) — fall back silently to fresh reviewers. You always get a review.explicit-pool-required— abort with an error naming the missing reviewers and the start-review-team/synthex:start-review-team command that would fix it. Use this when you want to catch a misconfigured or stopped pool rather than quietly paying for fresh reviewers.
When a reviewer fails mid-review. If one pool reviewer crashes, the command re-runs just that reviewer fresh, merges its findings with the rest of the pool's report, and adds a note at the top saying which reviewer was recovered. If the pool itself fails (the Pool Lead crashes, or draining times out), the command falls back to a full fresh review.
Configuration
Pool settings live under standing_pools: in .synthex/config.yaml. These are the shipped
defaults:
standing_pools:
enabled: false # turn on routing from review-code / performance-audit
ttl_minutes: 60 # idle minutes before a pool can be reaped; 0 = never
default_name: review-pool # pool name when start-review-team gets none
default_reviewers: # roster when start-review-team gets none
- code-reviewer
- security-reviewer
default_multi_model: false # start new pools with multi-model review on
routing_mode: prefer-with-fallback # or explicit-pool-required
matching_mode: covers # or exact
lifecycle:
submission_timeout_seconds: 300 # how long a command waits on a pool before falling backlifecycle is a top-level key, not nested under standing_pools, because it governs the
session submitting the review rather than the pool.
The pool storage paths (~/.claude/teams/standing and ~/.claude/tasks/standing) appear in
the defaults file but aren't configurable — every session relies on them to find pools.
Pool names must be 1–48 lowercase letters, digits, and hyphens, starting with a letter or
digit. index, standing, and names starting with . are reserved.
Legacy config file. If .synthex/config.yaml has no standing_pools block, Synthex still
reads it from the old .synthex-plus/config.yaml, printing a deprecation warning. That
fallback lasts for one major version. Move the block over (same key, same shape), or run
configure-teams/synthex:configure-teams, which always writes the new location.
Agent Teams hooks
Turning on standing_pools.enabled also activates two Synthex hooks on Agent Teams events:
TaskCompletedblocks a teammate from completing a non-documentation task until the completion note recordsReview verdict: PASSorReview verdict: WARN. The block message names the reviewers the work type needs. Turn it off withhooks.task_completed.review_gate.enabled: false.TeammateIdlehands an idle teammate the next unblocked task that matches its role. Standing-pool teammates are exempt — the Pool Lead manages them. Turn it off withhooks.teammate_idle.work_assignment.enabled: false.
Both fail open, and each nags only once per task, so neither can deadlock a team.
Multi-model pools
Start a pool with --multi_model (or set default_multi_model: true) and each review also
runs Synthex's multi-model orchestrator, which fans the review out to the external CLIs you've
configured and merges their findings into the same report. Startup runs the multi-model
preflight first and stops on a hard error. If any external CLI is configured in
sandbox-yolo mode, it also asks you to confirm, defaulting to no.
Only code-reviewer, security-reviewer, design-system-agent, and performance-engineer
support multi-model pools. Expect a multi-model review to cost roughly two to three times a
native-only one, depending on how many external CLIs are configured. See
Multi-model review.
Cost
An idle pool still holds its reviewers open. start-review-team/synthex:start-review-team warns and asks before spawning a pool with four or more reviewers, or with two or more reviewers and a TTL over 240 minutes. Stop pools you aren't using, or keep the TTL short.
Coming from synthex-plus?
Standing pools used to live in the separate synthex-plus plugin. They're now part of
Synthex, and synthex-plus has been removed from the marketplace. The four pool commands keep
their names under the synthex: namespace. The team-* commands are retired with no direct
replacement: their behavior now lives inside review-code/synthex:review-code,
next-priority/synthex:next-priority, write-implementation-plan/synthex:write-implementation-plan, and refine-requirements/synthex:refine-requirements.
The migration guide covers stopping old pools, moving your config, and the full command mapping.
See also
- start-review-team/synthex:start-review-team — start a pool (reference)
- stop-review-team/synthex:stop-review-team — stop one or all pools (reference)
- list-teams/synthex:list-teams — see running pools (reference)
- configure-teams/synthex:configure-teams — set up routing (reference)
- Reviewer pipeline — what a review does when no pool handles it
- Upstream guide —
plugins/synthex/docs/standing-pools.md