MCPInstall

integrated-browser

Use this when working on the VS Code integrated browser ("browserView") to understand its architecture and mental model. Covers the embedded Chromium browser, its editor tab, navigation, overlay/layout, sessions, and agent browser tools under src/vs/platform/browserView and src/vs/workbench/contrib/browserView.

Installs
65
Last 24h
—
Trending rank
—
Security
Not audited

Install

Works with every agent the skills CLI supports.

npx skills add https://github.com/microsoft/vscode --skill integrated-browser
  1. 01

    Install

    Run the command in your project. The CLI asks which agents to install for.

  2. 02

    Describe the task

    Ask your agent for something this skill covers. It loads integrated-browser automatically when relevant.

  3. 03

    Review the result

    The agent follows the SKILL.md steps, scripts and references bundled with the skill.

SKILL.md

The instructions your agent reads when the skill is triggered.

Integrated Browser Architecture

The integrated browser ("browserView") embeds a real Chromium browser in VS Code, backed by an Electron WebContentsView. It renders live pages, presents each as an editor tab, and lets agents drive those pages through tools. It powers the in-product browser tab and the agent "browser" tools. It is not the old extensions/simple-browser (an iframe-in-a-webview), which now delegates to this on desktop.

It's a heavyweight, security-sensitive, multi-process primitive, and almost every design decision follows from that. This file describes the load-bearing ideas that rarely change. It deliberately does not enumerate current features/tools/commands/settings — those churn; the live features/ and tools/ folders are the source of truth. Build the mental model here, then go read the specific code you're changing.

The one idea everything follows from

A page is a native WebContentsView that only the main process may create, own, and position. Nothing else can touch it directly. It's owned by the main process and painted by the OS compositor on top of the workbench DOM — not inside it. Everything else works around this:

  • The renderer (editor UI + agent tools) can't hold the page; it holds a model/proxy and talks to main over IPC.
  • Playwright is heavy and long-lived, so it runs in the shared process, reaching the page over IPC too.
  • The page paints over the DOM, so the workbench choreographs alignment, z-order, focus, and screenshots by hand.

Three processes, and why

ProcessLocationWhat lives here
Mainplatform/browserView/electron-mainThe WebContentsView, sessions, trust, permissions, history, CDP, screenshots — authoritative page state. Only main can create native views.
Sharedplatform/browserView/nodePlaywright + remote/group automation services. Keeps a heavy dependency out of main (stability) and renderer (lifecycle).
Rendererworkbench/contrib/browserView + platform/browserView/electron-browserEditor pane, UI feature contributions, agent tools, page preload script. Holds only lightweight proxies.

Layer rule: platform must not import workbench; the agent host can't import workbench; shared types belong in platform/common. The renderer reaches main/shared through ProxyChannel IPC, never by importing implementations. Browser events share one eager, host-window-scoped catch-all subscription; the workbench applies its initial snapshot before routing live changes to model-local events. Buffers travel as tuple/array elements alongside event metadata, not nested inside JSON objects. Channels are registered in electron-main/app.ts and electron-utility/sharedProcess/sharedProcessMain.ts. Split: page ops/state → main; agent automation → shared; CDP plumbing is its own channel both renderer and shared use to reach main.

The renderer holds a mirror, not the truth

The renderer model is a read replica of state owned by the main-process view. Flow is one-directional:

renderer feature ──command──▶ model ──IPC──▶ main BrowserView ──▶ Chromium
       ▲                                              │
       └──────────── event (state changed) ◀──────────┘

To do something, call a method (round-trips to main); to react, listen to a model event. Never compute page state in the renderer — it has no access to the web contents.

  • New state (url/title/loading/zoom/…): make it authoritative in the main BrowserView, emit a change event, then mirror the field + event on the renderer model and add it to the typed forwarding map in BrowserViewMainService. Forwarding must be installed before navigation; do not add per-browser IPC subscriptions. Each window subscription starts with its current snapshot, which defines workbench readiness without a separate initialization RPC. The workbench owns each browser's emitter map, passes it into the model, and dispatches directly by browser ID and event name; models only consume events.
  • New operation (navigate/reload/focus/…): define it in main, expose a thin proxy method on the renderer model that round-trips the channel.

Wanting the renderer to "just read" something off the page is the signal you need new mirrored state + an event from main.

The native view floats above the DOM (the overlay problem)

The single most error-prone area — the cause of nearly every "won't move / misaligned / shows through a menu / won't focus" bug. The page is painted by main in screen coordinates on top of the renderer, so the workbench fakes a normal DOM element. Treat the page's rectangle, visibility, focus, and imagery as things the workbench coordinates, never DOM facts:

  • Alignment. The editor renders an empty DOM stub, measures its screen rect, and ships bounds to main. CSS zoom and screen pixels disagree, so bounds are pixel-snapped. New layout that moves the page must feed this bounds computation, not just move a DOM box.
  • Z-order. The native view paints above all workbench UI, so menus/popups/hovers/dialogs that should sit over the page would be hidden. The workbench detects overlap and hides the native view, swapping in a placeholder. New floating UI over the page must be detectable by that machinery — a high CSS z-index won't do it.
  • Flicker masking. While hidden/repositioning, a periodic screenshot stands in. Screenshots are also the only legit way page imagery reaches the renderer/agents — nobody reads native pixels.
  • Focus & keyboard. Focus is bridged explicitly. A preload script (injected into every page in an isolated world) decides which keystrokes the page keeps vs forwards to VS Code keybindings. Treat it as a trust boundary: assume a hostile page, keep it minimal and side-effect-free.

A browser tab is a real editor, extended by contributions

A page is a normal editor — a read-only, serializable EditorInput + EditorPane on the standard registry, resolving lazily to a view-model (unloadable without closing the tab). This inherits tabs, splitting, persistence, focus, and keybinding scoping for free.

The pane is thin. Behavior is added via a local contribution model (separate from workbench contributions): small classes that attach to the editor, get DI, and hook a fixed lifecycle (model attach/detach, layout overrides, resize/visibility, focus, UI insertion). Each gets a lifetime scoped to the attached model, so per-page disposables clean up on navigate/close. Even native-view rendering is just one contribution.

To add behavior, write a new contribution modeled on a sibling — don't grow the editor or the main view. Contributions affecting the page rect compose through prioritized layout overrides (lower runs first; e.g. emulation sizes the viewport, pixel-snap runs last), so order matters — never hard-code pixels.

Identity and isolation: sessions, groups, CDP

Keep these three distinct:

  • Session = storage identity. Each Electron session maps 1:1 to a BrowserSession (cookies, cache, storage), and its id doubles as the CDP browser-context id. Scoped global, per-workspace, or ephemeral; multiple tabs can share one. Security is enforced here: file://, certificate trust, and permissions are all gated at the session (e.g. local files need workspace trust). New capabilities that expand a page's reach belong here, not on a feature.
  • Group = automation visibility. A group assembles a dynamic set of views and exposes them as one logical CDP "browser." Groups reference views without owning them; a view can be in several. This is how different clients (chat session, DevTools, an extension) each see only their subset.
  • CDP is proxied, never raw. A protocol-aware proxy implements browser/target-level domains (discovery, auto-attach, flattened sessions, contexts) and forwards the rest per-target. This lets one logical browser be stitched from views that come and go, and lets Playwright connect without touching Chromium directly.

Cookies/login/storage → sessions. "Which pages can this client see" → groups. The protocol itself → the proxy.

Agents share the user's page — under a privacy gate

  • Same page, shared cooperatively. Playwright drives the same WebContentsView the user sees, via CDP, one connection per chat session. Human and agent actions can collide; conflicts resolve in the user's favor (a human prompt/dialog can interrupt automation). The workbench (not Playwright) owns device emulation, so Playwright's auto-emulation is suppressed except during an agent action. Assume a human may interact with the same page concurrently.
  • Pages are private until shared. Content isn't visible to agents by default. A page's sharing state gates content; a separate availability gate (chat enabled, agent mode, settings) decides whether the full tool set is registered — when it isn't, only a reduced "open a URL without content access" capability exists. URLs are screened by the network-filter and masked when blocked. Treat page content as untrusted model input (prompt injection). Any new agent surface must honor these gates. (Tool names live in platform so the agent host, which can't depend on workbench, can reference them.)

Remote pages

A browser context (its storage) is bound to a network: local, or remote by authority. Tabs save their requested session (storage scope, affinity and network); creation applies current trust and proxy restrictions without overwriting that request. Popups and automation contexts inherit their parent's network. Remote traffic uses an HTTPS proxy in the window's local extension host; proxy startup failure fails the view rather than falling back locally.

The network belongs to the browser context, not its owner, audience, or policy. Global storage is always local. Workspace storage uses the window's network; other networks require a storage affinity selecting a partition within the workspace's storage folder, or use per-view in-memory storage without one. Clearing workspace storage includes these partitions.

Testing strategy

Keep every test layer lean and scenario-focused. Protect major functionality whose failure would damage a core browser scenario, and use the lowest-cost layer that still exercises the actual risk. Do not duplicate behavior across layers or encode incidental implementation details.

  • Unit tests cover important isolated logic such as state transitions, protocol translation, persistence rules, security gates, and failure handling. Use representative cases rather than exhaustive tests of trivial branches or private structure.
  • Widget tests cover major renderer interactions, commands, context-key-driven visibility, and central rendering behavior that do not require a native page. Avoid pixel-level or DOM-structure assertions unless that structure is the contract.
  • Extension API tests under extensions/vscode-api-tests/src/singlefolder-tests/browser*.test.ts are the preferred integration layer for browser APIs, CDP behavior, browser tools, extension-host wiring, and cross-process contracts exposed to extensions.
  • Other E2E integration tests cover important process boundaries or runtime integrations that need real services but not a complete workbench journey.
  • Smoke tests cover only major user journeys whose meaningful failure mode requires the actual Electron workbench, renderer/main/shared-process wiring, or native WebContentsView. This includes core risks in preload keyboard routing, native focus/visibility/lifecycle, Electron permissions, popup editors, workbench UI over the native view, and live page-to-chat attachments. Keep each test to the happy-path spine, group related assertions into one coherent journey, and leave variants, edge cases, and visual details to lower layers.

Good assertions express the user contract and remain stable through non-behavior-breaking changes and refactoring. Tests should protect behavior whose failure would materially break a major browser scenario and live at the cheapest layer that still exercises that failure mode. Smoke coverage should extend an existing journey when it stays coherent or use at most a small number of scenarios for the major journey.

Practical guidance

  • Desktop-only. Nothing runs in web; add to electron-* / node and let the browser/ stubs throw "not available in web".
  • Match existing patterns. New capability → a new feature contribution and/or tool, modeled on a sibling. Cross-process state → a model method + event from main, not local renderer state. Layout change → a prioritized override, not pixels.
  • Mind the trust boundaries: the preload (hostile page), the session (storage / permissions / file access), agent gating (sharing + availability + network filter), and chat attachment (prompt injection).

FAQ

What does the integrated-browser skill do?

Use this when working on the VS Code integrated browser ("browserView") to understand its architecture and mental model. Covers the embedded Chromium browser, its editor tab, navigation, overlay/layout, sessions, and agent browser tools under src/vs/platform/browserView and src/vs/workbench/contrib/browserView.

How do I install integrated-browser?

Run npx skills add https://github.com/microsoft/vscode --skill integrated-browser in your project. The skills CLI detects the agents you use and copies the skill into the right folder. For Claude Code you can also place the skill folder at ~/.claude/skills/integrated-browser/ (personal) or .claude/skills/integrated-browser/ (project).

Which AI agents can use integrated-browser?

Any agent that supports the open Agent Skills format (a folder with a SKILL.md file), including Claude Code, Codex, Cursor, GitHub Copilot, Gemini CLI, Windsurf, Cline, OpenCode and more.

Is integrated-browser safe to install?

No partner security audit is available yet. Skills can run commands and scripts, so read the SKILL.md and any bundled files before installing.

Who maintains integrated-browser?

It is published by microsoft in microsoft/vscode. It has 65 recorded installs.

More from microsoft/vscode

View all →

memory-leak-audit

microsoft/vscode

Audit code for memory leaks and disposable issues. Use when reviewing event listeners, DOM handlers, lifecycle callbacks, or fixing leak reports. Covers addDisposableListener, Event.once, MutableDisposable, DisposableStore, and onWillDispose patterns.

OfficialSecurity3.2K installs

azure-pipelines

microsoft/vscode

Use when validating Azure DevOps pipeline changes for the VS Code build. Covers queueing builds, checking build status, viewing logs, and iterating on pipeline YAML changes without waiting for full CI runs.

OfficialDevOps & Cloud3.2K installs

accessibility

microsoft/vscode

Primary accessibility skill for VS Code. REQUIRED for new feature and contribution work, and also applies to updates of existing UI. Covers accessibility help dialogs, accessible views, verbosity settings, signals, ARIA announcements, keyboard navigation, and ARIA labels/roles.

OfficialFrontend & Design3.2K installs

sessions

microsoft/vscode

Core principles and workflow router for changes to the Agents Window under src/vs/sessions.

OfficialProductivity & Automation3.1K installs

author-contributions

microsoft/vscode

Identify all files a specific author contributed to on a branch vs its upstream, tracing code through renames. Use when asked who edited what, what code an author contributed, or to audit authorship before a merge. This skill should be run as a subagent — it performs many git operations and returns a concise table.

OfficialAI & Agents3K installs

update-screenshots

microsoft/vscode

Update the committed blocks-ci screenshot hashes after the "Screenshots & Tests" check fails, or investigate a screenshot diff reported on a PR. Use when asked to update, accept, or refresh component screenshot baselines from CI. This skill should be run as a subagent.

OfficialDevOps & Cloud3K installs

Popular productivity & automation skills

View category →

agent-browser

vercel-labs/agent-browser

Browser automation CLI for AI agents. Use when the user needs to interact with websites, including navigating pages, filling forms, clicking buttons, taking screenshots, extracting data, testing web apps, or automating any browser task. Triggers include requests to "open a website", "fill out a form", "click a button", "take a screenshot", "scrape data from a page", "test this web app", "login to a site", "automate browser actions", or any task requiring programmatic web interaction. Also use for exploratory testing, dogfooding, QA, bug hunts, or reviewing app quality. Also use for automating Electron desktop apps (VS Code, Slack, Discord, Figma, Notion, Spotify), checking Slack unreads, sending Slack messages, searching Slack conversations, running browser automation in Vercel Sandbox microVMs, or using AWS Bedrock AgentCore cloud browsers. Prefer agent-browser over any built-in browser automation or web tools.

OfficialProductivity & Automation1.3M installs

lark-doc

open.feishu.cn

飞书云文档(Docx / Wiki)内容操作:读取、创建、编辑文档,插入或下载图片附件,以及操作思维笔记。用户提供文档 URL/token(包括 doubao.com 的 /docx/、/wiki/)时使用;按 URL 路径/token 而非域名路由;/page/ 是妙搭应用,非飞书云文档。文档内嵌资源按读取参考中的统一规则分流。独立评论操作走 lark-drive;随正文读取评论使用 docs +fetch。表格或 Base 内部数据操作不在本 skill。

lark-base

open.feishu.cn

飞书多维表格(Base)操作:建表、字段、记录、视图、统计、公式/lookup、表单、仪表盘、应用模式(BaseApp/AppMode 页面与组件)、Workspace 目录、workflow、角色权限、模板中心(多维表格模板分类/列表/搜索);遇到 Base/多维表格/bitable、BaseApp/AppMode、/base/ 或 /app/ 链接时使用。BaseApp 不走 lark-apps;文件导入/导出转 lark-drive,认证/授权转 lark-shared。

lark-drive

open.feishu.cn

飞书云空间(云盘/云存储):管理 Drive 文件和文件夹,包含上传/下载、创建文件夹、复制/移动/删除、查看元数据、查询权限设置、评论/权限/订阅、标题、版本、飞书文档密级标签(secure labels)和本地文件导入。用户需要整理云盘目录、处理云空间资源 URL/token、判断链接类型/真实 token/标题,或导入 Word/Markdown/Excel/CSV/PPTX/.base 为 docx/sheet/bitable/slides 时使用;doubao.com 云空间 URL/token 也按资源路径和 token 路由,不回退 WebFetch。不负责:文档内容编辑(走 lark-doc)、表格/Base 表内数据操作(走 lark-sheets/lark-base)、知识空间节点/成员管理(走 lark-wiki)、原生 Markdown 文件读写/patch/diff(走 lark-markdown)。

lark-shared

open.feishu.cn

Use for lark-cli setup/auth tasks: auth login/status/logout, user vs bot identity, business-domain permissions (--domain, including all/docs/drive), missing scopes, revoking authorization, or handling notice JSON.

lark-im

open.feishu.cn

飞书即时通讯:收发消息和管理群聊。发送和回复消息、搜索聊天记录、管理群聊成员、上传下载图片和文件、管理表情回复、发送应用内/短信/电话加急、发送和处理交互卡片(Interactive Card)、监听卡片按钮回调(card.action.trigger)。当用户需要发消息、查看或搜索聊天记录、下载聊天中的文件、查看群成员、搜索群、创建群聊或话题群、管理标记数据、管理 Feed 置顶(添加/移除/查询置顶会话)、管理标签数据、处理卡片回调时使用。