For agents
HTTP GET, not Chromium. 50ms, not 5s. About $0.000001, not $0.10 per loop.
Terminal-native web automation
Browse Hacker News, search X.com, write Discord messages, and read Reddit straight from your terminal. No browser loops, no API keys, no $100/mo plans.
$ web2cli hn top --limit 3 ┌──────┬──────────────────────────────────────────┬───────┬──────────┐ │ RANK │ TITLE │ SCORE │ COMMENTS │ ├──────┼──────────────────────────────────────────┼───────┼──────────┤ │ 1 │ Show HN: I built a CLI for every website │ 313 │ 37 │ │ 2 │ Why agents don't need browsers │ 271 │ 89 │ │ 3 │ The Unix philosophy, 50 years later │ 198 │ 64 │ └──────┴──────────────────────────────────────────┴───────┴──────────┘ $ web2cli x search --query "build for agents" --limit 1 --format json
Real terminal run from the project README
web2cli hn top --limit 3web2cli x search --query "agents" --limit 5web2cli discord messages --server ... --channel ...web2cli discord send --server ... --channel ... --message "deployed"One interface for humans and agents
HTTP GET, not Chromium. 50ms, not 5s. About $0.000001, not $0.10 per loop.
It is curl for the modern web. Pipe it, grep it, automate it.
One command model everywhere: web2cli <site> <command>.
Direct HTTP requests. No browser, no DOM, no screenshots.
| Metric | Browser automation | web2cli |
|---|---|---|
| Fetch 10 top news from HN | ~20s (launch + render) | 0.5s |
| Memory per request | ~821.3MB (Chromium) | ~5MB (HTTP) |
| Cost at 10k req/day | $20/day (LLM) or ~$23.3/day (LLM + remote browser) | ~$0 (HTTP) |
| Tokens to parse | ~8647 (HTML/DOM estimate) | ~300 (Markdown table) |
Some sites have great APIs. Some have expensive ones. Some have none. web2cli gives one interface for all of them.
Official API vs browser vs web2cli
| Task | Official API | Browser | web2cli | Speedup |
|---|---|---|---|---|
| Read Discord messages | Has API | 26s | 0.63s | 41x |
| Send a Slack message | Has API | 35s | 0.60s | 58x |
| Search X | $100/mo API | 75s | 1.54s | 50x |
| Search Stack Overflow | 300 req/day | 41s | 0.65s | 63x |
| Fetch HN submissions | partial API | 36s | 1.42s | 25x |
Cost profile for persistent bot workloads
| Scenario | Browser automation | web2cli |
|---|---|---|
| Monitor Discord (1 check/min) | $2.88/day | $0.0015/day |
| Scan X every 5 min, 24/7 | $1.58/day | $0.0003/day |
| 10k daily actions (typical bot) | ~$50/day | ~$0.01/day |
| Monthly infra for active agent | $50+/mo | $4/mo |
Browser automation is still the right tool for JS-heavy flows. web2cli targets the 80% that do not need rendering.
Production-like examples from README
web2cli hn top --limit 3 --fields title,url --format md | \ claude -p "Summarize each story URL in 1 sentence. Output bullets." \ --allowedTools "WebFetch" | \ web2cli discord send --server "ZENO.blue" --channel "testy-mo" > /dev/null
import json, subprocess, time, anthropic
NICK = "your_nickname"
SERVER = "YOUR_SERVER_NAME"
CHANNEL = "channel_name_here"
SYSTEM = "You are a bot on Discord. Respond briefly, in user language, without markdown."
seen = set()
def web2cli(*args):
result = subprocess.run(["web2cli", "discord", *args, "--format", "json"], capture_output=True, text=True)
return json.loads(result.stdout or "[]")
def fetch():
return web2cli("messages", "--server", SERVER, "--channel", CHANNEL, "--limit", "20")
def send(text):
web2cli("send", "--server", SERVER, "--channel", CHANNEL, "--message", text)
def fmt(msgs):
return "\n".join(f'{m["author"]}: {m["content"]}' for m in msgs)
def ask(context, new_msgs):
resp = anthropic.Anthropic().messages.create(
model="claude-sonnet-4-6", max_tokens=512, system=SYSTEM,
messages=[{"role": "user", "content": f"Last messages:\n{context}\n\nNew for you:\n{new_msgs}"}],
)
return resp.content[0].text
# Seed seen IDs
for m in fetch():
seen.add(m["id"])
print(f"Watching #{CHANNEL} for @{NICK}...")
while True:
time.sleep(30)
msgs = fetch()
new = [m for m in msgs if m["id"] not in seen and NICK in m.get("content", "").lower()]
for m in msgs:
seen.add(m["id"])
if not new:
continue
reply = ask(fmt(msgs), fmt(new))
print(f"→ {reply}")
send(reply)
Current domains and actions in v0.2
Spec-driven workflow for contributors and agent builders
Canonical adapter specification, LLM playbook, and schema for fast structural checks.
Create a minimal adapter end-to-end with httpbin.org.
mkdir -p ~/.web2cli/adapters/httpbin.org # create ~/.web2cli/adapters/httpbin.org/web2cli.yaml web2cli adapters validate web2cli adapters lint httpbin.org web2cli adapters info hb web2cli hb ip web2cli login hb --token "abc123" web2cli hb bearer-check --trace --verbose
Inspect parser quality and auth capture flow
web2cli adapters validate web2cli adapters lint web2cli reddit posts --sub python --limit 3 --trace web2cli so question --id 79861629 --format json --no-truncate web2cli doctor browser web2cli doctor browser --deep
Capture cookies and runtime tokens directly from a real browser. Sessions are encrypted
in ~/.web2cli/sessions/<domain>.json.enc.
web2cli login x.com --browser web2cli login x.com --status web2cli login slack --browser --browser-debug
OAuth-style auth layer for websites that do not have OAuth
Building an agent for other people? Users click a link, log in in a sandboxed browser, and your agent receives an opaque session token. No raw cookies on your backend.
Join the waitlist