Agent editing

Let a program edit your file

Your file is open in a tab. You type "add everything I need for a beach trip" into a box on the page and press Send. A program in your own terminal wakes up, edits the file, and the new lines appear in front of you, already saved.

camping.htmlclay Download

Trip list

  • Tent
  • Sleeping bag
  • Headlamp
  • Firewood
  • Rain jacket
  • Coffee and the little pot
  • Water filter

Terminal
[wire] attached as handler to http://127.0.0.1:52341 (/Users/you/Desktop/camping.htmlclay)

That is the whole loop. This one is a demonstration; the download in the corner is the real file, and the rest of the page attaches a program to it.

No copying out of a chat window and pasting back in. No service in the middle. The program runs on your computer, as you, and the file on your disk is the only thing the two sides share.

Usually that program is an AI agent. It can just as easily be a formatter, a script you wrote, or five lines of shell. This page sets it up both ways: first with a robot that cannot fail, so you can watch the whole loop with nothing clever in it, then with an AI.

Before you start

The commands below are written for a Mac and use nothing beyond what macOS already ships with. On Linux everything is identical except one line you get to skip, noted where it appears. Windows is covered at the bottom.

1 A page with an ask box

Save this as robot-notes.htmlclay, the same way you saved your first file: any plain text editor, plain text mode, keep the .htmlclay ending. Put it on your Desktop.

robot-notes.htmlclay
<!DOCTYPE html>
<html lang="en" autosave>
<head>
  <meta charset="utf-8">
  <title>Robot notes</title>
  <style>
    body {
      font-family: system-ui, sans-serif;
      max-width: 30rem;
      margin: 3rem auto;
      padding: 0 1rem;
    }
    form { display: flex; gap: 0.5rem; }
    input { flex: 1; font: inherit; padding: 0.4rem 0.6rem; }
    button { font: inherit; padding: 0.4rem 0.9rem; }
  </style>
</head>
<body>
  <h1 editable>Robot notes</h1>

  <form id="ask">
    <input id="said" placeholder="Ask for a change" autocomplete="off">
    <button>Send</button>
  </form>

  <ul id="log">
    <li>Lines the robot adds will show up here.</li>
  </ul>

  <div id="notes" editable>
    <p>This part is yours. Click and type.</p>
  </div>

  <script src="https://clayjs.com/clay.js?plugins=sync,wire"></script>
  <script>
    clay.ready.then(function () {
      var ask = document.getElementById("ask");
      var box = document.getElementById("said");

      // Built here, never typed into the file: everything you can see
      // in the page is what gets saved.
      var status = document.createElement("p");
      status.setAttribute("clay", "no-save no-snapshot no-watch");
      ask.after(status);

      clay.wire.on(function (request) {
        status.textContent = request.error
          || request.text
          || request.state;
      });

      ask.addEventListener("submit", function (event) {
        event.preventDefault();
        var words = box.value.trim();
        if (!words) return;
        box.value = "";
        status.textContent = "sent";
        clay.wire.send({ said: words }, { text: words });
      });
    });
  </script>
</body>
</html>

You do not have to read it. If you do, three lines are carrying the page.

Double-click the file now so it is open in a tab. Press Send if you like: a moment later the status reports that nothing is attached, which is the honest answer rather than a spinner that never stops.

2 The robot

A robot here is just a program. Any program. HTML Clay runs it once each time the page asks for something, and three plain rules connect the two.

  1. The request arrives on the program's standard input, and the file's location arrives in an environment variable called HTMLCLAY_WIRE_FILE.
  2. Every line the program prints shows up on the page as progress.
  3. When the program exits cleanly, the page is told the work is done. Any other exit code and the page shows an error.

Here is a whole working robot. Save it as robot.sh, next to the page file.

robot.sh
#!/bin/bash
echo "working on it"

NOW=$(date "+%H:%M:%S")
LINE="<li>The robot was here at $NOW.</li>"
perl -pi -e "s|</ul>|$LINE\n  </ul>|" "$HTMLCLAY_WIRE_FILE"

echo "added a line at $NOW"

It prints a progress line, adds one line to the list in the file stamped with the current time, and prints that it finished. It ignores what you typed, on purpose. This first robot exists so you can watch the loop run with nothing clever inside it. The words start mattering in the next step.

3 Connect them

Open Terminal and paste these three lines.

Terminal
alias htmlclay="/Applications/HTMLClay.app/Contents/MacOS/htmlclay"
cd ~/Desktop
htmlclay wire serve robot-notes.htmlclay -- bash robot.sh

The first line teaches this terminal window the htmlclay command, because on a Mac the command lives inside the app rather than on your path. It lasts until you close the window, and putting the same line in your ~/.zshrc keeps it. On Linux, skip it: htmlclay is already a command. On Windows it is htmlclay.exe, in the folder you unzipped.

The last line is the one doing the work: send requests from this file to this program. The terminal answers with one line and then waits.

Terminal
[wire] attached as handler to http://127.0.0.1:52341 (/Users/you/Desktop/robot-notes.htmlclay)

Your port number and your username will differ, and that is fine. Leave it running. The robot is attached to your file for exactly as long as this command runs, and not a second longer.

If it says no HTML Clay site is serving this file; open it first, the file has not been opened since HTML Clay last started. Double-click it and run the command again.

4 Press Send

Go back to the tab, type anything into the box, and press Send. Watch the page. Within a second or two, in this order:

  1. The status under the box reads working on it. That is your robot's first line, arriving on the page as it runs.
  2. A new line appears in the list: The robot was here at 14:03:52. The robot edited the file on your disk, and the page picked the change up and showed it to you, with no reload.
  3. The status settles on done.

Press Send a few more times. One press, one run, one new line.

Three things quietly happened that are worth saying out loud. The page saved itself before asking, so the robot read exactly what you were looking at. The robot's edit went into robot-notes.htmlclay itself, so it is already saved: close the tab, open the file again, and the robot's lines are all still there. And a complete copy of the file from before the edit went into Backups, exactly as for any other save, so nothing a robot does to your file is beyond undoing.

Now make it think

Same loop. Swap the program.

The robot ignored your words. An AI agent is a robot that reads them.

banana-bread.htmlclay Download

Banana bread

Serves 4

  • 3 ripe bananas
  • 1 stick butter, melted
  • ¾ cup sugar
  • 2 eggs
  • 1½ cups flour
  • 1 tsp baking soda

Bake at 350°F for 55 minutes.

Terminal
[wire] attached as handler to http://127.0.0.1:52341 (/Users/you/Desktop/banana-bread.htmlclay)

Watch the oven line: doubling a recipe is not multiplying every number, and the program left it alone. Cut down for the page, a real ask takes fifteen seconds to a minute.

This step needs one thing the rest of the page did not: an AI you can run from the terminal. The example uses Claude Code. If typing claude --version prints a version number, you are ready. If it prints command not found, the robot above has already shown you everything this page teaches, and this step will be here when you have one.

Save this as agent.sh, next to the others.

agent.sh
#!/bin/bash
REQUEST=$(cat)

claude --permission-mode acceptEdits -p "The file at
$HTMLCLAY_WIRE_FILE is an HTML page I have open on my screen.
This request came from inside the page: $REQUEST. Make the change
it asks for by editing that file directly. Leave everything else in
the file exactly as it is, and do not create any other files." 1>&2 &

agent=$!
while kill -0 "$agent" 2>/dev/null; do
  echo "thinking"
  sleep 5
done
wait "$agent"

Stop the robot with Ctrl+C, because one file has one program attached at a time, and start this one instead.

Terminal
htmlclay wire serve robot-notes.htmlclay -- bash agent.sh

Now ask for real things. "Add everything I need for a beach trip to the list." "Rewrite my notes so they are half as long." "Turn my notes into a haiku."

The rhythm is the same, only slower. The status says thinking while the agent works, and then the page changes in front of you: new list items, or your own notes rewritten in place. A small ask usually takes somewhere between fifteen seconds and a minute.

Two lines in that script are doing more than they look.

Where your file goes. An AI agent reads your file and sends what it reads to its own provider, under your own account with them. That is the agent doing what you installed it to do. HTML Clay sends nothing anywhere: it starts the program you named and gets out of the way.

The agent also runs with your permissions, in the folder you started it from. acceptEdits is what lets it write without stopping to ask about every change. If you would rather approve each one, use your agent's stricter setting instead.

What just happened

your page HTML Clay your program robot-notes.htmlclay, the file on disk asks runs it edits it and the page updates

No document travels between the page and the program. The file is the only thing they share.

The page never talks to your program directly, and no page content travels between them. The page sends a short message. Your program edits the file with whatever tools it already has. The edit reaches the page the same way any file change does. HTML Clay calls this channel the wire, and four things about it are worth knowing even if you never look deeper.

The program runs only while your command runs. Ctrl+C, and nothing is attached to anything.

A page cannot pretend to be your program. Browsers announce themselves in ways they cannot suppress, so a web page can ask, but only a program you started yourself can answer.

A page can only reach its own file. It cannot send requests about some other file on your disk, even one open in the next tab.

Every edit is versioned. A program's change is backed up exactly like yours, even when no tab is open at the time.

The rough edges

Said here so you do not have to find them yourself.

Open the file before you attach

The command finds files through the app, so attaching to a file that is not open answers no HTML Clay site is serving this file; open it first. Double-click the file, then run the command.

One program per file

A second attach to the same file is refused while the first is running. Stop the old one with Ctrl+C first.

A silent program gets two minutes

Every line it prints buys it more time, which is why both example scripts print while they work. An agent grinding silently on a huge request can time out. Small requests are fine.

Your next save after a robot edit warns you

The first time you edit the page yourself after a program has changed the file, the page reports that the file changed outside this tab. Nothing is lost, both versions are in Backups, and your save carries the program's edit forward. It reads more alarming than it is.

Give the parts a program rewrites an id

Changes arrive in the open page by matching elements up, so a program should edit inside elements with a stable id or data-id, like log and notes in the example file. A change inside an anonymous element may not appear until the next reload.

Windows

The app and the wire both work, but the example robots are bash scripts. Write the same three rules in PowerShell or any language you like: read standard input, print progress, edit the file named by HTMLCLAY_WIRE_FILE, exit 0. The command is the same, with the path to your htmlclay.exe in place of the alias.

Where next

Ask the page. Watch it change.

The file is the whole conversation.

Download HTML Clay