web2cli 0.2.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- web2cli/__init__.py +3 -0
- web2cli/__main__.py +5 -0
- web2cli/adapter/__init__.py +0 -0
- web2cli/adapter/lint.py +667 -0
- web2cli/adapter/loader.py +157 -0
- web2cli/adapter/validator.py +127 -0
- web2cli/adapters/discord.com/web2cli.yaml +476 -0
- web2cli/adapters/mail.google.com/parsers/inbox.py +200 -0
- web2cli/adapters/mail.google.com/web2cli.yaml +52 -0
- web2cli/adapters/news.ycombinator.com/web2cli.yaml +356 -0
- web2cli/adapters/reddit.com/web2cli.yaml +233 -0
- web2cli/adapters/slack.com/web2cli.yaml +445 -0
- web2cli/adapters/stackoverflow.com/web2cli.yaml +257 -0
- web2cli/adapters/x.com/providers/x_graphql.py +299 -0
- web2cli/adapters/x.com/web2cli.yaml +449 -0
- web2cli/auth/__init__.py +0 -0
- web2cli/auth/browser_login.py +820 -0
- web2cli/auth/manager.py +166 -0
- web2cli/auth/store.py +68 -0
- web2cli/cli.py +1286 -0
- web2cli/executor/__init__.py +0 -0
- web2cli/executor/http.py +113 -0
- web2cli/output/__init__.py +0 -0
- web2cli/output/formatter.py +116 -0
- web2cli/parser/__init__.py +0 -0
- web2cli/parser/custom.py +21 -0
- web2cli/parser/html_parser.py +111 -0
- web2cli/parser/transforms.py +127 -0
- web2cli/pipe.py +10 -0
- web2cli/providers/__init__.py +6 -0
- web2cli/providers/base.py +22 -0
- web2cli/providers/registry.py +86 -0
- web2cli/runtime/__init__.py +1 -0
- web2cli/runtime/cache.py +42 -0
- web2cli/runtime/engine.py +743 -0
- web2cli/runtime/parser.py +398 -0
- web2cli/runtime/template.py +52 -0
- web2cli/types.py +71 -0
- web2cli-0.2.0.dist-info/METADATA +467 -0
- web2cli-0.2.0.dist-info/RECORD +44 -0
- web2cli-0.2.0.dist-info/WHEEL +5 -0
- web2cli-0.2.0.dist-info/entry_points.txt +2 -0
- web2cli-0.2.0.dist-info/licenses/LICENSE +202 -0
- web2cli-0.2.0.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,467 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: web2cli
|
|
3
|
+
Version: 0.2.0
|
|
4
|
+
Summary: Every website is a command
|
|
5
|
+
Author-email: Michal Oblak <oblak.michal@gmail.com>
|
|
6
|
+
License-Expression: Apache-2.0
|
|
7
|
+
Project-URL: Homepage, https://github.com/jb41/web2cli
|
|
8
|
+
Project-URL: Repository, https://github.com/jb41/web2cli
|
|
9
|
+
Project-URL: Issues, https://github.com/jb41/web2cli/issues
|
|
10
|
+
Classifier: Development Status :: 4 - Beta
|
|
11
|
+
Classifier: Environment :: Console
|
|
12
|
+
Classifier: Intended Audience :: Developers
|
|
13
|
+
Classifier: Operating System :: OS Independent
|
|
14
|
+
Classifier: Programming Language :: Python :: 3
|
|
15
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
18
|
+
Classifier: Topic :: Internet :: WWW/HTTP
|
|
19
|
+
Classifier: Topic :: Utilities
|
|
20
|
+
Requires-Python: >=3.11
|
|
21
|
+
Description-Content-Type: text/markdown
|
|
22
|
+
License-File: LICENSE
|
|
23
|
+
Requires-Dist: typer>=0.24.0
|
|
24
|
+
Requires-Dist: httpx>=0.28.0
|
|
25
|
+
Requires-Dist: pyyaml>=6.0
|
|
26
|
+
Requires-Dist: rich>=14.0
|
|
27
|
+
Requires-Dist: selectolax>=0.3.0
|
|
28
|
+
Requires-Dist: jmespath>=1.1.0
|
|
29
|
+
Requires-Dist: cryptography>=46.0
|
|
30
|
+
Requires-Dist: curl_cffi>=0.7.0
|
|
31
|
+
Requires-Dist: beautifulsoup4>=4.12
|
|
32
|
+
Requires-Dist: XClientTransaction>=1.0
|
|
33
|
+
Provides-Extra: browser
|
|
34
|
+
Requires-Dist: playwright>=1.40; extra == "browser"
|
|
35
|
+
Dynamic: license-file
|
|
36
|
+
|
|
37
|
+
# web2cli
|
|
38
|
+
|
|
39
|
+
**Every website is a Unix command.**
|
|
40
|
+
|
|
41
|
+
Browse Hacker News, search X.com, write Discord messages, read Reddit — all from your terminal. No browser, no API keys, no $100/mo plans.
|
|
42
|
+
|
|
43
|
+

|
|
44
|
+
|
|
45
|
+
```bash
|
|
46
|
+
$ web2cli hn top --limit 3
|
|
47
|
+
┌──────┬──────────────────────────────────────────┬───────┬──────────┐
|
|
48
|
+
│ RANK │ TITLE │ SCORE │ COMMENTS │
|
|
49
|
+
├──────┼──────────────────────────────────────────┼───────┼──────────┤
|
|
50
|
+
│ 1 │ Show HN: I built a CLI for every website │ 313 │ 37 │
|
|
51
|
+
│ 2 │ Why agents don't need browsers │ 271 │ 89 │
|
|
52
|
+
│ 3 │ The Unix philosophy, 50 years later │ 198 │ 64 │
|
|
53
|
+
└──────┴──────────────────────────────────────────┴───────┴──────────┘
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
```bash
|
|
57
|
+
$ web2cli login x --browser
|
|
58
|
+
$ web2cli x search --query "build for agents" --limit 1 --format json
|
|
59
|
+
[
|
|
60
|
+
{
|
|
61
|
+
"author": "@karpathy",
|
|
62
|
+
"text": "CLIs are super exciting precisely because they are a \"legacy\" technology, which means AI agents can natively and easily use them, combine them, interact with them via the entire terminal toolkit.\n\nE.g ask your Claude/Codex agent to install this new Polymarket CLI and ask for any https://t.co/gzrpg0erGz",
|
|
63
|
+
"date": "2026-02-24 18:17",
|
|
64
|
+
"retweets": 1085,
|
|
65
|
+
"likes": 11481,
|
|
66
|
+
"replies": 610,
|
|
67
|
+
"views": "1923316"
|
|
68
|
+
}
|
|
69
|
+
]
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
```bash
|
|
73
|
+
$ web2cli login discord --browser
|
|
74
|
+
$ web2cli discord send --server "My Server" --channel general --message "deployed 🚀" > /dev/null
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
## Why?
|
|
78
|
+
- **For agents**: HTTP GET, not Chromium. 50ms not 5s. \$0.000001 not \$0.10.
|
|
79
|
+
- **For humans**: `curl` for the modern web. Pipe, grep, script anything.
|
|
80
|
+
- **For both**: One interface. `web2cli <site> <command>`. That's it.
|
|
81
|
+
|
|
82
|
+
```bash
|
|
83
|
+
pip install web2cli
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
## Performance
|
|
87
|
+
|
|
88
|
+
web2cli makes direct HTTP requests. No browser, no DOM, no screenshots.
|
|
89
|
+
|
|
90
|
+
| Metric | Browser automation | web2cli |
|
|
91
|
+
|---------------------------|:---:|:---:|
|
|
92
|
+
| Fetch 10 top news from HN | ~20s (launch + render) | 0.5s |
|
|
93
|
+
| Memory per request | ~821.3MB (Chromium) | ~5MB (HTTP) |
|
|
94
|
+
| Cost at 10k req/day | \$20/day (just LLM)<br>~\$23.3/day (LLM + remote browser) | ~\$0 (HTTP) |
|
|
95
|
+
| Tokens to parse | ~8647 (HTML/DOM estimate) | ~300 (Markdown table) |
|
|
96
|
+
|
|
97
|
+
### Real-world benchmarks
|
|
98
|
+
|
|
99
|
+
| Task | Official API | Browser | web2cli | Speedup |
|
|
100
|
+
|-----------------------|:------------:|:-------:|:-------:|--------:|
|
|
101
|
+
| Read Discord messages | ✓ has API | 26s | 0.63s | 41x |
|
|
102
|
+
| Send a Slack message | ✓ has API | 35s | 0.60s | 58x |
|
|
103
|
+
| Search X | $100/mo API | 75s | 1.54s | 50x |
|
|
104
|
+
| Search Stack Overflow | 300 req/day | 41s | 0.65s | 63x |
|
|
105
|
+
| Fetch HN submissions | partial API | 36s | 1.42s | 25x |
|
|
106
|
+
|
|
107
|
+
> Some sites have great APIs. Some have expensive ones. Some have none.
|
|
108
|
+
> web2cli gives you one interface for all of them
|
|
109
|
+
|
|
110
|
+
### What this means for agents
|
|
111
|
+
|
|
112
|
+
| Scenario | Browser automation | web2cli |
|
|
113
|
+
|------------------------------------|:------------------:|:-----------:|
|
|
114
|
+
| Monitor Discord (1 check/min) | $2.88/day | $0.0015/day |
|
|
115
|
+
| Scan X every 5 min, 24/7 | $1.58/day | $0.0003/day |
|
|
116
|
+
| 10k daily actions (typical bot) | ~$50/day | ~$0.01/day |
|
|
117
|
+
| **Monthly infra for active agent** | **$50+/mo** | **$4/mo** |
|
|
118
|
+
|
|
119
|
+
> Browser automation is the right choice for sites that require JS rendering
|
|
120
|
+
> or complex interaction flows. web2cli is for the 80% of tasks that don't.
|
|
121
|
+
|
|
122
|
+
## More code examples
|
|
123
|
+
### Daily HN top stories summary
|
|
124
|
+
```bash
|
|
125
|
+
web2cli hn top --limit 3 --fields title,url --format md | \
|
|
126
|
+
claude -p "For each story, fetch the URL and write a 1-sentence summary. Output as a bullet list." --allowedTools "WebFetch" | \
|
|
127
|
+
web2cli discord send --server "ZENO.blue" --channel "testy-mo" > /dev/null
|
|
128
|
+
```
|
|
129
|
+
|
|
130
|
+
### Minimal Discord answering bot
|
|
131
|
+
```python
|
|
132
|
+
import json, subprocess, time, anthropic
|
|
133
|
+
|
|
134
|
+
NICK = "your_nickname"
|
|
135
|
+
SERVER = "YOUR_SERVER_NAME"
|
|
136
|
+
CHANNEL = "channel_name_here"
|
|
137
|
+
SYSTEM = "You are a bot on Discord. Respond briefly, in user language, without markdown."
|
|
138
|
+
|
|
139
|
+
seen = set()
|
|
140
|
+
|
|
141
|
+
|
|
142
|
+
def web2cli(*args):
|
|
143
|
+
result = subprocess.run(["web2cli", "discord", *args, "--format", "json"], capture_output=True, text=True)
|
|
144
|
+
return json.loads(result.stdout or "[]")
|
|
145
|
+
|
|
146
|
+
|
|
147
|
+
def fetch():
|
|
148
|
+
return web2cli("messages", "--server", SERVER, "--channel", CHANNEL, "--limit", "20")
|
|
149
|
+
|
|
150
|
+
|
|
151
|
+
def send(text):
|
|
152
|
+
web2cli("send", "--server", SERVER, "--channel", CHANNEL, "--message", text)
|
|
153
|
+
|
|
154
|
+
|
|
155
|
+
def fmt(msgs):
|
|
156
|
+
return "\n".join(f'{m["author"]}: {m["content"]}' for m in msgs)
|
|
157
|
+
|
|
158
|
+
|
|
159
|
+
def ask(context, new_msgs):
|
|
160
|
+
resp = anthropic.Anthropic().messages.create(
|
|
161
|
+
model="claude-sonnet-4-6", max_tokens=512, system=SYSTEM,
|
|
162
|
+
messages=[{"role": "user", "content": f"Last messages:\n{context}\n\nNew for you:\n{new_msgs}"}],
|
|
163
|
+
)
|
|
164
|
+
return resp.content[0].text
|
|
165
|
+
|
|
166
|
+
|
|
167
|
+
# Seed seen IDs
|
|
168
|
+
for m in fetch():
|
|
169
|
+
seen.add(m["id"])
|
|
170
|
+
|
|
171
|
+
print(f"Watching #{CHANNEL} for @{NICK}...")
|
|
172
|
+
|
|
173
|
+
while True:
|
|
174
|
+
time.sleep(30)
|
|
175
|
+
msgs = fetch()
|
|
176
|
+
new = [m for m in msgs if m["id"] not in seen and NICK in m.get("content", "").lower()]
|
|
177
|
+
for m in msgs:
|
|
178
|
+
seen.add(m["id"])
|
|
179
|
+
if not new:
|
|
180
|
+
continue
|
|
181
|
+
reply = ask(fmt(msgs), fmt(new))
|
|
182
|
+
print(f"→ {reply}")
|
|
183
|
+
send(reply)
|
|
184
|
+
```
|
|
185
|
+
|
|
186
|
+
## Built-in Adapters
|
|
187
|
+
Current built-in adapters and actions:
|
|
188
|
+
|
|
189
|
+
### discord.com (`dc`, `discord`)
|
|
190
|
+
- `me` - Show current user info
|
|
191
|
+
- `servers` - List your Discord servers (guilds)
|
|
192
|
+
- `channels` - List channels in a server
|
|
193
|
+
- `messages` - Get messages from a channel
|
|
194
|
+
- `send` - Send a message to a channel
|
|
195
|
+
- `dm` - List DM conversations
|
|
196
|
+
- `dm-messages` - Get messages from a DM conversation
|
|
197
|
+
- `dm-send` - Send a DM to a user
|
|
198
|
+
|
|
199
|
+
### news.ycombinator.com (`hn`)
|
|
200
|
+
- `top` - Get top stories from Hacker News
|
|
201
|
+
- `new` - Get newest stories
|
|
202
|
+
- `item` - Get a single HN item (story, comment, job)
|
|
203
|
+
- `search` - Search HN stories (via Algolia)
|
|
204
|
+
- `saved` - Get saved stories (requires login)
|
|
205
|
+
- `upvoted` - Get upvoted stories (requires login)
|
|
206
|
+
- `submissions` - Get a user's submissions
|
|
207
|
+
|
|
208
|
+
### reddit.com (`reddit`)
|
|
209
|
+
- `posts` - List posts from a subreddit
|
|
210
|
+
- `thread` - Get a thread with comments
|
|
211
|
+
- `search` - Search posts in a subreddit
|
|
212
|
+
|
|
213
|
+
### slack.com (`slack`)
|
|
214
|
+
- `me` - Show current user and workspace info
|
|
215
|
+
- `channels` - List channels in workspace
|
|
216
|
+
- `messages` - Get messages from a channel
|
|
217
|
+
- `send` - Send a message to a channel
|
|
218
|
+
- `dm` - List DM conversations
|
|
219
|
+
- `dm-messages` - Get messages from a DM conversation
|
|
220
|
+
- `dm-send` - Send a DM to a user
|
|
221
|
+
|
|
222
|
+
### stackoverflow.com (`so`)
|
|
223
|
+
- `search` - Search Stack Overflow questions
|
|
224
|
+
- `question` - Read a specific question and its top answers
|
|
225
|
+
- `tagged` - Browse questions by tag
|
|
226
|
+
|
|
227
|
+
### x.com (`x`, `twitter`)
|
|
228
|
+
- `tweet` - Get a single tweet by ID or URL
|
|
229
|
+
- `profile` - Get user profile info
|
|
230
|
+
- `search` - Search tweets
|
|
231
|
+
- `timeline` - Home timeline (For you tab)
|
|
232
|
+
- `following` - Following timeline
|
|
233
|
+
|
|
234
|
+
To inspect adapter details from CLI:
|
|
235
|
+
|
|
236
|
+
```bash
|
|
237
|
+
web2cli adapters list
|
|
238
|
+
web2cli adapters info <domain-or-alias>
|
|
239
|
+
```
|
|
240
|
+
|
|
241
|
+
## Documentation
|
|
242
|
+
Key docs for contributors:
|
|
243
|
+
|
|
244
|
+
- `docs/adapter-spec.md` - canonical adapter specification (current: `0.2`)
|
|
245
|
+
- `docs/llm-adapter-playbook.md` - adapter authoring workflow for LLM agents
|
|
246
|
+
- `docs/adapter-spec.schema.json` - machine-readable schema for quick structural checks
|
|
247
|
+
|
|
248
|
+
## Custom Adapters Quickstart
|
|
249
|
+
Create a minimal custom adapter end-to-end using `httpbin.org` (global, simple, auth-friendly test target).
|
|
250
|
+
|
|
251
|
+
1. Create adapter directory:
|
|
252
|
+
```bash
|
|
253
|
+
mkdir -p ~/.web2cli/adapters/httpbin.org
|
|
254
|
+
```
|
|
255
|
+
|
|
256
|
+
2. Create `~/.web2cli/adapters/httpbin.org/web2cli.yaml`:
|
|
257
|
+
```yaml
|
|
258
|
+
meta:
|
|
259
|
+
spec_version: "0.2"
|
|
260
|
+
name: httpbin
|
|
261
|
+
domain: httpbin.org
|
|
262
|
+
base_url: https://httpbin.org
|
|
263
|
+
version: 0.2.0
|
|
264
|
+
description: "HTTPBin demo adapter"
|
|
265
|
+
author: custom
|
|
266
|
+
aliases: [hb]
|
|
267
|
+
transport: http
|
|
268
|
+
impersonate: chrome
|
|
269
|
+
default_headers:
|
|
270
|
+
Accept: "application/json"
|
|
271
|
+
|
|
272
|
+
auth:
|
|
273
|
+
methods:
|
|
274
|
+
- type: token
|
|
275
|
+
env_var: WEB2CLI_HTTPBIN_TOKEN
|
|
276
|
+
inject:
|
|
277
|
+
target: header
|
|
278
|
+
key: Authorization
|
|
279
|
+
prefix: "Bearer "
|
|
280
|
+
- type: cookies
|
|
281
|
+
keys: [session]
|
|
282
|
+
env_var: WEB2CLI_HTTPBIN_COOKIES
|
|
283
|
+
|
|
284
|
+
commands:
|
|
285
|
+
ip:
|
|
286
|
+
description: "Show IP seen by server"
|
|
287
|
+
pipeline:
|
|
288
|
+
- request:
|
|
289
|
+
name: fetch
|
|
290
|
+
method: GET
|
|
291
|
+
url: /ip
|
|
292
|
+
- parse:
|
|
293
|
+
name: parsed
|
|
294
|
+
from: fetch
|
|
295
|
+
format: json
|
|
296
|
+
extract: "$"
|
|
297
|
+
fields:
|
|
298
|
+
- name: origin
|
|
299
|
+
from: "$.origin"
|
|
300
|
+
output:
|
|
301
|
+
from_step: parsed
|
|
302
|
+
default_fields: [origin]
|
|
303
|
+
default_format: table
|
|
304
|
+
|
|
305
|
+
bearer-check:
|
|
306
|
+
description: "Check bearer auth"
|
|
307
|
+
pipeline:
|
|
308
|
+
- request:
|
|
309
|
+
name: fetch
|
|
310
|
+
method: GET
|
|
311
|
+
url: /bearer
|
|
312
|
+
- parse:
|
|
313
|
+
name: parsed
|
|
314
|
+
from: fetch
|
|
315
|
+
format: json
|
|
316
|
+
extract: "$"
|
|
317
|
+
fields:
|
|
318
|
+
- name: authenticated
|
|
319
|
+
from: "$.authenticated"
|
|
320
|
+
default: false
|
|
321
|
+
- name: token
|
|
322
|
+
from: "$.token"
|
|
323
|
+
default: ""
|
|
324
|
+
output:
|
|
325
|
+
from_step: parsed
|
|
326
|
+
default_fields: [authenticated, token]
|
|
327
|
+
default_format: table
|
|
328
|
+
|
|
329
|
+
cookies:
|
|
330
|
+
description: "Echo cookies seen by server"
|
|
331
|
+
pipeline:
|
|
332
|
+
- request:
|
|
333
|
+
name: fetch
|
|
334
|
+
method: GET
|
|
335
|
+
url: /cookies
|
|
336
|
+
- parse:
|
|
337
|
+
name: parsed
|
|
338
|
+
from: fetch
|
|
339
|
+
format: json
|
|
340
|
+
extract: "$.cookies"
|
|
341
|
+
output:
|
|
342
|
+
from_step: parsed
|
|
343
|
+
default_format: json
|
|
344
|
+
```
|
|
345
|
+
|
|
346
|
+
3. Validate and lint:
|
|
347
|
+
```bash
|
|
348
|
+
web2cli adapters validate
|
|
349
|
+
web2cli adapters lint httpbin.org
|
|
350
|
+
```
|
|
351
|
+
|
|
352
|
+
4. Inspect and run:
|
|
353
|
+
```bash
|
|
354
|
+
web2cli adapters info hb
|
|
355
|
+
web2cli hb ip
|
|
356
|
+
```
|
|
357
|
+
|
|
358
|
+
5. Test token auth (session-based):
|
|
359
|
+
```bash
|
|
360
|
+
web2cli login hb --token "abc123"
|
|
361
|
+
web2cli hb bearer-check --trace --verbose
|
|
362
|
+
```
|
|
363
|
+
|
|
364
|
+
6. Test cookie auth:
|
|
365
|
+
```bash
|
|
366
|
+
web2cli login hb --cookies "session=my-session"
|
|
367
|
+
web2cli hb cookies --format json
|
|
368
|
+
```
|
|
369
|
+
|
|
370
|
+
If you prefer env vars instead of stored sessions:
|
|
371
|
+
```bash
|
|
372
|
+
export WEB2CLI_HTTPBIN_TOKEN="abc123"
|
|
373
|
+
export WEB2CLI_HTTPBIN_COOKIES="session=my-session"
|
|
374
|
+
web2cli hb bearer-check
|
|
375
|
+
web2cli hb cookies
|
|
376
|
+
```
|
|
377
|
+
|
|
378
|
+
## Debugging and Quality
|
|
379
|
+
|
|
380
|
+
```bash
|
|
381
|
+
# Validate + semantic lint all adapters
|
|
382
|
+
web2cli adapters validate
|
|
383
|
+
web2cli adapters lint
|
|
384
|
+
|
|
385
|
+
# Inspect step-by-step runtime trace for a command
|
|
386
|
+
web2cli reddit posts --sub python --limit 3 --trace
|
|
387
|
+
|
|
388
|
+
# Disable adapter/parser truncation (full text fields)
|
|
389
|
+
web2cli so question --id 79861629 --format json --no-truncate
|
|
390
|
+
|
|
391
|
+
# Diagnose browser stack used by `login --browser`
|
|
392
|
+
web2cli doctor browser
|
|
393
|
+
web2cli doctor browser --deep
|
|
394
|
+
```
|
|
395
|
+
|
|
396
|
+
## Browser Login
|
|
397
|
+
|
|
398
|
+
For sites that use cookies and/or runtime tokens, you can capture a session directly from a real browser:
|
|
399
|
+
|
|
400
|
+
```bash
|
|
401
|
+
web2cli login x.com --browser
|
|
402
|
+
```
|
|
403
|
+
|
|
404
|
+
`web2cli` opens Chromium and waits until all required auth values are available:
|
|
405
|
+
|
|
406
|
+
- required cookie keys from `auth.methods[].keys`
|
|
407
|
+
- token values defined by `auth.methods[].capture` (for `type: token`)
|
|
408
|
+
|
|
409
|
+
Then it encrypts and stores the session in `~/.web2cli/sessions/<domain>.json.enc`.
|
|
410
|
+
|
|
411
|
+
Token capture example in adapter YAML:
|
|
412
|
+
|
|
413
|
+
```yaml
|
|
414
|
+
auth:
|
|
415
|
+
methods:
|
|
416
|
+
- type: token
|
|
417
|
+
env_var: WEB2CLI_DISCORD_TOKEN
|
|
418
|
+
inject:
|
|
419
|
+
target: header
|
|
420
|
+
key: Authorization
|
|
421
|
+
capture:
|
|
422
|
+
from: request.header
|
|
423
|
+
key: Authorization
|
|
424
|
+
match:
|
|
425
|
+
host: discord.com
|
|
426
|
+
path_regex: "^/api/"
|
|
427
|
+
```
|
|
428
|
+
|
|
429
|
+
Inspect current login state:
|
|
430
|
+
|
|
431
|
+
```bash
|
|
432
|
+
web2cli login x.com --status
|
|
433
|
+
```
|
|
434
|
+
|
|
435
|
+
Troubleshoot browser capture flow:
|
|
436
|
+
|
|
437
|
+
```bash
|
|
438
|
+
web2cli login slack --browser --browser-debug
|
|
439
|
+
```
|
|
440
|
+
|
|
441
|
+
This prints live capture state (have/missing cookies, token status, tracked tabs in browser context).
|
|
442
|
+
|
|
443
|
+
`--browser` automatically picks the best browser strategy (including local Chrome fallback for stricter sites) so users typically don't need extra setup.
|
|
444
|
+
|
|
445
|
+
## For LLMs
|
|
446
|
+
If you are using an LLM/agent to generate a new adapter, use this flow:
|
|
447
|
+
|
|
448
|
+
1. Start from `docs/llm-adapter-playbook.md` and the minimal adapter template.
|
|
449
|
+
2. Prefer declarative steps (`resolve`, `request`, `fanout`, `parse`, `transform`).
|
|
450
|
+
3. Avoid custom parser scripts unless declarative parsing is truly insufficient.
|
|
451
|
+
4. Always run `web2cli adapters validate`, `web2cli adapters lint`, and at least one command with `--trace`.
|
|
452
|
+
5. Do not stop until all three checks pass and output fields look correct.
|
|
453
|
+
|
|
454
|
+
### web2cli Cloud (coming soon)
|
|
455
|
+
|
|
456
|
+
Building an agent for other people? Cloud handles auth so you don't have to.
|
|
457
|
+
|
|
458
|
+
Your users click a link, log in to any site in a sandboxed browser,
|
|
459
|
+
and your agent gets an opaque session token. No cookies touch your server.
|
|
460
|
+
|
|
461
|
+
Think "OAuth for websites that don't have OAuth."
|
|
462
|
+
|
|
463
|
+
→ [Join the waitlist](https://web2cli.com#cloud)
|
|
464
|
+
|
|
465
|
+
---
|
|
466
|
+
|
|
467
|
+
Created by [@michaloblak](https://x.com/michaloblak).
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
web2cli/__init__.py,sha256=nkiq2pyOaDyshAD6Nsxnvtdl3mjZ2-6EHSZaWpfPLwY,69
|
|
2
|
+
web2cli/__main__.py,sha256=-9ezTckIr-xZEOVNYVb08DZVPcBBVw-slDj6P1fKT-o,71
|
|
3
|
+
web2cli/cli.py,sha256=XIBJR-EuNZIX786v2KbXoqxP3zanzeyrhpQvSA65qMs,44463
|
|
4
|
+
web2cli/pipe.py,sha256=u3kgxCAMDjJ-T5aTrkZ29mbMpWxQfcfuxsVe47VsWFM,259
|
|
5
|
+
web2cli/types.py,sha256=p2KdRiuwp9pZulbZNPhQuv_GEfRqOBnoocS_tcbpzf8,1850
|
|
6
|
+
web2cli/adapter/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
7
|
+
web2cli/adapter/lint.py,sha256=JwfgrAyXlgAUXz5dLq3xG92Qg62FFQ92l4E-_nVR2hM,21172
|
|
8
|
+
web2cli/adapter/loader.py,sha256=ygWJYzymI1JE3mWdFyPKnrHTGEjq8Hc3gZirWbvmgDc,4986
|
|
9
|
+
web2cli/adapter/validator.py,sha256=yP9MQY9zG-oWgufkVE3b01gwOG1x7KNmcgNTSjEYvCE,4976
|
|
10
|
+
web2cli/adapters/discord.com/web2cli.yaml,sha256=yxT_G9dGINfrU-1ZAZOn7tfg6MCnO2o8Ssmy2N85oWY,11762
|
|
11
|
+
web2cli/adapters/mail.google.com/web2cli.yaml,sha256=NQN-TrZfPTRdz7tEQ5R6_roRaZUJlEeq7OTlGFS12Vw,1332
|
|
12
|
+
web2cli/adapters/mail.google.com/parsers/inbox.py,sha256=wl7niuNlIpJx5j5SuCDX90dF9SYxkvLu_nN5B1Es8q4,5777
|
|
13
|
+
web2cli/adapters/news.ycombinator.com/web2cli.yaml,sha256=8cb8as42vWKBR_ho3ohpcODWp7cc_roX11ruuFsQ274,9482
|
|
14
|
+
web2cli/adapters/reddit.com/web2cli.yaml,sha256=kwbq_IvvY992TCw2idY5CTg2dmNduMjGgr1keg8D57A,6465
|
|
15
|
+
web2cli/adapters/slack.com/web2cli.yaml,sha256=3fipxSv3Ge-lisUiHD23kxwd2jxuDZdvFJyDN9kgKXg,10791
|
|
16
|
+
web2cli/adapters/stackoverflow.com/web2cli.yaml,sha256=QKcKRYD8MfIiVsilU8QYcD-iy-nnl-YMgacu3ow6WVY,7462
|
|
17
|
+
web2cli/adapters/x.com/web2cli.yaml,sha256=Nl_2EbD8-ZfufH-0irpJQ2IqMPpR11TH_O5CktjZDDM,14899
|
|
18
|
+
web2cli/adapters/x.com/providers/x_graphql.py,sha256=HNRbDvV1uUyD6R81s5CTrkye5mKWpB23mU591cFm6SY,10887
|
|
19
|
+
web2cli/auth/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
20
|
+
web2cli/auth/browser_login.py,sha256=spG4DXlj_K8dnRig_Lqk12M2b1J29kV8RcosSpulH_c,26959
|
|
21
|
+
web2cli/auth/manager.py,sha256=rcYLO1KVEh0udHJlgURG27FuYaWyiQWGXXr-g0lYxCQ,4709
|
|
22
|
+
web2cli/auth/store.py,sha256=9lQUMDyXe2uKoS1VUNNTd6VHL44c0PcjO1nN6-2T89w,2049
|
|
23
|
+
web2cli/executor/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
24
|
+
web2cli/executor/http.py,sha256=GHfCnz2jSM6PtCgWRmxznwKAljM8nA_TW_O5hVQuMks,4073
|
|
25
|
+
web2cli/output/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
26
|
+
web2cli/output/formatter.py,sha256=Gbm8BXpx8Xnc0G2S_9QWX0C8dwJJzpQXQpt9gTKzZrM,3420
|
|
27
|
+
web2cli/parser/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
28
|
+
web2cli/parser/custom.py,sha256=FJ_2DD6N3DBSnuYphuQA2ThHcIwCBwvIcKB-NFN72cM,579
|
|
29
|
+
web2cli/parser/html_parser.py,sha256=9C7Gl0y6Xolss2h6PB0859RgYp315LSoybVRn3uSJs4,3740
|
|
30
|
+
web2cli/parser/transforms.py,sha256=eRjJF8GXCid2V6G9yynkYbkz5X4E7Gwgd1azFBwUd1c,3951
|
|
31
|
+
web2cli/providers/__init__.py,sha256=SimP3TATEKllXMHUwF5vjuiNIsEIE17T_ujtQB6Bdh0,185
|
|
32
|
+
web2cli/providers/base.py,sha256=L-LpmJ-CAeO7v8X6639RXVdGe2KBW4fhaPCznhDSGLM,453
|
|
33
|
+
web2cli/providers/registry.py,sha256=kCgroE6A-z4ZJ1X7j0KKZS1ugS3ot0FlSzxzMAtuj5Y,2577
|
|
34
|
+
web2cli/runtime/__init__.py,sha256=sI17TxyfdMaxbHKNU3BhG0SSW_SaB9CEoO2EzonvF18,31
|
|
35
|
+
web2cli/runtime/cache.py,sha256=C4yG8d_uCOmfsSPLJQXkza8x_XFeRhwlfLK4jECpklo,1187
|
|
36
|
+
web2cli/runtime/engine.py,sha256=a9Nk-J-j_kIQvg3Gl8gYrSYvtXtxwWrwJCDAR7yDgAc,24193
|
|
37
|
+
web2cli/runtime/parser.py,sha256=laAXd_zvLFsdEMUVZ0N2TF6ymrwCutSdyh97w3ieK98,13090
|
|
38
|
+
web2cli/runtime/template.py,sha256=sxWLcywwcPeYb1rBhQJlSfXLO5HaS-bbVdrT6LslOgE,1506
|
|
39
|
+
web2cli-0.2.0.dist-info/licenses/LICENSE,sha256=_X1E6bg0D4OPd5751VT9CiF5GZnoyrbuM5wT3_u0pDc,11350
|
|
40
|
+
web2cli-0.2.0.dist-info/METADATA,sha256=dMk2obWwK_J7dfl6u2xVejK1mfdMelKotNz_jhwxWpQ,14416
|
|
41
|
+
web2cli-0.2.0.dist-info/WHEEL,sha256=YCfwYGOYMi5Jhw2fU4yNgwErybb2IX5PEwBKV4ZbdBo,91
|
|
42
|
+
web2cli-0.2.0.dist-info/entry_points.txt,sha256=6otIeQwB7mpuME0XwnrboEv1yDsGNg46WreFRZhBPaM,44
|
|
43
|
+
web2cli-0.2.0.dist-info/top_level.txt,sha256=Di-cAuJuPlTAskWxJmIgwEjEUF_gJpp9AsMqc7QwPNY,8
|
|
44
|
+
web2cli-0.2.0.dist-info/RECORD,,
|