app / adom-desktop-puppeteer-bridge
!

Not installable via adompkg

This app has no published release. adompkg install kyle/adom-desktop-puppeteer-bridge will not work until a maintainer publishes a tarball with install.sh and uninstall.sh.

See the publishing docs for the package.json schema and tarball layout required to ship this app.

Reference bridge: Puppeteer

Source code + contributing (2026-05)

The Puppeteer (Chrome) bridge moved out of adom-inc/adom-desktop's monorepo into its own dedicated repo so the community can extend it without coordinating with Adom Desktop's release cycle.

Where the source lives

The canonical repo is adom-inc/adom-bridge-puppeteer on GitHub. It's private today and will go public after a review pass.

In the meantime, the full source — code, history, contributing guide, license — is mirrored on this wiki page:

Download What it is How to use
adom-bridge-puppeteer-source.tar.gz Clean source tree, no .git directory. ~98 KB. tar xzf adom-bridge-puppeteer-source.tar.gz && cd adom-bridge-puppeteer/
adom-bridge-puppeteer.bundle Git bundle with full commit history. ~157 KB. git clone https://wiki-ufypy5dpx93o.adom.cloud/static/apps/adom-desktop-puppeteer-bridge/adom-bridge-puppeteer.bundle adom-bridge-puppeteer && cd adom-bridge-puppeteer && git log

No GitHub account needed to download either — both URLs are public.

How to contribute

We accept community improvements. Most useful targets right now:

  • macOS / Linux ports — bridge currently Windows-only; cross-platform PRs welcome.
  • New browser-automation verbs — Puppeteer surface is big; we wrap a useful subset. Add more if you need them.
  • Recording features — desktop recorder is new (v1.8.x); plenty of polish room (annotations, audio, GIF export).

Two contribution paths, depending on your access:

With a GitHub account (preferred): wait until we make the repo public, then fork on GitHub and open a PR. We're aiming to flip the repo public in the next maintenance pass.

Without GitHub access (patch-by-email-style, available right now): Clone the bundle, make your changes, generate a patch with git format-patch origin/main..HEAD --stdout > my-changes.patch, and email it to [email protected]. Adom maintainers will review and apply.

See CONTRIBUTING.md inside the tarball/bundle for the full PR + ship workflow.

How shipping works after merge

  1. Maintainer merges your PR into main
  2. Maintainer tags v<X.Y.Z> + runs bash scripts/release-bridge.sh puppeteer on their box
  3. New zip + manifest published to this wiki page (replaces current version)
  4. Every Adom Desktop install running v1.7.19+ auto-picks up your change within 4 hours OR immediately via adom-desktop refresh_bridges

No NSIS installer rebuild required. Your code reaches real users in ~30s after merge.

License

MIT — see the LICENSE file in the tarball.


The Puppeteer bridge is one of three reference implementations bundled with Adom Desktop. It wraps puppeteer-core + Chrome for Testing to give Docker-side Claude full headful browser automation on the user's desktop — multi-window, multi-tab, file uploads, network interception, video recording.

If you're authoring a new third-party bridge, see the bridge SDK guide first. Use this page when you want to see how a Node-based bridge is wired.

Quick facts

Name puppeteer
Display Puppeteer (Chrome for Testing)
Spawn kind Node (server.js)
Port 8851
Verb prefixes browser_*, desktop_recorder_*, desktop_record_* (22 verbs)
Source zip puppeteer-bridge-v1.0.0.zip
Manifest puppeteer-bridge-manifest.json
User-facing skill pup-SKILL.md

What it does

  • Sessions + tabsbrowser_open_window spawns Chrome for Testing with a per-session profile (cookies, IndexedDB, localStorage isolated). browser_open_tab / browser_close_tab manage tabs within a session.
  • Navigation + introspectionbrowser_navigate, browser_back/forward/reload, browser_screenshot (full-page or viewport), browser_evaluate (run JS, return result).
  • Input synthesisbrowser_click, browser_type, browser_press_key, browser_input_dispatch (low-level CDP Input.dispatchKeyEvent for cases where typing through React state handlers fails).
  • Recordingbrowser_record_start per-tab via CDP Page.startScreencast, desktop_record_start for full-desktop via getDisplayMedia + MediaRecorder in a hidden Chrome window.
  • Network capturebrowser_fetch_url runs fetch() from inside the page context (uses session cookies); useful for endpoints that gate by SameSite/CORS.

bridge.json

{
  "manifest_version": 1,
  "name": "puppeteer",
  "displayName": "Puppeteer (Chrome for Testing)",
  "version": "1.0.0",
  "description": "Headful browser automation via puppeteer-core + Chrome for Testing. Multi-window, multi-tab, recording, file uploads, network interception.",
  "homepage": "https://github.com/adom-inc/adom-desktop",
  "author": "Adom Inc.",
  "license": "MIT",
  "spawn": {
    "kind": "node",
    "entrypoint": "server.js",
    "port": 8851,
    "healthEndpoint": "http://127.0.0.1:8851/status",
    "stopMethod": "kill",
    "killImageName": "node.exe"
  },
  "verbPrefixes": ["browser_", "desktop_recorder_", "desktop_record_"],
  "verbs": [
    "browser_open_window", "browser_open_tab", "browser_close_tab", "browser_close_window",
    "browser_navigate", "browser_back", "browser_forward", "browser_reload",
    "browser_click", "browser_type", "browser_press_key",
    "browser_screenshot", "browser_evaluate", "browser_fetch_url",
    "browser_input_dispatch",
    "browser_record_start", "browser_record_stop", "browser_record_status", "browser_record_list",
    "desktop_recorder_open", "desktop_record_start", "desktop_record_stop"
  ],
  "dependencies": { "node": ">=20", "chrome": ">=120" },
  "category": "Browser Automation",
  "tags": ["puppeteer", "chrome", "headful", "recording"]
}

Note: verbPrefixes is an array with THREE entries (browser_*, desktop_recorder_*, desktop_record_*). One bridge can own multiple prefixes.

Architecture highlights

puppeteer/
├── server.js              ← HTTP entry point; routes /command → handler functions
├── credential_vault.js    ← Per-session cookie/storage isolation
├── adom-icon.svg          ← Window icon for spawned Chrome instances
└── (npm install lays down node_modules + puppeteer-core)

The bridge intentionally keeps minimal on-disk state — puppeteer-core does the heavy lifting and Chrome for Testing is downloaded into ~/.cache/puppeteer/ on first run. The bridge code itself is one large server.js (~2k lines) using http.createServer for the JSON-over-HTTP dispatch layer (same shape as the hello sample, just more handlers).

Session model

# Open a window for session "design-review" with its own Chrome profile
adom-desktop browser_open_window '{"sessionId":"design-review","profile":"design-review","url":"https://staging.example.com"}'

# Add a tab in the same window
adom-desktop browser_open_tab '{"sessionId":"design-review","url":"https://staging.example.com/cart"}'

# Screenshot the active tab
adom-desktop browser_screenshot '{"sessionId":"design-review"}'

# Evaluate JS in the page (returns the resolved value)
adom-desktop browser_evaluate '{"sessionId":"design-review","expr":"document.querySelectorAll(\"button\").length"}'

# Close the whole window when done
adom-desktop browser_close_window '{"sessionId":"design-review"}'

The sessionId is the persistence key — close + reopen the same session and you get the cookies + localStorage from before. profile defaults to the sessionId but can be shared across sessions for IndexedDB / login state sharing.

Recording example

# Per-tab recording → CDP screencast → JPEG frames → ffmpeg-mux'd tar on stop
adom-desktop browser_record_start '{"sessionId":"design-review","tabId":"tab-1","fps":30}'
# … drive the page …
adom-desktop browser_record_stop '{"recordingId":"rec-tab-…"}'

# Full-desktop recording → hidden Chrome window with getDisplayMedia + MediaRecorder → WebM
adom-desktop desktop_recorder_open
adom-desktop desktop_record_start '{"reason":"Demoing the alignment dialog flow","monitor":"primary"}'
# … drive the desktop …
adom-desktop desktop_record_stop

Reason is required for desktop recording so the user always knows why the recorder activated — it's shown in the HUD panel that opens.

Reference: install the source locally to read

curl -L https://wiki-ufypy5dpx93o.adom.cloud/static/apps/adom-desktop/puppeteer-bridge-v1.0.0.zip -o /tmp/puppeteer-bridge.zip
mkdir -p /tmp/puppeteer-bridge && cd /tmp/puppeteer-bridge && python3 -c "import zipfile; zipfile.ZipFile('/tmp/puppeteer-bridge.zip').extractall()"
ls -la

Open server.js to see the dispatch shape, recorder lifecycle, and per-session profile management.

Related