A browser agent that runs entirely on your device: GLiNER2 on WebGPU drives Chrome, no server, no API key
TypeScript
8
47 commits
updated Sep 26, 2026
A browser agent that runs entirely on your device. Type a goal in the side panel; GLiNER2 runs on your GPU with WebGPU, reads the page and drives it until the goal is done. No server, no API key, nothing about the page or your goal leaves the browser.
In the recording (real time, no cuts): "Find a one-way ticket from New York to San Francisco on the first Friday of November. I prefer the cheapest red-eye." Zipline sets the ticket type, types both cities and takes their autocompletes, picks Friday, November 6 in the calendar and searches: 9 actions, 8.0 seconds. It then checks the results page against every part of the goal and highlights the cheapest flight leaving between 9 PM and 5 AM, 8.4 seconds after Run was pressed. Dates are resolved in code ("next Friday", "the last Monday of October", "in 2 weeks"), and calendar clicks need no model call.
It is a port of gliner2-ultrafast (MIT) from Python to a Chrome extension:
fastino/gliner2-multi-v1, does both jobs: it extracts values from the goal ("New York", "October 9, 2026") and scores the page's controls against each part of the goal. It runs as a single ONNX graph (onnx-community/gliner2-multi-v1-agent-ONNX, 614 MB at fp16) in about 40 ms per call on an M-series Mac.src/agent/controller.ts). The model picks among observed controls; it never writes selectors or code.snapshot.js, and clicks and typing are sent through chrome.debugger with the same DevTools Protocol calls the Python version sends. Before every action it checks the page has not changed since the decision.Checked, not assumed. "Done" only means the controller found nothing left to do. Afterwards Zipline checks the finished page against each part of the goal and shows a checklist: a form field holding each value ("Where from?: New York", "Departure: Fri, Oct 9"), a control showing each setting (GLiNER2 picks "one-way ticket" out of the goal; the page shows "Change ticket type. One way"), the form actually sent, and not an error, empty or captcha page. The page's own form counts over cards beside it that name the same words. The answer is highlighted only on a verified page. It checks what the page's form says, not whether the results below it match.
The tab being driven goes into a Zipline tab group whose title shows the run: ⚡ step N, ✅ done with the time, ⛔ blocked.
pnpm install
pnpm build # writes dist/
chrome://extensions, switch on Developer mode, click Load unpacked and choose dist/.Chrome shows a "started debugging this browser" bar while Zipline drives a tab; that is the permission it uses to click and type.
tests/parity.test.ts: the JavaScript GLiNER2 runtime reproduces the Python library's token ids and outputs on 14 recorded calls (fp32 and fp16).tests/verify.test.ts: the goal check passes a sent, complete form and fails a Round-trip form beside "One way trip from New York…" cards, a form never sent and a captcha page.tests/controller.test.ts: the TypeScript controller makes the same decisions as the Python controller on captured Google Flights and Maps pages (tests/oracle.py produces the reference).scripts/e2e.mjs [flights|maps|walking] [--llm]: runs a task end to end in Playwright's Chromium.scripts/record-demo.mjs: records the page and the panel side by side in real time.Controller, loop, page snapshot and date parsing adapted from gliner2-ultrafast by Sahibzada Allahyar (MIT, copyright Browser Use), which began from Browser Use's jev-ultrafast. GLiNER2 by Fastino (Apache-2.0). Runs on Transformers.js.
MIT licensed.
A browser agent that runs entirely on your device: GLiNER2 on WebGPU drives Chrome, no server, no API key
TypeScript
8
47 commits
updated Sep 26, 2026
A browser agent that runs entirely on your device. Type a goal in the side panel; GLiNER2 runs on your GPU with WebGPU, reads the page and drives it until the goal is done. No server, no API key, nothing about the page or your goal leaves the browser.
In the recording (real time, no cuts): "Find a one-way ticket from New York to San Francisco on the first Friday of November. I prefer the cheapest red-eye." Zipline sets the ticket type, types both cities and takes their autocompletes, picks Friday, November 6 in the calendar and searches: 9 actions, 8.0 seconds. It then checks the results page against every part of the goal and highlights the cheapest flight leaving between 9 PM and 5 AM, 8.4 seconds after Run was pressed. Dates are resolved in code ("next Friday", "the last Monday of October", "in 2 weeks"), and calendar clicks need no model call.
It is a port of gliner2-ultrafast (MIT) from Python to a Chrome extension:
fastino/gliner2-multi-v1, does both jobs: it extracts values from the goal ("New York", "October 9, 2026") and scores the page's controls against each part of the goal. It runs as a single ONNX graph (onnx-community/gliner2-multi-v1-agent-ONNX, 614 MB at fp16) in about 40 ms per call on an M-series Mac.src/agent/controller.ts). The model picks among observed controls; it never writes selectors or code.snapshot.js, and clicks and typing are sent through chrome.debugger with the same DevTools Protocol calls the Python version sends. Before every action it checks the page has not changed since the decision.Checked, not assumed. "Done" only means the controller found nothing left to do. Afterwards Zipline checks the finished page against each part of the goal and shows a checklist: a form field holding each value ("Where from?: New York", "Departure: Fri, Oct 9"), a control showing each setting (GLiNER2 picks "one-way ticket" out of the goal; the page shows "Change ticket type. One way"), the form actually sent, and not an error, empty or captcha page. The page's own form counts over cards beside it that name the same words. The answer is highlighted only on a verified page. It checks what the page's form says, not whether the results below it match.
The tab being driven goes into a Zipline tab group whose title shows the run: ⚡ step N, ✅ done with the time, ⛔ blocked.
pnpm install
pnpm build # writes dist/
chrome://extensions, switch on Developer mode, click Load unpacked and choose dist/.Chrome shows a "started debugging this browser" bar while Zipline drives a tab; that is the permission it uses to click and type.
tests/parity.test.ts: the JavaScript GLiNER2 runtime reproduces the Python library's token ids and outputs on 14 recorded calls (fp32 and fp16).tests/verify.test.ts: the goal check passes a sent, complete form and fails a Round-trip form beside "One way trip from New York…" cards, a form never sent and a captcha page.tests/controller.test.ts: the TypeScript controller makes the same decisions as the Python controller on captured Google Flights and Maps pages (tests/oracle.py produces the reference).scripts/e2e.mjs [flights|maps|walking] [--llm]: runs a task end to end in Playwright's Chromium.scripts/record-demo.mjs: records the page and the panel side by side in real time.Controller, loop, page snapshot and date parsing adapted from gliner2-ultrafast by Sahibzada Allahyar (MIT, copyright Browser Use), which began from Browser Use's jev-ultrafast. GLiNER2 by Fastino (Apache-2.0). Runs on Transformers.js.
MIT licensed.