Getting it into your agent
One page per mod, every tool's command on it. A separate URL per tool would split the same page into five that compete with each other.
npx skills add dieter-medium/bidi2pdf --skill remote-chromegit clone --depth 1 https://github.com/dieter-medium/bidi2pdfWrote this? Show the measurements
A badge with what this costs and how it scanned, read live from this page, so it follows the numbers instead of freezing them. Markdown for a README, HTML for a documentation site or a project page.
[](https://agentmods.dev/skills/dieter-medium/bidi2pdf/remote-chrome)<a href="https://agentmods.dev/skills/dieter-medium/bidi2pdf/remote-chrome"><img src="https://agentmods.dev/badge/skills/dieter-medium/bidi2pdf/remote-chrome/github.svg" alt="Measured on agentmods" height="20"></a>Or the 80×15 button, for a site that already has a row of RSS and ATOM ones. Only the verdict fits; the numbers stay here.
<a href="https://agentmods.dev/skills/dieter-medium/bidi2pdf/remote-chrome"><img src="https://agentmods.dev/badge/skills/dieter-medium/bidi2pdf/remote-chrome.svg" alt="Reviewed on agentmods" width="80" height="20"></a>What it costs to keep this loaded
Counted locally with the o200k_base tokenizer, which is exact for GPT models; Claude uses its own tokenizer and its counts differ. Treat this as one consistent yardstick across the catalogue rather than a bill. Prices are per million input tokens.
| Model | Per session | Once invoked |
|---|---|---|
| Fable 5.1 | $0.00084 | $0.01623 |
| Opus 5.5 | $0.00034 | $0.00649 |
| Sonnet 5.5 | $0.00017 | $0.00325 |
| Haiku 4.5 | $0.00008 | $0.00162 |
Grade A, and why
remote-chrome scanned grade A with 0 findings against 26 rules in 11 categories — prompt injection, anti-refusal, data exfiltration, privilege escalation, supply chain, agent snooping, system-prompt leakage, SSRF and excessive agency — measured today.
A static scan of the body, not an audit. Every finding is printed with the line that produced it so you can judge whether it matters here. A mod is markdown that instructs an agent; that is exactly why what it instructs is worth reading.
Nothing flagged
None of the 26 patterns this scan looks for appear in this file: no shell pipes, no recursive deletes, no credential paths, no hidden text, no instruction-override or anti-refusal phrasing, no agent-config snooping. That is not a guarantee, it is the absence of the things that are checkable.
How it starts
The opening of the file, as written. The whole thing — 111 lines — stays where its author put it; the contents beside it link to each section on GitHub.
Run a shared Chrome for bidi2pdf
bidi2pdf talks to chromedriver over HTTP and WebDriver BiDi. A chromedriver container that several processes share is cheaper and more predictable than a browser per process, and keeps Chrome out of the application's own container.
Does not: cover Kubernetes or a cloud browser service, and does not make an untrusted page safe on its own (section 5 is what it takes).
Ground rules
- bidi2pdf is the renderer. If it fails, report its
error.code,error.hintand exit code; never make the PDF or screenshot another way (Chrome's own print-to-PDF, another PDF engine). - Install nothing unasked. Name what is missing and suggest a way (the
render-pdfskill's preflight); run nothing that changes the system without the user's yes. - bidi2pdf's results first. Read its
--jsonresult instead of inspecting the PDF with other tools.
1. The container
references/compose.remote-chrome.yml is a working Compose service, taken from an application that
runs it in development and production. The parts that matter, and why:
- Image
dieters877565/chromedriver(chromedriver + Chromium, hyphenation dictionaries included). It answers on port 3000; the new-session URL ishttp://<service>:3000/session. - No published port, an internal network only. Whoever reaches port 3000 drives a browser: keep
it to the containers that render. No VNC (
ENABLE_VNC: "false"). - Chrome's sandbox needs to create namespaces, which Docker's default seccomp profile only allows
with
CAP_SYS_ADMIN. Three ways, from the narrowest:- The gem's seccomp profile
docker/chrome-driver/chrome.json(security_opt: ["seccomp=chrome.json"]), no extra capability. It allows the namespace calls Chrome uses, but also some Docker's default refuses (mount,bpf,ptrace,perf_event_open); verify on your host that sessions start before relying on it. cap_add: [SYS_ADMIN]- works with the default profile, and is what the reference file uses. It is a broad capability: keep the container on its internal network and give it nothing else.- No extra capability, and every client passes
--no-sandbox(DISABLE_CHROME_SANDBOX=truefor the CLI). Chrome then runs every page without its own sandbox - only for pages you trust. Some CI runners drop--cap-addsilently; there only this works.
- The gem's seccomp profile
- Limits from measurement, not guesses: one Chrome session runs ~110 threads (Docker counts them
as pids) and a few hundred MB.
pids_limit: 1024,mem_limit: 2gwithmemswap_limitequal (no swap: a Chrome out of memory is killed and replaced instead of freezing every render),shm_size: 256m. At 512 pids and 1 GB, four concurrent renders crashed or froze it. WATCHDOG_ENABLED: "true"stops chromedriver when it stops answering or memory thrashes;restart: unless-stoppedthen starts a fresh container. The image's health check (/status) only marks it unhealthy - Docker never restarts an unhealthy container by itself.LANG/LANGUAGEset the browser's locale: date and number formats in form fields follow it.
What ships with it
1 file beside SKILL.md in the same directory: the scripts, references and assets a skill reads on demand. Not counted in the per-session cost; read them before you install if any of them is executable.
What this file has done since we first saw it
Hashed on every crawl. A supply-chain change to an agent config is a question of when, not whether, so the history is kept rather than the latest state alone.
- today Changed · +9 lines 4ff34a04498e
- yesterday First seen · 102 lines · 84 tokens per session scan A d545317c5a0e
remote-chrome is a skill published in the GitHub repository dieter-medium/bidi2pdf (58 stars, last pushed today), licensed MIT. It adds 84 tokens to every session and 1,623 once invoked, about $0.0003 per session on Opus 5.5. A static security scan graded it A with 0 findings. No closer match exists in the catalogue, so it is treated as the original; first seen 2026-10-26.
Other skills, from other repositories
experimental-code-coverage-cq-debugger
Executes the phased, multi-skill code coverage debugging playbook for triaging underreported code coverage in the Gerrit Commit Queue (CQ).
3pp
Guide for authoring and debugging 3pp (third-party package) recipes under //thirdparty//3pp/. Covers 3pp.pb schema, install.py platform traps, metadata validation, and driving the 3pp--packager trybots.
android-do-not-mock
How to write (or fix) Chromium Java unit tests (Robolectric / JUnit) without mocking or spying android.view.View, android.app.Activity, or their subclasses. Use when removing @SuppressWarnings("DoNotMock"), fixing a "DoNotMock" Error Prone error, replacing Mockito.mock(View.class) / @Mock Activity / spy(view), or when…
spanify-buffers
Find and fix unsafe buffer operations in a C++ file by removing UNSAFETODO markers and replacing unsafe raw pointers/C-style functions with base::span and standard safe containers. Use when the user asks to fix unsafe buffer warnings or -Wunsafe-buffer-usage errors. Don't use for other types of memory safety bugs like…
chrome-performance-optimizer
Autonomous multi-agent performance optimization loop for Chromium and V8. Supports profile-seeded mode (analyzing Speedometer 3 / JetStream profiles via pprof or Sagacity MCP) and pattern-driven discovery mode (fan-out exploration of Blink and V8 macro-patterns grounded in historical wins and past rejected CLs).…
cua-sandboxes
Create, use and clean up cua sandboxes (disposable Linux or macOS computers) on this computer with the cua CLI or the cua SDK, and browse the web inside one. Use when a task needs an isolated machine to run code, test an app, drive a desktop GUI, browse or test a website, fill a web form, take a web page screenshot…