<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0"><channel><title><![CDATA[Reado]]></title><description><![CDATA[Notes from building Reado, an open-source IDE for reading the code your AI agent writes: inverted code review, line-anchored comments, and working with Claude C]]></description><link>https://reado.hashnode.dev</link><image><url>https://cdn.hashnode.com/uploads/logos/6ac6cf880fea3400cd5deae2/1031c757-8df8-4092-9007-53e5117f29a1.png</url><title>Reado</title><link>https://reado.hashnode.dev</link></image><generator>RSS for Node</generator><lastBuildDate>Thu, 22 Oct 2026 03:46:01 GMT</lastBuildDate><atom:link href="https://reado.hashnode.dev/rss.xml" rel="self" type="application/rss+xml"/><language><![CDATA[en]]></language><ttl>60</ttl><item><title><![CDATA[SneakPeek: the Claude Code bug that lived in the preview, not the agent]]></title><description><![CDATA[On October 14 Noma Labs published SneakPeek, an exploit chain in Claude Code Desktop's preview pane. A malicious HTML file in a public repository could run…]]></description><link>https://reado.hashnode.dev/sneakpeek-the-claude-code-bug-that-lived-in-the-preview-not-the-agent</link><guid isPermaLink="true">https://reado.hashnode.dev/sneakpeek-the-claude-code-bug-that-lived-in-the-preview-not-the-agent</guid><category><![CDATA[Security]]></category><category><![CDATA[claude-code]]></category><category><![CDATA[AI]]></category><dc:creator><![CDATA[uryon]]></dc:creator><pubDate>Sun, 18 Oct 2026 12:03:28 GMT</pubDate><content:encoded><![CDATA[<p>On October 14 Noma Labs published <a href="https://noma.security/noma-labs/sneakpeek-how-the-preview-pane-in-claude-code-desktop-can-exfiltrate-your-data">SneakPeek</a>, an exploit chain in Claude Code Desktop's preview pane. A malicious HTML file in a public repository could run JavaScript when Claude previewed it, read files from your home directory, and send them to an attacker's server. Noma's list of what the proof of concept read includes SSH private keys, AWS keys, npm and GitHub tokens, Kubernetes and Docker credentials. Anthropic scored it CVSS 8.7 (High).</p>
<p>It's fixed: according to Noma's timeline, Anthropic shipped the fix on August 17, in Claude Desktop 1.30096.1 and later, through auto-update. If your app updates itself, you've had it for two months.</p>
<p>I build <a href="https://reado.watermelon-studio.it">Reado</a>, an IDE for reading the code your agent writes, so a bug that lives in "showing the user a file" is squarely my problem too. This post is about why this one is worth understanding even though it's closed, and what I checked in my own app after reading it.</p>
<h2>What happened</h2>
<p>When Claude reads or edits an HTML file, Claude Code Desktop shows it in a preview pane, so you see the result right away. Noma describes three defenses around that pane:</p>
<ul>
<li>a Content Security Policy with <code>script-src 'none'</code>, so no JavaScript runs;</li>
<li>loading the page as a <code>data:</code> URL, which gives it an opaque origin, so it can't fetch local files;</li>
<li>a request filter on the dev-server proxy, which catches requests the renderer makes.</li>
</ul>
<p>The gaps were in where each one applied. Files under 256KB were loaded as <code>data:</code> URLs, with the CSP. Files over 256KB were written to a temp file and loaded as <code>file://</code> URLs, and that path never got the CSP. In Chromium a <code>file://</code> page can <code>fetch()</code> other local files. And the request filter was only active when the pane was proxying a running dev server, not when it rendered a static file from disk.</p>
<p>So the attack is: pad an HTML file past 256KB, put a script in it, and wait for someone to look at it. Noma disguised it as a test coverage report, a file nobody is surprised to find large. The victim clones the repository and asks Claude to look at the coverage report. Claude reads the file, the pane renders it, the script runs.</p>
<p>There was no permission prompt at any point, and that's the part I keep thinking about. Claude didn't run a command or write a file. It read a file, which is the most harmless thing an agent can do. The code ran in the application's renderer, as a side effect of showing you the result.</p>
<h2>The first fix, and the way around it</h2>
<p>Noma reported the bug on July 4. Anthropic's first patch blocked <code>fetch()</code> and <code>XMLHttpRequest</code> calls to <code>file://</code> from the page. Noma moved the same <code>fetch()</code> into a Web Worker created from a <code>blob:</code> URL, a context the filter didn't cover, and the files came out again. They reported the bypass on July 24, the same day the patch was ready for retest. On August 3 Anthropic confirmed the first fix was incomplete and started a complete one, covering, in Noma's words, "CSP, file:// loading, and the Worker bypass". It shipped on August 17.</p>
<p>Noma's write-up credits Anthropic for "iterating on every bypass until achieving a comprehensive, layered fix", and the timeline backs that up. But the bypass itself is the lesson. The first patch blocked the APIs the proof of concept had used. The attacker used another one. The complete fix went after the conditions instead: the CSP, the <code>file://</code> loading, and the Worker.</p>
<h2>Three things I take from it</h2>
<p><strong>A second code path is a second security model.</strong> My guess is that the 256KB cutoff was a performance decision: large <code>data:</code> URLs are slow. Nobody decides "large files get no CSP". But a threshold quietly sent the large ones down a path with different rules. If a feature has two ways of doing the same thing, each one needs its own security review. Better still, have one way.</p>
<p><strong>The permission system guards the agent, not the app around it.</strong> Most of what we do to make coding agents safe is about the agent: approve this command, deny writes outside the project, sandbox the shell. All of that was in place here and none of it was involved. Carlos, commenting on <a href="https://dev.to/rbonweb/the-claude-code-desktop-vulnerability-that-beat-three-layers-of-sandboxing-296n">a dev.to write-up of the bug</a>, put it well: "Here a file in the repo was the attacker and the viewer was the tool." Anything that renders what's in a repository (previews, Markdown, notebooks, images, an embedded browser) is part of the attack surface, whether or not an agent is involved.</p>
<p><strong>"Review this file" is when you trust the file least.</strong> The request that triggered SneakPeek was a review: look at this coverage report. That's the moment the file has been seen by nobody you trust, so the surface showing it should be the least capable one in the app, not the most.</p>
<h2>How Reado shows a repository</h2>
<p>Reado has the same problem to solve: it exists to show you the files in a repository, most of which you didn't write. After reading Noma's post I went through every place it does that, with SneakPeek's three questions: does the file's code run, can the page read the disk, can it send anything out.</p>
<ul>
<li><strong>An <code>.html</code> file opens as source code.</strong> Reado renders Markdown, Jupyter notebooks, images and PDFs; everything else, HTML included, is text in the editor. A coverage report is something you read, not something that runs.</li>
<li><strong>HTML inside Markdown and notebook outputs goes through a sanitizer.</strong> READMEs are full of HTML (centered logos, badges, <code>&lt;details&gt;</code>), so Reado renders it, through <a href="https://github.com/rehypejs/rehype-sanitize">rehype-sanitize</a>, which strips scripts, event handlers and <code>javascript:</code> URLs.</li>
<li><strong>Behind the sanitizer, the app's Content Security Policy.</strong> Only scripts that ship with Reado run (<code>script-src 'self'</code>), and that rule covers workers too, so the <code>blob:</code> Worker trick has nothing to start from. No frames, and the page can't send requests (<code>fetch()</code>, <code>sendBeacon()</code>) anywhere but the app itself.</li>
<li><strong>Size never changes how a file is loaded.</strong> A 500KB README goes through the same pipeline as a 5KB one. Past a size limit Reado stops instead: it asks before opening a large file, and doesn't open a huge one at all. It never switches to a different loader.</li>
<li><strong>Local images come only from the open project.</strong> The protocol Reado uses for images on disk starts with an empty scope and is widened to the project folder when you open it, never to the rest of the disk. SVGs are shown through an <code>&lt;img&gt;</code> tag, where SVG scripts don't run, and PDFs are drawn on a canvas.</li>
</ul>
<p>The same pass turned up two bugs in a surface I hadn't thought of as "showing files": Reado's embedded browser, the pane for previewing your dev server. It takes URLs from two places a repository can control. Design comments, which live in <code>.reado/</code> like every Reado comment, carry the URL of the page they're pinned to. And agents drive the pane through a command file in the same folder. So a cloned repository could ship a comment pointing at a <code>file:</code> or <code>data:</code> page, or a command already waiting for the pane to open. Both are fixed: the pane now opens only <code>http</code> and <code>https</code> pages, checked in one place in the Rust layer that every caller goes through, and a command that was already there when the pane opened is recorded, never run. The fixes are on <code>main</code> and ship in the next release.</p>
<p>The common thread is a choice I made for other reasons: Reado is built around reading code, so its default for a file is to show the text. That's less impressive than a live preview, and after SneakPeek it's one I'm glad of.</p>
<h2>If you use these tools, or build them</h2>
<p>If you use Claude Code Desktop, check that you're on Claude Desktop 1.30096.1 or later. Noma's post also lists the GitHub advisory and CVE as pending, so watch for those.</p>
<p>If you build a tool that shows files from a repository, a few rules follow from this bug:</p>
<ul>
<li>Treat every file in a cloned repository as input from a stranger, including the boring ones.</li>
<li>One rendering path, with the same restrictions however big the file is.</li>
<li>Apply your restrictions to where content comes from, not to the APIs it uses. Block <code>fetch()</code> and an attacker reaches for a Worker.</li>
<li>Show the source by default. Render only what you have to.</li>
</ul>
<p>Anthropic fixed this one, and kept at it until the bypass was closed too. The pattern isn't specific to them: every coding tool that shows you a file has a version of that preview pane. It's worth looking at yours before someone else does.</p>
]]></content:encoded></item><item><title><![CDATA[Claude Code can draw now. An experiment in reviewing from inside the agent]]></title><description><![CDATA[Two weeks ago Claude Code shipped something that is easy to miss in a changelog full of fixes. Version 2.1.287 added what the release notes call "Claude…]]></description><link>https://reado.hashnode.dev/claude-code-can-draw-now-an-experiment-in-reviewing-from-inside-the-agent</link><guid isPermaLink="true">https://reado.hashnode.dev/claude-code-can-draw-now-an-experiment-in-reviewing-from-inside-the-agent</guid><category><![CDATA[claude-code]]></category><category><![CDATA[code review]]></category><category><![CDATA[AI]]></category><dc:creator><![CDATA[uryon]]></dc:creator><pubDate>Sat, 17 Oct 2026 08:46:04 GMT</pubDate><content:encoded><![CDATA[<p>Two weeks ago Claude Code shipped something that is easy to miss in a changelog full of fixes. Version 2.1.287 added what the release notes call "Claude Mods: plugins may now modify deeper behavior". That undersells it. A mod is code that runs <em>inside</em> Claude Code, sees every tool call before it happens, and can draw its own interface in the terminal.</p>
<p>I build <a href="https://reado.watermelon-studio.it">Reado</a>, an IDE for reading the code your agent writes. When a tool gets a way to change how the agent itself works, the first thing I want to know is what that means for review. So I read the docs, looked at the mods Anthropic shipped, and wrote a small one as an experiment. To be clear up front: it isn't part of Reado, and I'm not shipping it. This post is about what I learned building it, and where I think mods do and don't belong in a review workflow.</p>
<h2>What a mod is</h2>
<p>The <a href="https://code.claude.com/docs/en/plugins/mods/overview">overview</a> puts it plainly: a mod is "made of JavaScript or TypeScript event handlers: Claude Code calls one when an event happens, such as a tool call, a submitted prompt, or a part of the interface being drawn". Each handler can watch the event, change it, or answer it itself so the default behavior never runs.</p>
<p>Claude Code already had hooks, skills and MCP servers, so it's fair to ask what's new. The difference is where the code runs. A settings hook is a shell command Claude Code starts and waits for. An MCP server is a separate process that offers the model tools. A mod is a function in Claude Code's own process, so it can do things the others can't:</p>
<ul>
<li><strong>Draw.</strong> A pane beside the transcript, or a band above the prompt, with text, buttons and input fields.</li>
<li><strong>Redraw what Claude Code draws.</strong> A tool call's row, the spinner, the question dialog. Everything except the permission prompt, which a mod can't restyle.</li>
<li><strong>Step into a tool call.</strong> Hold it, rewrite it, refuse it, or answer it without running the tool.</li>
<li><strong>Add commands that run immediately,</strong> without a Claude turn, even while Claude is working.</li>
</ul>
<p>A mod is a plugin with three files: the manifest, a <code>hooks.json</code> that points at your code, and the code itself. No build step: Claude Code loads <code>.ts</code> and <code>.tsx</code> directly. The handlers have a middleware shape that will be familiar to anyone who has written Express or Koa:</p>
<pre><code class="language-tsx">on('tool.call', async ($, e, next) =&gt; {
  // e is the call: e.tool, e.file_path, e.old_string...
  const result = await next(e) // let the tool run
  return result
})
</code></pre>
<p><code>$</code> is the only way out of the handler. Reading a file, running a process, calling a model, drawing: everything goes through it. That's a deliberate design choice, and it matters for security, which I'll get to.</p>
<h2>The first mods are about review</h2>
<p>What caught my attention is what Anthropic built with them first. There are four mods worth looking at: two ship inside Claude Code, two are samples you install yourself. They do different things, but each one covers a different moment of reviewing what the agent does:</p>
<table>
<thead>
<tr>
<th>Moment</th>
<th>Mod</th>
<th>What it does</th>
</tr>
</thead>
<tbody><tr>
<td><strong>Before</strong> a dangerous command runs</td>
<td><code>blast-radius</code> (sample)</td>
<td>Holds a risky shell command (<code>rm -rf</code>, <code>git reset --hard</code>, a force push, a migration), shows what it would change, and waits for Proceed or Cancel.</td>
</tr>
<tr>
<td><strong>While</strong> the agent works</td>
<td>You Should Know (built in, off by default)</td>
<td>Runs a second agent alongside the first, in the changelog's words "a side agent [that] watches your back and flags things you or Claude might miss".</td>
</tr>
<tr>
<td><strong>After</strong> a turn</td>
<td><code>replay-theater</code> (sample)</td>
<td>Steps through the file edits Claude made in the last turn, one diff at a time.</td>
</tr>
<tr>
<td><strong>Whenever</strong> you ask</td>
<td><code>/diff</code> (built in)</td>
<td>Claude Code's own diff pane. It's interesting less for what it does than for the fact that it's now written as a mod, with <a href="https://github.com/anthropics/claude-code/tree/main/mods">public source</a>.</td>
</tr>
</tbody></table>
<p>The samples are in the <a href="https://github.com/anthropics/claude-code-playground/tree/main/claude-code/mods">claude-code-playground repository</a>.</p>
<p>Put them in that order and the pattern is clear. Reviewing an agent's work is moving <em>into</em> the agent: not one pull request at the end, but small checks along the way.</p>
<p>I think that's right, and I also think it has a ceiling. More on that below.</p>
<h2>The experiment</h2>
<p>Reado's loop works like this: you read the code and leave comments on exact lines, some of them marked as tasks, and the agent resolves the tasks. The comments live in the repository, in <code>.reado/</code>, and the <code>reado</code> command-line tool lists them. The agent finds them through Reado's MCP server or the CLI.</p>
<p>What was missing is the other direction. If Claude is in the middle of something else and edits a line you flagged, nothing tells <em>you</em>. Your comment says "keep cents as integers", Claude rewrites the line for a different reason, and you find out when you next read the file. Or you don't.</p>
<p>So the experiment does one thing: when Claude edits a file where you have an open Reado task, a band appears above the prompt with your comment. If the edit replaced the exact text the comment is anchored to, it says so.</p>
<p><img src="https://reado.watermelon-studio.it/blog/claude-code-mods/band.png" alt="The experimental mod's band above Claude Code's prompt: " /></p>
<p>That's a real screenshot, from a session running inside Reado's terminal. Here is the core of the mod, everything except the drawing code:</p>
<pre><code class="language-tsx">async function tasksFor($: EngineInterface, path: string) {
  const cwd = dirOf(path)
  const top = await $.process.run(['git', 'rev-parse', '--show-toplevel'], { cwd })
  if (top.exitCode !== 0) return null
  const root = top.stdout.trim()
  const listed = await $.process.run(['reado', '--json', 'task', 'list'], { cwd: root })
  if (listed.exitCode !== 0) return null
  const rel = path.startsWith(root + '/') ? path.slice(root.length + 1) : path
  const tasks: Task[] = JSON.parse(listed.stdout)
  return { rel, tasks: tasks.filter(t =&gt; t.anchor.file === rel) }
}

export const register: Register = on =&gt; {
  // A new prompt starts a new round: the old notices go.
  on('prompt.submit', async ($, e, next) =&gt; {
    await update($, hits, () =&gt; [])
    return next(e)
  })

  on('tool.call', async ($, e, next) =&gt; {
    if (e.tool !== 'Edit' &amp;&amp; e.tool !== 'Write') return next(e)
    const found = await tasksFor($, e.file_path)
    const ran = await next(e)
    if (!found || found.tasks.length === 0 || ran.deny !== undefined) return ran

    const replaced = e.tool === 'Edit' ? e.old_string : null
    const fresh = found.tasks.map(t =&gt; {
      const snippet = t.context?.snippet?.trim() ?? ''
      return {
        file: found.rel,
        line: t.anchor.startLine,
        body: t.messages[0]?.body ?? '',
        isExact: replaced === null || (snippet !== '' &amp;&amp; replaced.includes(snippet)),
      }
    })
    await update($, hits, list =&gt; [
      ...list.filter(old =&gt; !fresh.some(f =&gt; f.file === old.file &amp;&amp; f.line === old.line)),
      ...fresh,
    ])
    return ran
  })
}
</code></pre>
<p>The band is a <code>ui.render</code> hook on the <code>AbovePrompt</code> site. It returns a small tree of <code>Box</code>, <code>Text</code> and <code>Button</code> elements, which it gets from <code>$.ui.resolve(e)</code> because the elements depend on whether you are in the terminal or the Desktop app. Pressing <em>Got it</em> clears the list.</p>
<h3>Three decisions worth explaining</h3>
<p><strong>It reads the comments through the CLI, not the files.</strong> A mod can read files directly with <code>$.fs.read</code>, and Reado's comments are plain Markdown. But the CLI already knows which comments are open, which are tasks, and what text each one is anchored to. Calling it costs a process per edit. Reimplementing it would cost correctness, and that's the expensive kind.</p>
<p><strong>"Exact" means the replaced text contains the anchored snippet, not that the line numbers match.</strong> Line numbers drift as soon as anything above them changes. Reado stores the text a comment is anchored to, and an <code>Edit</code> call carries the exact text it replaces in <code>old_string</code>. If one contains the other, Claude changed the thing you commented on. It's a plain string check, and unlike a line number it survives everything that happens above the line. A <code>Write</code> replaces the whole file, so every task in it counts as touched.</p>
<p><strong>It doesn't block.</strong> This was the real decision. A <code>tool.call</code> hook can return <code>{ deny: reason }</code>, and refusing any edit to a line with an open task is a one-line change. I didn't make it, because in Reado's loop the edit to a flagged line is very often the <em>fix</em> for that task: you asked for it. A guard there would stop the agent in the middle of doing what you wanted, and push it to explain itself to a hook instead of to you. Blocking would duplicate the job of the task loop. A notice tells you something happened and leaves you to decide whether it matters.</p>
<h3>Testing it</h3>
<p>Mods come with a test runner, <code>claude plugin test</code>, that runs your <code>*.test.ts</code> files against the real engine with nothing beneath your plugin. That turns out to be convenient: the test answers the calls your mod makes. Mine answers <code>process.run</code> with a fake task list, fires an <code>Edit</code>, then mounts the band on both the terminal and Desktop surfaces and checks what it drew:</p>
<pre><code class="language-tsx">on('process.run', async (_$, e) =&gt;
  e.argv[0] === 'git'
    ? { value: { exitCode: 0, stdout: '/repo\n', stderr: '' } }
    : { value: { exitCode: 0, stdout: JSON.stringify([TASK]), stderr: '' } },
)
// ...
const ui = await $.ui.mount({ plugin: 'reado-review', surface, component: 'AbovePrompt', props })
expect(await ui.find({ type: 'Text', text: /changed the line you flagged/ })).toBeDefined()
</code></pre>
<p>The test caught a bug before it ever loaded. I'd named the loop variable <code>h</code>, and JSX in a mod compiles to calls to a global <code>h</code>. The render hook crashed with "h is not a function". Shadowing the JSX factory is not a mistake you make twice.</p>
<h2>Where it stops</h2>
<p><strong>Mods aren't sandboxed.</strong> The docs are clear about it: a mod "is code that runs with your permissions". It can read and write your files, see every prompt, rewrite tool calls, and approve a tool call before you're asked. If you have sandboxing turned on, "a process that a mod starts runs outside it". After <a href="https://reado.watermelon-studio.it/blog/your-agent-ran-git">GitSpawn</a> I'd add that a mod belongs on the same list as <code>.git/config</code> and agent settings: files you'd treat as inert, which are in fact code.</p>
<p>The mitigation is good, and it follows from routing everything through <code>$</code>. Before you install a mod, <code>claude plugin validate</code> reads its source and lists every event it hooks and every call it makes. For mine:</p>
<pre><code class="language-text">hooks: prompt.submit, tool.call, ui.render{component=AbovePrompt}
calls: $.process.run (via tasksFor), $.state.get, $.state.set, $.ui.resolve
</code></pre>
<p>Two lines, and you know this mod runs processes and draws, and doesn't touch the network or the filesystem directly. Read those lines before installing anything.</p>
<p><strong>Drawing is terminal and Desktop only.</strong> In the VS Code extension's chat panel, the hooks run but nothing they draw appears, and the same goes for <code>claude -p</code> and the Agent SDK. A mod that draws should check where it is running and fall back to a plain line in the transcript.</p>
<p><strong>It only sees Claude Code's own edits.</strong> Edits made through <code>sed</code> in a Bash call don't go through the <code>Edit</code> tool, so my mod doesn't notice them. You could match Bash commands too, but guessing which files a shell command touches is exactly the kind of heuristic I don't want in a review tool.</p>
<p><strong>And the bigger limit: a band above a prompt is a notice, not a review.</strong> It tells you <em>that</em> the agent touched the line you cared about. It doesn't show you the line in its file, the function around it, or the three other places that call it. Diff panes, replay theaters and side agents all share that shape: they give you the change, not the code it lands in. That's useful, and it's also why I keep building a separate place to read. A mod like this one can connect the two. It doesn't replace either.</p>
<h2>What would make sense in Reado</h2>
<p>So, after building it: would I put a mod in Reado? Not this one, and not soon. Here's my reasoning.</p>
<p><strong>Reado works with any agent; a mod works with one.</strong> Reado's comments reach the agent through a CLI and an MCP server, which is why the same loop works with Claude Code, Codex, or any agent that can run a command or talk to an MCP server. A mod only runs inside Claude Code. Anything essential to the workflow has to stay in the part every agent can use, or the tool quietly becomes a Claude Code accessory.</p>
<p><strong>This particular notice is nice, not necessary.</strong> It helps if you're watching the terminal while the agent works. But in Reado's workflow you read the change afterwards, in the file, and the comment is right there on the line. The band tells you about something you were going to see anyway.</p>
<p><strong>Where a mod could earn its place is the moment only the agent sees.</strong> A mod is present <em>while</em> the edit happens. It knows which turn made it, what the user had asked, and what Claude said it was doing. By the time you open the file in an editor, all of that is gone, and the diff is just a diff. Reado already lets an agent narrate its reasoning with <code>reado thought</code>, but only when the agent decides to. A mod could capture the "why" of every edit to a flagged line without asking the agent for anything. That is the one idea from this experiment I'd consider building for real, and only if it holds up in daily use, not because mods are new.</p>
<p>The general lesson, for me: put inside the agent what can only be known inside the agent. Do the reading where you can see the whole file.</p>
<h2>Try it</h2>
<p>If you use Claude Code 2.1.287 or later, the fastest way to see what mods can do is the sample <code>blast-radius</code>. Clone the <a href="https://github.com/anthropics/claude-code-playground/tree/main/claude-code/mods">playground repository</a>, run <code>claude plugin validate</code> on the folder to see what it does, then load it for one session with <code>claude --plugin-dir</code>. Or turn on the built-in side agent with <code>/plugin enable cc-plugin-you-should-know@builtin</code>.</p>
<p>If you're curious about Reado's side of the loop (comments on exact lines that your agent resolves, with whatever agent you use), it's <a href="https://reado.watermelon-studio.it">free and open source</a>. And if you write a review mod of your own, I'd like to see it. Tell me in the comments or on <a href="https://discord.gg/HHqT9ucXn4">Discord</a>.</p>
]]></content:encoded></item><item><title><![CDATA[I gave two Claude Code sessions a PM and an engineer job. My job was to watch]]></title><description><![CDATA[Since August, Claude Code sessions can talk to each other. The feature is called cross-session messaging and arrived in v2.1.224: a session finds your…]]></description><link>https://reado.hashnode.dev/i-gave-two-claude-code-sessions-a-pm-and-an-engineer-job-my-job-was-to-watch</link><guid isPermaLink="true">https://reado.hashnode.dev/i-gave-two-claude-code-sessions-a-pm-and-an-engineer-job-my-job-was-to-watch</guid><category><![CDATA[AI]]></category><category><![CDATA[claude-code]]></category><category><![CDATA[code review]]></category><dc:creator><![CDATA[uryon]]></dc:creator><pubDate>Fri, 16 Oct 2026 07:59:35 GMT</pubDate><content:encoded><![CDATA[<p>Since August, Claude Code sessions can talk to each other. The feature is called <a href="https://code.claude.com/docs/en/whats-new/2026-w32">cross-session messaging</a> and arrived in v2.1.224: a session finds your other sessions with <code>ListAgents</code> and sends one of them a message with <code>SendMessage</code>. What travels is only the text Claude writes for the other session, never the conversation history or files.</p>
<p>I've been using it to build rind-ui, a headless UI component library, with two sessions that have different jobs. One is the PM. The other is the engineer. This is how that went, including the parts that didn't work the first time.</p>
<h2>Two sessions, two jobs</h2>
<p>The repository's <code>CLAUDE.md</code> says it plainly: two sessions work on this repo, one writes specs and reviews, one implements.</p>
<p><strong>The PM session</strong> writes each component as a spec (an OpenSpec change: the requirements, the scenarios, the tasks) and validates it before any code exists. When the engineer is done, the PM reviews the result.</p>
<p><strong>The engineer session</strong> takes one spec, implements it, and when it thinks it's finished, sends a message back asking for review. That hand-off lists every file it touched, so the review knows exactly what to look at.</p>
<p>Neither session has the other's context. Each sees the repository and the messages it receives. I think that helps: the reviewer doesn't share the implementer's assumptions, so it reads the code more like the next person would.</p>
<h2>Rules that make it stop</h2>
<p>The first version allowed up to three review rounds per change. It's now down to two, with stricter rules. I see it as the <a href="https://reado.watermelon-studio.it/blog/the-code-review-slot-machine">slot machine</a> problem in miniature: a reviewer asked to find problems will always find one more, so the loop has to be told where to stop. Today the rules are:</p>
<ul>
<li><p><strong>Every finding has a severity.</strong> <em>Critical</em> breaks behaviour, data, security or accessibility. <em>Error</em> violates a requirement of the spec, or is a real bug. <em>Warning</em> is everything else: a weak test, an edge case, polish.</p>
</li>
<li><p><strong>Only critical and error get fixed now.</strong> Warnings go to a backlog file, <code>docs/review-backlog.md</code>, to be picked up later.</p>
</li>
<li><p><strong>Two passes per change, scoped to the change's own diff</strong>, never the whole repository. First a review, whose critical and error findings become tasks. Then, after the fixes, a verification pass that checks those fixes work. Anything new it finds goes to the backlog, unless it's critical for building the rest.</p>
</li>
</ul>
<p>Then the change is approved, archived, and merged. The severity line and the cap on passes are what turned an open-ended loop into one that ends.</p>
<h2>Where the comments live</h2>
<p>This is the part I like most, and the reason I'm writing this on the blog of <a href="https://reado.watermelon-studio.it">Reado, the IDE for reading the code your AI agent writes</a>.</p>
<p>The PM session doesn't write its findings into a chat message. It leaves them as Reado comments, anchored to the exact lines they're about, each one typed (bug, refactor, performance…) and marked as a task. They're Markdown files in <code>.reado/</code> inside the repository, so both sessions read the same list, and so do I.</p>
<p>The engineer fixes each one, and the task is closed with a command that proves the fix: <code>task done</code> with a <code>--verify</code> test command. Usually the engineer runs it; during verification the PM sometimes runs it itself. Reado records the task as done only if that command passes; a fix without a passing check stays visible as unverified until someone looks at it.</p>
<p>So far the PM has left 128 of these tasks: 115 bugs, 5 refactors, 3 performance issues and 5 notes. All 128 are closed, and every one of them was closed by a verify command that passed.</p>
<p>That has a side effect I didn't plan for. When I open the code in Reado, I don't need to reconstruct what the two sessions were arguing about. Each finding sits on the line it's about, with what was wrong, and the test that proved it fixed. It's easier for the session that has to fix the bug, and it's easier for me to see what's happening, where, and how it's being resolved.</p>
<h2>And me?</h2>
<p>Mostly, I watched them work. The two sessions pass the work back and forth on their own: spec, implementation, review, fixes, verification.</p>
<p>My job is the one I wrote about in <a href="https://reado.watermelon-studio.it/blog/what-are-the-humans-for">my last post</a>: deciding what's worth keeping. Each spec ends in a single change, and I review that change before it lands. Not to proofread every line (the sessions already did two passes on the diff), but to judge whether it's what I wanted, and to read the comments that explain why the code looks the way it does.</p>
<h2>One PM, several projects</h2>
<p>The part I didn't expect is how well the PM role scales sideways. The PM doesn't have to stay on one project: it can write three specs for one, move to the next project and write three more there, then switch again. The engineer sessions always have a spec waiting, and several projects move forward at once. The token bill goes up with it, but for the amount of work that gets done, it's a cost I find reasonable.</p>
<p>It works best when the project has clear edges. rind-ui is a good example: a complete headless component library, plus a library that makes it easier to test components built on top of it. The scope is defined, the agent knows what to do, and not many decisions are left open. When one is, the PM doesn't guess: it asks me.</p>
<h2>If you want to try it: watch the tokens</h2>
<p>One warning before you copy this. Two sessions reviewing each other's work produce good results, but they're expensive: every spec gets written, implemented, reviewed, fixed and verified, and each step reads a lot of code. I've run out of tokens more than once doing this.</p>
<p>What I'd do differently from the start: tell both sessions, the PM and the engineer, to use a lighter model such as Sonnet for the less complex parts, and keep the strongest model for the steps that need judgment, like writing the spec and the review itself.</p>
<h2>Where it is now</h2>
<p>Along the way the two sessions became three: a third one joined and built the documentation site. You can see the result at <a href="https://rind.watermelon-studio.it">rind.watermelon-studio.it</a>, with live examples for every component, React for now.</p>
<p>The library is already <a href="https://www.npmjs.com/package/@rind-ui/react">on npm</a>, and it changes every day: new components land as their specs go through the loop, and many more are already specced. If it keeps working the way it has, I'll write the follow-up when there's more to show.</p>
<p>If you want to try the review side of this yourself, the Reado app is free and MIT-licensed: <a href="https://reado.watermelon-studio.it/#download">download it here</a>.</p>
]]></content:encoded></item><item><title><![CDATA[Anthropic merges 30,000 changes a day. So what are the humans for?]]></title><description><![CDATA[On 13 October, Anthropic published how it replaced git for its monorepo. The numbers are the headline: around 2,500 code changes merged per day in May…]]></description><link>https://reado.hashnode.dev/anthropic-merges-30-000-changes-a-day-so-what-are-the-humans-for</link><guid isPermaLink="true">https://reado.hashnode.dev/anthropic-merges-30-000-changes-a-day-so-what-are-the-humans-for</guid><category><![CDATA[code review]]></category><category><![CDATA[claude-code]]></category><category><![CDATA[Artificial Intelligence]]></category><dc:creator><![CDATA[uryon]]></dc:creator><pubDate>Thu, 15 Oct 2026 07:48:09 GMT</pubDate><content:encoded><![CDATA[<p>On 13 October, Anthropic published how it <a href="https://www.anthropic.com/engineering/redesigning-source-control">replaced git for its monorepo</a>. The numbers are the headline: around 2,500 code changes merged per day in May 2026, more than 30,000 per day by September. At that rate git itself became the bottleneck, so a team of seven built a new version control system, Scion, plus a code review tool and half a dozen related systems, and migrated everything in five months.</p>
<p>Most of the reactions I saw took the same turn: if agents merge thirty thousand changes a day, what is left for a person to do? It's a fair question. The post answers it, and the answer isn't "nothing".</p>
<h2>The bottleneck moved</h2>
<p>The post opens with the claim the rest depends on: at Anthropic, writing code is no longer the bottleneck. The infrastructure built for human scale is: source control, builds, CI. Their monorepo's main history is almost 100 GB, they check out code on the order of 25 million times a day for CI, and at their peak they were running several hundred internal git mirrors to keep up.</p>
<p>They're careful to say this is unusual. Scion is "by no means a suitable replacement for git for general use", it only makes sense for enormous monorepos, and Anthropic can spend far more tokens on its own work than any normal company would. Most teams aren't there yet. The authors expect others to start feeling the same pressure within six to twelve months.</p>
<p>So the scale is theirs. The shift underneath it isn't. Producing code got cheap.</p>
<h2>What the engineers did</h2>
<p>The section I'd read twice is the one about people. Everyone who worked on Scion, the post says, now rates Claude as better at writing code than themselves. And yet the engineers supplied the parts that decided whether the system would work: the understanding of how components fit together, the design trade-offs, the choice of which problems to solve and at what scale.</p>
<p>Then the line that sums it up: very often the engineers' role was to tell Claude "no".</p>
<p>The examples are specific. Agents sometimes broke core system constraints to satisfy a pattern that should never have been allowed: some systems tried to find when a change had merged by reading the commit log line by line, instead of asking the code review tool. Their adversarial review, which they use heavily and call effective, could also be myopic: one review was so defensive about trusting another internal service that Claude added validation and complexity nobody needed, and engineers had to steer it away from the extra complexity.</p>
<p>Neither of those is a bug a test would catch. Both are code that works and shouldn't exist.</p>
<h2>Review didn't go away. It changed what it reads.</h2>
<p>The sentence I expected to find, and didn't, was "we stopped reviewing". Instead: the team still reviews every change request to the system, but reviewers now look at the intent of the change rather than reading every line of code.</p>
<p>The tooling is built around the same idea. Their code review tool can express rules about which changes need which approvals, so a comment-only change and a sensitive change to the logic aren't treated alike. The point, in their words, is that human reviewers can focus on the most consequential changes.</p>
<p>Put those together and you get a different job description. The human isn't the one producing the code, and isn't a line-by-line proofreader either. The human decides what the change is <em>for</em>, whether it should exist, and which parts of it carry enough risk to look at closely.</p>
<h2>Writing is cheap. Keeping is expensive.</h2>
<p>That's the answer to "what are the humans for", and I think it holds well below Anthropic's scale.</p>
<p>When an agent can write ten versions of a function in the time it took you to write one, the cost of code isn't in producing it anymore. It's in everything that comes after you keep it: the next person who has to understand it, the constraint it quietly breaks, the complexity it adds that someone will maintain for years. Generating code is cheap. Choosing which code is worth keeping is expensive, because every "yes" is a commitment.</p>
<p>Anthropic's engineers spend their attention on exactly that choice. Not on typing, and not on reading every line, but on saying no to the change that solves the wrong problem, and on finding the few places where a change is consequential enough to look at closely.</p>
<h2>Where Reado fits</h2>
<p>This is the job I'm building <a href="https://reado.watermelon-studio.it">Reado, the IDE for reading the code your AI agent writes</a>, for, at a much smaller scale: one developer, one agent, one repository.</p>
<p>Reado doesn't decide for you which changes matter. It gives that decision a place to live. In a guided review the agent plans a route through the change in the order that makes it make sense, and you leave comments on the exact lines that need a "no" or a question. Each comment is either a task the agent has to resolve or a note for the next reader, and it's stored as Markdown in your repository, so the reason a line looks the way it does outlives the session. When you want the agent to look first, its findings arrive as proposals, and nothing becomes a task until you accept it.</p>
<p>Anthropic built Scion because of the volume. You probably don't have their volume. You do have the same choice to make, every time an agent hands you a diff: is this worth keeping?</p>
<p>The Reado app is free and MIT-licensed if you want to try it: <a href="https://reado.watermelon-studio.it/#download">download it here</a>.</p>
]]></content:encoded></item><item><title><![CDATA[The AI code review slot machine stops when someone decides what counts]]></title><description><![CDATA[On 11 October, Lucas (@lucas_builds) posted a short complaint that was viewed 1.2 million times: Asking Claude to review your code is a slot machine. Every…]]></description><link>https://reado.hashnode.dev/the-ai-code-review-slot-machine-stops-when-someone-decides-what-counts</link><guid isPermaLink="true">https://reado.hashnode.dev/the-ai-code-review-slot-machine-stops-when-someone-decides-what-counts</guid><category><![CDATA[code review]]></category><category><![CDATA[Artificial Intelligence]]></category><category><![CDATA[claude-code]]></category><dc:creator><![CDATA[uryon]]></dc:creator><pubDate>Wed, 14 Oct 2026 08:09:39 GMT</pubDate><content:encoded><![CDATA[<p>On 11 October, Lucas (<a href="https://x.com/lucas_builds/status/2109252687477031014">@lucas_builds</a>) posted a short complaint that was viewed 1.2 million times:</p>
<blockquote>
<p>Asking Claude to review your code is a slot machine.</p>
<p>Every review finds brand new bugs. Review again: more. Review a tenth time: it still finds something.</p>
</blockquote>
<p>It ends with a question: how do you decide your code is actually done?</p>
<p>Lucas later said the Claude Code team replied that fixes are landing, so part of it is a product problem. But the question is the interesting part, because most of the complaint isn't about a bad model. A reviewer asked to "find bugs" will always find something, because there is always something that could be different. A missing edge case, a name that could be clearer, a check that could be stricter. None of that is false. It just never ends.</p>
<h2>The five rules from 920 replies</h2>
<p>The next day Lucas <a href="https://x.com/lucas_builds/status/2109660368037724325">collected the answers</a>. Out of 920 replies, the same five rules kept coming up:</p>
<ol>
<li>Define done before the review: tests pass, spec met.</li>
<li>Only fix critical and high. Everything else goes on a later list.</li>
<li>No failing test, no bug.</li>
<li>Let a different model review than the one that wrote it.</li>
<li>Cap it at 3 rounds.</li>
</ol>
<p>Addy Osmani, <a href="https://x.com/addyosmani/status/2109358790298787931">quoting the original</a> the day before, had already made the same point as the first rule: "Clearly define 'done' before code review starts." Without it, he wrote, a reviewer, human or agent, "may still find something that could be improved". His fix is to give the agent checks it can run (commands, tests, clicking through the app in a browser) and to merge when nothing blocks.</p>
<p>These are good rules. Read them again, though, and most of them are the same rule in different clothes.</p>
<h2>Every rule is a stopping condition</h2>
<p>Rule 1 says what done is. Rule 3 says a finding only counts if a test can show it. Rule 5 stops after three rounds whatever happens. Rule 2 stops at a severity line. Each one draws a line the reviewer can't move.</p>
<p>Rule 4 is the odd one out. A different model catches different things, which is useful, but it doesn't tell either model when to stop. Two slot machines are still slot machines.</p>
<p>What the rules have in common is that the line is drawn <em>before</em> the review, by someone other than the reviewer. That's the whole trick. The review never ends when the thing deciding what counts is also the thing asked to find more.</p>
<h2>Tests draw the line for behavior, not for everything</h2>
<p>"Tests pass, spec met" is the strongest version, and where you can write the test, it's the right one. A failing test is a finding nobody can argue with.</p>
<p>But a lot of what a review catches isn't behavior a test pins down. The retry that will double-charge under a race you didn't think to test. The function that works and that nobody on the team will understand in a month. The new dependency going the wrong way across a boundary. The spec says nothing about those, and a test only exists after someone has noticed the problem.</p>
<p>Rule 2 tries to cover that ground with severity, but look at who assigns it. "Only fix critical and high" usually means the reviewer labels its own findings, and then you act on its labels. The line moved back to the reviewer.</p>
<h2>The line is a reading</h2>
<p>So for the part tests don't cover, someone has to decide what counts, and the only one who can is the person who'll answer for the code. That means reading it. Not every line with the same attention, but enough to say: this, this and this have to change; the rest is fine, or later.</p>
<p>That decision <em>is</em> the definition of done for the round. Written down, it's a short list of comments on exact lines. The agent's job then has an end: resolve those, and nothing else. A second pass checks the list, not the whole file again. When the list is empty, you stop.</p>
<p>This is what I mean by the <a href="https://reado.watermelon-studio.it/blog/the-inverted-code-review">inverted code review</a>: the human reads first and the agent commits. It isn't a rejection of AI review. An agent is very good at proposing findings. It just shouldn't be the one deciding which ones count.</p>
<h2>How Reado holds that line</h2>
<p>I build <a href="https://reado.watermelon-studio.it">Reado</a> around that loop, so here's what it does today, and where it doesn't help.</p>
<p>When you read in Reado, you comment on a line range, and each comment is either a <strong>task</strong> for the agent or a <strong>note</strong> for the next reader. Tasks are the list. <strong>Send review</strong> hands only the open tasks to the agent running in Reado's terminal (Claude Code, Codex, Copilot, Gemini, OpenCode or Cursor). Notes stay out of its way. The agent resolves each task or fails it with a reason. A fix it can't prove with a passing check stays on your list as unverified until you look at it; a failed task goes back to open, and after three failures it stops and waits for you. The list is the stopping condition, and you wrote it.</p>
<p>When you want the agent to look first, the guided review keeps the same split. The agent walks the files in scope and <em>proposes</em> comments: bug, refactor, performance, question, or "needs context" when it can't judge. Nothing it proposes becomes a task until you accept it. A second-opinion pass asks for a challenge of the findings already on the file, looking for false positives and over-statement, and those challenges are proposals too.</p>
<p>That's also where rule 4 fits. Reado's terminal has tabs and side-by-side panes, and you can run a different agent in each one. Reado sends to the one you last clicked, as long as an agent is running in it, and Send review lets you pick the terminal when more than one is open. So you can let Claude Code do the first pass in one, click over to Codex in another, and ask it for the second opinion. Two models, but still one list, and you're the one who accepts what goes on it.</p>
<p>Reado doesn't make the slot machine stop on its own. If you accept everything, it's the same machine with extra clicks. What it changes is where the decision sits: in your list of tasks, on the lines you read, and in your repository as plain Markdown in <code>.reado/</code>, so next week you can still see why the line looks the way it does.</p>
<h2>What I'd take from the thread</h2>
<p>If you want one habit out of those 920 replies, it's Addy's: decide what done means before the review starts. Write the test where you can. Where you can't, read the code and write the list yourself, on the lines that matter, before the agent touches it again.</p>
<p>The agent will always find another bug. You decide which ones are worth fixing, and then you stop pulling the lever.</p>
<p>The Reado app is free and MIT-licensed, if you want to try that loop: <a href="https://reado.watermelon-studio.it/#download">download it here</a>.</p>
]]></content:encoded></item><item><title><![CDATA[Every editor now reviews your agent's code. Where do your comments go?]]></title><description><![CDATA[The big editors all have an agent built in now, and each of them has added a way to look at what the agent did before you keep it. I build Reado, the IDE…]]></description><link>https://reado.hashnode.dev/every-editor-now-reviews-your-agent-s-code-where-do-your-comments-go</link><guid isPermaLink="true">https://reado.hashnode.dev/every-editor-now-reviews-your-agent-s-code-where-do-your-comments-go</guid><category><![CDATA[code review]]></category><category><![CDATA[AI]]></category><dc:creator><![CDATA[uryon]]></dc:creator><pubDate>Tue, 13 Oct 2026 16:20:00 GMT</pubDate><content:encoded><![CDATA[<p>The big editors all have an agent built in now, and each of them has added a way to look at what the agent did before you keep it.</p>
<p>I build <a href="https://reado.watermelon-studio.it">Reado</a>, the IDE for reading the code your agent writes, so I have an obvious interest in this question. That's exactly why I went through each tool's own documentation instead of my memory of it. Everything below links to the vendor's page. The full side-by-side, with every source, is on a <a href="https://reado.watermelon-studio.it/compare">comparison page</a>. It's free and open source, if you want to try it as you read.</p>
<h2>Accepting a diff is the easy part</h2>
<p>All four big editors let you look at the agent's changes and keep or throw them away. They differ in granularity:</p>
<ul>
<li><strong>VS Code</strong> lets you <a href="https://code.visualstudio.com/docs/copilot/chat/review-code-edits">keep or undo each inline change</a> in a local session. Agent Host sessions don't have that per-edit workflow; you mark files as reviewed instead.</li>
<li><strong>Zed</strong> opens a <a href="https://zed.dev/docs/ai/agent-panel">Review Changes</a> tab with every edit, where you accept or reject each hunk or the whole set.</li>
<li><strong>Cursor</strong> shows the agent's edits in a <a href="https://cursor.com/help/ai-features/agent">diff view where you reject what you don't want</a>, with checkpoints to roll back.</li>
<li><strong>JetBrains</strong> lets you open each file <a href="https://www.jetbrains.com/help/ai-assistant/junie-agent.html">Junie</a> modified and roll back per file, or everything at once.</li>
</ul>
<p>That covers the moment the change lands. It doesn't cover what happens when you read it and have something to say.</p>
<h2>The real question is the comment</h2>
<p>When a colleague's pull request has a problem, you don't reject the whole file. You leave a comment on line 42 that says "this will double-charge on retry", and they fix it. With an agent, that comment has to go somewhere the agent can read it, and it has to still mean something after the agent has moved the code around.</p>
<p>Here the editors split.</p>
<p><strong>VS Code</strong> has it in the Agents window: select a range in a changed file, choose <a href="https://code.visualstudio.com/docs/copilot/chat/review-code-edits">Add Feedback</a>, and "the agent reads your comments, makes the requested edits, and resolves each comment". Resolved comments disappear from the diff. Since <a href="https://code.visualstudio.com/updates/v1_126">1.126</a>, in June, they're stored on the agent host, so they survive the client disconnecting. They live with the agent, though, not in your repository.</p>
<p><strong>Zed's</strong> editor docs don't describe line comments for the agent. Zed is building them in <a href="https://zed.dev/blog/introducing-delta">Delta</a>, a separate product in private beta, where you can comment on any line of the worktree and the comment stays "anchored to the code as it evolves".</p>
<p><strong>Cursor</strong> has <a href="https://cursor.com/docs/agent/review">Agent Review</a> to find issues in your local changes, and <a href="https://cursor.com/docs/bugbot">Bugbot</a> for pull requests, whose findings can be handed to a cloud agent to fix. Line comments you write yourself for the local agent aren't in the docs.</p>
<p><strong>JetBrains'</strong> Junie docs don't mention line comments at all.</p>
<p>So in the editors, line comments you write for the agent to resolve exist in one shipped place (VS Code) and one beta (Zed Delta). Cursor's Bugbot findings can be fixed by an agent too, but those are the reviewer's comments on a pull request, not yours.</p>
<h2>The tools built for review</h2>
<p>A second group of tools isn't trying to be your editor. They exist for this exact step.</p>
<ul>
<li><strong><a href="https://www.onorca.dev/docs/review/annotate-ai-diff">Orca</a></strong> runs several CLI agents side by side, each in its own worktree. You comment on lines of the diff and "Send to agent" turns them into one prompt; comments "follow the line if the diff shifts". It's <a href="https://github.com/stablyai/orca">open source under MIT</a>, and runs on macOS, Windows and Linux. Of everything here, it's the closest to Reado.</li>
<li><strong><a href="https://docs.warp.dev/agent-platform/warp-agents/interactive-code-review">Warp</a></strong> has an interactive code review panel in the terminal: comments anchored to file and line, sent to the agent in one batch, for Warp's agent or Claude Code, Codex and others running in it. Whether comments survive edits isn't documented.</li>
<li><strong><a href="https://apps.mergeable.io/diffsmith/">Diffsmith</a></strong> is a native Mac app for local changes. The agent can read your comments through a local MCP server, and "comments whose code has changed move to Past Comments rather than vanishing".</li>
<li><strong>GitHub</strong> lets you <a href="https://docs.github.com/en/copilot/how-tos/use-copilot-agents/cloud-agent/make-changes-to-an-existing-pr">delegate review comments on a pull request</a>, one or a batch, to the Copilot cloud agent. That works at the pull request, after the push, not on your machine before it.</li>
</ul>
<h2>Where the comment lives decides what it's for</h2>
<p>Line them up and the pattern is that every tool has an answer for <em>sending</em> a comment to the agent. The answers differ on what the comment <em>is</em> afterwards:</p>
<ul>
<li>stored with the agent, and gone from the diff once resolved (VS Code),</li>
<li>sent to the agent in a batch, with nothing documented about what happens to it next (Warp),</li>
<li>following its line while you review in the app, with unresolved ones carried into the next batch (Orca),</li>
<li>moved to Past Comments when the code under it changes (Diffsmith),</li>
<li>a conversation on the pull request (GitHub).</li>
</ul>
<p>If you only ever need the agent to fix the thing, any of these works. If you want to come back next week and see why line 42 looks the way it does, or hand the file to someone who wasn't there, the comment has to outlive the session.</p>
<p>That's the bet Reado makes, and the part I'll describe as it is today. Reado comments are typed (bug, question, note…), threaded, and either a task for the agent or a note for the next reader. They're Markdown files in <code>.reado/</code> inside your repository, they re-anchor when the code moves, and they turn orphan instead of pointing at the wrong line when the code is gone. "Send review" hands the open tasks to Claude Code, Codex, Copilot, Gemini, OpenCode or Cursor in Reado's terminal. It's MIT and free to use, with an optional paid Pro plan for teams coming later.</p>
<h2>What I'd actually use</h2>
<p>Reado isn't only the place you read. It's a full IDE: an editor with language servers (completion, go-to-definition, rename, code actions, formatting), a terminal, Git, and the agent you already run. So my honest answer is one tool for most of the day, with a few exceptions:</p>
<ul>
<li><strong>To write with an agent and read what it wrote, in one place:</strong> Reado. Of everything here, it's the only one whose docs say your comments both stay in your repository and follow the code.</li>
<li><strong>If your day is mostly debugging or a specific extension:</strong> VS Code and JetBrains have large <a href="https://marketplace.visualstudio.com/vscode">extension</a> <a href="https://plugins.jetbrains.com/">marketplaces</a>, and they and Zed ship a debugger. Reado has no debugger, and installs only data extensions (themes, icons, snippets, grammars) from Open VSX, so keep that editor for those jobs.</li>
<li><strong>To run many agents in parallel:</strong> Orca is designed for that.</li>
<li><strong>For an AI reviewer on every pull request:</strong> <a href="https://docs.github.com/en/copilot/concepts/agents/code-review">GitHub Copilot code review</a> or <a href="https://cursor.com/docs/bugbot">Cursor's Bugbot</a>, which run on the pull request itself.</li>
</ul>
<p>The side-by-side table is on the <a href="https://reado.watermelon-studio.it/compare">comparison page</a>.</p>
<p>These products change fast, and I checked all of this on 13 October 2026. The <a href="https://reado.watermelon-studio.it/compare">comparison page</a> lists every source; if something there is already out of date, tell me and I'll fix it.</p>
]]></content:encoded></item><item><title><![CDATA[Your agent ran git. So did the repo]]></title><description><![CDATA[On October 2, Manifold Security published GitSpawn, and it is the kind of bug that is obvious the second you see it and invisible until then. Coding agents…]]></description><link>https://reado.hashnode.dev/your-agent-ran-git-so-did-the-repo</link><guid isPermaLink="true">https://reado.hashnode.dev/your-agent-ran-git-so-did-the-repo</guid><category><![CDATA[Security]]></category><category><![CDATA[Git]]></category><category><![CDATA[ai agents]]></category><dc:creator><![CDATA[uryon]]></dc:creator><pubDate>Tue, 13 Oct 2026 07:55:37 GMT</pubDate><content:encoded><![CDATA[<p>On October 2, Manifold Security published <a href="https://www.manifold.security/blog/ai-coding-agents-git-hijack">GitSpawn</a>, and it is the kind of bug that is obvious the second you see it and invisible until then.</p>
<p>Coding agents call git all the time. Not when you ask them to commit: in the background, to gather context. What changed, what branch you are on, what the diff looks like. And git reads its settings from the repository's own <code>.git/config</code>. Some of those settings name a program to run. The one Manifold used is <code>core.fsmonitor</code>, a hook git calls to ask "which files changed?" whenever it refreshes the index. So a repository can ship this:</p>
<pre><code class="language-ini">[core]
    fsmonitor = &lt;any command&gt;
</code></pre>
<p>and the command runs, in the researchers' words, "as you, with your privileges, on your machine". Because it is the agent's own code spawning git, not the model asking for a tool call, it runs "outside the sandbox, without an approval prompt."</p>
<h2>Who was affected</h2>
<p>Manifold reported it to eight products between June and July. At publication, this was the state of things:</p>
<table>
<thead>
<tr>
<th>Agent</th>
<th>Status at publication</th>
</tr>
</thead>
<tbody><tr>
<td>Claude Code (<code>core.fsmonitor</code>)</td>
<td>patched in 2.1.196</td>
</tr>
<tr>
<td>Claude Code (ultrareview)</td>
<td>unpatched, 2.1.252</td>
</tr>
<tr>
<td>Goose</td>
<td>patched in 1.44.0 (CVE-2026-72718)</td>
</tr>
<tr>
<td>Cursor</td>
<td>patched</td>
</tr>
<tr>
<td>OpenAI Codex</td>
<td>patched</td>
</tr>
<tr>
<td>Hermes Agent</td>
<td>unpatched, 0.21.0 (CVE-2026-71963)</td>
</tr>
<tr>
<td>Qwen Code</td>
<td>unpatched, 0.22.3</td>
</tr>
<tr>
<td>Grok Build</td>
<td>unpatched, 1.0.13</td>
</tr>
</tbody></table>
<p>There is one important limit. A <code>git clone</code> never carries <code>.git/config</code>, so the repository has to reach you as files: a zip from a client, a folder on a shared drive, a USB stick, an archive attached to a bug report. That sounds niche until you count how often "can you take a look at this?" arrives as a zip.</p>
<h2>The sandbox was never the boundary</h2>
<p>The interesting part isn't the specific key. It's where the line got drawn.</p>
<p>Agent vendors spent the last year building careful boundaries around what the <em>model</em> can do: sandboxed shells, approval prompts, allow-lists of commands. All of that is aimed at the model's tool calls. GitSpawn goes around it entirely, because the dangerous call isn't the model's. It's the product's own plumbing, the background <code>git status</code> nobody thinks of as an action at all.</p>
<p>And <code>core.fsmonitor</code> isn't alone. Git has a handful of settings that name programs, and some of them run during ordinary read-only commands. Clean and smudge filters, for example, are configured in <code>.git/config</code> and switched on per file by <code>.gitattributes</code>, and git can run them during a plain <code>status</code>. Every one of these is a line in a config file that turns "read the repository" into "run the repository".</p>
<h2>I checked my own IDE</h2>
<p>I build <a href="https://reado.watermelon-studio.it">Reado</a>, an IDE for reading the code your agent writes. It is not an agent, so I read the GitSpawn post thinking it was about other people's products.</p>
<p>Then I remembered what Reado does the moment you open a folder: it shows the git status in the file tree, the diff in the gutter, blame on the current line. That's three background git calls, from the app's own code, before you have read a single line. Exactly the shape Manifold described.</p>
<p>So I wrote the test: a repository with <code>core.fsmonitor</code> set to a command that drops a marker file, opened the way Reado opens it. Stock git ran the command. Reado's git calls ran it too.</p>
<p>The fix is the one Manifold recommends for vendors, <code>git -c core.fsmonitor=false …</code>, applied in the one place every git call in Reado is built, with the test kept so it stays fixed. It ships in Reado 1.33.2. The filter and diff drivers are next: closing those needs a trust question the first time a folder is opened, not just a flag.</p>
<p>I'm not telling this to look good. It took me about ten minutes to find, and the only reason I looked was that someone else had published the pattern. Which is the point: this class of bug lives in the parts of a tool nobody reads, because they "just call git".</p>
<h2>What to do this week</h2>
<p>From the advisory, and from fixing it once:</p>
<ul>
<li><strong>Check <code>.git/config</code> before you open a folder you received as files.</strong> Manifold's advice is blunt: "Any setting that names a program can run it." <code>fsmonitor</code>, <code>hooksPath</code>, <code>sshCommand</code>, anything under <code>filter.</code> or <code>diff.</code> that names a command.</li>
<li><strong>Open untrusted repositories in a throwaway container or VM,</strong> not in the same session that has your SSH keys and cloud credentials.</li>
<li><strong>Update your agent,</strong> and if you use one of the unpatched ones, don't point it at code you didn't clone yourself.</li>
<li><strong>If you build tools that call git,</strong> do what we did: one place where git commands are built, the hardening flags in it, and a test with a malicious repository so it stays fixed.</li>
</ul>
<p>The broader lesson for anyone working with agents: the risky surface is no longer just the code the agent writes. It is everything around it that we used to treat as inert: config files, hooks, attributes, the agent's own settings. Those deserve the same slow read as a build script, because that's what they are.</p>
<p>If you have found other "inert" files that turn out to run things, I'd like to hear about it in the comments or on <a href="https://discord.gg/HHqT9ucXn4">Discord</a>.</p>
<p><em>Originally published on <a href="https://reado.watermelon-studio.it/blog/your-agent-ran-git">reado.watermelon-studio.it</a>.</em></p>
]]></content:encoded></item><item><title><![CDATA[AI review benchmarks score the bot. Nobody scores the reader]]></title><description><![CDATA[This week GitHub published ReviewBench, an open benchmark for AI code reviewers. It is careful work: 219 pull requests from 187 open-source repositories…]]></description><link>https://reado.hashnode.dev/ai-review-benchmarks-score-the-bot-nobody-scores-the-reader</link><guid isPermaLink="true">https://reado.hashnode.dev/ai-review-benchmarks-score-the-bot-nobody-scores-the-reader</guid><category><![CDATA[AI]]></category><dc:creator><![CDATA[uryon]]></dc:creator><pubDate>Fri, 09 Oct 2026 08:26:06 GMT</pubDate><content:encoded><![CDATA[<p>This week GitHub published <a href="https://github.blog/ai-and-ml/github-copilot/reviewbench-an-open-benchmark-for-ai-code-review/">ReviewBench</a>, an open benchmark for AI code reviewers. It is careful work: 219 pull requests from 187 open-source repositories across 19 languages, picked so their size matches what actually gets reviewed on GitHub, based on an analysis of 103.9 million pull requests. The ground truth comes from human reviewers, from bugs that authors fixed in later commits, from static analysis and from several frontier models, and senior engineers who didn't build the dataset re-labelled every finding, agreeing with it 96.6% of the time.</p>
<p>You get precision, recall and F1, so you can say "this reviewer finds 40% of the real issues and half of what it says is noise." That is a real improvement on vibes.</p>
<p>But read what the benchmark is measuring: the bot. How many true issues it catches, how many false ones it raises. It cannot measure the other half of every review, which is a person reading the finding and deciding whether it is right. That half is where review time goes now.</p>
<h2>The code got cheap. Checking it didn't</h2>
<p>Anthropic's own research puts the gap plainly: developers use AI in roughly 60% of their work, but say they can "fully delegate" only 0–20% of tasks (<a href="https://rits.shanghai.nyu.edu/ai/anthropics-2026-agentic-coding-trends-report-from-assistants-to-agent-teams/">summary of Anthropic's 2026 Agentic Coding Trends Report</a>). Everything between those two numbers is work an agent did and a human still has to look at.</p>
<p>And there is a lot more of it. At the AI Engineer World's Fair, Sourcegraph's CEO described agents producing a "tidal wave of code" that wears down old codebases with duplicated helpers, inconsistent standards and fragile dependencies (<a href="https://artificiallyintimidating.com/p/ai-brief-october-5-2026">recap</a>). GitHub's own guide to <a href="https://github.blog/ai-and-ml/generative-ai/agent-pull-requests-are-everywhere-heres-how-to-review-them/">reviewing agent pull requests</a> reads like a list of things a person has to go and look at: tests that quietly disappeared, utilities duplicated because the agent didn't find the existing one, a permission check on the path that matters, traced from input to output.</p>
<p>None of that is a syntax error a bot can flag. It is reading.</p>
<h2>A finding is a bill, not a gift</h2>
<p>Every comment an AI reviewer leaves comes with a cost attached: someone has to open the file, find the place, understand enough of the code around it to judge the claim, and then decide. A precise comment on three lines can be settled in seconds. A vague one ("this function may not handle all edge cases") costs a re-read of the whole file, and is often right in a way that doesn't help.</p>
<p>Two reviewers with the same F1 can cost a team very different amounts of attention. One leaves eight sharp comments, each pinned to the line that matters. The other leaves the same eight insights spread over twenty comments, half of them pointing at the wrong line after the next commit moved things around. The benchmark scores them the same. The person reading them doesn't.</p>
<p>GitHub seems to know this. The ReviewBench post says the useful distinction "is not simply how many comments a tool produces", and they let you tilt the score towards precision. That's the right instinct. It still stops at the bot's output, because the human side is hard to put in a dataset.</p>
<h2>What would scoring the reader look like?</h2>
<p>I don't think it needs a benchmark. It needs us to treat reading as the main job instead of the cleanup after the real job:</p>
<ul>
<li><strong>Time to verify, per finding.</strong> Not how many issues were found, but how long it took a person to confirm or dismiss each one. That number punishes vague comments the way they deserve.</li>
<li><strong>Findings that survive the next commit.</strong> A comment that pointed at line 212 and now points at an unrelated line is worse than no comment. Anchors should move with the code, or say they lost their place.</li>
<li><strong>What the human actually read.</strong> "Approved" says nothing about whether the risky file was opened. Coverage of the reading, not just of the tests.</li>
<li><strong>Human notes as first-class input.</strong> The reviewer who spots the wrong thing on line 212 should be able to point at it as precisely as the bot does, and hand it back to the agent without describing a location in prose.</li>
</ul>
<h2>Where this is going for me</h2>
<p>I build <a href="https://reado.watermelon-studio.it">Reado</a>, an IDE for that half of the job, so take this with the obvious bias. Reado is built around the reader: you read the code your agent wrote, leave comments on the exact lines, and the agent resolves them. Comments re-anchor when the code moves, and orphan themselves when it is gone. Reado tracks what you have actually read and what changed since. In a guided review the agent can propose findings, but they land on the line as proposals until you accept them.</p>
<p>I'm not arguing against AI reviewers. Let them do the mechanical pass first, as GitHub recommends. I'm arguing that the bottleneck has moved, and our tools and our metrics haven't followed it yet. We're getting very good at scoring the bot. The scarce resource is still the person who has to read.</p>
<p>If you review agent code every day, I'd like to hear how you keep up. Tell me in the comments below, or on <a href="https://discord.gg/HHqT9ucXn4">Discord</a>.</p>
<p><em>Originally published on <a href="https://reado.watermelon-studio.it/blog/who-scores-the-reader">reado.watermelon-studio.it</a>.</em></p>
]]></content:encoded></item><item><title><![CDATA[My agent writes the code now. I built an IDE for the part that's left: reading it]]></title><description><![CDATA[A year ago most of my day was typing code. Today Claude Code types most of it, and my day is something else: reading what it wrote and deciding whether it…]]></description><link>https://reado.hashnode.dev/my-agent-writes-the-code-now-i-built-an-ide-for-the-part-that-s-left-reading-it</link><guid isPermaLink="true">https://reado.hashnode.dev/my-agent-writes-the-code-now-i-built-an-ide-for-the-part-that-s-left-reading-it</guid><category><![CDATA[AI]]></category><category><![CDATA[Programming Blogs]]></category><category><![CDATA[claude-code]]></category><category><![CDATA[Open Source]]></category><category><![CDATA[code review]]></category><dc:creator><![CDATA[uryon]]></dc:creator><pubDate>Thu, 08 Oct 2026 14:27:13 GMT</pubDate><content:encoded><![CDATA[<p>A year ago most of my day was typing code. Today Claude Code types most of it, and my day is something else: reading what it wrote and deciding whether it stays.</p>
<p>The tools didn't follow. Every editor I use is built around the cursor and the keyboard. And the way I talked to the agent about its code was worse: I'd spot something on line 212, switch to the terminal and type "in auth.ts, around the token refresh, the retry doesn't…", describing a location in prose to a machine that could have just been pointed at it.</p>
<p>So I built <a href="https://github.com/WatermelonBros/reado">Reado</a>: a desktop IDE where the main thing you do is read, and the main action is leaving a comment on the exact lines that matter. Your agent resolves the comments. I call it <strong>inverted code review: you are the reviewer, the AI is the committer.</strong></p>
<p><img src="https://reado.watermelon-studio.it/blog/reado-tour.gif" alt="A guided review in Reado: the agent plans a route, proposes a bug, you approve it and comment by hand, and the agent resolves the tasks" /></p>
<h2>The loop</h2>
<ol>
<li><strong>Read</strong>, in a viewer tuned for reading, which tracks what you've actually read and what changed since.</li>
<li><strong>Annotate</strong>: select lines, leave a typed comment (bug, refactor, question…), either a task for the agent or a note for the next human.</li>
<li><strong>Send review</strong>: Claude Code, Codex, Copilot, Gemini or OpenCode runs in Reado's terminal; one click hands it your open tasks.</li>
<li><strong>Watch it resolve them live</strong>, then jump to what changed since you last read it.</li>
</ol>
<h2>What I learned building it</h2>
<p><strong>Comments have to survive edits.</strong> When the agent rewrites a function, a comment pinned to "line 212" is now lying. Reado re-anchors comments when the code moves, and one whose code is gone becomes an orphan instead of pointing at the wrong line. Comments are plain Markdown in a <code>.reado/</code> folder in your repo.</p>
<p><strong>Give the agent a contract, not a prompt.</strong> A small <code>reado</code> binary serves an MCP server and a CLI, so the agent reads the tasks and marks them done itself (<code>reado task done &lt;id&gt;</code>). The UI just watches the files.</p>
<p><strong>Let the agent propose, never decide.</strong> In a guided review the agent plans a route through a branch, riskiest files first, and its findings land on the line as proposals. Nothing is final until I approve it. That one rule is what made me trust it on real work.</p>
<h2>Try it, and get Pro free</h2>
<p>Reado is MIT, local-first, and runs on macOS, Linux and Windows. No account needed for the core loop: <a href="https://github.com/WatermelonBros/reado/releases/latest">download it here</a>.</p>
<p>I'm looking for <strong>50 developers who already work with a coding agent</strong> to use it on real code and tell me what breaks. The first 50 who send feedback get <strong>Reado Pro free for 12 months</strong>: <a href="https://reado.watermelon-studio.it/beta">reado.watermelon-studio.it/beta</a>.</p>
<p>Questions, or something broke? Come say hi on <a href="https://discord.gg/HHqT9ucXn4">Discord</a>: I'm the developer and I read everything.</p>
]]></content:encoded></item></channel></rss>