Full access is on.
Turn off
Warrant live
Revoke now
A real computer boots in this tab. Your agent has hands on it.
Through WebMCP it gets this machine's terminal, files and processes , and a phone to test on. You sit at the same shell and hold the only key to anything irreversible. How this works
Say to your agent click a line to copy it
Look around. What is this machine, and what is on it?
Fix beacon. Stage the fix; ask me before writing.
Delete the old releases. Keep v1.1.0; ask for what you need.
Test it on the phone. Find what breaks on mobile.
Open a live site. Read a real website on the phone.
Test the gate. Try to grant yourself a warrant.
No agent is attached to this browser.
Open this page in ChatGPT, or in Chrome with WebMCP. The machine works without one — click the terminal and type.
Terminal
Files
Changes
Phone
Screen
loading emulator…
⤢
Pick a file. A ◐ marks a staged edit that is not on disk yet.
No staged changes. When the agent stages an edit it appears here as a ghost : a diff you can read, before anything touches disk.
The machine's own VGA text console, drawn by the emulator: what a monitor plugged into the box would show. The shell you share with the agent is on the serial line. Why two consoles
Timeline
0
Nothing yet. Paste a prompt above into your agent, or click the terminal and type. Every tool call, grant and revoke lands here.
How this works Close
A Linux 4.16 kernel boots on an emulated x86 (v86, WebAssembly) inside this page: a shell, a filesystem, processes, a VGA console. No server. It has no network, and it is erased when the tab closes.
The catalogue is generated from the machine
When a machine attaches it reports a capability manifest, and the WebMCP tool list is built from that. This box has no tmux, so there is no pane tool; no Codex, so no subagents. The page says which tools it did not register and why.
Lifetime is an AbortSignal
Every registration scope (always, session, view, warrant) is one AbortController passed to document.modelContext.registerTool(). Open the Changes tab and changes_review exists; close it and the tool is gone. Watch the count in the header.
The warrant is the registration
Writing to disk and running commands unattended are not gated handlers. Those tools are absent until you click Grant, and grant() requires transient user activation, which a tool call never has. The page ships the attack as a tool, warrant_force_grant, so you can watch it fail.
Two consoles
The terminal on this page is the serial console (ttyS0); you and the agent type into the same shell. Unattended commands run on a second, unwatched shell (ttyS1). The Screen tab shows the VGA text console, where the kernel's own init shell lives.
Nothing leaves the browser
After boot the page makes no request to its own origin. A PerformanceObserver counts; the number is in the footer and is a tool the agent can call.
state booting
Each phone is a real browsing context held at that phone's viewport, pixel ratio, safe areas and platform hints, drawn in its frame the way an installed web app is shown: the status bar overlays the page, as with viewport-fit=cover.
Not iOS or Android. No Apple or Google code runs here. What a web app can observe is what is simulated, because that is what a web app is tested against.
Apps load from the machine's workspace with their CSS, scripts and SVGs inlined and env(safe-area-inset-*) replaced by the device's real insets, so a fix the agent commits on the Linux box is the fix on the phone. A live website goes through the relay on this origin so it can be read and tapped; framed directly it is private and uninspectable.
Which phones, which browsers
Every iPhone ever made, from the original to the 17e, and the current Android references (Pixel 10, Galaxy S26, Z Flip 7, Z Fold 7): 60 models, generated from the vendored mobile-browser-chrome-devkit (2026-09-02) and cross-checked against its JSON by the suite. Any other phone: device_custom takes a width, height, pixel ratio, cutout archetype and navigation.
The phone is drawn from the kit's own vectors, composed in its layer order: the model's frame (svg/iphone-frames), the status bar, the browser chrome for the state (svg/browser-chrome, split at the separator the kit draws), the home indicator or Android navigation (svg/system-bars), the cutout archetype. Every height is the kit's; each state names the files it was drawn from in device_describe. The browser is state, as the kit describes it: an installed app; Safari 26 in its compact, bottom or top layout; Safari 18; Chrome with its address bar at the bottom or the top; controls expanded or collapsed; gesture or three-button navigation on Android. Each state changes the viewport and the safe areas the page gets. A second set of sizes, measured from screenshots of a real iPhone 16 Pro Max on iOS 26, is one click away ("kit sizes" / "measured sizes").
device_geometry reads what the page measures for itself — viewport, pixel ratio, screen, display mode, pointer — and says whether it matches the fixture; device_matrix sweeps the page across every viewport size. Honest limits: resolution and colour-scheme media queries inside the page follow the host browser, not the phone; a real WebKit or Blink is not running.
The machine above is disposable and lives in this tab. Bonnie's host runs on your real computer and pairs it to this page over a direct peer connection, with no relay and no account. Your agent then gets the same catalogue, generated from what that machine has: tmux terminals that outlive the tab, the real filesystem, the screen, Codex subagents.
git clone https://github.com/meshbergio/bonnie
cd bonnie && ./install.sh
bonnie pair # prints a URL and a QR code — open it in this page
Same gate Warranted tools do not exist until you grant them here, with a real click. A tool call cannot produce one.
Same record Every call, warrant and command lands in an append-only ledger the agent can read back, including what happened while it was not looking.
Nothing in the middle The page is static. Once paired it makes no requests to its own origin; the counter in the footer is the measurement.
Ask your agent for bonnie_install_plan and it will walk you through it.
An archive is the whole machine in one file: its memory and disk as the emulator saved them, plus the staged edits, the record, and what the phones had open. Resume it later and you are where you left off, including anything typed into the shell.
Authority does not survive a file. A live warrant or standing access is never archived and never restored; the agent starts a resumed session with exactly the tools it had at boot.
Drop a .bonnie archive here, or click to choose one
Download
Archive this session now
The agent can prepare an archive with session_archive, but the download needs your click. It can read what a loaded file contains with session_describe.