Observable Electron browser · macOS arm64 cask · v0.1.2

The model
never touches
the page.

AI Web Debugger embeds one sandboxed browser page and hands a model a list of named tools. The model can read the page, and it can click or type after you confirm. It does not get the DOM, the network stack, or storage.

brew tap dickwu/tap
brew install --cask ai-web-debugger

Every call lands in one lane.

page.snapshot snapshot · read · allowed

Allow

These run without a prompt.

navigatesnapshotgetwaitdialog

page.snapshot
network.list_requests
console.list_messages
diagnostics.doctor

You decide

Confirm

The Agent tab asks. If the countdown ends, the call is denied.

clickfillinteracteval-readonly

page.click
page.type
page.press
page.scroll
page.evaluate_readonly

Deny

No configured tool uses these categories.

evalnetworkstatedownloadupload

Window

One page, one debug panel.

The address bar has Back, Forward, Reload, Stop, and a URL field. The target page is a separate WebContentsView: nodeIntegration off, contextIsolation on, sandbox on, no preload. The debug tabs are Network, Console, Snapshot, Agent, and Settings. An approval request switches to Agent.

Diagram of the window, using the debug-site fixture at http://127.0.0.1:4321/. Not a screenshot. Confirm calls open Action Requires Approval, with Approve and Deny. A countdown that runs out denies the action.

The Agent tab has a task field (the placeholder example is “Why is login failing?”), Run Agent, Cancel, Manual Tools, an Activity feed, and Agent Result. Page-derived tool output is marked “untrusted page content”. Evidence in a result can jump to Network, Console, or Snapshot.

Settings cards are Capture, Security, Browser, and LLM. Capture covers max body bytes, POST data, response bodies, and a Redact secrets control described as masking authorization headers, tokens, and cookies. Content boundaries stay on. Allowed domains are one domain per line; empty means allow all. Viewport, user agent, and timeout come from the environment or a config file. The LLM card keeps the provider, the model, and the name of the variable that holds the key.

Containment

The record is redacted before the model sees it.

CDP events from the target page stay in the main process. NetworkRecorder and ConsoleRecorder redact secrets and write CaptureStore. Tool handlers read that store. ContentBoundaryWrapper wraps page text with a nonce for the run. AgentRunner calls only toolRegistry.run(), then the provider: mock by default, or anthropic.

  1. Target page
  2. CDP in main
  3. Recorders
  4. CaptureStore
  5. ToolRegistry
  6. Content boundary
  7. AgentRunner
  8. mock or anthropic

The renderer talks through window.debuggerApp, exposed by the preload contextBridge. Raw ipcRenderer is not exposed. require inside the target page is undefined.

Sandboxed page
nodeIntegration false, contextIsolation true, sandbox true, no preload.
CDP in main
The renderer and the target page never call CDP. CDPClient lives in the main process.
Tools only
The agent loop does not call CDP, the filesystem, or the network itself.
Page boundary
Tools whose output is page data are wrapped before that text reaches the model, so page content cannot rewrite the prompt.
Default deny
Deny beats confirm, then allow. A category the policy does not name is confirm.

Tool registry

Thirty-two tools, sorted by category.

Risk on a tool is read or page_action. The lane comes from the category, not from that risk label. dialog.accept and dialog.dismiss are page_action and still allowed, because dialog is on the allow list.

Configured tools in v0.1.2 and the default ActionPolicy decision for each category.
Tool Category Risk Policy
Allow
browser.open_urlnavigatepage_actionAllow
browser.open_blanknavigatepage_actionAllow
browser.reloadnavigatepage_actionAllow
browser.backnavigatepage_actionAllow
browser.forwardnavigatepage_actionAllow
browser.stopnavigatepage_actionAllow
browser.batchnavigatepage_actionAllow
browser.wait_for_load_statewaitreadAllow
page.snapshotsnapshotreadAllow
page.screenshotsnapshotreadAllow
page.get_interactive_elementssnapshotreadAllow
page.get_by_refsnapshotreadAllow
page.findsnapshotreadAllow
page.query_selectorsnapshotreadAllow
page.wait_forwaitreadAllow
network.list_requestsgetreadAllow
network.get_requestgetreadAllow
network.get_response_bodygetreadAllow
console.list_messagesgetreadAllow
storage.get_cookiesgetreadAllow
storage.get_local_storagegetreadAllow
storage.get_session_storagegetreadAllow
dialog.statusdialogreadAllow
dialog.acceptdialogpage_actionAllow
dialog.dismissdialogpage_actionAllow
diagnostics.summarize_current_pagegetreadAllow
diagnostics.doctorgetreadAllow
Confirm
page.scrollinteractpage_actionConfirm
page.clickclickpage_actionConfirm
page.typefillpage_actionConfirm
page.pressinteractpage_actionConfirm
page.evaluate_readonlyeval-readonlyreadConfirm

Deny covers eval, network, state, download, and upload. None of those categories has a configured tool. Precedence is deny, then confirm, then allow.

Install

Tap, then install the cask.

The Homebrew cask is ai-web-debugger in dickwu/tap. It requires macOS Big Sur or newer on Apple silicon, and it installs AI Web Debugger.app from the arm64 disk image. The cask homepage is the GitHub repo.

Homebrew

These two lines are the install in the product README and the tap README.

brew tap dickwu/tap
brew install --cask ai-web-debugger

Same cask, one command. Homebrew taps dickwu/tap if you do not already have it.

brew install --cask dickwu/tap/ai-web-debugger

The macOS build is unsigned and not notarized. If macOS shows a damaged app or quarantine warning, run:

sudo xattr -d com.apple.quarantine /Applications/AI\ Web\ Debugger.app/

v0.1.2 builds

The disk image and zip are Apple silicon. The release also has a Windows setup exe and a Linux AppImage.

From source

The app uses Bun. bun run fixture is optional. It serves the debug site at http://127.0.0.1:4321/, with a deliberate 500, a two-second /api/slow response, and /api/secret for the redactor. Open that URL from the address bar.

git clone https://github.com/dickwu/ai-web-debugger.git
cd ai-web-debugger
bun install
bun run dev
bun run fixture
  1. Tap dickwu/tap and install the ai-web-debugger cask, or download the arm64 disk image.
  2. If macOS quarantines the app, clear the quarantine flag, then open AI Web Debugger.
  3. Open the fixture or any page you are willing to expose to the tool list. Run a task from the Agent tab.

On disk

Settings load in order. Later entries win.

Precedence

  1. Built-in defaults
  2. config.json in the user data directory
  3. ./ai-web-debugger.json in the project
  4. Environment variables prefixed with AI_WEB_DEBUGGER_

On macOS the user data directory is ~/Library/Application Support/ai-web-debugger.

Provider variables

  • LLM_PROVIDER — mock (default) or anthropic
  • LLM_API_KEY — key for that provider
  • LLM_MODEL — for example claude-3-5-sonnet-20241022
  • AI_WEB_DEBUGGER_LLM_PROVIDER, AI_WEB_DEBUGGER_LLM_API_KEY, and AI_WEB_DEBUGGER_LLM_MODEL override the three above

Each launch

A new session id is created. Under the user data directory:

  • sessions/<id>/screenshots/*.png
  • sessions/<id>/events.jsonl
  • sessions/<id>/session.json
  • logs/main.jsonl

Updates

The status bar shows the version and Check for updates. The v0.1.2 release includes latest-mac.yml, latest.yml, and latest-linux.yml for electron-updater.

v0.1 limits

What this version does not do.

  • One target WebContentsView per session. No multi-tab.
  • No full iframe or OOPIF tracking.
  • CaptureStore is in memory. No SQLite.
  • Distribution builds are not code-signed or notarized.
  • No tools that intercept or mutate network requests.
  • page.wait_for implements a subset of Playwright-style assertions.
  • Providers are mock and anthropic. No OpenAI adapter.

Questions

Questions people ask.

What does the model get from the page?

The model never touches the DOM, network, or storage. It calls tools on a ToolRegistry. Those tools read a CaptureStore of network and console records after secrets are redacted, and every tool that returns page text is wrapped in a content boundary with a nonce for that run before the model sees it.

Which tool calls run on their own?

ActionPolicy allows navigate, snapshot, get, wait, and dialog. It asks you to confirm click, fill, interact, and eval-readonly. It denies eval, network, state, download, and upload. A call that needs confirmation opens Action Requires Approval on the Agent tab, shows the tool name, risk, and input summary, and denies the action if the countdown runs out.

How do I install it with Homebrew?

On an Apple silicon Mac running Big Sur or newer, run brew tap dickwu/tap and then brew install --cask ai-web-debugger. That cask is dickwu/tap/ai-web-debugger. It installs AI Web Debugger.app from the arm64 disk image.

What if macOS says the app is damaged?

The macOS build is unsigned and not notarized. If macOS shows a damaged app or quarantine warning, run sudo xattr -d com.apple.quarantine /Applications/AI\ Web\ Debugger.app/

Which LLM providers are wired?

mock is the default, and anthropic is the other wired provider. Set LLM_PROVIDER, LLM_API_KEY, and LLM_MODEL, or override them with AI_WEB_DEBUGGER_LLM_PROVIDER, AI_WEB_DEBUGGER_LLM_API_KEY, and AI_WEB_DEBUGGER_LLM_MODEL. An OpenAI adapter is not wired in v0.1. The README gives claude-3-5-sonnet-20241022 as a model name example.

What does version 0.1 leave out?

One target page per session. v0.1 does not include multi-tab support, full iframe and OOPIF tracking, SQLite persistence, code-signing and notarization, network interception or mutation, the rest of the Playwright-style assertions in page.wait_for, or an OpenAI provider. CaptureStore stays in memory.

Where are sessions stored?

Each launch creates a new session id. On macOS the user data directory is ~/Library/Application Support/ai-web-debugger. Screenshots, events.jsonl, and session.json live under sessions, and the main process log is logs/main.jsonl. Settings load from built-in defaults, then that directory's config.json, then ./ai-web-debugger.json, then AI_WEB_DEBUGGER_ environment variables. Later entries win.

Install it, then open a page.