The chat works. Before you build on it, read it. Never merge code you haven't read, however confident the agent sounds. A second agent session can help you read: ask it to review the diff, in plan mode, so it can look but not touch.
Verified claude-code 2.1.317remix 3.1.0
Start from d-09 on GitHub. Starting here, or behind? Get the code at that tag:
git clone https://github.com/ryanyogan/klippy cd klippy git checkout d-09
1. The review prompt
Goal: review the chat front end (git diff d-07..d-09 -- apps/web) before I build on it, so nothing unread gets merged. Use the remix skill and AGENTS.md; check claims against apps/web/node_modules/remix guides 04 and 05, not memory. Constraints: - Read only. Don't edit files; don't run the dev server. - Look for: code that isn't isolated (protocol logic inside a component), UI that misrepresents what happened, security (token, Origin, hrefs from model output), accessibility (labels, live regions), and Remix v2/React patterns. Done when every finding names a file and line and says why it matters. Report at most 6 findings, most important first, each with the smallest fix. Say "none" for a category with nothing.
We ran it headless, in plan mode, with read-only tools:
claude -p "<the prompt>" --permission-mode plan --max-turns 25 --allowedTools "Read,Grep,Glob,Bash(git diff:*),Bash(git show:*),Bash(git log:*)"Categories to look for. "Review this" gets style nits. Naming what matters gets findings.
File, line, why, smallest fix. Each finding is checkable and actionable.
"Say none for a category with nothing." Permission to find nothing, so it doesn't invent problems to fill the list.
2. What it found
A real run, quoted (excerpt; it found six, here are the first three headlines and its security verdict):
Plan mode also saves a copy of its notes under ~/.claude/plans/, outside the repo.
We took every finding except two it marked as optional. But it missed one. In our own run last lesson, the tool card was drawn above the text, so the model's early "Note saved" looked like it came after the tool. A review agent misses things too. Your own run is the other half of the review.
3. Steer: one change per prompt
Each steer prompt quotes the problem and says what you want instead:
Move the socket and protocol code out of Chat into app/actions/public/chat-session.ts, a ChatSession that extends TypedEventTarget like guide 05's CartModel. The component only draws and calls send()/answer().Sending your answer… can stick, and a failed send looks delivered. Clear answering in every case, treat a null stream as an error, and on a failed send take the message back and keep the typed text.The tool cards render above the text, so 'Note saved' looks like it came after the tool ran. Render parts in order.And one from our run after the refactor:
After Deny the card still says 'Waiting for you'. Apply the agent's saved chat when the reply ends.The result: the island's file now only draws (about 70 lines), and the protocol lives in a class with no JSX. Its send() takes your message back if it didn't go through:
4. Run it again: Deny this time
Our second browser run (real; the Workers AI fallback answered):
The card says You said no, and the note wasn't saved: the newest note on /notes is still last lesson's. The model said "the system returned an error", which isn't what happened. Read the card, not the model's sentence.
5. Review the refactor
chat.tsxhas noAgentClient,MessageTypeorJSON.parseleft;chat-session.tshas no JSX.Every path through
send()andanswer()ends withbusy = false, and a failure sets a message.Live regions are rendered from the start, never conditionally.
Nothing new in
package.json.Reject: a refactor that changes behaviour you didn't ask for, a new state library.
Save it as a skill (optional). You'll ask for reviews like this again. A skill with a description such as "Review a diff in apps/web against AGENTS.md and the Remix guides. Use before merging front-end changes." loads it when you need it. Keep it in your own .claude/skills/.
Your repo matches tag d-10 (changes from d-09).