FeaturesReview agents
A second pair of eyes on every commit.
Turn review agents on, and an agent reads each new commit of every pull request in the project's repositories, whoever wrote it: your agents, your teammates, Dependabot. It says what it found where you already look, on the lines it is about, and stays quiet when there is nothing to say.
Turn them on How review agents work
Pull requests from your team, your agents and the apps you choose. Outside contributors' when someone asks.
What the change breaks, security problems and breaks of the repository's rules, most severe first.
Findings on an fctl agent's pull request go back to that agent, which fixes what's real and answers in the thread.
The next review strikes out what was fixed and resolves its own threads. The check on the commit says where things stand.
Where you already read.
A review is one summary on the pull request, then each finding on its lines: a title, how severe it is,
a few sentences on why, and a suggested change where one helps. The commit gets a check,
fctl review: green when there's nothing to look at, neutral when there is, since acting on it is
up to the pull request's people.
Anouk sent milkfloat her first pull request, driver breaks. Noor asked for a review, and its agent read the code, ran none of it, and found the break that could hang the solver.
From finding to fix, before anyone wakes up.
Noor's agent opened shop#1287 at eleven at night: a link in the reminder email that skips next week's box. Two minutes later the review agent found that last week's email would skip this week's box too. fctl handed the finding to the agent that opened the pull request. It agreed, signed the delivery's date into the link, pushed, and answered in the thread. The next review saw the fix and resolved it.
- A reading, not an order. The agent checks each finding, fixes what's real, and says why when it disagrees.
- No ping-pong. After five reviews in a row without a person in between, findings wait for one.
- On someone's subscription. Reviews run on the Claude plan of the owner who turned them on.
Fixed in 4e1c9a2. The token carries the delivery's date now, and an old one stops working once that day has passed.
The skip token isn't tied to a delivery
Medium severity. The token only names the subscription, and the route skips whatever delivery comes next, so last week's email skips this week's box. Sign the delivery's date into the token and refuse it once that day has passed.
Found by fctl review in b81d0e7.
Fixed in 4e1c9a2: signSkip signs the subscription and the delivery's date, and
verifySkip refuses a token whose date has passed. Two tests try last week's link.
Every review is a session you can open.
Each review runs in a sandbox of its own, as a session of the project, with a token that only reads on GitHub: no secrets, no setup script, no memory. Open it to see what the agent read, what it ran and why it concluded what it did. The session that received the findings shows them in a few lines, each a click from its thread.
What a review agent may do
The agent that wrote it gets the memo.
Asha's agent was chasing a double charge. Its fix still let two workers race to charge the same card, and the review said so. The finding arrived in the agent's session as a message from fctl, it reproduced the race with two workers, and pushed the fix that the next review passed.
Off until an owner says on.
A project's owners turn review agents on, on their own Claude subscription, and choose the model, the
effort, instructions of their own and the apps whose pull requests are reviewed by themselves. Pull
requests from people who can't write to the repository start nothing alone: whoever looks at one first
asks for its review from the Reviews tab, or with fctl review start.
In the docs
What starts a review, what its agent may do, and what it posts.
Start a factory tonight.
curl -fsSL https://fctl.sh/install | sh
fctl-shBotyesterday
A break it can't reach makes
insert_breakloop foreverMedium severity. When the break's window ends before the shift starts, or no stop departs inside it,
at <= brk.window.endnever holds, and once the van has no departures left,next_departurereturnsatitself:solvenever returns. Stop at the window's end and returnInfeasibleafter the loop. None of the three tests tries a window the route can't reach.Found by fctl review in
9c2e1f4.