Architecture
How the OpenBrowse codebase is organized.
OpenBrowse is a pnpm monorepo. The product is a Chrome extension built with WXT, React, and the Vercel AI SDK. The docs site is a Next.js + Fumadocs app.
Monorepo Layout
apps/
├── extension/ — WXT Chrome extension (the product)
└── docs/ — Next.js + Fumadocs site (this site)
packages/
└── connectors/ — @openbrowse/connectors registry, shared by extension + docsThe connectors package is the only deliberately cross-app concern: the docs site renders /connectors and /connectors/[id] from the same data the extension uses to populate Settings → Connectors. Provider/model metadata lives in the extension's registry/models-dev/ snapshot, fetched live at runtime from models.dev.
Extension Entrypoints
apps/extension/src/entrypoints/
├── background/ # Service worker — tab events, messaging, MCP client, models.dev refresh
├── content/ # Content script — overlay injection
├── home/ # New tab / home page
├── offscreen/ # Offscreen document — AI inference (WebLLM, cloud APIs), Pyodide
├── overlay/ # Command palette UI (⌥K)
├── settings/ # Settings page
└── sidepanel/ # Chrome side panel — agent chat (also rendered as the popout popup)Key Directories
apps/extension/src/
├── components/ # Shared React components (chat UI, tool result renderers, ...)
├── hooks/ # Shared React hooks
├── lib/
│ ├── agent/ # Agent transport, tool definitions, memory, compaction
│ │ └── tools/ # Per-tool implementations (clickElement, executePython, fs, ...)
│ ├── python/ # Pyodide message protocol
│ └── vfs/ # OPFS abstraction + change event bus (per-conversation workspaces)
├── registry/
│ ├── models-dev/ # Vendored models.dev snapshot, Zod schemas, refresh logic
│ └── providers/ # Static provider entries (browser-ai, web-llm, openai-compatible)
└── entrypoints/...
public/
└── skills/ # Bundled agent skills (python-env, find-skills)Connector metadata lives in the @openbrowse/connectors workspace package and is imported directly where needed (e.g. src/components/ui/registry-icon.tsx); there is no extension-side re-export.
Data Flow
- User interacts via the side panel (or popover, or overlay).
- The agent transport composes the system prompt (memory, todos, MCP tools, the per-turn tab legend) and the toolset.
- Tool calls execute where they belong:
- Browser tools (
clickElement,readPage, etc.) take a stabletabhandle (e.g.t1) in their input. The transport resolves the handle via the conversation's persisted handle map (chatDb →tab-handles.ts) before dispatching to the content script. executeCoderuns in an isolated worker;executeOnPageruns in the resolved tab's page context.executePython→ bundled Pyodide running in a sandboxed iframe (via the offscreen document).- Filesystem tools (
Read,Write,Edit,Glob,Grep,LS) → per-conversation OPFS workspace. - MCP tools → the connector's MCP server.
- Browser tools (
- Results stream back to the UI; the Cowork side panel reflects workspace + todo changes via the
vfs:changeevent bus.