Site icon Efficient Coder

Zero-Drama Browser Automation: How Vibium’s 10MB Binary Enables AI Agents

Vibium: The “Zero Drama” Browser Automation Infrastructure for AI Agents

Snippet:
Vibium is a browser automation infrastructure designed for AI agents, utilizing a single ~10MB Go binary to manage the Chrome lifecycle and expose an MCP server. It enables zero-setup WebDriver BiDi protocol support, allowing Claude Code and JS/TS clients to drive browsers with both async and sync APIs while automatically handling Chrome for Testing installation.

Browser automation has long been synonymous with configuration headaches. From matching WebDriver versions to managing headless flags and handling flaky element detection, the “drama” often overshadows the actual utility of the automation. Vibium enters this landscape as a foundational shift—browser automation infrastructure built specifically for the era of AI agents.
By consolidating the browser lifecycle, WebDriver BiDi protocol handling, and MCP (Model Context Protocol) server capabilities into a single binary, Vibium aims to make browser control invisible. Whether you are building a test automation framework, a scraping bot, or integrating browser control into Claude Code, the promise is simple: zero setup, immediate execution.

The Architecture: From LLM to Chrome

To understand why Vibium is different, we need to look at how data flows through the system. The architecture is designed to bridge the gap between Large Language Models (LLMs) and the physical browser instance.
The system consists of two primary components: the Clicker (the backend engine) and the JS Client (the developer interface).

The Clicker: A 10MB Powerhouse

At the core of Vibium is the Clicker, a single Go binary approximately 10MB in size. Its design goal is ambitious: to become invisible. Developers using the JavaScript client should never need to know that a Go binary is managing the orchestration in the background.
The Clicker handles four critical responsibilities:

  1. Browser Management: It detects and launches Chrome with the BiDi (Bidirectional) protocol enabled. It intelligently manages the browser process to ensure clean shutdowns.
  2. BiDi Proxy: It operates as a WebSocket server (defaulting to port 9515) that routes commands from clients to the browser and events from the browser back to the clients.
  3. MCP Server: It exposes a stdio interface compatible with the Model Context Protocol, allowing AI agents like Claude Code to drive the browser directly.
  4. Auto-Wait & Screenshots: It includes built-in polling mechanisms to wait for elements before interacting and can capture viewport screenshots as PNGs.

Data Flow and Protocol

The interaction begins at the top layer with the LLM or AI Agent (such as Claude Code, Codex, or local models). The agent communicates via the MCP Protocol over stdio. This stream flows into the Vibium Clicker.
Inside the Clicker, the MCP Server processes the request and hands it off to the BiDi Proxy. The Proxy maintains a persistent WebSocket connection with the Chrome Browser, using the WebDriver BiDi protocol to execute commands like navigation, clicking, and typing.
For human developers, a secondary path exists. The JS/TS Client (installed via npm install vibium) connects directly to the Clicker’s WebSocket interface on port 9515. This bypasses the MCP layer and provides a direct programmatic API.

The “Sense, Think, Act” Vision

While the current release focuses heavily on execution, the roadmap reveals a broader architectural philosophy inspired by robotics control loops: Sense → Think → Act.

  • Act (Current): The Clicker represents the “Act” layer, executing commands on the browser.
  • Think (Future – Cortex): A planned SQLite-backed data store to build an “app map,” helping agents remember navigation paths and plan multi-step interactions.
  • Sense (Future – Retina): A Chrome extension designed to passively record all browser activity, providing the AI with full context of what is happening on the screen.
    By separating these concerns, Vibium positions itself not just as a test tool, but as an operating system for AI-browser interaction.

Deep Dive: Actionability Checks

One of the most significant sources of “drama” in browser automation is the “Element Not Interactable” error. Vibium tackles this head-on with a rigorous Actionability system inspired by Playwright.
Before performing any action, the system verifies specific conditions. This is not a simple “wait for element to exist” check; it is a multi-dimensional validation process.

The Five Dimensions of Actionability

When you command Vibium to click or type, it runs the following checks:

  1. Visible
    The element must have a non-empty bounding box. It cannot be hidden via CSS properties like visibility: hidden or display: none.
    • Verification: getBoundingClientRect() and getComputedStyle().
  2. Stable
    The element’s position must be consistent. If the element is moving due to animation or layout thrashing, the action will wait.
    • Verification: Compares the bounding box at time t and time t+50ms.
  3. Receives Events
    The element must be the actual target at the point of interaction. This prevents clicking through an overlay or a modal that is technically “invisible” but blocking the click.
    • Verification: elementFromPoint() at the center of the element.
  4. Enabled
    The element must not be disabled.
    • Verification: Checks for [disabled] or [aria-disabled=true] attributes.
  5. Editable
    Specifically for text input, the element must not be read-only.
    • Verification: Checks for [readonly] or [aria-readonly=true] attributes.

Check Configuration

Different actions require different sets of checks:

  • Click: Requires Visible + Stable + ReceivesEvents + Enabled.
  • Type: Requires Visible + Stable + ReceivesEvents + Enabled + Editable.
  • Find: Requires only existence (no actionability checks).

Timing and Polling

This mechanism relies on a polling system with a default timeout of 30 seconds and a polling interval of 100 milliseconds. If an element fails to pass all required checks within 30 seconds, the system throws a specific TimeoutError rather than failing silently or hanging indefinitely.

For Developers: The JS/TS Client Experience

Vibium is distributed as an npm package, making it accessible to the vast ecosystem of JavaScript and TypeScript developers. The installation process is designed to be as frictionless as possible.

Zero-Configuration Installation

When you run npm install vibium, the postinstall script automatically performs several tasks:

  1. Installs the Clicker binary specific to your platform.
  2. Downloads the latest stable version of Chrome for Testing and the matching chromedriver.
  3. Caches these binaries in platform-specific directories:
    • Linux: ~/.cache/vibium/
    • macOS: ~/Library/Caches/vibium/
    • Windows: %LOCALAPPDATA%\vibium\
      If you prefer to manage your own browsers, you can skip this step by setting the environment variable VIBIUM_SKIP_BROWSER_DOWNLOAD=1.

Sync vs. Async API

Understanding the execution model is crucial for integrating Vibium into your workflow. The library supports both asynchronous and synchronous APIs, catering to different use cases.

The Asynchronous API

This is the standard approach for modern Node.js applications. It uses async/await syntax and is non-blocking.

import { browser } from "vibium";
const vibe = await browser.launch();
await vibe.go("https://example.com");
const el = await vibe.find("a");
await el.click();
await vibe.quit();

The Synchronous API

For scenarios where blocking behavior is preferred—such as simple automation scripts or REPL usage—Vibium provides a synchronous wrapper. This allows you to write code that executes sequentially without Promises.

const { browserSync } = require('vibium')
const fs = require('fs')
const vibe = browserSync.launch()
vibe.go('https://example.com')
const png = vibe.screenshot()
fs.writeFileSync('screenshot.png', png)
const link = vibe.find('a')
link.click()
vibe.quit()

Import Methods

The package is flexible regarding how you import it, supporting CommonJS, dynamic imports, and static ES modules:

  • REPL-friendly: const { browserSync } = require('vibium')
  • Dynamic Import: const { browser } = await import('vibium')
  • Static Import: import { browser, browserSync } from 'vibium'

For AI Agents: MCP Integration

The killer feature of Vibium is its native support for the Model Context Protocol (MCP). This allows AI agents, specifically Claude Code, to control a browser with zero manual configuration.

Setting up the MCP Server

Connecting Vibium to Claude Code requires a single terminal command:

claude mcp add vibium -- npx -y vibium

This command handles the entire setup. No manual browser configuration, no path management. The binary is downloaded, Chrome is installed, and the MCP server is registered.

Available Tools

Once connected, the AI agent has access to a standardized toolkit of browser functions. These tools map directly to the underlying capabilities of the Clicker:

Tool Name Description Parameters
browser_launch Starts the browser session headless (boolean, default false)
browser_navigate Navigates to a specific URL url (string, required)
browser_find Locates an element selector (string, required)
browser_click Clicks an element selector (string, required)
browser_type Inputs text into an element selector, text (strings, required)
browser_screenshot Captures the viewport filename (optional)
browser_quit Closes the browser None

Practical Usage

With this integration, interaction becomes conversational. You can simply instruct the agent:

“Go to example.com and click the first link”
Vibium translates this natural language intent into the precise BiDi protocol commands required to execute the action.

The Roadmap: From V1 to V2

The development of Vibium is tracked via detailed roadmaps, distinguishing between the current MVP (V1) and the future vision (V2).

V1: The Core Loop (MVP)

The V1 release focuses on the “Act” layer. The development plan was broken down into a 14-day sprint, highlighting the modular nature of the build:

  • Days 1-2 (Infrastructure): Project scaffolding, Go binary creation, and the implementation of the Chrome for Testing installer. The installer fetches the latest stable versions directly from Google Chrome Labs’ JSON endpoint.
  • Day 3 (Connectivity): Establishment of the WebSocket connection using gorilla/websocket and the implementation of BiDi protocol types (Command, Response, Event).
  • Day 4 (Navigation): Implementation of the browsing context, navigation logic, and screenshot capture.
  • Day 5 (Interaction): Element finding via CSS selectors, mouse input (pointer move, down, up), and keyboard input (key sequences).
  • Day 6 (Proxy Server): Creation of the WebSocket proxy server that routes messages between the JS client and the browser, including session management and clean shutdown on disconnect.
  • Days 7-8 (Client API): Development of the TypeScript client, including the binary manager, BiDi client, and the Async/Sync APIs.
  • Day 9 (Actionability): Integration of the comprehensive stability and visibility checks detailed earlier in this article.
  • Day 10 (MCP Server): Implementation of the stdio-based MCP server and tool schemas.
  • Day 11 (Polish): Error type definition (ConnectionError, TimeoutError, ElementNotFoundError, BrowserCrashedError), structured logging, and graceful shutdown handling (SIGINT, SIGTERM).
  • Days 12-13 (Packaging): Cross-compilation for Linux (x64/arm64), macOS (x64/arm64), and Windows (x64). Creation of platform-specific NPM packages (@vibium/linux-x64, etc.).
  • Day 14 (Documentation): Finalization of READMEs and tutorials.

V2: The Future (Sense and Think)

With the “Act” layer solidified, the roadmap turns toward the “Sense” and “Think” layers.

Cortex (Think Layer)

Cortex is envisioned as a persistent memory layer using a SQLite-backed datastore. It would build an “app map” of the application being tested, tracking pages, actions, and sessions.

  • Components: SQLite database, sqlite-vec integration for vector embeddings, REST API for JSONL data ingestion, and a graph builder using Dijkstra’s algorithm for pathfinding.
  • Use Case: Preventing agents from repeatedly “rediscovering” the same navigation flows and enabling multi-step planning.

Retina (Sense Layer)

Retina is planned as a Chrome Manifest V3 extension. Unlike the Clicker, which drives the browser, Retina would passively observe it.

  • Components: Content scripts with listeners for clicks, keypresses, and navigation; DOM snapshot capture; and screenshot capture via background scripts.
  • Use Case: Recording human sessions for replay and debugging agent runs.

Additional V2 Features

  • Python and Java Clients: Extending the pip install vibium and Maven/Gradle support to bring the same zero-drama experience to Python and Java ecosystems.
  • Video Recording: Built-in session recording using FFmpeg. Screenshots would be captured at intervals (e.g., 10fps) and encoded to MP4/WebM.
  • AI-Powered Locators: The most ambitious feature, allowing natural language interaction (e.g., “click the blue submit button”). This involves integrating vision models (either local like Qwen-VL or API-based) to handle ambiguity.
  • Network Tracing: Capturing and inspecting network requests/responses, including HAR export and request interception.
  • Docker & Cloud Deployment: Official Docker images and deployment guides for platforms like Fly.io to support CI/CD pipelines.

Platform Support and Compatibility

Vibium is engineered to support the vast majority of developer environments. The current support matrix includes:

Platform Architecture Status
Linux x64 Supported
Linux arm64 Supported
macOS x64 (Intel) Supported
macOS arm64 (Apple Silicon) Supported
Windows x64 Supported
The use of Go for the Clicker binary ensures that static linking is possible (CGO_ENABLED=0), resulting in single-file executables that require no external runtime dependencies on the host machine.

Error Handling and Debugging

A robust automation tool must provide clear feedback when things go wrong. Vibium categorizes errors specifically to aid debugging:

  • ConnectionError: Raised when the tool cannot connect to the browser instance.
  • TimeoutError: Thrown when an element or action does not meet the actionability criteria within the 30-second default window.
  • ElementNotFoundError: Returned when a CSS selector matches zero elements in the DOM.
  • BrowserCrashedError: Triggered if the underlying browser process dies unexpectedly.
    Logging is handled via structured JSON logs (using libraries like zerolog or slog) output to stderr. Debugging can be enabled via CLI flags (--verbose) or the VIBIUM_DEBUG=1 environment variable in the JS client.
    Graceful shutdown is a priority. The system is designed to clean up browser processes on normal exit, client disconnect, and signal interrupts (Ctrl+C), ensuring no zombie Chrome processes remain running in the background.

Conclusion

Vibium represents a maturation of the browser automation space. By moving away from the complexities of WebDriver setups and towards a unified binary that speaks the modern BiDi protocol, it lowers the barrier to entry for both human developers and AI agents.
Whether you are using the synchronous API for quick scripts, the asynchronous API for complex applications, or the MCP server to empower Claude Code, the underlying promise remains consistent: browser automation without the drama.

FAQ

How do I install Vibium?

You can install Vibium via npm. Simply run npm install vibium. This will automatically download the Clicker binary for your platform and Chrome for Testing to your cache directory.

Does Vibium work with Claude Code?

Yes, Vibium natively supports the Model Context Protocol (MCP). You can add it to Claude Code using the command claude mcp add vibium -- npx -y vibium. This allows the AI to control the browser directly using tools like browser_navigate and browser_click.

What is the difference between the Sync and Async API?

The Async API (await browser.launch()) uses Promises and is non-blocking, suitable for modern Node.js applications. The Sync API (browserSync.launch()) blocks execution, allowing for sequential scripting without await keywords, which is useful for simple automation tasks or REPL usage.

How does Vibium handle dynamic web pages?

Vibium uses an “Actionability” system. Before clicking or typing, it polls the element to ensure it is Visible, Stable, Receives Events, Enabled, and Editable. It waits up to 30 seconds (default) for these conditions to be met before throwing a TimeoutError.

Can I use my own Chrome installation?

Yes. By default, Vibium downloads Chrome for Testing. However, you can skip this by setting the environment variable VIBIUM_SKIP_BROWSER_DOWNLOAD=1 before running npm install vibium. The Clicker will then attempt to locate your system Chrome installation.

What platforms are supported?

Vibium supports Linux (x64, arm64), macOS (x64, arm64), and Windows (x64).

How large is the Clicker binary?

The Clicker is a single Go binary approximately 10MB in size. It includes all necessary functionality for browser management, BiDi proxying, and MCP server capabilities.

Does Vibium support other languages besides JavaScript?

Currently, the official client is for JavaScript/TypeScript. However, the V2 roadmap includes plans for Python and Java clients. The core functionality resides in the Clicker binary, which is language-agnostic.

Exit mobile version