@crouton-kit/capture

中文文档
1.4.36发布于 2026/11/02MIT近 30 天下载 6972

Browser automation and UI validation via CDP — session-based screenshots, HAR, a11y, click/type, and JS exec

原始使用文档
文档目录19 节
  1. Against the alternatives
  2. See it
  3. 1. Every command succeeded. The page is still broken.
  4. 2. The page looks finished. The measurements disagree.
  5. 3. Two changes shipped. Which one moved the button?
  6. 4. The layout flips between two pixel widths. Which two?
  7. 5. Name a component. Get the component.
  8. 6. How fast did that click actually answer?
  9. 7. Seven seconds of motion, in one still.
  10. 8. Drive the browser you are already signed into.
  11. 9. The cards paint first. Then one image moves them 400 pix…
  12. 10. The panels are closed. The browser is still holding all…
  13. 11. The API never answered. The dashboard didn't change by …
  14. Quick start
  15. The command surface
  16. How it fits together
  17. Targeting elements
  18. For agents
  19. License

capture — a browser automation command line for agents, built on the Chrome DevTools Protocol

capture

ci npm license

Browser automation that measures instead of guessing. A CDP command line built for agents.

A screenshot shows you what a page looks like. It does not show you why the button doesn't work.

capture answers questions about a live page with numbers and coordinates: what is covering this button, which CSS rule moved it, how long the page took to answer a click, what changed between two states, and which pixels moved and when. Every finding comes back with the element, the geometry, and the evidence it was read from.

npm install -g @crouton-kit/capture

Against the alternatives

Compared against @playwright/mcp 0.0.79 and chrome-devtools-mcp 1.8.0 — the Chrome DevTools MCP surface Claude Code drives — read at those published versions.

Both ship a JavaScript escape hatch, so much of this is reachable in either one — by writing the code yourself. ❌ below means the answer is not returned to you as a fact; it means you write and maintain the measurement.

capturePlaywright MCPChrome DevTools MCP
Bounding box of every element✅✅ browser_snapshot boxes:true❌ Must use raw JS
Names the element covering a target✅❌ Must use raw JS❌ Must use raw JS
Percentage of the target's box it covers✅❌ Must use raw JS❌ Must use raw JS
Full receiver stack at a point✅❌ Must use raw JS❌ Must use raw JS
Winning CSS declaration for a property✅❌ Must use raw CDP❌ Not reachable — no CSS tool, no CDP passthrough
Its specificity and source location✅❌ Must use raw CDP❌ Not reachable
Tap-target and contrast findings✅❌ Must use raw JS✅ lighthouse_audit, written to a report file
A rect on every finding✅❌ Must use raw JS❌ Inside the report file
A PNG crop of every finding✅❌ One screenshot call per element❌ No crops
Per-element style and geometry delta between two states✅❌ Must use raw JS❌ Must use raw JS
Cascade provenance on the property that changed✅❌ Must use raw CDP❌ Not reachable
Raster diff of two states✅❌ Diff two screenshots yourself❌ Diff two screenshots yourself
Steps a width range in one command✅❌ Your own resize loop❌ Your own resize loop
Brackets the exact pixel where layout state changes✅❌ Your own resize loop❌ Your own resize loop
Input → mutation → paint → settle for one interaction✅❌ Video file only❌ Trace insights are page-level
Per-frame geometry of one element through an animation✅❌ Video file only❌ Must use raw JS
Changed pixel regions attributed to elements✅❌ Must use raw JS❌ Must use raw JS
A whole interaction as one image✅❌❌
Stub network responses from ordered rules✅ tab mock✅ browser_route❌ No interception tools
Core Web Vitals with subparts and attribution✅ perf vitals❌ Trace file for the Trace Viewer✅ Trace insights
DevTools insight set — render-blocking, forced reflow, shift culprits✅ perf insights❌✅
Lighthouse, failing nodes in the reply✅ Per-node DOM path, selector, snippet❌❌ Scores and counts; findings in the report file
Heap census, retaining paths, snapshot diff✅ heap❌✅ Behind --memoryDebugging

Both still do things capture does not. Playwright MCP is cross-browser — the sharpest structural gap — and has storage-state save/restore, test-code generation, device presets, PDF export, and richer input verbs (hover, drag, file upload). Chrome DevTools MCP automates Chrome extensions and PWAs and has CPU-throttling presets. capture is Chromium-only and points at one question — what is this page actually doing, in numbers.

See it

Eleven short clips. Every overlay is real: the text is extracted from the command's actual stdout, the boxes are drawn at the coordinates the command printed, and the inset images are files a command actually wrote.

Each player below contains the full clip. Use its controls to play, pause, scrub, or fullscreen.

1. Every command succeeded. The page is still broken.

An agent checks out. The promo code applies and the total drops $691.20 → $518.40, so the page is clearly working. Then it clicks Complete purchase — reported clicked, nothing happens. Rather than guess, it measures. The hit test resolves the click to something that is not the button, and measure map paint names it: #consent, z-index 99, covering 100.00% of the button's ink box.

Playwright throws "element intercepts pointer events" and names nothing. A screenshot shows a perfect page.

capture measure map paint <snap> --selector "#pay" · full clip, 22s

2. The page looks finished. The measurements disagree.

One command measures a team-access page against thresholds and draws every failure onto it at real coordinates: a row control at 28×28 under the 44×44 floor, a helper line at 2.16:1 contrast, an identity column clipping the address it is showing you. Each finding carries a cropped PNG of its own evidence, and the gate exits nonzero.

capture measure check <snap> --for tap-targets,contrast,truncation --gate · full clip, 22s

3. Two changes shipped. Which one moved the button?

A report switches to Weekly, then a design-system stylesheet lands live. The Publish button is somewhere new. A pixel diff can only say "3% of pixels differ" — this names the element, both of its boxes, how far it moved, and the declaration that now wins, down to tokens-v2.css line 6.

capture measure diff --before <snap> --after <snap> · full clip, 27s

4. The layout flips between two pixel widths. Which two?

Instead of dragging a window edge until something snaps, sweep the axis. The viewport steps 619 → 620 → 621 → 622, the grid goes one column to two, and the command brackets the exact pair it happened between.

capture measure sweep --axis width --from 619 --to 622 · full clip, 21s

5. Name a component. Get the component.

The agent asks for a card and gets a cropped, padded, zoomed image of exactly that card — no coordinates, no full-viewport screenshot to squint at. It can ask by CSS selector or by the visible label a screen reader would read. Ask for button when six match, and it refuses to guess and lists all six.

capture page shot --crop-selector "#revenue-card" --pad 8 --zoom 1.5 · full clip, 24s

6. How fast did that click actually answer?

Record a real interaction, then read its timeline off the recording rather than eyeballing a screenshot: input dispatch, DOM mutation at +7.20ms, first paint at +18.76ms across 6276 changed pixels, settled at +325.06ms. Every row names the evidence it came from.

capture motion response <rec> --action "click:Run sweep" · full clip, 23s

7. Seven seconds of motion, in one still.

A model cannot watch a video. Hand it a screen recording and you are really handing it dozens of separate frames to reason across one at a time — expensive, and still hopeless, because the thing you care about is the motion between frames and no single frame contains it.

motion mask collapses the whole interaction into one image, which is the format a model reads well. Colour encodes when each pixel changed — blue is early, red is late — so the entire route of the payload is legible at a glance. Underneath it, the changed regions ranked largest first with the window each one moved in. The agent gets to see the animation.

capture motion mask <rec> --limit 4 · full clip, 22s

8. Drive the browser you are already signed into.

No storage-state dance and no separate automation profile. Attach over --port, adopt the tab already in front of you, drive it, and finish with one bundle: the recording, the HAR, the shots and the measurements together. The network panel is drawn from the captured HAR — every field read from that entry, nothing inferred, and credential headers withheld with their length marked in place.

capture session start --target <tab-id> --port 9860 · full clip, 30s

9. The cards paint first. Then one image moves them 400 pixels.

Record the load once, then ask it different questions. perf vitals reads the largest paint off the trace — nearly all of it one image's load, named by element and URL — and lists the shifts that image caused. perf insights returns the element each shift moved, with the rectangle it was in before and after: old_rect [28,99,1224,174] → new_rect [28,499,1224,174]. Then measure explain measures that same element on the settled page and prints x=28 y=499.75 w=1224 h=172.64. The trace engine and the DOM agree on where the KPI row ended up.

capture perf insights <trace> --name CLSCulprits --full · full clip, 24s

10. The panels are closed. The browser is still holding all five.

A console opens and closes five session panels. The deck ends empty and the page reports zero open — but two heap snapshots disagree. heap diff lists ten detached nodes still reachable and names each one by the constructor that built it: <div class="panel" id="session-1">. heap census puts 1,049,008 retained bytes behind one of them, and heap retainers walks the edge keeping it alive — a ClosedSession object holding the panel on its element property.

capture heap retainers <snap> --node <node-id> · full clip, 24s

11. The API never answered. The dashboard didn't change by one pixel.

The agent reads $518.40 off a revenue dashboard, installs one rule document that fails the metrics API, and reloads. The skeletons shimmer, the cards fill, and the page shows $518.40 again. measure diff --pixels reports 0 changed pixels across 1280×800, while the HAR for that one URL carries both loads side by side: 200 · 56 bytes, then response incomplete: failed. Mocking the route is the setup. The measurement is what shows the failure left nothing on screen to see.

capture tab mock start --rules <rules.json> · full clip, 26s

Quick start

Needs Node and a Chrome. capture tab launch starts a headless browser that capture owns and reaps — it looks for $CAPTURE_BROWSER, then a ~/.cache/puppeteer Chrome, then a system Chrome. If a CDP-enabled browser is already running, capture can attach to that instead.

capture tab launch                                    # start a browser capture owns
capture session start --url https://example.com       # open a tab, begin recording traffic
capture measure snap                                  # → snap-mtdpfnkr-08fbabdd
capture measure check snap-mtdpfnkr-08fbabdd --for contrast,tap-targets
capture session stop <session-id>                     # write the bundle manifest

Under a crtr agent node (CRTR_NODE_ID set), a browser command with no --port, no --target and no active session of that node is refused (no_owned_browser) rather than falling back to CDP_PORT, CDP_TARGET or localhost discovery, which could reach another node's browser. Start a session, or pass --port or --target. A shell without CRTR_NODE_ID is unchanged.

measure check reports real measurements, not opinions:

1. tap-targets — html > body > div > p:nth-of-type(2) > a measures 82×18px; threshold is 44×44px
   Rect: x=160 y=186.078125 w=82 h=18
   crop: snap-mtdpfnkr-08fbabdd/findings/1-tap-targets.png

Add --gate to check or diff and it exits nonzero on findings, so the same command works in CI.

The command surface

Ten roots. Every leaf renders prose by default and mirrors the same result under --json.

rootwhat it owns
sessionthe artifact container — records HAR, bundles artifacts, sets the active context
pageverbs against the live tab — click, type, scroll, navigate, exec, repeat, shot, elements, inspect
tabbrowser and tab plumbing — launch, quit, list, open, close, reset, network, mock
measuresettled-snapshot substrate plus read-only queries — snap, check, diff, explain, sweep, census, map, text
motionrecorder lifecycle plus queries over a recording — rec, mask, timeline, response, jank
perfperformance-trace substrate — trace records, vitals and insights read it
heapV8 heap-snapshot substrate — snapshot, census, objects, retainers, diff
lighthouseruns Lighthouse against a URL and stores its report unmodified
cdpraw Chrome DevTools Protocol escape hatch
libvault-lib introspection, for running forked libs in the tab

Run any of them bare for the subcommand list, or capture <root> <leaf> -h for a leaf's usage.

How it fits together

A session is the container; recorded substrates are what keep queries cheap.

  • A session is the container. It opens or adopts a tab, records HAR while it is active, and writes a bundle manifest when it stops. Everything produced while it runs lands in one directory.
  • A snapshot (measure snap) drives the page once and writes a settled substrate — geometry, styles, accessibility, layers, hit testing, text, forms, screenshot. Every other measure leaf is a cheap read over that artifact and never re-drives the browser.
  • A recording (motion rec) captures an interaction, one-shot or composed across several commands. Every other motion leaf reads the finalized recording.
  • A performance trace (perf trace) and a heap snapshot (heap snapshot) work the same way: record once, then vitals/insights and census/objects/retainers/diff are read-only queries over the artifact.

Findings exit 0 — they are a report, not a crash. Only check and diff accept --gate, which turns findings into exit 2.

Targeting elements

The driving verbs resolve exactly one element through a single grammar, and reject an ambiguous target with the list of candidates rather than picking one:

  • a bare CSS selector (takes precedence)
  • an exact accessible name, when CSS finds nothing
  • ax:<name>, axid:<id>, or backend:<id>

For agents

The CLI is designed to be read by a model: errors are structured, every error carries a follow_up naming the command that would fix it, and help is available at every level.

License

MIT

See CONTRIBUTING.md to contribute.

版本与发布记录

@crouton-kit/capture 共发布 51 个版本,首次发布于 2026/04/17;过去 12 个月发布了 51 个版本。

版本发布日期距今
1.4.36latest2026/11/029 天前
1.4.352026/11/029 天前
1.4.342026/10/2814 天前
1.4.332026/10/2714 天前
1.4.322026/10/2715 天前
1.4.312026/10/2715 天前

关于 @crouton-kit/capture 的常见问题

@crouton-kit/capture 是什么?

Browser automation and UI validation via CDP — session-based screenshots, HAR, a11y, click/type, and JS exec

如何安装 @crouton-kit/capture?

在项目目录运行 npm install @crouton-kit/capture,或使用 pnpm add / yarn add / bun add。它还提供命令行工具 capture,可以用 npx capture 直接运行。

@crouton-kit/capture 支持 TypeScript 吗?

该包的 package.json 没有声明类型入口。需要类型提示时,可以在 npm 上查找社区维护的 @types/crouton-kit__capture 是否存在。

@crouton-kit/capture 可以商用吗?

@crouton-kit/capture 使用 MIT 许可。宽松许可:允许商业使用、修改和再分发,通常只需在分发时保留原版权与许可声明。以上为概括,不构成法律意见,请以许可原文为准。

@crouton-kit/capture 的下载量有多少?

根据 npm 官方下载统计,@crouton-kit/capture 在 2026/10/11 – 2026/11/09 这 30 天内被下载 6,972 次,日均约 232 次。下载量会把 CI 构建、镜像同步和作为其他包依赖的安装一并计入,适合横向比较热度,不能直接等同于使用人数。

@crouton-kit/capture 还在维护吗?

最新版本 1.4.36 发布于 2026/11/02(9 天前);至今共发布 51 个版本,其中过去 12 个月发布了 51 个;首次发布于 2026/04/17。发布频率只是参考信号:功能稳定的工具可能很少需要更新,建议结合源码仓库的 issue 和提交记录判断。