The browser is built in
What you get
Your agent reads documentation, searches the web and works with pages that take shape in the browser. One call opens the page, waits for the result and pulls out exactly the data the agent needs. Page content enters the context fenced, as data.
Before and after
The question for the serde_json documentation on docs.rs: Which types have a from_str method? The search of the Rust documentation answers that. It runs as JavaScript in the browser.
Without greppy
The agent loads the search page with curl and searches the HTML.
$ curl -sL 'https://docs.rs/serde_json/latest/serde_json/?search=from_str' | grep -o 'href="[^"]*from_str[^"]*"'
href="/serde_json/1.0.151/serde_json/?search=from_str"
href="fn.from_str.html"
href="fn.from_str.html"
$ curl -sL 'https://docs.rs/serde_json/latest/serde_json/?search=from_str' | grep -c 'search-results'
0
curl gets the page, but no search: the page's JavaScript builds the result list afterwards. All the HTML holds is the from_str function from the sidebar. Without a browser, the agent loads every type page one by one and searches it.
With greppy
$ greppy web do open 'https://docs.rs/serde_json/latest/serde_json/?search=from_str' :: wait 'css=.search-results a' :: extract 'css=.search-results .result-name'
returned; page observed — snapshot, not a verified task outcome
…
title: "\"from_str\" Search - Rust"
url: "https://docs.rs/serde_json/latest/serde_json/?search=from_str"
…
returned; expectation held
operation="web.wait"
UNTRUSTED_PAGE_CONTENT
{"detail":{"matched":9.0},"held":true,"waited_ms":2124}
…
value: {"count":9.0,"rows":[{"text":"function serde_json::from_str"},{"text":"method serde_json::Deserializer::from_str"},{"text":"method serde_json::Map::from_str"},{"text":"method serde_json::Value::from_str"},{"text":"method serde_json::Number::from_str"},{"text":"method serde_json::value::RawValue::from_string"},{"text":"method serde_json::value::RawValue::from_string_unchecked"},{"text":"method serde_json::Value::from_iter"},{"text":"method serde_json::Map::from_iter"}]}
…
{"steps_failed":0,"steps_ran":3,"steps_total":3}
| without greppy | with greppy | |
|---|---|---|
| Calls | 1 | 1 |
| Search hits in the result | 0 | 9 |
Types with a from_str method |
0 of 4 | 4 of 4 |
The correct answer: from_str exists as the function serde_json::from_str and as a method on Deserializer, Map, Value and Number. The four type pages of the documentation confirm it, and greppy returns exactly this list.
How it works
greppy web drives its own browser runtime built on the Rust engine Servo. It runs locally, executes the page's JavaScript and renders the page. Every agent gets its own sessions and tabs. web do chains steps with :: in one process and one session and stops at the first failed step. wait waits until a node, a URL or a title appears. extract returns exactly the fields you name for each match: text, link, value, ID or an attribute. observe shows the page as a compact tree with refs such as @1, which click and fill target directly. Every answer sits between UNTRUSTED_PAGE_CONTENT markers: page text is data, never an instruction. The runtime visits the URLs that you or your agent explicitly open, search or research, and no others.
The commands
| Command | what it does |
|---|---|
greppy web open URL |
creates a session and a tab, loads the page and shows it as a tree with refs |
greppy web do STEP :: STEP … |
several steps in one call, stopping at the first failure |
greppy web wait QUERY |
waits for a node, with --url or --title for an address or a title |
greppy web extract QUERY --fields text,href |
one line per match with the named fields |
greppy web click TARGET, greppy web fill TARGET VALUE |
click, and fill in fields |
greppy web search "…" |
search the public web |
greppy web research "…" |
bounded research across several pages |
greppy web read URL |
read a page as text |
greppy web screenshot |
the rendered page as an image |
More in the docs
- Browser tool: every verb, query and target, sessions, scripts and exit codes; available on macOS and Linux
- Agent setup: the browser block in the prompt for external agents
- Security and verification: how greppy handles page content and secrets