brijr/iris: a Chrome-driven screenshot CLI and MCP camera for coding agents
Screenshots of live websites. Minimal interface, powerful engine.
At a glance
- What is it?
- Iris is a Rust CLI that renders live pages with your installed Chrome over the DevTools Protocol, and serves the same capture engine to coding agents through a local stdio MCP tool called capture. It is small, opinionated, and deliberately not a browser automation framework.
- Who is it for?
- Adopt Iris if you want one deterministic image per command or one inline image per agent tool call, and you already have a Chrome-family browser installed. Do not adopt it if you need to click, type, scroll interactively, capture cross-origin iframe contents, or grab every match of a selector; the README states those are out of scope.
- Can I use it commercially?
- Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Yes. The repository last received commits 8 days ago.
- What is it written in?
- Mainly Rust, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on September 18, 2026, and from our analysis. They are not legal advice.
DEEP OPEN-SOURCE ANALYSIS
The problem Iris picks: one trustworthy image, not a browser session
Most screenshot tooling asks you to think like a browser driver. You launch a session, navigate, wait for the right event, set a viewport, then decide when the page is really done. Iris collapses that into a single command. The README's framing is blunt: "A camera for coding agents. One fast command or MCP tool call produces one trustworthy image." The word doing the work there is trustworthy. A screenshot that fires before fonts and images settle is worse than no screenshot, because it looks correct at a glance.
The audience is narrow on purpose. It is for developers who need a visual check from a terminal or from an agent loop: a designer verifying a hero section, a backend engineer confirming a local dev server renders, an agent that has just edited CSS and needs to see the result. It is not for end-to-end test suites, visual regression platforms, or anyone who needs to script clicks and form fills. The README says so directly under the element-capture notes, and the setup prompt repeats the instruction to the agent: use Iris only as the camera.
How the capture engine works: your Chrome, the DevTools Protocol, and correctness waits
Iris does not ship a browser. It drives the Chrome-family browser you already have (Chrome, Chromium, Edge, or Brave) over the DevTools Protocol, which is why the only documented runtime dependency is that installed browser. The Rust dependency list backs this up: `chromiumoxide` with the `tokio-runtime` feature, plus `tokio` itself for the async runtime, `clap` for the CLI surface, `rmcp` for the MCP server, and `serde`/`serde_json` for the JSON Lines output.
The interesting part is what happens between navigation and shutter. The README states that Iris waits for fonts, image loads, entrance animations, and, on `--full`, scroll-triggers lazy-loaded content before capturing. Element capture with `--selector` scrolls the target into view and settles newly visible content before framing it. Those waits are the product. They are also why the README is careful about benchmarking: capture time includes navigation and the correctness waits, so comparisons are only meaningful when URL, capture mode, viewport, scale, Chrome version, and hardware all match.
One architectural detail matters for how you deploy it. The CLI starts a Chrome process for every invocation, while `iris mcp` keeps one Chrome process alive for the server's lifetime. That is a real difference in shape, not a tuning knob, and the README tells you to benchmark the two paths separately for exactly that reason.
Installing Iris and taking a first real capture
There are two documented install paths. The shell installer fetches a script from the repository and runs it; the Cargo path builds from source. Note the naming split: the crates.io package is `iris-screenshot`, but the installed command is `iris`. Building from source requires Rust 1.88 or newer, which matches the `rust-version` field in Cargo.toml.
curl -fsSL https://raw.githubusercontent.com/brijr/iris/main/install.sh | shcargo install iris-screenshotBefore anything else, confirm the binary resolves and that a Chrome-family browser is actually installed, since Iris has no bundled engine. The README's setup prompt suggests checking `iris --version` alongside the browser check.
iris --versionThe simplest real capture is a bare host. According to the README, this produces a 1440x900 image at 2x scale written to `example.com.png` in the working directory.
iris example.comFor a tighter, more useful image, target an element. `--selector` captures the first match in document order and `--padding` adds space around it. The README notes that `--padding` requires `--selector`, and that `--selector` conflicts with `--full`. Those two constraints will shape most of your commands.
iris --selector '#hero' --padding 24 app.devIf you want machine-readable output rather than a file, `--json` writes one JSON object per completed capture to stdout. The README gives this example, and the setup prompt uses the same shape for a smoke test.
iris https://example.com --selector h1 --padding 8 --scale 1 --json -o /tmp/iris-smoke.pngA successful run reports `status: ok` along with dimensions, scale, format, and byte count. Batch mode is also available: pass several URLs with `-o` pointing at a directory, or pipe a list from stdin with `iris - -o shots/`, where `#` comments are accepted. A failed URL prints a cross mark and does not abort the batch, though the process still exits 1 if anything failed.
Wiring iris mcp into a coding agent, and the first-capture cost
The MCP server is a local stdio server in the same binary, so there is nothing extra to install. For Codex, registration is one command, and the README suggests confirming it afterwards with `codex mcp get iris`. Other MCP clients use the equivalent JSON block with command `iris` and args `["mcp"]`.
codex mcp add iris -- iris mcp{
"mcpServers": {
"iris": {
"command": "iris",
"args": ["mcp"]
}
}
}The server exposes exactly one tool, `capture`. It returns the image inline with structured metadata and writes nothing by default; you pass `output` when the agent also needs a file on disk. The README's example arguments include `url`, `selector`, `padding`, `size`, `dark`, `format`, `timeout_seconds`, and `output`. Bare localhost, `.localhost`, and loopback addresses use HTTP automatically, while other bare hosts use HTTPS, which is a sensible default for local dev servers.
Two operational notes from the README are worth internalizing before you blame the tool. First, MCP clients may need a fresh agent task before the newly registered `capture` tool appears. Second, the first capture pays a startup cost. The README's reference table lists 965 ms for the MCP first capture on an Apple M2 Max, against a 366 ms median and 383 ms p95 for the next ten. Those figures are labeled as reference results, not a performance guarantee.
Where Iris stops: selectors, iframes, and the full-page scale fallback
The limitations are stated plainly, which is refreshing. Element capture is intentionally CSS-selector based and captures the first match in document order. There is no option to capture every match. Cross-origin iframe contents are not supported. `--selector` conflicts with `--full`, and `--padding` requires `--selector`. If your page renders its important content inside a third-party embed, Iris will frame the iframe element but not its interior.
There is also a hard ceiling inherited from Chrome. Full pages taller than Chrome's roughly 16k pixel render limit fall back to 1x scale automatically. The README says the report tells you which scale you got, so a downstream script that assumes 2x output can silently receive 1x on very long pages. Parse the JSON rather than assuming.
Finally, consider what Iris is not. It has no interaction primitives, no assertions, and no review tooling. The setup prompt explicitly instructs the agent not to add browser automation or interaction scripting. If your task is "log in, open the billing tab, screenshot the invoice table," Iris is the wrong tool, and no amount of selector work will fix that.
How Iris differs from Puppeteer and Playwright screenshot scripts
The obvious alternative is a screenshot script written with Puppeteer or Playwright. Those libraries give you a full automation API: click, type, wait for network idle, intercept requests, and capture as a side effect. Iris gives you a camera and nothing else.
The difference in approach shows up in three places. First, process model: a Puppeteer or Playwright script manages the browser lifecycle inside your program, whereas the Iris CLI spawns a Chrome process per invocation and `iris mcp` holds one open for the server's lifetime. Second, waiting strategy: with a general automation library you decide what to wait for, while Iris applies a fixed set of waits for fonts, images, entrance animations, and lazy-loaded content. That is less control and more consistency. Third, agent integration: Puppeteer and Playwright are libraries your agent would have to be taught to call, while Iris ships an MCP tool the agent can invoke directly and receive pixels inline.
If you already maintain a Playwright suite, adding a screenshot step there is cheaper than a second tool. If you want a single command or a single tool call that returns an image without writing browser code, Iris is the smaller surface.
Editorial conclusion
Adopt Iris if you want one deterministic image per command or one inline image per agent tool call, and you already have a Chrome-family browser installed. Do not adopt it if you need to click, type, scroll interactively, capture cross-origin iframe contents, or grab every match of a selector; the README states those are out of scope. Before wiring it into a pipeline, verify three things on your own machine: that `iris --version` resolves to a binary on PATH, that `codex mcp get iris` (or your client's equivalent) shows the server registered once rather than twice, and that a smoke capture against a local fixture returns `status: ok` with a non-empty file. The MCP first capture is the slow one, and the README's own numbers put it near a second, so do not judge the server by its first response.
Frequently asked questions
Does Iris require Chrome to be installed?
Yes. The README states the only runtime dependency is an installed Chrome-family browser: Chrome, Chromium, Edge, or Brave. Iris does not bundle a rendering engine.
What is the difference between the iris command and the iris-screenshot package?
The crates.io package is named `iris-screenshot`, while the installed command is `iris`. The README calls this out explicitly, so `cargo install iris-screenshot` is the correct install command.
Can Iris capture more than one element matching a selector?
No. The README states that element capture is intentionally CSS-selector based and captures the first match in document order, and that capturing every match is not supported.
Community notes