condensate

Applications

gt-review

Run the review hub, register checkouts and arm review rooms.

On this page

gt-review is the review hub. It serves each registered checkout through its own repository instance and runs review rooms, where agent reviewers and a fixer work on a branch as Condensate threads. The hub serves the review API and no review page. The review interface is Dex, which reads the hub's /api routes through its /hub/* proxy. This page covers starting the hub, registering checkouts and running review rooms.

Start the hub

From apps/gt-review:

bun run build
bun dist/cli.js hub --no-open

The hub listens on http://127.0.0.1:4700 by default. Pass --port to choose another port. To reach the hub from your tailnet, keep the default bind and put tailscale serve http://127.0.0.1:4700 in front of it. Do not bind the hub to all interfaces with --host 0.0.0.0 unless you also turn on its admin-token gate. The gate is off by default, so such a hub accepts POST, PATCH and DELETE requests from any host that can reach it, with no authentication. To turn the gate on, start the hub with GTR_REQUIRE_ADMIN_TOKEN=1 and a secret in GTR_ADMIN_TOKEN. The hub then refuses those requests unless they send the same secret in the x-gtr-admin-token header. Dex does not send that header, so writes through Dex fail while the gate is on. A request to / returns one line of plain text saying the port serves the review API. GET /api/health tells you the hub is up, and GET /api/hub/repos lists the checkouts it serves.

The hub runs reviewers and fixers as runtime threads. It reaches the runtime at CONDENSATE_AGENTS_URL, which defaults to http://127.0.0.1:4741. If you installed Condensate with the installer, start the hub with the ports the installer printed: CONDENSATE_AGENTS_URL=http://127.0.0.1:<runtime port> bun dist/cli.js hub --no-open --port <hub port>.

Reviews run only in review rooms. You arm a room yourself, or the hub arms it for you after a pull request sync when automatic arming is on, as described below.

Register a checkout

The hub serves only checkouts in its registry. Register each one with a path to a git checkout:

bun dist/cli.js register /absolute/path/to/checkout

If a hub is running, register adds the checkout to it at once. If none is running, the checkout is saved and served the next time the hub starts. Registering the same checkout twice does nothing. If you installed Condensate with the installer, register reads HUB_PORT from the installation's install.env. It looks in CONDENSATE_INSTALL_DIR, or in ~/.local/state/condensate-fresh when that is unset, so set CONDENSATE_INSTALL_DIR as the installer printed it. With no installation, register uses port 4700. The quickstart shows the full local setup.

Review a repository

Open Dex with the hub running. Choose the registered repository, inspect the changes and the discussion, and open the review thread you need. Choosing the repository matters. A hub can serve several repositories, each under its own /<repo-name>/ path, and every request has to name the right one.

Review rooms

A review room holds the review of one branch. When you arm a room, it gets:

PartWhat it does
Reviewer per engineReads the branch diff and raises findings. An arm can name up to two engines.
Standing fixerWorks on the findings the reviewers raise.
RoundsGives the reviewers and the fixer another turn each, so the reviewers can challenge each other's findings. Start rounds with POST /api/review-rooms/<branch>/rounds. One request runs one to three rounds.

The reviewer engines are Claude Code (engine id claude), Condensate's own agent (pi) and Codex (codex). Condensate's own agent runs OpenAI models on a Codex login. An arm with no engines starts the reviewer that the models.reviewAgent setting names, which is Claude by default.

Arm one branch with POST /api/pr-reviewer/arm. Arm a whole stack, bottom to top, with POST /api/pr-reviewer/arm-stack. You can also let the hub arm rooms for you. After it syncs a repository's pull requests, it arms up to three rooms per pass. It considers only open, non-draft pull requests that target the trunk branch and come from the same repository, not a fork. It skips a branch a person disarmed at its current head, and a branch whose last automatic arm failed waits between one and 30 minutes before the next try. This is on by default for the condensate workspace. The variables below control it:

SettingEffect
GTR_AUTO_REVIEW=0Turns automatic arming off for every workspace.
GTR_AUTO_REVIEW_<WORKSPACE>=0Turns it off for one workspace, such as GTR_AUTO_REVIEW_CONDENSATE=0.
GTR_AUTO_REVIEW_<WORKSPACE>=1Turns it on for a workspace other than condensate.

Two pull request labels change what happens. no-review leaves the pull request out of automatic arming. no-autofix turns off automatic fixing for that pull request. Automatic arming never turns on auto-merge.

Models

  • The reviewer's model comes from the models.reviewAgent setting. The fixer's model comes from models.gtFixer. If that setting names no model, the fixer runs Claude Opus 5.5 with a 1M context window.
  • The standing fixer reads models.gtFixer when it starts. A change reaches a running fixer only after the fixer is replaced. A per-finding fixer reads the setting each time it is dispatched.
  • Re-arming a room keeps its existing fixer and its model, until the fixer is replaced or the room is pruned.

Account limits

If every account for an engine is out of quota, the hub does not start a reviewer on that engine. It runs that reviewer's lens on Claude instead and tells the room why, with the time the quota resets. If Claude's accounts are out of quota too, no reviewer can run, and the runtime refuses the turn and raises an alert.

Deployments

The installer does not start the hub. It prints the command to start it. To run the hub as a container, use the repository's docker-compose.yml, which binds the hub to 127.0.0.1:4700 on the host. It also picks up checkouts placed in its ./repos directory. deploy.sh redeploys a container to a machine on your tailnet and keeps that machine's .env and cloned repositories.

Follow your deployment's update procedure, and keep the runtime's data directory. Local development commands do not update a deployed hub.

A hub restart does not drop a review round in flight. The round's progress is saved with the repository, and the reviewer and fixer agents run as runtime threads. When the hub starts again, it reattaches to the rounds that are still running. Rebuilding the hub is safe at any time.