`##auto web`: autonomous browser recipes in one markdown file
Write a browser chore down once — YAML budget, markdown task — and it becomes a command you can run, schedule, and trust.
Every recurring browser chore has the same shape: browse → judge → collect → merge → repeat next week. Competitor watching. Speaker sourcing. Listing hunting. Docs auditing. You do it in twenty tabs, paste fragments into a doc, lose the doc, start over.
In rysh, that chore becomes a file. ##auto web turns a markdown recipe into a reusable, budgeted browser automation:
##auto web run --headless competitor-watch "ai terminals"
One command sends an agent into a real Chromium on a browser profile you logged into once, under limits the runtime enforces, and the recipe has it save its findings as dated files when it's done. This post is the anatomy of a recipe — and the leash that makes "let it run unattended" a reasonable sentence.
The recipe is a file
##auto web save <name> "<prompt>" is the quick way in, but the real form of an automation is a markdown file with YAML frontmatter under .rysh/automations/webs/ (here, competitor-watch.md). Versionable, reviewable, PR-able:
---
description: Watch competitor changelogs and pricing pages for a topic area.
Read-only; saves a dated findings file.
web_profile: research # persistent, pre-authenticated browser profile
url: https://example.com/start
args: [topic] # run as: ##auto web run competitor-watch "ai terminals"
output_dir: competitor-watch/results
loop:
do: # the INNER loop — one working session
interval: 30
max_iterations: 300
max_duration: 7m
auto_continue: true
budget:
size: 3b # 3 "books" = 600k tokens, per-pass ceiling
watch:
takeover_when: 90 # at 90% consumed, switch to the wrap-up leg
takeover_prompt: >
Budget is nearly gone — stop browsing now. Save findings as-is,
mark the file PARTIAL at the top, print the path and what to
cover next time.
while: # the OUTER loop — repeat sessions until the GOAL holds
enabled: true
max_iterations: 5
max_duration: 40m
budget: 15b
prompts:
until: >
The findings file covers every competitor on the list, each with a
source URL, a what-changed line, and a date — no duplicates.
iterate_with: >
Continue the watch for {{args}}, same rules. The current findings
are seeded above: cover what's MISSING, merge, save back to the
same file.
---
You are researching public pages about: **{{args}}**.
This is **read-only research** — do not post, message, or interact. If you
hit a login wall you don't own, a captcha, or a rate limit: STOP and report.
For each source collect: URL, what changed since the last file, why it
matters, and a quote or number that backs it up.
When done, write the findings as Markdown to {{output_dir}}/<topic>-<date>.md
and print the saved file path here.
Everything about the job lives next to the goal it protects. The body is the task. The frontmatter is the contract: which browser identity, which start page, what "done" means, how much it may spend, how to stop gracefully. {{args}} templating makes one file a family of automations — competitor-watch "ai terminals" today, competitor-watch "support chatbots" next quarter.
One-time setup: a browser identity that persists
The agent drives a real Chromium, not an HTTP scraper — so it should be logged in the way you are. That's web_profile. You authenticate once, by hand, in a headed browser:
##web headless login research https://example.com/
# a visible browser opens on the "research" profile — log in like a human, close it
The session now lives in that profile, and every --headless run reuses it — including on a machine with no display:
##auto web run --headless competitor-watch "ai terminals"
Two things worth appreciating about this split: the agent isn't attached to the login window (you typed your password, once, into a browser rysh doesn't drive), and the identity is scoped — the research profile is only for research, not your personal everything-browser.
The leash
The reason this can run while you sleep, and not as a horror-story opener:
- Enforced budgets. Token budgets use units of pages, books, shelves — a page is 1,000 tokens, a book 200 pages, a shelf 20 books.
size: 3b= 600k tokens per session. A ceiling, not a vibe. Iteration and wall-clock caps stack on top, and flags override per-run:--budget-size 50p --max-duration 10m. - A graceful takeover, not a wall. At
takeover_when: 90, the run switches to thetakeover_promptwith the remaining budget (raised to a floor when that share is too thin to finish): save partial results, mark them PARTIAL, report what's left. The agent lands the plane instead of hitting one. - An LLM judge decides "done." The outer
whileloop re-enters only if theuntilcondition — checked against the latest saved output file — doesn't hold, under its own budget (15b, split evenly across the passes) and session cap. The judge is an LLM: a strong signal, not a proof. Review before you act. - Interruptions are cheap. Double-Ctrl+C pauses a run mid-pass;
##auto web continue competitor-watchresumes that pass from the last checkpoint, budget re-armed — not from zero. (How resumption grounds itself on saved state is its own post.) - Behavioral guardrails live in the prompt — instructions the agent is given, not stops the runtime enforces: read-only, stop at walls, stop at rate limits.
And before trusting any of it, rehearse:
##auto web check competitor-watch # lint the recipe
##auto web run --dry-run competitor-watch "x" # print the resolved plan, dispatch nothing
From chore to infrastructure
Once a recipe works, the machinery composes:
# fan out over topics, sequentially
##auto web run --each "ai-terminals,support-chatbots,agent-frameworks" competitor-watch
# put it on a schedule — a ##cron job that runs the recipe headless with its topic:
##cron add monday-watch "0 2 * * 1" ##auto web run --headless competitor-watch ai terminals
##cron logs monday-watch # when it fired, and whether it dispatched
A notify: block pings a channel when a run ends — via one of a rysh humanoid's channels, with how the run ended and where its results are. And on_success: chains recipes: when the watch succeeds, the next recipe runs — say, a summarizer you point at the results folder, written to draft the digest for you to review. Write it to draft, not send.
Results are files, not chat scrollback:
##auto web results competitor-watch # list saved runs
##auto web results competitor-watch ai-terminals-2026-07-13.md
Dated markdown you can diff, review, and commit.
The ethics section (read before you build one)
- Read-only by instruction. Recipes for other people's platforms should forbid messaging, following, posting — in the prompt, as this one does. The step where a human gets contacted stays human — you read, you decide, you reach out yourself. Automating outreach is how you become spam.
- It's told to stop at walls. Login walls, captchas, rate-limit notices are stop conditions in the prompt, not puzzles to defeat. The agent reads public pages on sessions you own, under a session cap.
- Your account, your responsibility. Platform terms apply to you, not your tooling. This is a research assistant on a browser profile you logged into yourself — treat it that way.
Honest scope
- rysh runs on Claude — bring your own Anthropic key. Provider layer pluggable.
- rysh is open-core — the CLI is Apache-2.0, the server is proprietary (your machine, your keys, your data).
- Headless works on a server; the one-time
loginneeds a display on that machine, once. ##autois an umbrella — the same save/run/budget/schedule machinery drivestask,agent, andcodeautomations. This post coveredwebonly.
Got a chore shaped like browse → judge → collect → merge? It's probably one recipe file away from being a command. We're recruiting design partners — tell us what you'd point this at and we'll tell you honestly whether it works today. → rysh.ai/design-partner
Companions: Grounded resumption: when a browser agent gets interrupted · Pages, books, and shelves: budget your agents like a library