Pairing with an AI agent

In this tutorial you share a playground with an AI agent, so that the agent and you work on the same live page. You open a small page, let the agent edit it, have it read the console and a screenshot, leave it a pin with a comment, and let it run code in the playground. It takes about 20 minutes.

Prerequisites:

  • Chrome or Edge on a desktop computer. Agent πŸ“‚ Shareβ„’ is not available in other browsers, or in an embedded playground.
  • An AI coding agent that you can start in a terminal, such as Claude Code or Codex, or any agent that reads AGENTS.md or CLAUDE.md, with your own subscription.
  • A folder on your computer to hold the shared work. A new folder named RTCode in your home folder works well. You pick it in step 2.

Step 1: Open the starter page

The page below has a heading, a green badge, a list and a script that writes a line to the console. Its <style o:=.css> element is an exported file, which you will meet again in step 3. Select Open in RTCode.io to open the page in a tab of its own.

html
<style o:=.css>
  :root    { color-scheme: light dark; }
  main     { display: grid; gap: 1rem; padding: 1rem; }
  #badge   { justify-self: start; padding: .25rem .6rem; border-radius: 1rem; background: oklch(.75 .15 150); }
</style>
<main>
  <h1>Pairing demo</h1>
  <span id=badge>new</span>
  <ul id=list><li>One<li>Two<li>Three</ul>
</main>
<script>
  console.log('page ready', document.querySelectorAll('#list li').length)
</script>

You should see: the heading Pairing demo, a green pill that reads new and a list of three items in the output, and the same code in the input.

Step 2: Share a folder

Press Alt+A / βŒ₯+A, or choose Share in the Agent section of the Code menu. The Code menu is the logo button at the far left. The first time, the browser's folder picker opens. Choose or create your RTCode folder, and allow the browser to edit files in it. This folder is the root. You pick it once, and the browser remembers it.

The playground now creates the work folder inside the root. A playground without a route shares into a folder named Unrouted. Open a terminal there and look at what the share wrote:

plain
cd ~/RTCode/Unrouted
ls -A

You should see: a toast with the Root β†’ Work tree, an amber folder badge on the Playground menu button, and the tab icon A__. Chromium also shows the notice Folder sharing is active. The address bar is paused; reloads and deployments stay up to date. In the terminal, ls -A lists .agents, .claude, .css, AGENTS.md, CLAUDE.md, πŸ“„.html, πŸ“„.sel, πŸ“œ.json and πŸ“œ.json.crswap.

Note: If the share asks Another window is already sharing this route. Unshare it and try again?, choose Unshare & Retry. To share a second unrouted playground at the same time, Alt+click Share in its menu. Keys such as Alt+A do nothing while the output has focus, so click the editor first. See Agent πŸ“‚ Shareβ„’.

Step 3: Let the agent edit the page

Start your agent in the work folder. AGENTS.md is for Codex and other agents that read AGENTS.md, and CLAUDE.md is for Claude Code. They are identical copies of the current RTCode.io agent guide, which describes the files that the share creates. If your agent does not read the guide by itself, tell it to. Then give it a task:

plain
Read CLAUDE.md first. Then add a fourth item, Four, to the list in πŸ“„.html and make the heading dark green in .css. Do not touch anything else.

Name AGENTS.md instead of CLAUDE.md in the prompt if your agent reads that file. The agent edits πŸ“„.html for the list. For the heading it can edit .css, which is the <style> element as a separate file. File Sync keeps both files and the editor in sync, so the agent can make a focused change without rewriting the page. See File Sync.

You should see: the fourth list item and the dark green heading in the output, with no reload, and the same edits in the editor. Each file that the playground reads from the folder shows a green toast with its name. Each import is one undo step in the editor.

Note: If you type into the editor while the agent edits the same text, a Files differ dialog asks which side wins. Compare opens a read-only diff of the disk and playground versions. See Conflicts.

Step 4: Read the console

The starter page logs a line when it runs. Press F5: this forces a full refresh of the output from the input, so the script runs again. Then ask the agent what the console says. It reads the console file like this:

plain
cat πŸ“œ.json*

The pattern πŸ“œ.json* matters. While you share, Chromium keeps the live console data in the swap file πŸ“œ.json.crswap, and πŸ“œ.json itself stays empty until you unshare. Every console call from the output is one JSON line, { "<method>": [ …arguments ] }.

You should see: a line like {"log":["page ready",4]}. The second value is the number of list items, so it is 4 after the agent's edit. See Agent files for the whole format.

Step 5: Show the agent a screenshot

An agent can look at the output through πŸ“Έ.png, which exists while a screen capture runs. Click the editor, then press Ctrl+Alt+Shift+C / ⌘+βŒ₯+⇧+C (Capture (output)). In the browser's dialog, choose this tab. Then ask your agent:

plain
Look at πŸ“Έ.png and tell me what color the heading is.

The playground refreshes πŸ“Έ.png after edits that reach the output, after evals and when the output scrolls. An agent that wants a fresh picture can delete the file, and the playground takes a new one. Next time, Ctrl+Alt+A / ⌘+βŒ₯+A (Share + πŸ”΄ Output…) shares and captures in one step. See Screen capture.

You should see: the file πŸ“Έ.png in the work folder, and the tab icon AO_: sharing, Output capture, no pins yet. The agent describes the heading from the image.

Step 6: Leave a pin for the agent

A pin points at a part of the output and carries a comment. Press Ctrl+P / ⌘+P. The Pins panel opens at the bottom right and picking starts. Click the green badge in the output. The comment field in the new row of the panel has the focus, so type Make this pill smaller. To stop picking, click ⏸️ in the panel header, or press Ctrl+Alt+Shift+P / ⌘+βŒ₯+⇧+P. Then ask your agent:

plain
Read the pin files in this folder and do what the comment asks.

The agent reads πŸ“.0.json. Because the Output capture from step 5 runs, there is also πŸ“.0.png, a crop of the badge. This is the file, abridged:

plain
{
  "version": 1,
  "type": "rtcode.pin",
  "id": "pin_mutrqtc0_a1b2c3",
  "image": { "file": "πŸ“.0.png", "capture": { … } },
  "pin": {
    "kind": "element",
    "selector": "span#badge",
    "comment": "Make this pill smaller",
    "outerHTML": "<span id=\"badge\">new</span>",
    "linked": true
  }
}

The pin is linked to the badge, so its mark follows the element when the page changes. Edits to the pin files have no effect while the share runs: pins change through code, as step 7 shows. See Pins and comments.

You should see: a mark over the badge, your comment in the panel, and the files πŸ“.0.json and πŸ“.0.png in the folder. When the agent has changed .css, the badge in the output is smaller.

Step 7: Run code in the playground

Agents control the playground by writing JavaScript to a request file and reading a result file. io.eval.js runs in the playground, and o.eval.js runs in the output. Ask your agent:

plain
Use io.eval.js to tell me which routes this playground has, and use o.eval.js to list the headings in the output.

The agent should write a request in one piece, wait until the request file disappears, which means that the playground accepted it, and then read the result. This is what that looks like in a shell:

plain
printf '%s' 'Code.D' > io.eval.tmp && mv io.eval.tmp io.eval.js
while [ -e io.eval.js ]; do sleep 0.05; done
until [ -e io.eval.json ] && [ ! -e io.eval.json.crswap ]; do sleep 0.05; done
cat io.eval.json

For the output, the request is JavaScript that returns plain data. This one lists the headings with their boxes:

js
[...document.querySelectorAll('h1, h2')].map(h => ({ tag: h.localName, text: h.textContent.trim(), box: h.getBoundingClientRect().toJSON() }))

Evals can also answer your pin. This request replaces the pin's comment with a reply, hands the output back to you, and returns a short summary:

js
await o.pins.setComment('Done: the badge is smaller now.', 0);
await o.pins.pause();
o.pins.map(p => `${p.index} ${p.kind} ${p.label}: ${p.comment}`)

Pin calls open the Pins panel and turn picking on, so pause() gives the output back to you. Write one request at a time, and wait for its result before the next. See File evals.

You should see: an empty list, [], in io.eval.json for the first request, if this playground has no route. The headings of the output, Pairing demo, in o.eval.json. After the last request, the comment in the pin's row has changed, and the result is a list with one line, 0 element new: Done: the badge is smaller now. The pin's label, new, is the badge's text.

Step 8: End the share

First stop the screen capture that you started in step 5, with πŸ”΄ ⏹️ Capture: Stop from the command palette (F1) or the Capture section of the Code menu. Stopping a capture deletes the pin images, πŸ“.0.png, and rewrites the pin JSON files without image references. Then choose Unshare in the Agent section of the Code menu, or run ✨ Agent: πŸ—‚οΈ Unshare. Unshare leaves the other files in the folder and closes the console writer, which commits πŸ“œ.json. It stops a screen capture too, but only one that the share itself started.

plain
cat πŸ“œ.json

You should see: a toast with Root ← Work, no folder badge on the Playground button, and the address bar updating again. πŸ“œ.json now holds the console lines. Your files, including AGENTS.md and CLAUDE.md, stay in the work folder.

Summary

Next steps

Agent πŸ“‚ Shareβ„’

Auto-Share, Share ← Folder, Explore, reload recovery and the cautions.

Agent files

Every file in the work folder, who writes it and its format.

File Sync

File names, content, conflicts and the Files differ dialog.

File evals

The request and result protocol, return values, timeouts and the diagnostics command.

Pins and comments

Picking, marks, the panel, image options and o.pins.

Screen capture

Capture kinds, screenshots, video and picture-in-picture.

Deploying

Publish your page, which an agent can also do with edge.save.limit().

See also