Skip to content

Commit 95a07ec

Browse files
kapaleshreyasclaude
andcommitted
docs(runtime-bwrap): list poppler-utils as a required host package
The claude-agent-sdk engine's Read tool shells out to pdftoppm (from poppler-utils) for every PDF read — without it, "pdftoppm is not installed" fails the agent. Because we already bind /usr read-only into every sandbox, one apt install on the host makes pdftoppm visible in every current and future bwrap session. Surfaced live: a 3.7MB arxiv PDF uploaded via the attachments field arrived in the workdir byte-perfect but the agent couldn't render it until poppler-utils was installed on the EC2 host. After the install no code/restart was needed — the existing /usr read-only bind picks up the new binary automatically. Also expanded the host setup to document the same pattern for any other host CLI tools agents may need (unzip, jq, ffmpeg, sqlite3, ...) — install on host, available to all sandboxes for free. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
1 parent 5d3b2d0 commit 95a07ec

1 file changed

Lines changed: 25 additions & 4 deletions

File tree

packages/runtime-bwrap/README.md

Lines changed: 25 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,11 @@ Inside the sandbox the agent sees:
5151
```bash
5252
# Debian/Ubuntu
5353
sudo apt-get update
54-
sudo apt-get install -y bubblewrap unzip curl ca-certificates
54+
sudo apt-get install -y \
55+
bubblewrap `# the sandbox itself` \
56+
unzip curl ca-certificates `# build/install prereqs` \
57+
poppler-utils `# PDF rendering — Claude Code's Read tool shells out to pdftoppm` \
58+
git `# for git-source GAP repos`
5559

5660
# Node 22 (NodeSource)
5761
curl -fsSL https://deb.nodesource.com/setup_22.x | sudo -E bash -
@@ -63,12 +67,29 @@ curl -fsSL https://bun.sh/install | bash
6367
echo 'export PATH="$HOME/.bun/bin:$PATH"' >> ~/.bashrc
6468

6569
# Verify
66-
bwrap --version # >= 0.11
67-
node --version # >= 22
68-
pnpm --version # 9.x
70+
bwrap --version # >= 0.11
71+
node --version # >= 22
72+
pnpm --version # 9.x
6973
~/.bun/bin/bun --version
74+
pdftoppm -v 2>&1 | head -1 # >= 23.x (any recent poppler is fine)
7075
```
7176

77+
### Why poppler-utils?
78+
79+
The `claude-agent-sdk` engine spawns the Claude Code CLI binary inside the
80+
bwrap sandbox. Claude Code's `Read` tool, when given a `.pdf` file path,
81+
calls `pdftoppm` from `poppler-utils` to rasterize each page to a PNG, then
82+
ships those PNGs to the Anthropic API as image content blocks. **Without
83+
`pdftoppm` on PATH, every PDF read fails with "pdftoppm is not installed".**
84+
85+
Because we bind `/usr` read-only into every sandbox (see `bwrap-args.ts`),
86+
installing `poppler-utils` once on the host makes it visible to every
87+
current and future bwrap session — no per-session staging needed.
88+
89+
The same applies to any other host-side CLI tool an agent might need at
90+
runtime (`unzip`, `jq`, `ffmpeg`, `sqlite3`, etc.). Install on the host,
91+
they show up in `/usr/bin` inside the sandbox automatically.
92+
7293
### Get the code
7394

7495
The simplest path is a tarball of committed files (no node_modules, no

0 commit comments

Comments
 (0)