{"id":50835330,"url":"https://github.com/jeet-dhandha/agent-webbridge","last_synced_at":"2026-06-15T04:01:13.432Z","repository":{"id":363298506,"uuid":"1262711160","full_name":"jeet-dhandha/agent-webbridge","owner":"jeet-dhandha","description":"Kimi WebBridge with multiple Chrome profiles \u0026 logins at once — drive several Google accounts simultaneously, not one at a time. Fixes the single-slot / one-login limit.","archived":false,"fork":false,"pushed_at":"2026-06-14T01:56:32.000Z","size":12815,"stargazers_count":2,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-06-14T03:19:57.179Z","etag":null,"topics":["ai-agent","browser-automation","chrome","chrome-extension","chrome-profiles","claude-code","google-accounts","kimi","kimi-webbridge","macos","moonshot-ai","multi-account","multi-login","multi-profile","multiple-accounts","web-automation","webbridge"],"latest_commit_sha":null,"homepage":"https://jeet-dhandha.github.io/agent-webbridge/","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/jeet-dhandha.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":"AGENTS.md","dco":null,"cla":null}},"created_at":"2026-06-08T08:47:09.000Z","updated_at":"2026-06-14T01:56:22.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/jeet-dhandha/agent-webbridge","commit_stats":null,"previous_names":["jeet-dhandha/kimi-webbridge-fleet","jeet-dhandha/agent-webbridge"],"tags_count":4,"template":false,"template_full_name":null,"purl":"pkg:github/jeet-dhandha/agent-webbridge","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jeet-dhandha%2Fagent-webbridge","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jeet-dhandha%2Fagent-webbridge/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jeet-dhandha%2Fagent-webbridge/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jeet-dhandha%2Fagent-webbridge/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/jeet-dhandha","download_url":"https://codeload.github.com/jeet-dhandha/agent-webbridge/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jeet-dhandha%2Fagent-webbridge/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":34346870,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-06-15T02:00:07.085Z","response_time":63,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["ai-agent","browser-automation","chrome","chrome-extension","chrome-profiles","claude-code","google-accounts","kimi","kimi-webbridge","macos","moonshot-ai","multi-account","multi-login","multi-profile","multiple-accounts","web-automation","webbridge"],"created_at":"2026-06-14T03:04:20.991Z","updated_at":"2026-06-15T04:01:13.379Z","avatar_url":"https://github.com/jeet-dhandha.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# agent-webbridge — drive your real Chrome, across many profiles, in parallel\n\n\u003e Open-source (MIT), clean-room browser automation for AI agents. It drives **your real Chrome** — with your **real login sessions** — across **multiple Chrome profiles at once**, and runs **multiple tabs per profile concurrently**. No closed-source dependency, no account, no telemetry, no `curl | bash` installer.\n\n`agent-webbridge` is a lightweight Node daemon (only runtime dependency: [`ws`](https://www.npmjs.com/package/ws)) plus a clean-room MV3 Chrome extension. An AI agent posts a command to a local router; the router fans it out to the right profile's daemon, which speaks to the extension, which attaches the Chrome DevTools Protocol **per tab**. Everything stays on `127.0.0.1` — no data ever leaves your machine.\n\n## Why\n\nIt's **clean-room and standalone** — its own lightweight Node daemon and its own MV3 Chrome extension, with **no closed-source dependency, no account, no telemetry, and no bootstrap installer**. Install it from npm, load the extension once, and drive your real Chrome over localhost.\n\nThe killer feature is **true per-tab parallelism**.\n\nMost browser-automation bridges funnel every CDP call through **one global \"current tab\"** — so they drive exactly one tab per profile at a time. `agent-webbridge` attaches `chrome.debugger` **per tab** (a `Map` keyed by tab), so **N tabs in one profile run concurrently**.\n\nThis is proven live and it **scales**: 2, 5, and **10 tabs in a single profile** each finish in **~2 seconds flat** (measured 2007 / 2007 / 2010 ms, with every tab's interval overlapping every other). The same work run serially would take 4 s → 10 s → **20 s**. Wall-clock stays flat as you add tabs — that's true N× per-profile parallelism.\n\nCombine that with multiple profiles and you get two axes of concurrency at once: **N profiles × N tabs per profile**, all driven from a single endpoint.\n\n## Install\n\n**1. The daemon + CLI** (via npm):\n\n```bash\nnpm i -g agent-webbridge\n```\n\nThis puts the `awb` command on your PATH (with `kwb` kept as an alias) and brings the Node daemon. The only runtime dependency is `ws`.\n\n**2. The Chrome extension** — a clean-room MV3 extension (stable id `ifodkkbkmngjlkhiphcjmbceeolhpfeo`) installed via Chrome's built-in **\"Load unpacked\"**. There is no Chrome Web Store listing — and you don't need one. Let the CLI walk you through it:\n\n```bash\nawb setup \"Work\"          # or any profile name / email / \"Profile 2\"\n```\n\n`awb setup` prints the exact extension folder, opens `chrome://extensions`, then **polls** while you do the one manual step Chrome requires: toggle **Developer mode** on (top-right) and click **Load unpacked** → pick that folder. As soon as it detects the load, it wires the profile to its daemon and brings the fleet up. Because the extension ships its public key in `manifest.json`, Chrome always derives the same stable id — the folder you load *is* the published build. (Manual steps: [Dev](#dev). Driving install from an agent: [`awb check --json`](#dev).)\n\n**Requirements:** macOS + Google Chrome, and Node.js ≥ 18.\n\n## 60-second Quickstart\n\n```bash\n# 1. One-time install — walks you through \"Load unpacked\", then connects + brings the fleet up.\n#    Pass the profile(s) you want to drive (name / email / \"Profile 2\").\nawb setup \"Work\" \"Personal\"\n\n# 2. Already set up? Just bring the fleet up (setup already did this on first run).\nawb up \"Work\" \"Personal\"\n\n# 3. Drive any profile by name — same endpoint, one extra field\ncurl -s -X POST http://127.0.0.1:10086/command \\\n  -H 'Content-Type: application/json' \\\n  -d '{\"action\":\"navigate\",\"args\":{\"url\":\"https://search.google.com/search-console\"},\"session\":\"audit\",\"profile\":\"Work\"}'\n\n# 4. When done\nawb down\n```\n\nEvery command is a `POST /command` on the router at `127.0.0.1:10086`. A `\"session\"` groups a task's tabs into a Chrome tab group; a `\"profile\"` selects which Chrome profile to drive.\n\n## Tools\n\nFull parity with the official bridge — **13 tools, all verified live in a real browser**:\n\n| Tool | What it does |\n|---|---|\n| `navigate` | Open a URL in a (new or existing) tab |\n| `find_tab` | Locate an existing tab by URL / title |\n| `evaluate` | Run JavaScript in the page and return the result |\n| `snapshot` | Accessibility tree with stable `@e` refs for elements |\n| `click` | Click an element (by `@e` ref) |\n| `fill` | Set a value on native inputs **and** `contenteditable` fields |\n| `network` | Capture network requests |\n| `upload` | Upload a file to a file input |\n| `screenshot` | Capture a screenshot of the page |\n| `save_as_pdf` | Save the current page as a PDF |\n| `list_tabs` | List the tabs in the current session |\n| `close_tab` | Close a tab |\n| `close_session` | Close a session and its tab group |\n\n## Architecture\n\n```\n  AI agent / caller\n        │  HTTP POST /command\n        ▼\n  ┌───────────────────────────┐\n  │ router  (127.0.0.1:10086) │   routes by \"profile\"\n  └───────────────────────────┘\n        │\n        ├──────────────┬───────────────┐\n        ▼              ▼               ▼\n  ┌───────────┐  ┌───────────┐   ┌───────────┐\n  │  daemon   │  │  daemon   │   │  daemon   │   one Node daemon per profile\n  │ (Profile  │  │ (Profile  │   │ (Profile  │   on a deterministic hashed port\n  │   \"Work\") │  │\"Personal\")│   │    …)     │\n  └───────────┘  └───────────┘   └───────────┘\n        │  WebSocket\n        ▼\n  ┌───────────────────────────┐\n  │  MV3 extension            │   clean-room, per profile\n  └───────────────────────────┘\n        │  chrome.debugger  (a Map: one attach PER TAB)\n        ▼\n  ┌───────────────────────────┐\n  │  Chrome DevTools Protocol │   tab 1 ║ tab 2 ║ tab 3  (concurrent)\n  └───────────────────────────┘\n```\n\nA caller POSTs to the **router**; the router proxies the command to the right **per-profile daemon** (chosen by the `\"profile\"` field) over its deterministic hashed port; the daemon relays over a **WebSocket** to that profile's **MV3 extension**; the extension attaches `chrome.debugger` **per tab** and issues **CDP** calls.\n\n## Parallelism model\n\nTwo independent axes multiply:\n\n- **Cross-profile** — one daemon per Chrome profile, each on its own deterministic hashed port, each with its own real login session. N profiles run side by side.\n- **Per-tab** — within a single profile, the extension keeps a `Map` of `chrome.debugger` attachments, one per tab. N tabs in that profile run concurrently — the thing the official single-\"current-tab\" extension cannot do.\n\nTotal concurrency = **N profiles × N tabs per profile**, all addressed through the one router endpoint. Proven live: 2, 5, and **10 tabs in a single profile** each finish in ~2 s (2007 / 2007 / 2010 ms) — flat wall-clock, **10× parallelism** — versus serial time that grows linearly with tab count.\n\n## CLI reference\n\nThe CLI is `awb` (with `kwb` kept as an alias — both invoke the same binary).\n\n| Command | What it does |\n|---|---|\n| `awb setup \u003cprofile…\u003e` | One-time install: walk you through \"Load unpacked\", then connect + bring the fleet up |\n| `awb check [profile…] [--json]` | Read-only readiness probe (folder? dev-mode? loaded? connected?) — what an agent polls during install |\n| `awb connect \u003cprofile…\u003e` | Point each profile's extension at its own daemon |\n| `awb up \u003cprofile…\u003e` | Start the named profiles' daemons + the router, open windows, connect |\n| `awb down` | Stop the router + fleet daemons |\n| `awb status` | Fleet status — every profile's daemon + whether its extension is connected |\n| `awb doctor` | Diagnose the environment (Chrome, profiles, daemon, extension) |\n| `awb profiles` | List Chrome profiles, their hashed ports, and extension presence |\n\n`\u003cprofile\u003e` is anything that resolves uniquely — the profile **name** (`\"Work\"`), an **email**, or the Chrome **directory** (`\"Profile 2\"`).\n\n## Dev\n\nTo run the extension from source during development:\n\n1. Open `chrome://extensions/` in the target profile.\n2. Enable **Developer mode** (top-right).\n3. Click **Load unpacked** (top-left).\n4. Select the [`agent-webbridge-extension/`](agent-webbridge-extension/) directory in this repo (or run `npm root -g`/`npm i -g agent-webbridge` and load the `agent-webbridge-extension/` inside the installed package). `awb setup` prints the exact path.\n\nBecause the unpacked extension ships its public key in `manifest.json`, Chrome derives the same stable id (`ifodkkbkmngjlkhiphcjmbceeolhpfeo`) every time — the \"dev\" build and the released build are the same artifact.\n\n**Driving install from an agent.** `awb check [profile…] --json` is a read-only readiness probe an orchestrating agent can poll: for each profile it reports whether the extension folder is present, **Developer mode** is on, the extension is **loaded + enabled**, and the daemon is **up + connected**, plus a single `nextStep` hint. Loop on it until `ready: true`, guiding the user through the one Chrome click in between.\n\n## Verified\n\nDaemon contract test **11/11 PASS** · adversarial interface audit **0 defects** · M1 live **7/7** + scaling **6/6** (2 / 5 / 10 tabs in one profile all fully parallel, flat ~2 s wall-clock) · M2 live **19/19** (all 13 tools verified in a real browser, Chrome for Testing 149) · **real-consumer gate**: the external `yc_scan.ts` scraper ran end-to-end against live ycombinator.com through the stack — harvested **144 companies**, scraped 5 in parallel (10-tab concurrency), exit 0.\n\n## Platform\n\n**macOS-first.** The profile launcher / connect layer uses AppleScript, so macOS + Google Chrome is the supported platform today. Linux / Windows support is a documented follow-up.\n\n## License\n\nMIT © jeet-dhandha\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjeet-dhandha%2Fagent-webbridge","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fjeet-dhandha%2Fagent-webbridge","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjeet-dhandha%2Fagent-webbridge/lists"}