Repository navigation
Conversation
Add `plannotator-tui rex last|open|terminal`. Each command finds the agent in a Rex block, opens plannotator-tui in a split to the right of the block, and exits. The split is an ordinary pane, so it keeps the frame and theme of Rex. When an agent runs in the block, a send pastes the feedback into the block as one bracketed paste and presses Enter. Without an agent, the review copies to the clipboard. - The block is --block, else REX_BLOCK. An agent that runs a launcher in its own shell hands the human a document to review. - --paste leaves the feedback in the agent's prompt and focuses the agent's block, so the human can edit it before sending. - A send waits while Rex reports the agent blocked on a permission prompt or a question, like agent_blocked in Herdr. - A Rex action runs commands with a bare PATH. The launcher then runs the rex binary of its parent process, the Rex server. - `rex pane` is the entry point of the split. An error waits for Enter, because Rex closes the split when the program exits. Move the terminal review out of src/herdr into src/terminal.rs, because Herdr and Rex now share it. Each host only reads the output.
There was a problem hiding this comment.
🟡 Changes recommended
Missing agent and session validation can cause annotation text to execute in a shell or display another session’s replies while sending feedback to the selected block.
3 open issues
What changed in this PR
Adds Rex integration so users can open reviews beside an agent’s block and return feedback to it, while sharing terminal-review rendering with Herdr.
Changes:
- Adds
rex open,last,terminal, andfindlaunchers. - Adds agent feedback delivery with send/paste modes and blocked-agent checks.
- Extracts shared terminal-review code and documents Rex usage.
| File | Description |
|---|---|
skills/plannotator-tui/SKILL.md |
Extends review instructions to Rex. |
README.md |
Documents Rex commands and feedback behavior. |
crates/plannotator-tui/src/terminal.rs |
Houses shared terminal cleaning, wrapping, rendering, and tests. |
crates/plannotator-tui/src/rex/terminal.rs |
Captures Rex output for terminal reviews. |
crates/plannotator-tui/src/rex/paths.rs |
Finds Markdown files mentioned in output. |
crates/plannotator-tui/src/rex/mod.rs |
Declares the Rex integration modules. |
crates/plannotator-tui/src/rex/launch.rs |
Detects agents and opens review splits. |
crates/plannotator-tui/src/rex/command.rs |
Wraps session-scoped Rex CLI calls. |
crates/plannotator-tui/src/rex/cli.rs |
Parses launchers and review-pane commands. |
crates/plannotator-tui/src/rex/agent.rs |
Implements feedback delivery to Rex agents. |
crates/plannotator-tui/src/main.rs |
Registers Rex and shared terminal modules. |
crates/plannotator-tui/src/herdr/terminal.rs |
Delegates rendering to shared terminal code. |
crates/plannotator-tui/src/herdr/launch.rs |
Exposes agent-name recognition for reuse. |
crates/plannotator-tui/src/cli.rs |
Routes Rex commands and selects Rex delivery. |
AGENTS.md |
Documents the Rex module boundary. |
Review effort: Balanced
| let status = self.rex.terminal_method(&self.block, "program_status").map_err(unavailable)?; | ||
| if let Some(reason) = blocked_reason(&status) { | ||
| return Err(DeliveryError::Blocked(format!("{} is {reason}", self.describe()))); | ||
| } |
There was a problem hiding this comment.
Fixed. The launcher passes the agent's PID, and each send checks that it still runs in the block. If not, the send returns Unavailable and the clipboard takes over.
| let host = fg.host.context("no supported agent runs in this block")?; | ||
| args.extend(["last".to_owned(), "--pid".to_owned(), fg.pid.to_string()]); | ||
| args.extend(["--host".to_owned(), host.to_owned()]); |
There was a problem hiding this comment.
This comes from the existing macOS fallback in last, which Herdr uses too. This PR does not change it. I will keep it out of scope and open a separate issue.
| self.rex.api("block.event", &paste).map_err(unavailable)?; | ||
| let next: &[&str] = | ||
| if self.submit { &["send-key", "-b", &self.block, "enter"] } else { &["focus", &self.block] }; | ||
| self.rex.run(next, None).map_err(unavailable)?; |
There was a problem hiding this comment.
Fixed. A retry of the same feedback presses Enter without pasting again, and a focus failure no longer counts as a delivery failure.
88c6205 to
6c5e762
Compare
Add `plannotator-tui rex find`. It reads the pane's recent output, picks the newest .md path that exists on disk, and opens it in a split.
3039971 to
0dc4658
Compare
An empty program_status said "not blocked", so a send pasted and pressed Enter into whatever was on screen. Claude Code reports nothing at its startup trust prompt, where Enter picks "No, exit": the agent quit and the review still said "sent". A done or idle record left by an earlier process passed the check too. A send now needs a status record owned by the agent's process, else it is unavailable and the review copies instead, like Herdr's agent_not_ready. --paste presses no Enter, so it still pastes.
When Enter failed after the paste, the send failed and the notes stayed pending. A retry of the same text pressed Enter only, but any change in between (one more note) pasted everything again on top of the text already waiting in the prompt, and the agent got the first notes twice. Once the paste lands the feedback is in the agent's prompt, so the send counts: the block takes focus and the status line says to press Enter there. Delivery gains a notice for that; Herdr leaves it empty.
The refusal read "claude no longer runs in claude in 4eb9f1".
SKILL.md tells agents to open a plan with --gate for a sign-off, but `rex open` rejected the flag. It now takes --gate and --result-file like `herdr open`: the split shows Approve, the decision reaches the agent's block, and the result file records it. A gated `rex open` was also caught by the direct gate, which read `rex` as the file to review.
…ument --gate AGENTS.md listed src/rex/ as a repo-root path, the delivery module doc described Herdr only, and SKILL.md's --gate step had no Rex form.
|
Thanks, Kyle. We tested this in Rex on macOS (build 1630, Claude Code 2.1.312, Codex 0.160) and pushed five small commits on top of your 0dc4658:
Checked live and left alone:
Agreed that the Codex fallback is pre-existing and out of scope here. Not tested: key bindings, and status reporting from pi, opencode and agy. |


Summary
Add
plannotator-tui rex open|last|terminal|find. Each command finds the agent in a Rex block, opens plannotator-tui in a split to the right of the block, and exits. A send pastes the feedback into the block as one bracketed paste and presses Enter. Without an agent, the review copies to the clipboard.Rex mirrors the Herdr module. The terminal review code moves out of
herdr/so both hosts share it.--pasteleaves the feedback in the agent's prompt and focuses the agent's block.agent_blockedin Herdr.--block, elseREX_BLOCK.Evidence
plannotator-tui rex openis an unknown command.After: the command opens a split. 15 new tests pass, for example:
cargo fmt --all,cargo clippy --workspace --all-targets, andcargo test --workspaceare clean.Merge Danger
Door: two-way
The Rex code is new and runs only through
plannotator-tui rex. A revert removes it.Blast Radius: Herdr
herdr/terminal.rsloses its review code tosrc/terminal.rs, andherdr terminalnow calls the shared copy.known_hostinherdr/launch.rsbecomespub(crate). Herdr behavior does not change.