{"slug": "show-hn-opera-cli-36-smaller-accessibility-snapshots-for-browser-agents", "title": "Show HN: Opera CLI, 36% smaller accessibility snapshots for browser agents", "summary": "Opera Software released Opera browser CLI - compact, a new accessibility snapshot format for AI browser agents that reduces snapshot size by 36% and cuts input token usage by up to 80% on a 7-task benchmark, while maintaining task completion rates.", "body_md": "06.30.26\n\n**Opera browser CLI - compact** is the default snapshot format of [opera-browser-cli](https://github.com/operasoftware/opera-browser-cli), a browser-automation tool built for AI agents. Across 50 static pages spanning Wikipedia, GitHub, MDN, Python documentation, and the RFC Editor, **Opera browser CLI - compact** produces snapshots roughly 36% smaller than the raw accessibility output browser agents typically consume. On a 7-task agentic browser benchmark adapted from the [AXI suite](https://axi.md), an LLM agent driving **Opera browser CLI - compact** completes every task while spending 66% fewer input tokens than the closest competing format and 80% fewer than the unprocessed baseline, in shorter wall time. Pass rate is unchanged across all conditions.\n\n**Opera browser CLI - compact** is a compression layer on top of three upstream projects that this paper credits and measures against. The sections below describe the transformation, the benchmarks, and the limits of what those benchmarks establish.\n\nBrowser-driving tools for language agents share a common shape: the page is captured as an accessibility-tree snapshot, returned to the model as text, and the model picks an element by id to drive the next action. The cost of every iteration is dominated by the size of that snapshot. opera-browser-cli inherits its place in this ecosystem from three upstream projects: chrome-devtools-mcp, opera-devtools-mcp, and chrome-devtools-axi.\n\n[ chrome-devtools-mcp](https://github.com/ChromeDevTools/chrome-devtools-mcp) (Google, Apache-2.0) is the Model Context Protocol server that drives a real Chrome browser. It is the source of the accessibility snapshot that every downstream tool starts from. An\n\n*accessibility tree*is the browser's semantic model of the page; each node carries a\n\n*role*and a set of attributes defined by the W3C\n\n[WAI-ARIA specification](https://www.w3.org/TR/wai-aria/). chrome-devtools-mcp serializes that tree as text: nodes labelled by ARIA role (\n\n`RootWebArea`\n\n, `StaticText`\n\n, `link`\n\n, …), each carrying attributes such as `url=`\n\n, `description=`\n\n, and a unique `uid=`\n\nreference the agent can act on. The role and attribute names used throughout this paper are standard ARIA terms drawn from that specification. In our benchmarks, this raw output is the `mcp-raw`\n\nbaseline.[ opera-devtools-mcp](https://github.com/operasoftware/opera-devtools-mcp) (Apache-2.0) is Opera's fork of chrome-devtools-mcp. It adds four Opera Neon AI tools —\n\n`opera_chat`\n\n, `opera_do`\n\n, `opera_make`\n\n, `opera_research`\n\n— that let agents delegate work to Opera's built-in AI. The snapshot format is unchanged from upstream. The `mcp-raw`\n\nnumbers reported below are the bytes opera-devtools-mcp returns, identical in shape to chrome-devtools-mcp's output.**AXI** (Agent eXperience Interface; Kun Chen, [https://axi.md](https://axi.md)) is a design framework of ten principles for command-line tools intended for AI agents: token-efficient output, combined operations, contextual next-step hints, ambient session context, structured errors, definitive empty states, and others. Its reference browser implementation, [ chrome-devtools-axi](https://github.com/kunchenguid/chrome-devtools-axi), wraps chrome-devtools-mcp in an AXI-shaped CLI: a persistent local bridge process, a compact\n\n`@uid`\n\nreference convention, TOON-encoded metadata, and a `help[]`\n\nblock on every response that suggests next-step commands.**opera-browser-cli** is a fork of chrome-devtools-axi that wraps opera-devtools-mcp instead of chrome-devtools-mcp. From AXI it inherits the CLI shape, the bridge architecture, the help-block convention, and the broad surface of commands. From opera-devtools-mcp it inherits the raw snapshot format and the Neon AI tools. **Opera browser CLI - compact** is the additional layer opera-browser-cli applies between the raw MCP output and the text the agent receives.\n\nThe contributions documented here are the specific transformation, the benchmark results, and the decision to apply the transformation by default.\n\nA typical browser-agent loop looks like:\n\n```\nopen → inspect → identify element → act → inspect → extract → answer\n```\n\nEach `inspect`\n\nstep pays the snapshot cost in input tokens. On dense pages the raw accessibility output can exceed a hundred thousand tokens. A multi-step task that re-snapshots after every action multiplies that cost across the trajectory.\n\n**Opera browser CLI - compact** removes redundant bytes that do not add useful information for the agent, such as repeated labels, implied ARIA defaults, duplicate URL origins, whitespace-only nodes, and repeated citation links. This makes the page representation smaller while preserving the information the agent actually needs.\n\n**Opera browser CLI - compact** applies three layers of transformation, in order: structural clean-up, an output-length cap, and a URL lookup table.\n\nEach transformation in this layer is applied independently to each line of the snapshot.\n\n**References are rewritten** from`uid=X_Y`\n\nform to`@X.Y`\n\nform, because the dot tokenises into fewer tokens than the underscore.**Role names are shortened** where the long form carries no extra meaning:`RootWebArea`\n\nbecomes`root`\n\n,`StaticText`\n\nbecomes`text`\n\n,`DisclosureTriangle`\n\nbecomes`disclosure`\n\n, and so on.**Redundant attributes are stripped.** Most are values the[WAI-ARIA specification](https://www.w3.org/TR/wai-aria/)defines as implicit for the role and therefore recoverable: the`polite`\n\n/`assertive`\n\nlive-region settings and`atomic`\n\nflag on`status`\n\nand`alert`\n\n,`relevant=\"additions text\"`\n\n(the ARIA default for any live region), the selectable nature of`option`\n\nand`tab`\n\n, and the expandable-with-popup nature of`combobox`\n\n. A few attributes that do not affect which actions the agent can take are also dropped —`aria-orientation`\n\nand`aria-autocomplete`\n\nmodes — on the grounds that they rarely inform navigation. Empty values (`valuetext=\"\"`\n\n) and attributes made redundant by a sibling (`disableable`\n\nalongside`disabled`\n\n) are removed as well.**Empty nodes are dropped**— line-break nodes, whitespace-only text, and text children that simply echo the accessible name of their parent.** Headings become Markdown.**A node like`heading \"Foo\" level=2`\n\nis rewritten as`## Foo`\n\n, which is shorter and uses a format models already parse fluently.**URLs are cleaned.** Same-origin URLs are stripped to their path (`https://en.wikipedia.org/wiki/Moon`\n\nbecomes`/wiki/Moon`\n\non a Moon page); cross-site tracking parameters (`utm_*`\n\n,`gclid`\n\n,`fbclid`\n\n,`msclkid`\n\n, etc.) are removed;`javascript:`\n\nand`data:`\n\nURLs that carry no actionable destination are dropped entirely.**Repeated boilerplate is deduplicated.** Description strings repeated on every element of a list (\"use arrow keys to navigate\" and similar) are kept on first occurrence and elided thereafter.**Fragments are merged.** Consecutive text nodes at the same indent — common in fragmented Wikipedia infobox rows — are collapsed into one line.**Numeric attribute values are unquoted**—`level=\"2\"`\n\nbecomes`level=2`\n\n, saving the two quote characters per numeric attribute.\n\nAll transformations are deterministic and preserve addressability: every `@X.Y`\n\nreference remains a valid handle for subsequent tool calls.\n\nopera-browser-cli truncates compact snapshots at **12,000 characters** by default. Raw snapshots cap at 16,000. The `--full`\n\nflag disables the cap entirely, and every truncated response carries a `help[]`\n\nentry telling the agent how to ask for the full snapshot if it needs more.\n\nThe cap is not a fixed token budget — pages compress to different sizes — but it bounds the worst case.\n\nAfter clean-up and after truncation, URLs that appear multiple times are replaced with short `$uN`\n\ntokens, and a trailer lists each token's full value. Very long single-occurrence URLs — typically signed cloud URLs or data-encoded images — are also tokenised; the trailer reports only their byte size and a short preview rather than the full value.\n\nThe lookup table runs after the cap, so the trailer never references a URL absent from the body. The bytes that fit within the cap therefore carry page content rather than repeated URL strings.\n\nThe three layers compose as follows. Structural clean-up reduces the bytes required to represent the same content by roughly a third. The cap converts that reduction into an order-of-magnitude reduction on long pages, at the cost of completeness. The lookup table runs on the already-truncated body, so it does not change which content fits within the cap; it shortens repeated and oversized URLs in that body and reclaims those bytes in the final output, with a trailer that lists only URLs the agent can actually see.\n\n`example.com`\n\nin raw mode:\n\n```\nuid=2_0 RootWebArea \"Example Domain\" url=\"https://example.com/\"\n  uid=2_1 heading \"Example Domain\" level=\"1\"\n  uid=2_2 StaticText \"This domain is for use in documentation examples without needing permission. Avoid use in operations.\"\n  uid=2_3 link \"Learn more\" url=\"https://iana.org/domains/example\"\n    uid=2_4 StaticText \"Learn more\"\n```\n\nThe same page in compact mode:\n\n```\n@2.0 root \"Example Domain\" url=\"/\"\n  @2.1 # Example Domain\n  @2.2 text \"This domain is for use in documentation examples without needing permission. Avoid use in operations.\"\n  @2.3 link \"Learn more\" url=\"https://iana.org/domains/example\"\n```\n\nChanges visible in these five lines: the `uid=X_Y`\n\n→ `@X.Y`\n\nreference rewrite, the Markdown heading, the shortened role name (`RootWebArea`\n\n→ `root`\n\n), the same-origin URL collapsed to a single slash, and the removal of the echoed `\"Learn more\"`\n\ntext node whose content was already carried by its parent link.\n\nThe tail of the Moon Wikipedia article in compact mode, showing the tokenised citation URLs and the trailer:\n\n```\n    @8.324 link \"[5]\" url=$u7\n    @8.328 link \"Polar\" description=\"Geographical pole\" url=\"/wiki/Geographical_pole\"\n    @8.330 text \" radius1736.0 km(0.2731 of Earth's)\"\n    @8.337 link \"[5]\" url=$u7\n    @8.341 link \"Flattening\" url=\"/wiki/Flattening\"\n    @8.343 text \"0.0012\"\n    @8.344 link \"[5]\" url=$u7\nurls:\n  $u1 /wiki/Natural_satellite\n  $u2 /wiki/Light-second\n  $u3 /wiki/Astronomical_unit\n  $u4 /wiki/Lunar_distance_(astronomy)\n  $u5 /wiki/Moon#cite_note-W06-1\n  $u6 /wiki/Orbital_period\n  $u7 /wiki/Moon#cite_note-NSSDC-7\n```\n\nEach `[5]`\n\nfootnote would otherwise carry its full citation URL inline. The tokenised form costs three characters per occurrence; the full URL appears once in the trailer.\n\nThe same page (Moon, capped output) under each mode, counting interactive elements — links, buttons, inputs, headings — visible within the snapshot:\n\n| Mode | Cap (chars) | Bytes used | Interactive elements visible |\n|---|---|---|---|\n`opera-compact` |\n12,000 | 12,499 | 104 |\n`opera-raw` |\n16,000 | 16,706 | 80 |\n\nAt roughly 25% less byte budget, the compact snapshot surfaces **30% more actionable elements**. Bytes that raw mode spends on echoed text, default ARIA attributes, and repeated origin prefixes are instead spent on content from further down the page. Both snapshots reach roughly the same depth in the document.\n\nTwo benchmarks are reported, both implemented [in the opera-browser-cli repository](https://github.com/operasoftware/opera-browser-cli/tree/main/benchmarks): a static benchmark that measures the byte cost of CLI output without involving a language model, and an agentic benchmark that runs an LLM against a fixed set of browser tasks.\n\n50 static pages — 10 each from Wikipedia, GitHub, MDN, Python docs, and the RFC Editor — opened by each tool in full (uncapped) mode, with tiktoken counting the output.\n\n| Condition | Avg tokens | Median tokens | p95 tokens |\n|---|---|---|---|\n`opera-compact` |\n60,600 |\n24,300 |\n256,100 |\n`mcp-raw` |\n94,700 | 45,000 | 391,300 |\n`opera-raw` |\n94,900 | 45,100 | 381,400 |\n`axi` |\n98,500 | 46,600 | 396,900 |\n\n`mcp-raw`\n\nis the raw snapshot from opera-devtools-mcp; `opera-raw`\n\nis the same content through opera-browser-cli with compression disabled; `axi`\n\nis chrome-devtools-axi's full snapshot.\n\nThe three uncompressed conditions land within a few percent of one another, indicating they report substantively the same accessibility tree with thin CLI-shaped differences. The size gap to `opera-compact`\n\nis attributable to the compression layer rather than to differences between the underlying tools.\n\nThe gap is consistent across average, median, and p95 (roughly 36%, 46%, and 35% respectively). The p95 figure is the most relevant for production budgeting: a single 256k-token snapshot can exhaust a context window regardless of average page cost.\n\nSeven browser tasks adapted from the [AXI bench-browser suite](https://github.com/kunchenguid/axi/tree/main/bench-browser), run by an LLM agent (`gpt-5.5`\n\n, medium reasoning effort) and graded pass/fail by an LLM judge. Each task is repeated five times per condition for a total of 35 runs per condition. The agent itself decides whether to ask for a full snapshot based on what it observes. Tasks span single-step lookups (page heading, fact in an infobox, repo metadata), multi-step navigation (follow a link, extract a value from the next page), and short investigations (recent issue titles, top of a long table).\n\n| Condition | Pass | Avg input tokens | Avg snapshot chars | Avg wall time [s] | Avg tool calls |\n|---|---|---|---|---|---|\n`opera-compact` |\n100% |\n36,300 |\n83,100 |\n6.8 |\n1.4 |\n`opera-raw` |\n100% | 107,500 | 198,100 | 8.5 | 1.6 |\n`axi` |\n100% | 102,200 | 203,900 | 9.8 | 1.5 |\n`mcp-raw` |\n100% | 179,200 | 218,700 | 9.4 | 2.1 |\n\nAll four conditions complete every task. The differences are in cost:\n\n**66% fewer input tokens than**(107.5k → 36.3k), the closest condition.`opera-raw`\n\n**80% fewer input tokens than**(179.2k → 36.3k), the unprocessed baseline.`mcp-raw`\n\n`mcp-raw`\n\nalso requires more tool calls per task (2.1 vs 1.4), compounding the per-call cost.**~30% lower wall time**(6.8 s vs 8.5–9.8 s).`axi`\n\nsits between`opera-raw`\n\nand`opera-compact`\n\non input tokens, indicating that the AXI CLI layer contributes savings independent of`opera-compact`\n\ncompression layer.`opera-compact`\n\nis additive to that contribution rather than a substitute.\n\nThe results above apply to a specific evaluation setup:\n\n**Pass rate ceilings at 100%** across all four conditions on the 7-task suite. The benchmark therefore cannot detect whether compression introduces occasional task failures. The efficiency results are valid as measured; the reliability claim is bounded by the difficulty of the tasks.**The static corpus is documentation-class.** All 50 pages are server-rendered, text-heavy reference material. Single-page applications, dashboards, and app-style UIs are not represented; per-byte reductions on those page types may differ.**Single model, single run set.** Results use`gpt-5.5`\n\nat medium reasoning effort with`n=5`\n\nrepeats per task. Variance, alternative models, and alternative reasoning settings were not measured.\n\n**AXI**(Kun Chen,[https://axi.md](https://axi.md)) articulates the principle that agent-tool interfaces should be designed for agents from the start, not protocol-translated from human tools, and provides[chrome-devtools-axi](https://github.com/kunchenguid/chrome-devtools-axi)as a reference.**Opera browser CLI - compact** is an additional compression layer on top of that reference, not an alternative to it.**chrome-devtools-mcp**(Google, Apache-2.0) — the upstream MCP server jointly responsible for the underlying snapshot format we compress.** opera-devtools-mcp**(Apache-2.0) — our fork of chrome-devtools-mcp, adding the Opera Neon AI tools. Snapshot format is unchanged from upstream, which is what makes the`mcp-raw`\n\ncomparison meaningful.**TOON format**— used for the structured metadata blocks (`page:`\n\n,`help:`\n\n) in CLI output. Inherited from chrome-devtools-axi, not part of the snapshot-compression pipeline itself.\n\n**Opera browser CLI - compact** applies three transformations to the raw accessibility snapshot returned by opera-devtools-mcp: structural clean-up of nodes and attributes that are redundant under the role they appear in, a default 12,000-character cap on output length, and a URL lookup table that replaces repeated and very long URLs with short tokens. Together these transformations produce snapshots roughly 36% smaller per byte than the raw output, carry roughly 30% more interactive content within the default cap, and reduce LLM input tokens on a 7-task agentic benchmark by 66–80% relative to the nearest baseline, without changing pass rate.\n\nThe transformations remove only structure that is redundant under the role information already present in each node. Reference identifiers, interactive affordances, headings, and link destinations are preserved.\n\n- opera-browser-cli —\n[https://github.com/operasoftware/opera-browser-cli](https://github.com/operasoftware/opera-browser-cli) - opera-devtools-mcp —\n[https://github.com/operasoftware/opera-devtools-mcp](https://github.com/operasoftware/opera-devtools-mcp) - chrome-devtools-mcp —\n[https://github.com/ChromeDevTools/chrome-devtools-mcp](https://github.com/ChromeDevTools/chrome-devtools-mcp) - chrome-devtools-axi —\n[https://github.com/kunchenguid/chrome-devtools-axi](https://github.com/kunchenguid/chrome-devtools-axi) - AXI —\n[https://axi.md](https://axi.md) - AXI bench-browser —\n[https://github.com/kunchenguid/axi/tree/main/bench-browser](https://github.com/kunchenguid/axi/tree/main/bench-browser)\n\nFor any questions or clarifications, please reach out to [press@opera.com](mailto:press@opera.com)", "url": "https://wpnews.pro/news/show-hn-opera-cli-36-smaller-accessibility-snapshots-for-browser-agents", "canonical_source": "https://github.com/operasoftware/opera-browser-cli/blob/main/docs/opera-compact-whitepaper.md", "published_at": "2026-07-01 12:10:25+00:00", "updated_at": "2026-07-01 12:20:35.364119+00:00", "lang": "en", "topics": ["ai-agents", "developer-tools", "ai-tools"], "entities": ["Opera", "Google", "Chrome DevTools", "AXI", "Opera browser CLI", "chrome-devtools-mcp", "opera-devtools-mcp", "chrome-devtools-axi"], "alternates": {"html": "https://wpnews.pro/news/show-hn-opera-cli-36-smaller-accessibility-snapshots-for-browser-agents", "markdown": "https://wpnews.pro/news/show-hn-opera-cli-36-smaller-accessibility-snapshots-for-browser-agents.md", "text": "https://wpnews.pro/news/show-hn-opera-cli-36-smaller-accessibility-snapshots-for-browser-agents.txt", "jsonld": "https://wpnews.pro/news/show-hn-opera-cli-36-smaller-accessibility-snapshots-for-browser-agents.jsonld"}}