Write a goal, get the exact command that runs it, then read what a real run produced. Execution happens on your machine: the runtime drives your browser with your keys, so nothing is sent to mlola.com and no public endpoint can be abused to browse the web.
Example prompts
Click one to load it into the playground. Two of these run on the hosted runner — choose them under Run it live; the others run where their requirements are met. The templates never resolve as written: they show the shape of a goal for your own application.
Your prompt
Run this on your machine
npx @mlola/browser-cli browser run \
--goal "Download my latest invoice" \
--url "http://127.0.0.1:4311/billing" \
--headless --no-human --yes
Providers come from mlola.config.json, .env.local or the shell — check with `mlola browser config show` before running. The first run opens its own Agent Window, and a tab of yours is only borrowed with your approval.
Run a proven task live (not your prompt)
The runner service runs the catalogue task selected below — proven tasks only, because a public runner that accepted a goal or a URL from a visitor would be an open proxy. Your playground prompt above is never sent: it is for you to run on your own machine, with the command composed for you. So the goal you see here may differ from what you typed — that is the design, not a bug.
Runner offline right now, so the recorded run below is what you get. It is the same task, unchanged, captured from a real run.
What a real run looks like
Verbatim output from runs on a developer machine, with the same goal in the playground.
A real site: fetch a file from ftp.gnu.org
goal: Download the file hello-1.3.tar.gz · url: https://ftp.gnu.org/gnu/hello/
step 1 — the file link is observed and chosenfinal — the same page, because a download does not change the DOM. That is why the proof is the download event and the verified artifact, not a screenshot.
Want a hosted runner instead? That needs a rate-limited allowlisted service on our side, and the runtime would no longer be using your logins — so the local-first flow stays the default.