The approval prompt deserves its own tool.
Pinrail is a new desktop app for macOS and Linux. A coding agent submits a review through the pinrail command, waits, and receives the person's decision as Markdown or JSON. The project names Claude Code, Codex, Cursor, and OpenCode as compatible because the only hard requirement is the ability to run a command.[1]
The app is early. Version 0.1.2 shipped on October 7. The release fixes sidebar placement on macOS and moves the plugin SDK dependency to npm. Windows support is still planned rather than shipped.[2]
Chat is good for discussion. It is a poor place to hide a production gate.
The useful part is the return contract.
A review begins as pending. It can end as decided, discarded, withdrawn, or expired. Those outcomes are separate. A decided review returns the structured answer. A discarded review tells the agent to stop and exits with code 5. A withdrawal or expiry exits with code 3.[3]
That is better than asking an agent to infer intent from "looks good" somewhere in a long transcript. The workflow gets a bounded result it can branch on. The person gets a view built for the object under review, such as a diff, a list, a document, or an image.
Pinrail also keeps revision rounds connected. A new round can carry the earlier verdict beside the changed item. The operator can inspect what moved without rereading the whole conversation.
Local is a boundary, not a verdict.
The project says the app listens on loopback and stores reviews locally. Its CI guide says a hosted runner cannot reach that server. A review from CI must run on the same computer, such as a self-hosted runner, or use another deliberate route.[4]
Loopback cuts one network path. It does not prove that a submitted payload is safe, that a plugin view is trustworthy, or that the person has enough context to decide. The artifact, origin, requested action, expiry, and stop behavior still belong in the review.
Do not let a person become the timeout.
A waiting agent can hold a shell, a worker, or a paid runner. Pinrail exposes a timeout and an expiry. Its guide also documents a split route. Submit without waiting, save the review ID, then let a later job retrieve the decision.[4]
Use that pattern when the work can park. Reserve a blocking wait for short, attended decisions. The receipt should say which route was chosen. "Human in the loop" does not explain who is watching, how long the loop may wait, or what happens when nobody answers.
Use this checkpoint contract.
- Attach the exact artifact or diff that needs a decision.
- Name the one action the decision can release.
- Record the repository, run, branch, or other origin.
- Set a wait limit and an expiry policy.
- Give reject, discard, timeout, and withdrawal distinct behavior.
- Return a machine-readable result and a human-readable record.
- Keep merge, send, deploy, and publish authority outside the review unless the request names that action.
AGENT REVIEW CHECKPOINT REQUEST=[CODE / MESSAGE / PRODUCTION] ARTIFACT=[PATH OR REVISION] ORIGIN=[REPOSITORY / RUN / BRANCH] RELEASED_ACTION=[ONE ACTION] WAIT_BUDGET=[SECONDS OR PARKED] EXPIRY=[TIME AND RESULT] DISCARD=[STOP] DECISION_RECORD=[MARKDOWN AND JSON] STATUS=[TEMPLATE ONLY / NO DECISION RECORDED]