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.
Files changed (44) hide show
  1. web2cli/__init__.py +3 -0
  2. web2cli/__main__.py +5 -0
  3. web2cli/adapter/__init__.py +0 -0
  4. web2cli/adapter/lint.py +667 -0
  5. web2cli/adapter/loader.py +157 -0
  6. web2cli/adapter/validator.py +127 -0
  7. web2cli/adapters/discord.com/web2cli.yaml +476 -0
  8. web2cli/adapters/mail.google.com/parsers/inbox.py +200 -0
  9. web2cli/adapters/mail.google.com/web2cli.yaml +52 -0
  10. web2cli/adapters/news.ycombinator.com/web2cli.yaml +356 -0
  11. web2cli/adapters/reddit.com/web2cli.yaml +233 -0
  12. web2cli/adapters/slack.com/web2cli.yaml +445 -0
  13. web2cli/adapters/stackoverflow.com/web2cli.yaml +257 -0
  14. web2cli/adapters/x.com/providers/x_graphql.py +299 -0
  15. web2cli/adapters/x.com/web2cli.yaml +449 -0
  16. web2cli/auth/__init__.py +0 -0
  17. web2cli/auth/browser_login.py +820 -0
  18. web2cli/auth/manager.py +166 -0
  19. web2cli/auth/store.py +68 -0
  20. web2cli/cli.py +1286 -0
  21. web2cli/executor/__init__.py +0 -0
  22. web2cli/executor/http.py +113 -0
  23. web2cli/output/__init__.py +0 -0
  24. web2cli/output/formatter.py +116 -0
  25. web2cli/parser/__init__.py +0 -0
  26. web2cli/parser/custom.py +21 -0
  27. web2cli/parser/html_parser.py +111 -0
  28. web2cli/parser/transforms.py +127 -0
  29. web2cli/pipe.py +10 -0
  30. web2cli/providers/__init__.py +6 -0
  31. web2cli/providers/base.py +22 -0
  32. web2cli/providers/registry.py +86 -0
  33. web2cli/runtime/__init__.py +1 -0
  34. web2cli/runtime/cache.py +42 -0
  35. web2cli/runtime/engine.py +743 -0
  36. web2cli/runtime/parser.py +398 -0
  37. web2cli/runtime/template.py +52 -0
  38. web2cli/types.py +71 -0
  39. web2cli-0.2.0.dist-info/METADATA +467 -0
  40. web2cli-0.2.0.dist-info/RECORD +44 -0
  41. web2cli-0.2.0.dist-info/WHEEL +5 -0
  42. web2cli-0.2.0.dist-info/entry_points.txt +2 -0
  43. web2cli-0.2.0.dist-info/licenses/LICENSE +202 -0
  44. 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
+ ![DEMO](demo.gif)
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,,
@@ -0,0 +1,5 @@
1
+ Wheel-Version: 1.0
2
+ Generator: setuptools (82.0.0)
3
+ Root-Is-Purelib: true
4
+ Tag: py3-none-any
5
+
@@ -0,0 +1,2 @@
1
+ [console_scripts]
2
+ web2cli = web2cli.cli:app