Changelog
All notable changes, in reverse chronological order. The full version lives inCHANGELOG.md.
Unreleased
Unreleased — in main, not yet tagged
Added
webrain chat --serve— the same session in a browser: the binary serves its own page (no build step, nothing from a CDN) plusGET /,GET /events(SSE of the runtime’s own events),POST /turnandPOST /permission. Each event becomes one element — a tool card, a token meter, an error card that keeps the provider’s message — and the composer re-enables onassistant.idle. The permission modal is the security boundary: it shows the exact request, answers once, denies after 120 s without an answer, and--servedoes not imply--yes. Loopback only.webrain chat— one Copilot agent turn on your own model key, with the 18webrain_*tools attached over stdio. BYOK resolution is a table, first match wins: flags →WEBRAIN_CHAT_*→ the ambient vendor variable, across OpenRouter, OpenAI, Anthropic/Claude, Gemini/Google, Fireworks, DashScope/Qwen, Groq and DeepSeek.--print-configresolves and prints the chain with the key redacted, offline, even in a build without the feature. Exit 0 completed, 1 turn failed, 2 could not start.webrain doctorreports chat as a third state beside engines and vault.--search— live web results in front of the turn, per provider: OpenRouter rewrites the model to its:onlineslug; DeepSeek, OpenAI, Anthropic and Gemini are asked on their own search endpoints with the same key (/v1/tools/search,/v1/responses+web_search,/v1/messages+web_search_20250305,/v1beta/interactions+google_search); every other provider is grounded by webrain’s own engines. A vendor call that fails falls back to ours instead of ending the turn.- chat cost line — each model call prints
· model · N in / M outas it runs, and the turn ends with totals,tok/s(output tokens over real API time), request count and cost, straight from the runtime’s own metrics;--jsoncarries the sameusageobject. webrain diff <a> <b> [--max N] [--json]— what changed between two pages (URL or local file). Whitespace-normalised line multiset, not an LCS diff; exit 1 when they differ so a cron job can act on it.- build — releases build
--features pdfium,chaton every target, the two static musl builds included; achat-buildmatrix job builds the feature on Linux, macOS and Windows on every push, and the container image takes--build-arg FEATURES=. - docs — a chat guide with the provider table, plus the
WEBRAIN_CHAT_*/COPILOT_*variables in the environment reference.
Changed
- build — the two static musl targets carry
chattoo. The SDK is not hostile to musl (its build script fetchescopilot-linuxmusl-x64) and a vendored OpenSSL 3 links fine:webrain-clideclaresopensslwithvendoredfortarget_env = "musl"only, somusl-gcccompiles OpenSSL from source and the binary staysstatic-pie linked. Achat-build-muslCI job guards it on every push. - build — workspace MSRV 1.88 → 1.94, forced by
github-copilot-sdk(resolver 3 is MSRV-aware, so the floor applies even with the feature off). The container builder moves torust:1.94-slim-bookwormwith it. - chat — sends its own system prompt instead of inheriting the runtime’s coding-agent one: 8048 → 272 static tokens per turn, and the agent is told it drives a browser rather than that it edits repositories. Output budget is 4096 rather than the runtime’s 64k, because some providers reserve the requested maximum against your balance.
Fixed
webrain chat --serveon a taken port saidoserror 10048, which names neither the port nor the cause. It now says the address is in use, suggests--port N, and points at the usual reason: a previous--servewhose terminal was closed without stopping the process.webrain help chatnow lists--searchandDEEPSEEK_API_KEY. The flag worked but appeared in no help text, so the only provider search a user could discover was the one the chat guide mentioned.- chat — no longer inherits this machine’s Copilot install. The client starts
in
ClientMode::Emptywith an explicit state directory, so a turn stops loading ~20 unrelated MCP servers (toolDefinitionsTokens: 137019against a 128000 limit) and dying withcompaction_static_context_blocked. - chat — explains a rejected prompt instead of echoing the SDK’s catch-all: both real causes are quotas, not the context window, and the message now says which knob to turn.
- install — the POSIX installer asks the login shell what
PATHit gets, so it stops claiming to have added~/.local/binon Debian/Ubuntu, where~/.profilealready does exactly that (curl | bashis not a login shell). - build —
.gitattributespins*.shtotext eol=lf; a CRLF checkout committed from Windows shipped an installer that died the moment it was piped intobash.
v0.16.2
November 3, 2026
Added
observe what="assets"— one pass returning every link (internal/external grouped by host,other_schemescounts, file kinds), every image (srcset, lazydata-src,<picture>, icons/og:image, CSSbackground-image) and every video source (embeds,.mp4/.m3u8, HLS/DASH requests).only=links|images|videosnarrows it,maxcaps each array; the companionbatch op:"assets"does the same acrossurls[].- PDF layout map —
webrain_pdf op=extractreports which pages the text layer cannot deliver (pages_with_captions,pages_with_raster_images,pages_needing_vision), soop=renderis a decision instead of a guess. op=render dir:/observe what=pixel tiles_dir:— PNGs are written to disk and returned as paths. A 9-page render was 15 MB of base64 in one reply; withdirthe same render answers in ~500 bytes and feedsvision{op:"ask", images:[...]}directly. Tiles are cropped from one page raster instead of one screenshot per tile.- vision providers are a table —
VISION_PROVIDERSlists every OpenAI-compatible hop in priority order (OpenRouter → OpenAI → Anthropic → Gemini → Fireworks → DashScope → Groq → bundled local Qwen3-VL-2B), with the vendor spellings (CLAUDE_API_KEY,GOOGLE_API_KEY,QWEN_API_KEY) accepted as aliases. Adding a provider is one row. webrain install pdfium— downloads the bblanchon/pdfium-binaries build for this OS/arch into the engine cache, soop=renderworks on a released binary with no PATH edit and no source build. Every release target now builds--features pdfium; musl stays extract-only (the published library is glibc-linked).- skills —
monitoring(the self-containedwebrain_evaltick, repeat-and- diff, external cron, and what it must not paper over) andpage-tiles(text-before-pixels rule, tile geometry, VLM prompt shapes). - build — OCI image labels, so ghcr stops showing “No description provided”;
engine-image.ymlpasses the release tag asVERSION.
Fixed
webrain upgradesilently downgraded a build newer than the last tag — it downloadedreleases/latestwith no version comparison, replacing 0.16.2 with the 0.15.3 release. It now reads the newest tag off the redirect and refuses when the running build is equal or newer, with--forceto reinstall.- PDF extraction —
op=extractreturned a 16.8 MB reply once the image walker was fixed, and 0 images before that:/Resourcesand/XObjectare indirect references, and a single-element/Filter [ /FlateDecode ]array was unreadable. Both fixed (arXiv 1706.03762: 0 → 3 images); extract now keeps only the inventory and the bytes belong toop=images dir:…. - PDF images — figures embedded as pages arrive as
/Subtype /FormXObjects with their own/Resources, which the walker never visited: arXiv 2206.01062 went 0 → 29 images, with a depth cap so a nested form cannot loop. - vision failover — reported only the last provider error, so “OpenRouter out
of credits” + “Groq never had that model” + “no local model” surfaced as one
misleading 404. Every failure is listed with its endpoint, and Groq’s dead
qwen/qwen3.6-27bhop was corrected toqwen/qwen3.8-27b. - per-page PDF lists —
pages_with_captions/pages_needing_visionwere 0-based while their siblings were 1-based, and comparing across the two origins reported captioned pages as needing vision. All five lists are 1-based. webrain_statsreturned fivenulls behindavailable:falseon Windows/macOS; it now says why (host stats are Linux-only) and names the platform.- assets —
observe what="images"runs the asset scanner, so it returns thesrcset/lazy/background images a page is mostly made of; counts are deduped before the cap (pages were all reporting exactly the limit); embed detection compares hostname suffixes, so a YouTube login redirect is no longer an embed. - ci — the image workflow pushes
…:latestonly when the built version is the newest release;webrain-cliforwards thepdfiumfeature towebrain-mcp, soop:"render"is reachable in shipped binaries at all. - docs — the tool count said 17 everywhere; the server advertises 18
(
webrain_statswas never documented).
v0.15.3
November 3, 2026
Added
webrain_pdftakes anhttp(s)URL anywhere it took a path (path,paths[],images,render) — the link is fetched once into a temp file that is removed on every exit path, so “extract this PDF” needs no manual download.webrain_batch op:"pdf"— the same browserless download+extract engine, concurrent acrossurls[], in input order. PDF extraction needs no CDP tab, so it serves before any browser connect; previously a PDF URL returned empty text because Chrome’s viewer has no DOM.interact action=clickaccepts aselector, resolved through CDP (DOM.getDocument({pierce:true})→ per-shadow-root query) — the one path that can click a widget inside a closed shadow root, a node page JS cannot see and noindexcan name.- skills —
pdf-extraction(single/batch/URL extraction, tables and figures, when to escalate from text torender+ vision).
Fixed
- shadow DOM —
observe what=a11yprints a css path for nodes inside shadow roots (root-scoped, since no absolute path can cross the boundary), and the shared selector→nodeId resolver falls back to the pierced tree, so a selector that only matches inside a shadow root resolves instead of “not found”. webrain serpattaches the browser for the HTTP-first engines (duckduckgo/yandex/yahoo/baidu) unless--httpis set — previously only google/brave/bing built a backend, so--engine yandexsilently fell through to bing and the SmartCaptcha retry could never fire from the CLI.- container image — the build had been failing since
skills/becameinclude_str!-embedded, so 0.14.0 and 0.14.5 published no image at all. The build stage copiesskillsand.dockerignoreno longer excludes it. webrain mcpno longer aborts withthread 'main' has overflowed its stackon the firstnavigateon Windows — the server runs on a 16 MB-stack thread instead of the 1 MB the OS givesmain.
v0.14.5
November 2, 2026
Added
WEBRAIN_TZ/WEBRAIN_LOCALE— applied as CDPEmulation.setTimezoneOverride/setLocaleOverrideon every attached tab before page scripts run. Chrome reports the host’s timezone and locale, so a foreign proxy exit had the page telling two conflicting stories. Geolocation stays unset: without coordinates it would be a third lie.- trusted-pointer path seeded per call — randomised start offset, 12–22 steps,
quadratic/cubic easing, ±3–6px jitter, 6–18ms cadence, landing exactly on the
target so the following
mousePressedhas no jump. The previous constant trace was identical in every profile, which is itself a behavioural fingerprint.
Fixed
- ci — the Scoop manifest now declares
binper architecture; one top-level entry namingwebrain-windows.exeshimmed nothing andscoop installended with Can’t shim ‘webrain-windows.exe’: File doesn’t exist. webrain_pdfno longer advertisesop=renderas always available — the default build’s error names what a release-binary user can do instead of telling them to rebuild.- docs — troubleshooting gains the three install-time symptoms that cost real
time: Hash check failed from a good download, the pdfium-gated
op=render, and an older manual binary shadowing a package-managed one.
v0.14.0
November 2, 2026
Security
zip7.2.0 → 9.2.2, closing five advisories against the engine archive extractor (Chrome for Testing, whisper, llama-server) — critical GHSA-m665-v7pm-7grj and high GHSA-hjqx-j4rw-g7xv (arbitrary file write outside the extraction directory) among them. The zip-slip guard is unchanged and stays the last line of defence.rustls0.23.43 → 0.23.46, closing four advisories including aDebugthat exposed the TLS master secret.
Added
- a binary per platform and architecture — the matrix was three native
builds named
webrain-linux/webrain-macos/webrain-windows.exe, sowebrain-macoswas whatevermacos-latesthappened to be (arm64) whileinstall.shrefused arm64 and accepted x86_64. Assets are nowwebrain-{linux,macos}-{x86_64,aarch64},…-linux-{x86_64,aarch64}-muslandwebrain-windows-{x86_64,aarch64}.exe, with arm64 Linux and arm64 musl built natively on GitHub’s arm64 runner. An unpublished combination fails with “build from source” instead of downloading a binary for another architecture. checksums.txtfromsha256sum *instead of three hardcoded filenames, so adding a target cannot ship a binary with no checksum (which every installer treats as “skip verification”). The Scoop bump also writes thearm64entry.- docs — a
Skillssection in the README:webrain install skills(offline bundle),skills/skills add/skills rm, where files land, how the agent reads them, and the third-partynpx skills addroute.
Changed
- build — workspace
rust-version1.85 → 1.88, forced by thezipfix.clippy::collapsible_ifsites stay nested and are allowed once per crate root. - deps —
tokio-tungstenite0.24 → 0.30,scraper0.24 → 0.27,pdf-inspector1.14.1 → 1.25.2,ureq3.3.0 → 3.4.2,aes-gcm0.11.0 → 0.11.1, plus the five outstanding Dependabot action bumps. ARCHITECTURE.mdwas an August scaffold kept as “superseded history”, so the file GitHub shows first described 11 MCP tools, two planned backends, awebrain-pythoncrate and modules that do not exist. Replaced with the map.- skills —
.github/skills/carried copies of four product skills, one of which had already drifted onto tool names folded away releases earlier. The copies are gone;skills/webrain/**is the only place a product skill is edited. - docs —
AGENTS.mdandARCHITECTURE.mdnamedmap_surfacerouting targets (webrain_a11y,webrain_spider,webrain_cookies, …) as if they were MCP tools; none is inlist_tools(). Both now name the real entry points.
Fixed
WEBRAIN_SKILLS_DIRwas printed bywebrain install skillsand listed in--help, butskills::dir()never read it — following the instruction changed nothing.install.shsent Windows users to ascoop bucket addthat needs a manual step; it now points atinstall.ps1.
v0.13.0
November 2, 2026
Added
- skills, offline —
webrain install skillswrites the bundled operator skills into the engine cache frominclude_str!, so an install cannot drift from the tool surface that serves it;skills add <url|path>/skills rm/skillsmanage single skills. The frontmattername:is authoritative and required (it is thewebrain_guide(topic="skill:<name>")key), and install warns when a skill names awebrain_*tool this build does not expose. - per-session proxy —
webrain_session{op:"open", proxy}creates a Chrome browser context carryingproxyServerand attaches its first tab, which is the only way to change a live browser’s egress. Real Chrome only; obscura and lightpanda have no per-context proxy and now say so instead of reporting egress they do not have.keep_identitycopies the previous session’s cookies. proxyon the HTTP paths —webrain_download(both engines),webrain_crawl{mode:"sitemap"|"validate"},webrain_scrape(all three HTTP forms) andwebrain_search, through the same per-proxy agent pool as serp. The schema omits it where it cannot apply.webrain_batch{op:"autoschema"}— selector discovery across URLs, sharing one in-page expression with the single-page tool so the two cannot drift.webrain launch <service> <profile> [url] --proxy URL— the same launch-time exit without the MCP surface.
Fixed
filter_extensionwas ignored on the MCP path: the no-browser short-circuit returns before the dispatcher, so a caller asking for.pdfgot every type downloaded.session_idis now declared on all eleven page/browser tools. The router always honoured it, but an undeclared parameter is one no client sends, sosession{op:"open", cdp_url}was write-only for everything exceptbatch.webrain_serpguest-launched its fallback Chrome on a hardcoded9222whatever endpoint the call named, and two endpoints shared one guest profile — Chrome hands a second launch to the running instance and exits 0 without opening CDP. Non-default endpoints now get their own profile.- engines — a batch worker that cannot get a tab reported “no tab available” for every URL; the real error is carried into the per-URL message.
- media —
webrain watchreportedtranscript_source: "none"for every video after a non-defaultinstall whisper --model X, because the model lookup was hardcoded while the installer writesggml-<model>.bin. It now uses whichever model is on disk, multilingual before English-only. - docs — two facts an operator previously had to read the Rust to learn:
cookie transfer moves login state, not bot clearance (
cf_clearanceis TLS-fingerprint-bound, so obscura and lightpanda stay on the challenge page), and what each engine’s--storage-dir/--user-agent/--cookiereally are.
v0.12.1
October 29, 2026
Added
install vision --model <id>— an allowlist (qwen3-vl-2b,qwen3-vl-2b-q6k, fourqwen35-9bquants), each with its own mmproj; an unknown id prints the choices with download size and RAM/VRAM. Models live invision/<id>/and an existing flat install keeps working.--model-updatere-checks against Hugging Face, anduninstall vision --model <id>|--all.- GPU offload for the local Qwen3-VL —
-ngl 99when a GPU backend library sits beside thellama-serverbinary (a capability check on the build, not a probe of the machine, because-nglon a CPU-only build is silently ignored).WEBRAIN_VISION_GPU=0|1forces it off or on. - screenshots arrive as a real MCP
imagecontent block beside the JSON, so a client can display them without decoding a megabyte of base64 it also bills as text tokens.format(png|jpeg|webp|avif) andquality; avif is captured as png and converted in-process byravif(no system libavif). - interact —
hold(trusted press-and-hold for “Press & Hold to confirm you are a human” widgets, default 6 s),drag ms(hold before the movement starts),press keycombos (ctrl+a,shift+Tab) sent on keyDown and keyUp with a realcode,type ms(real per-key events instead ofInput.insertText), andscroll x/yto wheel the element under that point instead of the window.
Changed
- interact drag — the 10-step straight-line teleport became an eased, slightly arced 28-step path with a settle on both ends; even steps read as synthetic to slider captchas.
- cli help —
--helpprinted 12 of the ~40 environment variables the binary reads. The env block is now a grouped table built from oneENVconstant, andwebrain help envprints just that section.
Fixed
install visionreported a failed download as"skip: probe …"and exited 0, so a 404 looked like a deliberate no-op. The model step is fatal.vision askclipped the wrong band on any scrolled page: CDP’scliprect is document-space while every caller speaks viewport-space, so withscrollY=307a clip at y=440 captured 307px too low and the model answered confidently about nav text.- CDP input is no longer silently dropped on a background or occluded tab
(12
mouseMovedlanded, 0mousePressed):Page.bringToFront+Emulation.setFocusEmulationEnabledare sent at attach.
v0.11.0
October 26, 2026
Added
- three more SERP engines —
yahoo,baidu,yandexon both paths with their parsers,--safe/--regionmapping and pagination, each derived from a real captured SERP rather than an assumed layout: yahoo needs a cookie jar (a replay without one answers500 INKApi Error) and its redirect host is not constant (r.over HTTP,rd.rendered), baidu keeps the target in the container’smuattribute and the abstract in a<!--s-data:…-->island, yandex isli.serp-item+.OrganicText. engine=autofills to the requested limit — after the ddg+bing merge it tops up from baidu, yandex, then yahoo last (the only one of the three that pages reliably), asking yahoo for the full limit because the merge dedupes afterwards.--limit 50 --http: 25 results before, 50 after.- a challenge page is reported as a challenge, never as an empty result set. Baidu answers ~7 rows then 302s to a captcha; yandex answers a 14 KB SmartCaptcha from a datacenter IP. Both used to parse to 0 and read “this engine has nothing for your query”.
Fixed
webrain_batchexposesop=markdown—batch_markdownexisted in core but the tool’sopenum stopped atscreenshotand the catch-all sent every unknown op tobatch_fetch, soop=markdownsilently returned innerText and no agent could reach the capability. 50 URLs at concurrency 8: 50/50 ok, 14 s.--limitabove ten returned one page in the browser path for the new engines (the paged loop was gated togoogle|brave|bing), andbrowser_pagesused integer division, so--limit 25budgeted two pages and stalled short.- an engine that walled with no fallback returned an empty list, which reads as “no results”; the wall error is now propagated.
- docs —
--guestChrome cannot create tabs over CDP (Target.createTarget→ Failed to open a new tab), sowebrain_batchfails there whilenavigateon the existing tab keeps working.
v0.10.0
October 26, 2026
Added
webrain_guideanswers progressively — notopicreturns the tool list plus an index,topic=<section>returns one section,topic="all"returns everything (827 / 763 / 2745 tokens measured). Topic selection stays the model’s job on purpose: matching a prompt to a section in Rust is the intent detection this server exists to avoid.- operator skills via
WEBRAIN_SKILLS_DIR—topic="skills"lists,topic="skill:<name>"returns one. Names are validated before the join and both sides canonicalized, because the argument would otherwise be an arbitrary file read on behalf of a remote model. - real help pages —
webrain --help,webrain <command> --helpandwebrain help <command>, all from oneHELPtable, plushelp env. - the agent guide documents environment variables — including the fact that decides most failures: they are read at process start / CDP attach, so no tool call can change one.
Fixed
wait_selectorswas ignored whenevercdp_urlswas set (the grouping lived inside thecdp_urls.is_empty()branch), so a site that hydrates afterreadyState: completecame back as shells. Probed: plural returned in 492 ms, singular took 12.6 s; after the fix, 13.0 s and the expected rows.wss://CDP endpoints connected at all:tokio-tungstenitehad no TLS connector, so every hosted endpoint — Lightpanda Cloud included — failed despiteresolve_wspassingwss://through.rustls-tls-webpki-rootsnow ships the roots in the binary.webrain_batchwithcdp_urlsreturns rows in input order (they were appended per backend, soresults[i].urldid not matchurls[i]), runs the per-backend batches concurrently (the loop awaited each in turn, so N backends bought zero throughput), and counts the tab budget across backends (per_backend_concurrencyis clamped totab_budget / backends).- batch now uses a fixed tab pool — one tab per worker draining a shared
queue instead of an attach + init per URL, so live tabs are bounded by
concurrencyhowever long the list is;statsreportsrequested/effective_concurrency,single_targetandms_wall, because lightpanda silently collapses to one tab andms_totalcannot show parallelism. - a killed browser no longer wedges the server — after a kill the error is
CDP write failed: channel closed, which shares no phrase withconnection closed, sois_connection_errornever dropped the cached backend and every later call replayed the dead socket until the MCP process restarted. - bing returned zero results on every query and had for a while, silently,
because
autojust merged duckduckgo and moved on: its HTML SERP is JS-rendered for programmatic clients. Page 0 now uses the RSS form Bing advertises (which deliberately omitsmkt/cc— both empty the feed), so--limit 20reportsbing ok(10)where it used to reportbing empty(0). - google returned zero results from a perfectly good page — the target is now
an opaque
/goto?url=CAES…token, so every row resolved togoogle.comand was discarded as an internal link. The URL is recovered from the<cite>line (9 of 10 organic rows); a cite holding metadata yields nothing rather than a fabricated link. webrain_scrapecan parse instead of probe — the browserless fetch capped every body at 3000 chars, so 3 KB of<head>was all a caller ever saw.max_chars/fulllift it and the reply reports the truebytesplustruncated; a Sklavenitis page is 427 KB in 266 ms, 3–8× faster than the same page in a tab.serp --http— never touch a browser.--engine bing --limit 50used to guest-launch Chrome for 26 s and return 10 results; with--httpthe same 10 arrive in 0.3 s.- Chrome’s own throttling, not the SERP code, made browser searches slow by
5–30× — an automated window behind the editor reads
document.visibilityState === "hidden"and one google page took 16–22 s against 3.4 s visible.webrain launchnow passes--disable-features=CalculateNativeWinOcclusionplus the backgrounding flags. autoasked browser engines for the full limit, so a deep request became 8 google pages and the 20 s browser cap threw the render away; the browser stage is a diversity top-up and now asks for exactly one page.consent_buttonclicked the last button inside any dialog when no accept/reject label matched — Google’s own “About this result” panel is a dialog, so every run opened a side panel over a good results page. The blind fallback is deleted.- docs — obscura does have a paint engine (
fetch -s out.pngwrote a 63 KB PNG); what fails on a data-driven SPA is boot, not paint, and the cause is that obscura gives every element one sharedElementprototype, so a polyfill forHTMLTemplateElement.firstChildpatchesfirstChildfor all elements and React never hydrates. Probe before trusting any engine on an SPA:HTMLTemplateElement.prototype === Element.prototypemust befalse. The MCP relaunch recipe is written down too, including the trap thatwebrain serpsetsWEBRAIN_NO_STEALTH=1on itself.
v0.9.0
October 23, 2026
Added
- Brave Search API provider —
BRAVE_API_KEYroutesbravethroughapi.search.brave.com(typed JSON,count≤ 20, no browser needed), authenticated withX-Subscription-Token.--engine bravenow works headless with a key instead of demanding a CDP browser, andserp::brave_api_ready()is the one predicate the core, MCP and CLI layers share.
Fixed
- SERP pagination — offsets advance by the results a page actually
delivered. The guessed stride truncated deep requests: duckduckgo stepped
sby 30 while the endpoint serves ~10 per page, solimit=50returned 11.
Performance
- CDP replies are dispatched off the connection lock — one slow
Page.captureScreenshot(or a paused renderer) no longer stalls every other tab, sowebrain_batchconcurrency is real. Network capture is armed per page session and capped; the vision store stores unit vectors; token counting uses thechars/4estimate above 32 KiB replies; session eviction is LRU.
Changed
- docs — accuracy audit against the 18-tool surface:
quickstart/cursor/agent-decision-guide/runtime-flowstale “15”/“63-tool” counts fixed (the agent-guide table gained the missingwebrain_serprow); the CLI reference drops the non-existentwebrain snapshot, the false click-with-selectorclaim, and gains the missingwebrain serpcommand; the environment reference adds the SERP / vision / stealth env vars, theWEBRAIN_PROXIESrotation pool, the HTTP-cache, download-cap and fetch-timeout knobs, andEMBED_FALLBACK_*; the tools reference gains thewebrain_statstool plus the selectors added since the last pass (observe what=assetswithonly/max,batch op=pdf|assets,interact action=hold, browserlessscrapeschemas,session save_state inline/restore_state payload,vision images[]) and names the 11 tools that declaresession_id; the agent decision guide’s tool dialect is modernized to the consolidated names; two unreferenced landing images removed.
v0.8.0
August 27, 2026
Security
- engine archives are extracted behind a zip-slip guard — absolute paths,
..traversal and Windows drive-prefixed entries are rejected, exec bits are preserved, and each download chunk has a timeout. lightpanda/obscuraCDP servers bind to127.0.0.1(they were on0.0.0.0, exposing unauthenticated browser control on the LAN).- 2captcha credentials leave the URL — the submit is a form POST, so the key and proxy credentials stop appearing in access logs; the proxy is validated up-front instead of silently dropped from a paid solve.
- vault hardening —
vault.keyis created exclusively with0600, unreadable keys error instead of reading as “empty”, writes are atomic, and read-modify-write is serialized so concurrent mutations cannot drop an entry. - installers verify the binary against the release’s
checksums.txtand fail closed; downloads go to a temp file and move into place atomically, and HTML-200 downloads are rejected by magic bytes. - HTTP transport caps the request body at 16 MiB; search queries are
percent-encoded (
&/#/%could inject parameters or truncate); third-party Actions are pinned to full commit SHAs.
Added
batch op=markdown— full page HTML → Markdown via pure-Rusthtmd, past the 3000-charinnerTextcap, with optionalquery+top_kBM25 pruning (zero LLM).per_engineSERP breakdown —[{engine, status: ok|empty|skipped, count}]so a reply says which engines contributed and which were skipped.
Fixed
autois relevance-filtered — results sharing no significant query token are dropped at the source, so a junk page from a flagged IP can no longer filllimitahead of duckduckgo’s real results; a fallback reply now carriessource(the actual provider), so substituted results are never mislabelled.- consent dismissal can no longer click a search result — Google’s app-shell
#yDmH0dwas in the consent-gate selector and the last-button fallback then clicked a result link. The gate now requires a real dialog/banner container. - google’s URL is a real-browser URL again —
numandlrmade it answer an empty page on automated sessions, and that soft-block is now detected as a wall so the retry loop fails fast instead of burning four attempts. - bing routes through the browser (
first=1,11,21…) and falls back to plain HTTP when no Chrome can be launched; its browser path makes one attempt, so a no-result query falls back in ~6 s instead of ~30 s. - serp reliability — an HTTP engine that parses to zero on a 2xx page is
retried before being called broken, google pagination budgets ~7 results per
page (carousels and AI overviews crowd the SERP),
braveleftHTTP_ENGINES, andlimitwent 50 → 100. - CDP — consistent
active → tabslock order (a deadlock inversion), a 30 s response timeout, a serialized first attach, unique per-element selectors so a bareinputcannot set files on the wrong node, and the network block list is re-applied on every navigation. detect_antibotrequires two corroborating markers for generic phrases, so a support article mentioning “access denied” is no longer read as a block;crippledis gated on element-extraction success.ELEMENTS_JS/LINKS_JSmoved onto theBrowserBackendtrait, so any backend supplies its own extraction script instead of the shared snapshot path reaching intobackends::cdp.serp’s stealth-off is a per-backend flag, notstd::env::set_var("WEBRAIN_NO_STEALTH")from a concurrent handler — an edition-2024 data race that disabled stealth for every session in the process.- long-running work left the executor —
webrain_watch,http_fetch,pdf_images,vault::list, robots.txt fetch, vision’s provider chain andindex_current_pageall run off-thread, so a slow call no longer ties up a tokio worker (the watch session table is capped at 64). vault/login— a TOTP seed with non-zero trailing bits is refused, and a missing captcha token bails withwaiting_for_humaninstead of submitting a guaranteed-403 empty one.- docker — the release build no longer loses the binary (the target cache
mount never reaches the image layer), and the cache is keyed by
$TARGETARCH. - docs — landing coverflow order, its no-JS fallback and the playground generation guard fixed; the SERP showcase made capability-honest (duckduckgo over HTTP, “2 browserless by default”), tool counts corrected to 16, and a docs-orphan check added to CI.
v0.7.3
August 15, 2026
Added
- Structured SERP API —
webrain_serp+webrain serpreturn typed results{position,title,url,domain,snippet}across 5 engines (duckduckgo · bing · google · brave · auto) with provider fallback, URL dedupe, pagination, safe/region, retries,request_id+ms. - Google/brave trusted browser flows — trusted-commands-only (no stealth
JS, zero
Runtime.evaluate; DOM + Accessibility discovery, trustedInput.*), consent dismissal (TRUSTED click, ~42s → ~1.2s), sequential page-turn pagination, guest-mode + warm persistent-profile launches,--remote-debugging-pipe, market defaulting, per-enginelimit. - Anti-bot hardening — optional 2captcha solving (
WEBRAIN_2CAPTCHA_KEY), serpapi.com provider (used first whenlimit > 10), per-request proxy for HTTP engines + launched Chrome, honest wall/fallback handling. - MCP surface 15 → 16 tools —
webrain_serpadded;interactadvertises thedragaction. - docs — landing first-load flash fix, verified-results proof band.
v0.6.2
August 12, 2026
Added
- Native CAPTCHA v2 — trusted
drag(slider CAPTCHAs) +eval_in_frame(CDP isolated world inside a reCAPTCHA/hCaptcha/Turnstile frame) →webrain_drag/webrain_eval_in_frame; reCAPTCHA v2 anchor-click fix (checkbox is top-left, ~27,37) +mouseMovedbefore every CDP click. - Vision v2 —
webrain_visionop=ask (screenshot → local/cloud → answer, batch tiles in one request,scaleupscales small captcha tiles); offline caption index; warm llama-server singleton (no ~90s cold load per call); provider failover OpenRouter → OpenAI → Fireworks → Groq → local.
Changed
- Docs/skill rearchitecture — Mintlify nav gains an Agent group
(
agent/protected-sites,agent/session-strategy) + new Concepts pages (profiles, sessions); the agent decision guide andwebrain_guidere-center on persistent profile + real Chrome + session (browser identity is state). - Obscura v0.2.0 rendering — render builds now screenshot + PDF natively; no-render builds and lightpanda still lack a paint engine.
Removed
- Python stealth sidecar —
stealth_solve.py+preflight.pydeleted; no Python in the repo. Challenge handling is native (vault + TOTP).
v0.6.1
August 9, 2026
Changed
- deps: RustCrypto stack upgraded together (sha1/sha2/hmac/aes-gcm/getrandom)
— they share the
digesttrait and must move as one;getrandom::fillreplacesgetrandom(). - deps: lopdf 0.41→0.44; GitHub Actions bumped (checkout 7, upload-artifact 7, download-artifact 8, sticky-comment 3).
- deps: Dependabot enabled — weekly version-update PRs for cargo + GitHub Actions; security alerts + automated security fixes on.
- ci: changelog gate no longer blocks dependabot PRs.
- chore: repo security hardening — branch protection on
main, squash-only merging, auto-merge + delete-branch-on-merge, CodeQL scanning.
v0.6.0
August 8, 2026
Changed
- MCP surface — 63 → 16 intent-based tools (
map_surfacerouter):navigate / observe / interact / extract / scrape / batch / crawl / search / pdf / download / watch / session / vision / eval / guide, each with awhat/action/op/modeselector. Every capability is preserved; legacy one-action names still dispatch (backward compatible). - Install progress — every package download streams with a live
X / Y bytes (N%)line (lifts the old 10 MiBread_to_veccap). - Patchright-parity stealth — fingerprint noise ON by default
(
WEBRAIN_STEALTH_NOISE=0opts out), new puppeteer-extra evasions (outerdimensions, iframe.contentWindow, media.codecs), no forged UA /Emulation.setAutomationOverride; real Chrome preferred for launch. - Native Cloudflare/captcha solving —
webrain_login/webrain openauto-wait challenges and claim Turnstile/reCAPTCHA/hCaptcha widgets; the Python sidecar prefers the patchright driver with interactive Turnstile solving. - style — cargo fmt.
v0.5.0
August 6, 2026
New Features
- Watch any video (
webrain_watch/webrain watch) — timestamped transcript (yt-dlp captions → local whisper-cli → cloud Whisper API) + ffmpeg frames, no browser. Batchsources[]in parallel. - Local AI, whisper-style, all OS —
webrain install watchbundles ffmpeg/yt-dlp/whisper-cli + a GGUF model as self-contained mono packages;webrain install whisperpulls a model;webrain install visionbundles llama-server + Qwen3-VL-2B (GGUF + mmproj) for local vision. - Local vision hero —
watch --vision/vision:truefalls back to the bundled Qwen3-VL-2B when no GROQ/OPENAI key is set (chain: Groqqwen3.6-27b→ OpenAIgpt-4o-mini→ local). Opt-in (API cost / model size); failure surfaces asvision_error, never fails the watch. DeepSeek’s hosted API is text-only (live-verified), so it’s excluded. - Install warnings —
webrain install watchreports what’s missing (STT key / local model / vision key / local vision) so nothing fails silently. - Batch eval (
webrain_batch op=eval), cookies —netscape, doctor hints (relay/headless detection), screenshot path, login truth fix, antibot false-positive fix.
Changed
- Media guidance — extract media URLs from
meta[og:image|og:video], notvideo.src(blob: URLs).
Fixed
- Login no longer reports logged-in falsely; download collisions; captcha false positives.
v0.4.0
August 6, 2026
New Features
- Agent-browser interaction primitives —
webrain_select,webrain_hover,webrain_check,webrain_dialog,webrain_wait,webrain_uploadon the element-index model. - Trusted CDP input — click/type/press via
Input.*CDP events with a JS fallback;webrain_click_coordsfor cross-origin/reCAPTCHA; stable backend-node clicks; single-fire click; click-hang bounded on sync dialogs. - Extraction —
webrain_flatten(Shadow DOM composed text),webrain_annotate(numbered boxes for vision models),webrain_fit(dense-content extractor). - Signals —
webrain_add_init_script, Chrome error-page detection (chrome_error),needs_js/visible_charson the HTTP probe,crippledbot-shell hint. - Docs — multi-agent delegation doctrine in the agent decision guide.
Bug Fixes
webrain upgradecloses other running webrain instances beforescoop update, so Scoop can replace the binary.
v0.3.3
August 5, 2026
New Features
- Added a runtime-flow architecture page (
concepts/runtime-flow.mdx) - CLI entrypoint → MCP dispatcher → tool dispatch → CDP backend → engines, with a request-flow diagram and a symptom→layer failure table. reference/tools.mdxgains a tool-to-code map (each tool family → implementation file, browser vs no-browser, shared vs engine-specific).concepts/browsers.mdxgains an engine capability matrix (Chrome / Obscura / Lightpanda /fetch_http).- Light/dark logo variants for the Mintlify theme + a GitHub icon in the navbar.
Bug Fixes
webrain upgradenow spawns the package-manager update (brew / scoop) detached and exits, so Scoop no longer sees the upgrade command itself as a running instance of webrain and refuses to replace the binary.
v0.3.2
August 5, 2026
Documentation
- Added a full Mintlify docs site in
docs/- overview, quickstart, installation, browsers/challenges concepts, extraction / scrape-at-scale / auth-and-login guides, a full 51-tool reference, CLI + env reference, deployment, troubleshooting, and contributing. Existingdocs/*.mdfiles left in place, untouched. - Added the
docs/changelog.mdxchangelog map, linked in the Project nav. - quickstart.mdx and the README now show the full MCP client setup
(stdio + HTTP transports, VS Code / Claude Desktop / Cursor configs,
webrain_guideverification). - Added a Prerequisites section to the README and docs site.
- Added
.mintignoreso the ADR / legacy markdown files stay on disk but out of the Mintlify build (fixes the ADR MDX parse error). - Refreshed ADR-001 graph note - 875 nodes / 2287 edges, 3 entry points, 51 MCP tools, new hotspots.
Improvements
- Upgraded
skills/webrain/SKILL.mdto a full agent-skill contract - richer frontmatter,When to use, recommended limits, and a 7-step end-to-end invocation flow. - Ran
cargo fmton the mcp session-routing match indent.
v0.3.1
August 5, 2026
New Features
webrain install --engine lightpandanow downloads the lightpanda binary from thelightpanda-io/browserGitHub release into the engine cache, mirroring--engine obscura;find_lightpanda()also discovers the cached build. No Windows binary - the install bails with the Docker fallback instead of silently installing Chrome.
Improvements
webrain install --engine <unknown>now errors clearly instead of silently installing Chrome.
Bug Fixes
webrain_open_session(cdp_url=…)now actually routes tools to that session - every browser tool accepts an optionalsession_id.- A browser kill/restart no longer wedges the cached backend forever - dead-socket errors drop the backend so the next call reconnects.
- The CDP WebSocket connect retries once with a longer budget (20s), tolerating obscura’s slow cold-start handshake.
v0.3.0
August 5, 2026
New Features
webrain_page_info- just-in-time page context (viewport/page size, scroll position, position %).webrain_save_state/webrain_restore_state- export/import a profile’s auth state (cookies + localStorage) across machines.webrain -v/--version/version.
Bug Fixes
webrain installfailed with “response body is larger than request limit” - ureq’s 10 MB cap was too small for the Chrome/Obscura engine zips; now reads via the unlimited reader.
Improvements
- Rewrote the README - install-first, “Why webrain?”, use-cases, Scoop extras.
- Moved the Dockerfile into
docker/and addeddocker-compose.yml(persistent vault/profile/cache volumes). - Deduped the JS→JSON parse chain in
tools.rsintoparse_json_str/arr_len.
v0.2.0
August 5, 2026
New Features
webrain upgrade- updates to the latest release (Homebrew/Scoop-aware, else self-updates the binary in place).- One-line installers -
scripts/install.sh(Linux/macOS) andscripts/install.ps1(Windows). - Submitted to the official Scoop
extrasbucket and published a Homebrew tap (prokopis3/homebrew-webrain). - Added
CONTRIBUTING.md, README badges, and the Quick Start + Traditional Selectors + Commands + Updating sections.
v0.1.1
August 4, 2026
New Features
- All-OS install one-liners (PowerShell + curl) and the working scoop
bucket (
prokopis3/scoop-webrain).
Bug Fixes
- The Linux release binary now builds on
ubuntu-22.04(glibc 2.35) - the previousubuntu-latestbuild required glibc 2.39.
v0.1.0
August 4, 2026
New Features
- Cargo workspace (
resolver 3,edition 2024, Rust 1.85) withwebrain-core/webrain-mcp/webrain-cli; MIT license; CI + release + changelog-enforce workflows. - Rust CDP browser-automation agent - one
BrowserBackendtrait over CDP WebSocket (CdpBackend) driving Chrome, Edge, Lightpanda, or Obscura;SessionPoolisolation;STEALTH_JSanti-bot injection. - stdio MCP server owning the CDP connection, 25-tool dispatch table.
- Single
webrainbinary,match-based subcommands (no clap) mirroring the MCP tool surface. - Page interaction (navigate/eval/click/type/press/scroll/snapshot, multi-tab,
a11y), capture (screenshot, PDF, PixelRAG vision tiles + cosine
VectorStore), extraction (extract_json/extract_regex/eval), spider + web search, batch + download. webrain doctor- full install diagnosis.- agent-browser-style engine install -
webrain installdownloads Chrome for Testing (and--engine obscura);webrain lightpanda/webrain obscuraspawn CDP servers.

