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 m4ttstack/fast-browser --skill composing-evidencegit clone --depth 1 https://github.com/m4ttstack/fast-browserWrote 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/m4ttstack/fast-browser/composing-evidence)<a href="https://agentmods.dev/skills/m4ttstack/fast-browser/composing-evidence"><img src="https://agentmods.dev/badge/skills/m4ttstack/fast-browser/composing-evidence/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/m4ttstack/fast-browser/composing-evidence"><img src="https://agentmods.dev/badge/skills/m4ttstack/fast-browser/composing-evidence.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.00068 | $0.05894 |
| Opus 5.5 | $0.00027 | $0.02358 |
| Sonnet 5.5 | $0.00014 | $0.01179 |
| Haiku 4.5 | $0.00007 | $0.00589 |
Grade A, and why
composing-evidence 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 yesterday.
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 — 379 lines — stays where its author put it; the contents beside it link to each section on GitHub.
Composing Evidence
You name page elements and write words. Fast Browser measures them, crops to the card that holds them, and lays out every mark and label. On a live page you never place anything by pixel.
The pipeline
- Choose selectors. On a large page a full
browser_snapshotcan run to tens of thousands of tokens; usebrowser_find, or a snapshot scoped to the section you need, instead. Choose one for each thing the brief names and one for each personal detail the frame will hold, named in the brief or not, all in the first capture (seeredact). - Capture. Call
browser_capture_evidencewith{ targets: { <key>: "<selector>" }, frame: "auto", out: "<board>.c1" }.outis a plain file name. The tool screenshots the viewport at 2x, measures each target, and writes<board>.c1.pngand<board>.c1.capture.json(the sidecar) into~/.fast-browser/screenshots/. If the tool is not in your tool list, runfast-browser setup, ask the human to restart the Fast Browser session, and capture once it is back. - Check the return. Never edit the sidecar. A return is finished only
when
missedis empty,frameSnapis notunionand there is nofailedStep, and a thin strip the tool chose has had its retry or was left for the hiding budget (below); until then fix the cause, capture again, and write no spec. Remove a key the board does not need fromtargets. If the same key misses on the second capture, report it and stop that board; other boards in the same job continue. Do not compose around it.- It has
failedStep: readerror, then fix what that step names (args,resolve,frame,measure). failedStep: "frame"withframeSnap: "too-large": the targets cannot share one viewport-sized frame. Enlarge the viewport withbrowser_resize, or split them into separate boards.failedStep: "frame"saying the frame selector is larger than the viewport: pick a smaller element, or enlarge the viewport withbrowser_resize.failedStep: "frame"saying the frame selector does not contain every target: the frame is too tight. Pass, once, the next ancestor that holds each target's whole box (for a tab or link in a strip, the header region that holds the strip and the page title). Another selector for the same element is not a fix. If that fails too, report it and stop that board.- A key is in
missedasno-matchorambiguous: the selector is wrong. Fix it, scoping to a unique container. Forambiguous,countsays how many elements matched; read the structure of that region (browser_find, or abrowser_snapshotscoped to it) before the second capture, then scope to the smallest element that holds the wanted match and none of the others. Changing the words inside the same kind of selector is not a fix. - A key is in
missedasnot-visible(zero-size box): the element is collapsed or hidden. Open, expand or reveal it first. - A key is in
missedasout-of-view: it fell outside the viewport once the frame was centred, so the targets are too far apart for one view. Pass a tighterframe, enlarge the viewport withbrowser_resize, or split into separate boards. failedStep: "resolve"or"frame"saying the element is inside a shadow root or an iframe: it cannot be a target. Name the element that hosts it (the custom element, or theiframe) instead.frameSnapisunion: passframe: "<selector>"for the element that holds the targets and capture again. The frame from that capture is final, thin strip or not; if it is a thin strip, say so in the report. If that capture fails atframesaying the frame selector is larger than the viewport, try once more with a smaller element inside it that still holds every target: for a section heading, the heading's own header block with what sits beside it, not the whole section. Pick one that is not a thin strip; if the only one that fits is a thin strip, pass it, and its frame is final as above. Stop that board, and say so in the report, when that capture fails too, at any step (do not go one ancestor up from it), or when the budget is spent.frameis a thin strip (far wider than it is tall, or cutting through the card) when the tool chose the frame, that isframeSnapis neitherunionnorselector: try once withframe: "<selector>"for the element that holds the targets. If that capture succeeds and is no better, capture once more withframe: "auto"to get the tool's frame back, and say so in the report. If it fails, the earlier files are untouched: keep them and say so in the report. This retry is required, not optional, unless the budget went to hiding personal details (see the hiding rule): a report that names a thin strip names its retry, or says the retry was skipped for budget.- The capture PNG shows a value the board compares wrapped onto two
lines: widen the viewport with
browser_resizeuntil it sits on one line, and capture again. If a wider viewport leaves it wrapped, the page wraps it: write the value on one line in the mark'snoteand say there that the page wraps it. - The call fails with an error instead of a return (it timed out, the page moved while it was captured, the page lays out differently at 2x, the page is pinch-zoomed): do what the message says, then capture again once. If it fails the same way, report it and stop that board; other boards in the same job continue.
- It has
- Keep the sidecar. The return carries its path as
sidecar; carry that path forward. Compose refuses a sidecar whose image, frame, boxes or scale were changed afterwards. - Write the spec beside the sidecar, in
~/.fast-browser/screenshots/.capturenames the sidecar by its file name only. - Render.
fast-browser compose <spec.json>. If it lists problems, fix every one and run it again. Read any warnings it prints. Each warning names something compose could not lay out well; a tighter frame or a different mark usually clears it. The warninga panel is drawn small; frame the card that holds its marksmeans a panel shows too much to read at the size it is drawn. In apair, capture that panel again with a tighterframeselector (in apairof one region, capture both panels again on the same tighter region, with one selector where one names it on both pages; for a ticket image, shrink the panel'sframerectangle instead). Astepspanel is already cropped to its marks, so there mark fewer things in the panel, or things closer together. The warninga crop edge cuts through contentmeans astepspanel was cut at its marks' margin on a busy page: check that the cut hides nothing the step needs, and if it does, mark the element it cuts as well. If it says the renderer is not installed, runfast-browser setup.
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.
- yesterday Changed · +106 lines 68e9e0810edb
- 3d ago Changed · +159 lines · +9 tokens per session 56df14258a04
- 4d ago First seen · 114 lines · 59 tokens per session scan A 9a7e58be8b6e
composing-evidence is a skill published in the GitHub repository m4ttstack/fast-browser (0 stars, last pushed today), licensed MIT. It adds 68 tokens to every session and 5,894 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-12.
Other skills, from other repositories
browse
Use the browse CLI for Browserbase browser automation, Browserbase cloud APIs, Browserbase Functions, templates, web fetch/search, diagnostics, and Browse.sh skill discovery/installation. Use when the user asks to navigate pages, inspect browser state, run local or remote browser sessions, manage Browserbase…
auto-research
Research uncertain questions with an explicit, user-approved web search or ChatGPT consultation, then present options and wait for implementation approval.
moli-webfetch
Fetch, inspect, crawl, and capture live, JavaScript-rendered websites with Moli. Use when Codex needs current web content, web research, fact lookup, link following, a bounded crawl, client-rendered or response-gated content, network diagnostics, or a standalone HTML, Markdown, JSON, semantic-tree, viewport or…
moli-websearch
Search the web by keyword or reverse-search images with Moli to find subjects, sources, exact matches, or similar images—even when Moli is not named. For fetching a known URL, use moli-webfetch.
moli-cdp-server
Start Moli's CDP server and connect Playwright, Puppeteer, or raw CDP clients. Use to run a headless-browser CDP endpoint, replace a Chromium process, attach over CDP, enable real layout and screenshot surfaces, or diagnose CDP discovery, connection, and target startup—even when Moli is not named.
webcmd-browser
Use when a live browser task requires Playwright interaction, authenticated handoff, visible UI verification, or ad-hoc page inspection.