← back

Architecture

How iframer actually runs, underneath the CLI and the MCP tools.

Claude / Codex (MCP) ──▶ iframer MCP server ──▶ shared local server (127.0.0.1) ├─ patchright (stealth Chromium) ├─ Chrome for Testing ├─ your real Chrome (extension) └─ SQLite at ~/.iframer

The flow

  1. 1.Call a tool: The MCP client (or the CLI) sends steps to iframer. The CLI routes to the same shared daemon the MCP uses, so a warm CLI call is as fast as the MCP.
  2. 2.The daemon picks a browser: One shared local server per machine, discovered via ~/.iframer/server.json, loopback only. Each agent gets its own browser instance, keyed off the session id, so concurrent agents never share a window.
  3. 3.It runs the pipeline: navigate, click, fill, snapshot, whatever the steps say, against a stealth-patched Chromium. Session cookies and stored credentials are re-injected automatically.
  4. 4.Blocked? It escalates: headless → binary-headful → docker-headful, without a round-trip back to the agent. The mode that worked is recorded per domain, so the next run starts there.
  5. 5.It writes back what it learned: Endpoints seen, auth headers, the mode that worked, into a per-domain knowledge cache. The next visit can skip the browser entirely.

The shared daemon

install mcp runs local mode by default, no Docker needed. Both MCP clients and the iframer CLI talk to one shared local server that keeps a stealth-patched Chromium warm between calls, tracks every browser it spawns in an on-disk PID registry so nothing leaks, and idle-exits when no one needs it. It registers itself in both Claude Code (~/.claude.json) and Codex (~/.codex/config.toml).

Resuming a task

The browser and its page persist in the daemon between calls and survive an interrupt. Name a multi-step or human-in-the-loop task's browser with a stable instanceId, then resume by calling execute again with the same id and acting on the current page. Don't navigate again, that reloads the page and loses state like an OTP screen.

Credentials & sessions

One SQLite file at ~/.iframer/iframer.db holds credentials, session cookies/localStorage, and the knowledge cache, encrypted with AES-256-GCM. Store a password once and every mode (headless, binary-headful, docker-headful) uses the same row; a session captured in one mode loads into another on the next run.

Knowledge cache

After a successful run, iframer writes a plain markdown file at ~/.iframer/knowledge/<domain>.md: which cookies, localStorage keys, and headers the site needs for auth, which endpoints it called, and which browser mode worked. The agent is told to read this before touching a browser; if there's a direct-API path, it skips the browser and hits the endpoint straight.

On disk, under ~/.iframer

server.json
Where the shared local server is listening. How the CLI and MCP find the same daemon.
secret
Encryption key, 0600 permissions, generated on first install mcp. Override with IFRAMER_SECRET.
iframer.db
SQLite: credentials, sessions, knowledge cache. AES-256-GCM encrypted.
knowledge/<domain>.md
Plain markdown per domain: auth requirements and captured endpoints.
domain-modes.json
Which browser mode last worked, per domain.
chrome/
Downloaded Chrome for Testing binary.

Security

  • Credentials encrypted with AES-256-GCM using IFRAMER_SECRET via HKDF
  • Sessions (cookies + localStorage) encrypted before writing to SQLite
  • AI model never receives credential values, only success/failure
  • Write-only credential API, no endpoint returns stored passwords
  • IFRAMER_SECRET auto-generated and persisted to ~/.iframer/secret on first run

Extension mode

The optional Chrome extension dials out to iframer's local server and relays CDP over chrome.debugger, so a tab already open in your real, logged-in Chrome is driven by the exact same pipeline engine as every other mode, find/click/snapshot/API-capture included, with real trusted input instead of a spawned browser.

Stack

Browser engine
patchright (stealth-patched Playwright fork)
Browser binary
Chrome for Testing, downloaded to ~/.iframer/chrome/
Local server
One shared warm server per machine, on-disk PID registry, idle auto-exit
Extension
chrome.debugger → connectOverCDP over a WebSocket relay
Credential store
SQLite, AES-256-GCM, shared by every browser mode
Knowledge cache
Plain markdown at ~/.iframer/knowledge/<domain>.md
Captcha solving
Anthropic vision API
Live viewing
Xvfb + x11vnc + noVNC + websockify (Docker mode only)
MCP server
@modelcontextprotocol/sdk

This is the mechanism. For the tools an agent actually calls, see agent docs. To run this yourself instead of locally, see self-hosting.

Open source · MIT license · 2026