dieter-medium/bidi2pdf/render-pdf
Claude Code and agent skill by dieter-medium/bidi2pdf
- community
Checking that the SKILL.md file is still in the repository.
This skill should be used when a web page, a URL or an HTML file has to become a PDF with bidi2pdf's command line, including a PDF of a page's screen view, dark mode or mobile layout, a tagged (accessible) PDF, or a PDF piped through stdin/stdout. Covers the order of commands, the waits, reading the JSON result and the exit codes.
Install
npx vskill@latest install dieter-medium/bidi2pdf/render-pdfSKILL.md
Render a PDF with the bidi2pdf CLI
bidi2pdf prints a page in a real Chrome over WebDriver BiDi. This skill is the order of work and the pitfalls; the exact options are in bidi2pdf help render, the exact result shape in bidi2pdf schema render. Read those instead of guessing an option.
Does not: scrape page content or automate a site (log in, click through). bidi2pdf is a renderer; for a page that needs steps before printing, write a recipe (the pdf-recipe skill).
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. Preflight
One call answers three questions: is bidi2pdf there at all, which version (bidi2pdf), and whether pages will be filled (pdf_reader is null without that gem). --media, --color_scheme and --reduced_motion, and a clean stdout for --json and --output -, need 0.1.23 or later. If bidi2pdf help render does not list an option, the installed gem is older - say so instead of working around it.
When bidi2pdf is missing, look first, install nothing yet, and suggest the lightest way that fits:
- Docker answers (
docker infoprints a server version, not an error - an installed client
without a reachable daemon or socket permission does not count): nothing to install, the image has Ruby, Chromium and pdf-reader. Inside a container that uses the host's Docker, -v mounts a path of the host, not of the container.
- Ruby 3.4 or later is there:
gem install bidi2pdf, plus a browser if none was found.
pdf-reader only when the page count is needed.
- No Ruby, or an older one: a distribution's Ruby is too old (Debian 12 ships 3.1, Debian 13
3.3, Ubuntu 24.04 3.2 - and a node image is Debian). Homebrew's ruby on macOS, a version manager (mise, rbenv) elsewhere - or option 1, which needs no Ruby at all.
bidi2pdf fetches a matching chromedriver itself, which may fail on ARM Linux - there use the packaged chromium-driver. Ubuntu's chromium is a snap that does not run in a container: use a shared browser there (the remote-chrome skill).
Show the user the commands that fit and run them only after a yes - they change the system.
Where Chrome runs:
- A shared browser (a chromedriver container): pass `--remote-browser-url
http://<host>:3000/session to every command. The remote-chrome` skill sets one up.
- Local: bidi2pdf starts chromedriver itself; Chrome or Chromium must be installed. Inside a
container add --no-sandbox (or set DISABLE_CHROME_SANDBOX=true).
2. Render
- Waits. Without one, bidi2pdf prints as soon as the page's load event fired.
--wait-network-idle waits for late requests (lazy images, fetched data). --wait-window-loaded waits until the page's own script sets window.loaded = true - use it for Paged.js or any page that finishes rendering itself, never for a page that does not set it: that one waits the whole --default-timeout (60 s) and fails with COMMAND_TIMEOUT.
- Input.
--url,--html-file, or--stdinfor HTML on standard input - exactly one. - Output.
--output file.pdf;--output -writes the PDF bytes to stdout and nothing else (it
cannot be combined with --json).
- `--manifest` records what was rendered with which options, to reproduce or debug it later
(cookie values and secret headers are left out).
- Cookies, headers, basic auth:
--cookie name=value,--header Name=value,--auth user:pass.
3. Page size, margins, screen view, mobile layout
All sizes are centimetres: --page-width/--page-height (default US Letter, 21.59 x 27.94), --margin-top/-bottom/-left/-right. Chrome's own default margin is 1 cm a side.
By default Chrome prints with the page's print stylesheet. To print what the screen shows:
A mobile layout needs a narrow page. A printed page is laid out between its side margins, at 96 / 2.54 = about 37.8 CSS px per cm, so set the side margins yourself:
9.525 cm without side margins is 360 px; 8.467 cm is 320 px. With Chrome's default 1 cm margins a 9.5 cm page is only about 283 px wide and may hit a smaller breakpoint than intended.
For an accessible PDF add --generate-tagged-pdf (and --generate-document-outline for bookmarks).
4. Read the result, not the logs
With --json, stdout carries exactly one JSON document; logs go to stderr. Check ok, then:
pages,bytes,sha256of the PDF.pagesisnullwithoutpdf-reader, with a warning:
report it that way, or ask before installing that gem - no other PDF tool for a page count.
navigation.final_url- a redirect to a login page answers 200 and prints perfectly. (A status
of 400 or more fails the render instead.)
network_failuresandconsoleeven whenokis true: a missing image still gives a PDF.- On failure
error.code,error.retryableanderror.hint. Retry only whenretryableis true.
The exit code says the same without parsing:
| Code | Exit | Meaning | |
|---|---|---|---|
INVALID_PRINT_OPTION | 2 | an option value bidi2pdf refuses - fix the command | |
MISSING_INPUT | 2 | none of --url, --html-file, --stdin given | |
DNS_ERROR | 3 | the host does not resolve from the browser's machine | |
NAVIGATION_TIMEOUT | 3 | the page did not load in time | |
NAVIGATION_NOT_FOUND | 3 | the URL answered 404 | |
NAVIGATION_FAILED | 3 | the URL answered another 4xx/5xx, or the connection failed | |
BROWSER_LAUNCH_FAILED | 3 | no Chrome/chromedriver - see section 1 | |
COMMAND_TIMEOUT | 3 | a wait never finished (often --wait-window-loaded) | |
PDF_GENERATION_FAILED | 6 | Chrome could not print | |
OUTPUT_WRITE_FAILED | 6 | the output path cannot be written |
The full list: bidi2pdf schema render (the error object) and README "Exit codes".
--json-stream writes one progress event per line to stderr while it runs (bidi2pdf schema event), for a long render a user should see move.
5. When it fails or looks wrong
Only then, with the same options as the render:
diagnose loads the page like render and prints no PDF; console, network_failures, fonts.status, print_media and paged_js usually name the cause. The checklist: the diagnose-pdf skill.
Security
- Security scanPassed, 90 of 100Pattern checks on the skill's files.
- Model reviewPassed
Quality evaluation
- Task evaluationNot runNo evaluation yet. Run one in Skill Studio.
Source
- SKILL.md in the repositoryCheckingclaude-plugin/skills/render-pdf/SKILL.md
Popularity
- Repository stars
- 58
- 7-day trend score
- 0
Stars and forks are for the whole GitHub repository, not this skill alone. Not refreshed yet.
Works with
Any agent vskill installs to: 56 targets in all. These 39 have a page on this site.
- Claude Code
- Cursor
- GitHub Copilot
- Windsurf
- Codex
- Gemini CLI
- Cline
- Amp
- Roo Code
- Goose
- Continue
- Kilo Code
- Junie
- Trae
- OpenHands
- Qwen Code
- AI Agent
- Tabnine Chat
- Sourcegraph Cody
- Amazon Q
- Firebase Genkit
- Sweep
- Devin
- Phind
- Mentat
- Claude Desktop
- Aider
- GPT Pilot
- Plandex
- bolt.new
- v0
- Replit Agent
- Anse
- TypingMind
- BetterChatGPT
- LibreChat
- Warp AI
- Pieces
- Fig AI
Embed badge
[](https://verified-skill.com/skills/dieter-medium/bidi2pdf/render-pdf)