RemixletDocs

How it works

The agent and the sandbox

The two places code runs in Remixlet, what each one can reach, and the two APIs a remixlet is written against.

Remixlet has two runtimes, and they are easy to confuse because both act on the same page. One is the agent. The other is the sandbox. This page introduces them and the two APIs a remixlet's code is written against, so that The dom API and The rmx API can be pure reference. The security case for the split is in Security architecture.

The agent#

The agent lives in the side panel and runs only while you are chatting. It talks to the AI provider you connected, works on the one tab the chat started on, and reads that tab through tools the extension gives it: a capture of the page as a structural outline, element queries, computed styles, the network resources the page loaded, and a scratch snippet it can run to try an idea. It writes remixlet files with one tool and activates them, which reloads the tab. Then it checks its own work: it can click an element, assert page state, read the remixlet's log, and take a look at the page to compare against what it set out to change.

The agent never runs a remixlet's code itself. Its snippets run in a scratch sandbox, described below, and its file writes go through the same approval gate a remixlet's manifest does. When the conversation ends, the agent is gone. Nothing of it stays on the page.

The sandbox#

The sandbox is where a remixlet's JavaScript runs, on every matching page, for as long as the remixlet is active. It is a sandboxed extension page loaded as an iframe in a document the extension keeps offscreen, one sandbox per remixlet per page. It has a null origin, no extension API, and a content security policy with no network directive and no eval. Every page-shaped global a script could reach for is shadowed before the script loads, so document, fetch, localStorage and the rest throw a message naming what to use instead.

What the sandbox can do, it does by sending messages. Two things answer them.

The page agent is a content script we ship. It runs in the page's isolated world, holds the real document, and answers every dom call. Reads it runs as asked. Writes it checks against a fixed policy first, the same policy for every remixlet, and refuses the ones that would turn the page into a way out: an injected script or frame, a URL that carries data to a host nobody trusted, a form submit, a navigation.

The background worker answers every rmx call. It holds the record of what you approved when the remixlet activated and checks each call against it. The message reaches the worker through the extension's own host page, which attaches a secret token for that remixlet. The token never enters the sandbox, so neither the remixlet's code nor the page can forge a call.

The scratch sandbox is a third thing worth naming. When the agent tries a snippet during a chat, the snippet runs in a sandbox on the current page with the same dom and the same write policy, but no capabilities and no token. It is a remixlet's view of the page with the powers turned off, which is why a snippet is the right way to try a dom sequence before writing it into a file.

The two APIs#

Inside the sandbox there are exactly two globals. dom is the page. rmx is everything else: storage, network, notifications, the clipboard, the toolbar menu, timers, and the runtime helpers keep, navigation, log and prefix that every script gets. Both are asynchronous, both are messages that leave the sandbox, and both leave a line in the remixlet's log when a call is refused. The split is about who gets to say no.

domrmx
Reachesthe one page this sandbox is attached tothe extension's own machinery
Answered bythe page agent, in the page's isolated worldthe background worker
Gated bya fixed write policy, the same for every remixlet; reads always passthe capabilities you approved at activation, re-checked on every call
Declared in the manifestneverevery call except log, keep, navigation, and prefix
Returnshandles that stand in for elements, and plain valuesJSON
Livesas long as the document; a navigation or tab close ends itacross every tab and host the remixlet runs on
Refusal readsrefused: … with the rule that firedthe name of the capability that was missing

A rule of thumb. If the thing you want is on the page, it is a dom call and needs no approval. If it has to survive the page, leave the browser, or reach you outside the tab, it is an rmx call and needs a capability.

The two meet in one place. rmx.keep is the mechanism for a page condition that must keep holding while the site redraws itself, and its callbacks are written with dom. It is on the rmx page because it needs no capability, and it is the call most remixlets are built around.

Where to go next#

  • The dom API: handles, every call and its limits, marks, events, and what the page agent refuses.
  • The rmx API: what each capability unlocks, the limits on each call, and how the contract is versioned.
  • Anatomy of a remixlet: the files, the manifest, and how capabilities are declared and approved.