Hublot

One window, several watchers

One porthole.
Every eye gets its own tab.

Hublot opens a single, real, visible Chromium window that any number of AI agents can look through at once, each through a tab scoped to a label of its own. The glass stays clear for a human too: click, type a password, take over, at any moment, on any tab.

A porthole built for one pair of eyes

Playwright MCP works well for a single agent, but two structural limits keep it from serving several agents at once:

  1. One agent owns the browser session. No other agent can open a tab or act in parallel without stepping on the first one's tab.
  2. An MCP server has to be declared before the agent's session even starts. There is no way to add one on the fly once an agent discovers, mid-task, that it needs a browser.

Hublot works around both: it is an ordinary CLI, exactly like git or curl, callable at any moment from any agent's regular shell tool, with nothing to configure beforehand.

Skipping the MCP layer and driving Playwright directly does not solve this either. Playwright's own tooling (codegen, test, a one-off script) is one-shot by design: it launches a browser, runs, and the process ends with it. Nothing keeps a window alive between two separate shell commands, which is exactly what letting several agents act on the same tab minutes apart requires. Hublot's broker is that missing piece: a small process that stays resident, keeps the browser and its tabs alive, and answers one command at a time over a local socket instead of launching a fresh browser per call.

> playwright_mcp.navigate("https://example.com")

Error: browser context already claimed by another session.

SESSION LOCKED · ONE AGENT AT A TIME

Three brass fittings hold it together

Hublot is one small broker process, spawned once and left running in the background, that owns the browser and answers a plain TCP socket on 127.0.0.1. Everything else follows from three deliberate choices.

A real, visible window

headless: false is not an option, it is the point. The Chromium window sits on screen at all times, with a profile that persists on disk: cookies, autofill, and the browser's own saved passwords, exactly like a normal browsing profile, nothing reinvented.

One tab, one label

Each agent opens its own tab under a --label of its choosing (claude-main, agent-debug...). Every command that follows is scoped to that label: two agents can never act on the same tab by accident, and a human can always tell which tab belongs to whom.

A plain CLI, no MCP to pre-wire

No server to declare ahead of time, no session to negotiate. An agent runs hublot open the moment it discovers it needs a browser, the same way it would reach for git or curl.

RULE OF THE GLASS Every command fails cleanly (a clear message, exit code 1) if the broker isn't listening, rather than doing nothing silently.

The commands

Start the broker once, then open one tab per agent and drive it: navigate, click, type, hover, drag, upload, wait for content, read the accessibility tree, run raw JavaScript, capture. 24 commands, tested against a real Chromium tab, not just compiled.

  1. 01

    Start the broker (idempotent: does nothing if it's already running)

    hublot start
  2. 02

    Check its state and the open tabs (alias: hublot list)

    hublot status
  3. 03

    Open a tab for this label (reuses it if it already exists)

    hublot open --label claude-main --url "https://example.com"
  4. 04

    Navigate inside that tab

    hublot navigate --label claude-main --url "https://example.com/page2"
  5. 05

    Go back to the previous page

    hublot back --label claude-main
  6. 06

    Click an element (Playwright CSS selector)

    hublot click --label claude-main --selector "button.submit"
  7. 07

    Hover an element (e.g. to reveal a menu)

    hublot hover --label claude-main --selector "nav .menu-trigger"
  8. 08

    Type into a field (replaces the value outright, no fake keystrokes)

    hublot type --label claude-main --selector "input[name=q]" --text "search"
  9. 09

    Press a key, on an element or globally

    hublot press --label claude-main --selector "input[name=q]" --key Enter
  10. 10

    Pick an option in a dropdown

    hublot select --label claude-main --selector "#country" --value FR
  11. 11

    Drag one element onto another

    hublot drag --label claude-main --source "#card-1" --target "#column-2"
  12. 12

    Send a file into an <input type=file>

    hublot upload --label claude-main --selector "input[type=file]" --files "C:\path\file.pdf"
  13. 13

    Decide how this tab answers JS dialogs (default: dismiss)

    hublot dialog --label claude-main --action accept
  14. 14

    Wait for an element or a piece of text to show up

    hublot wait --label claude-main --text "Loading complete"
  15. 15

    Find elements containing a text, without guessing a CSS selector

    hublot find --label claude-main --text "Add to cart"
  16. 16

    Run a JS expression inside the page's own sandbox and print the result (JSON)

    hublot evaluate --label claude-main --expression "document.title"
  17. 17

    Resize this tab's viewport

    hublot resize --label claude-main --width 1280 --height 800
  18. 18

    Extract text (innerText) from an element, or the whole page if --selector is omitted

    hublot extract --label claude-main --selector ".result"
  19. 19

    Accessibility tree (roles/names) — more reliable than a screenshot for an agent to locate something

    hublot snapshot --label claude-main
  20. 20

    Take a screenshot: a timestamped PNG is written to disk, its path printed to stdout

    hublot screenshot --label claude-main
  21. 21

    Read the JS console log captured since the tab was opened (capped at 500 entries)

    hublot console --label claude-main
  22. 22

    Read the network requests captured since the tab was opened (method, status, URL)

    hublot network --label claude-main
  23. 23

    Close this tab (the browser itself stays open)

    hublot close --label claude-main
  24. 24

    Stop the broker entirely and close the browser

    hublot stop

hublot run-code-unsafe --label claude-main --code "async (page) => page.title()"

Runs Playwright/Node code inside the broker process itself — full filesystem and process access, not just the page's JS sandbox like evaluate.

OPT-IN · PERSONAL, TRUSTED MACHINES ONLY

MULTI-AGENT CONVENTION Each agent should keep a stable --label that names itself, not just the task at hand, and reuse it for its whole session instead of opening a new tab for every command. That is what keeps several agents from ever stepping on each other, even on the same machine.

Full command reference and every flag live in the repo README.

Fitting the porthole

Version 0.1.0 is out, signed on both platforms (Azure Trusted Signing). Windows gets a proper installer (adds hublot to your PATH); Linux gets an in-house apt repository. winget is planned but not published yet.

WINDOWS

Installer (Inno Setup), signed: adds Hublot to your user PATH, ships with an uninstaller.

hublot-0.1.0-x64-setup.exe
Download for Windows
LINUX

Debian/Ubuntu, via the in-house apt repository (same one used by BeamMeUp).

sudo curl -fsSL https://apt.breizhzion.com/KEY.gpg -o /usr/share/keyrings/breizhzion.asc
echo "deb [signed-by=/usr/share/keyrings/breizhzion.asc] https://apt.breizhzion.com stable main" \
  | sudo tee /etc/apt/sources.list.d/breizhzion.list
sudo apt update && sudo apt install hublot
Or download the .deb directly
BROWSER ENGINE

Hublot reuses whatever Chromium-based browser is already installed, in order: Google Chrome, then Microsoft Edge. If neither is present, or to keep Hublot isolated from your everyday browser:

npx playwright install chromium
WINGET PACKAGE

Coming soon, following the same signed-release pattern already in place for sibling tools. Until then, the installer above is the supported path.

winget install Breizhzion.Hublot
# not published yet

Known limits of this early version: hublot type replaces a field's value outright rather than simulating real keystrokes, which covers almost every form but won't trigger handlers that specifically listen for keydown; the Playwright-downloaded Chromium fallback has not yet been exercised on a machine without Chrome or Edge already installed.