waidrop-cli 1.0.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.
@@ -0,0 +1,477 @@
1
+ Metadata-Version: 2.5
2
+ Name: waidrop-cli
3
+ Version: 1.0.0
4
+ Summary: Query encrypted WAiDrop archives in Dropbox by name/number and time window
5
+ Project-URL: Homepage, https://github.com/thabiger/waidrop-cli
6
+ Project-URL: Repository, https://github.com/thabiger/waidrop-cli
7
+ Project-URL: Issues, https://github.com/thabiger/waidrop-cli/issues
8
+ Project-URL: Changelog, https://github.com/thabiger/waidrop-cli/blob/main/CHANGELOG.md
9
+ Author-email: Tomasz Habiger <tomasz.habiger@gmail.com>
10
+ License-Expression: Apache-2.0
11
+ License-File: LICENSE
12
+ License-File: NOTICE
13
+ Keywords: archive,backup,cli,dropbox,privacy,whatsapp
14
+ Classifier: Development Status :: 5 - Production/Stable
15
+ Classifier: Environment :: Console
16
+ Classifier: Intended Audience :: End Users/Desktop
17
+ Classifier: Operating System :: OS Independent
18
+ Classifier: Programming Language :: Python :: 3
19
+ Classifier: Programming Language :: Python :: 3.10
20
+ Classifier: Programming Language :: Python :: 3.11
21
+ Classifier: Programming Language :: Python :: 3.12
22
+ Classifier: Programming Language :: Python :: 3.13
23
+ Classifier: Programming Language :: Python :: 3.14
24
+ Classifier: Programming Language :: Python :: 3.15
25
+ Classifier: Topic :: Communications :: Chat
26
+ Classifier: Topic :: System :: Archiving :: Backup
27
+ Requires-Python: >=3.10
28
+ Requires-Dist: cryptography>=42
29
+ Requires-Dist: tzdata>=2025.2; sys_platform == 'win32'
30
+ Provides-Extra: mcp
31
+ Requires-Dist: mcp<3,>=2.3; extra == 'mcp'
32
+ Description-Content-Type: text/markdown
33
+
34
+ # waidrop-cli
35
+
36
+ [![PyPI](https://img.shields.io/pypi/v/waidrop-cli.svg)](https://pypi.org/project/waidrop-cli/)
37
+ [![CI](https://github.com/thabiger/waidrop-cli/actions/workflows/ci.yml/badge.svg)](https://github.com/thabiger/waidrop-cli/actions/workflows/ci.yml)
38
+ [![Python](https://img.shields.io/pypi/pyversions/waidrop-cli.svg)](https://pypi.org/project/waidrop-cli/)
39
+ [![License](https://img.shields.io/badge/license-Apache--2.0-blue.svg)](LICENSE)
40
+
41
+ Query the WhatsApp archive written by the **WAiDrop** Chrome extension into a
42
+ Dropbox App Folder. Fetch messages for one or more conversations — by phone number,
43
+ contact name (wildcards supported), chat hash or JID — over a date- or hour-precise
44
+ window.
45
+
46
+ The CLI talks only to Dropbox and runs entirely locally. It decrypts encrypted
47
+ archives with your archive key; no server is involved.
48
+
49
+ > **Companion extension:** the WAiDrop Chrome extension is required to create
50
+ > the archive. The store link will be added here.
51
+
52
+ ## Requirements
53
+
54
+ - Python ≥ 3.10.
55
+ - An encrypted WhatsApp archive created by the WAiDrop Chrome extension.
56
+ - The archive key generated by the extension.
57
+ - A Dropbox account connected to the same Dropbox app. The built-in app key is
58
+ used by default.
59
+
60
+ On Windows, the `tzdata` package is installed automatically so `--tz` can use
61
+ IANA timezones.
62
+
63
+ ## Install
64
+
65
+ ```sh
66
+ pip install waidrop-cli
67
+ ```
68
+
69
+ Other installers:
70
+
71
+ ```sh
72
+ uv tool install waidrop-cli
73
+ pipx install waidrop-cli
74
+ ```
75
+
76
+ From source:
77
+
78
+ ```sh
79
+ git clone https://github.com/thabiger/waidrop-cli.git
80
+ cd waidrop-cli
81
+ uv sync
82
+ uv run waidrop --help
83
+ ```
84
+
85
+ Upgrade or remove:
86
+
87
+ ```sh
88
+ pip install --upgrade waidrop-cli
89
+ uv tool upgrade waidrop-cli
90
+
91
+ pip uninstall waidrop-cli
92
+ uv tool uninstall waidrop-cli
93
+ ```
94
+
95
+ ## Dropbox setup
96
+
97
+ The CLI uses **OAuth 2.0 with PKCE** and the same Dropbox app as the Chrome
98
+ extension, so both see the same App Folder. The built-in app key is a public
99
+ client id; no client secret is involved for the built-in app. Each user
100
+ authorizes once and the CLI stores a long-lived refresh token locally.
101
+
102
+ ### Connect the CLI
103
+
104
+ ```sh
105
+ waidrop auth
106
+ ```
107
+
108
+ This opens a browser (or prints a URL), asks you to click **Allow** on Dropbox,
109
+ and prompts for the authorization code. Credentials are stored at
110
+ `~/.config/waidrop/credentials.json` (file mode `0600`, directory `0700`).
111
+ On Windows the default is `%APPDATA%\waidrop\credentials.json`.
112
+
113
+ On headless hosts or over SSH:
114
+
115
+ ```sh
116
+ waidrop auth --no-browser # print URL only
117
+ waidrop auth --code <CODE> # non-interactive (pass the code)
118
+ waidrop auth --loopback # localhost callback (desktop)
119
+ ```
120
+
121
+ For `--loopback`, register `http://127.0.0.1:53682/callback` as a redirect URI
122
+ in the Dropbox App Console. The paste flow needs no redirect URI.
123
+
124
+ Check or remove the connection:
125
+
126
+ ```sh
127
+ waidrop auth --status # human-readable
128
+ waidrop auth --status --json # machine-readable
129
+ waidrop auth --revoke # revoke remote access + delete local credentials
130
+ ```
131
+
132
+ `auth --revoke` only deletes local credentials after a successful remote
133
+ revoke. If Dropbox cannot be reached, the local credentials are kept and the
134
+ command exits with code `5`.
135
+
136
+ ### Custom Dropbox apps
137
+
138
+ The built-in app key is `ydtsl7okrf4xuee`. To use your own app, create a
139
+ **Scoped access** app with **App folder** access in the
140
+ [Dropbox App Console](https://www.dropbox.com/developers/apps), enable and
141
+ submit these permissions:
142
+
143
+ - `account_info.read` (account display)
144
+ - `files.metadata.read` (list folders/files)
145
+ - `files.content.read` (downloads; used by this CLI)
146
+ - `files.content.write` (uploads + folder creation; used by the extension)
147
+
148
+ Use PKCE; never ship a client secret. Set the app key with
149
+ `--dropbox-app-key` or `WAIDROP_DROPBOX_APP_KEY`.
150
+
151
+ > **Production note:** Dropbox apps in development mode are limited to test
152
+ > users, and some scopes require review. Verify the app status and scopes before
153
+ > announcing the CLI publicly.
154
+
155
+ > **Old archives:** a Dropbox App Folder is namespaced per app. If your archive
156
+ > was created with a different app key, pass `--dropbox-app-key <old-key>` or
157
+ > set `WAIDROP_DROPBOX_APP_KEY` so the CLI looks in the matching folder.
158
+
159
+ ## Archive format
160
+
161
+ The CLI reads `account=<alias>/_format.json` before fetching data. Only
162
+ encrypted archives are supported:
163
+
164
+ - **encrypted** — objects use `.enc` envelopes and keyed HMAC path hashes.
165
+ `--key` / `WAIDROP_KEY` is required.
166
+ - **legacy v2** — an archive without `_format.json` is treated as encrypted and
167
+ still requires a key.
168
+
169
+ Plaintext archives are not supported. An archive whose `_format.json` declares
170
+ `"mode": "plaintext"` is rejected with a clear error.
171
+
172
+ ## Configuration
173
+
174
+ Flags override environment, which overrides the credentials file.
175
+
176
+ | Setting | Flag | Env | Default |
177
+ |---|---|---|---|
178
+ | Dropbox access token | `--dropbox-token` | `WAIDROP_DROPBOX_TOKEN` | credentials file |
179
+ | Dropbox refresh token | `--dropbox-refresh-token` | `WAIDROP_DROPBOX_REFRESH_TOKEN` | credentials file |
180
+ | Dropbox app key | `--dropbox-app-key` | `WAIDROP_DROPBOX_APP_KEY` | built-in / credentials file |
181
+ | Dropbox app secret | `--dropbox-app-secret` | `WAIDROP_DROPBOX_APP_SECRET` | — (not needed for built-in) |
182
+ | credentials file | `--credentials-file` | `WAIDROP_CREDENTIALS` | `~/.config/waidrop/credentials.json` |
183
+ | archive encryption key | `--key` | `WAIDROP_KEY` | required |
184
+ | account alias | `--account` | `WAIDROP_ACCOUNT` | `primary` |
185
+ | subfolder in app folder | `--folder` | `WAIDROP_FOLDER` | app-folder root |
186
+ | timezone for bounds | `--tz` | — | system local |
187
+ | HTTP timeout (s) | `--timeout` | — | 60 |
188
+ | part guard | `--max-parts` | — | 1000 |
189
+
190
+ An explicit access or refresh token (flag/env) disables the credentials file so
191
+ secrets injected by a host are never overwritten. The archive key is the base64
192
+ 32-byte key generated by the extension. It is required; without it the archive
193
+ cannot be decrypted.
194
+
195
+ Prefer environment variables or the credentials file over command-line secrets:
196
+ `--dropbox-token`, `--key` and `--code` can appear in shell history and process
197
+ listings.
198
+
199
+ ## Usage
200
+
201
+ ```sh
202
+ # store the archive key and account for MCP and headless use
203
+ waidrop config
204
+
205
+ # list chats (no messages fetched): names, phones, hashes, jids
206
+ waidrop chats
207
+ waidrop chats --name "*Family*"
208
+
209
+ # by contact name (glob/substring, case-insensitive) for a date range
210
+ waidrop query --name "Alice*" --from 2026-10-01 --to 2026-10-17
211
+
212
+ # by phone number (any format) for an hour-precise window
213
+ waidrop query --number "+1 555 0100" --from "2026-10-17 08:00" --to "2026-10-17 18:00"
214
+
215
+ # rolling window
216
+ waidrop query --name "Alice*" --last 36h
217
+ waidrop query --name "Alice*" --last 7d --format text
218
+
219
+ # all chats, recent window (no selectors)
220
+ waidrop query --last 1h
221
+ waidrop query --from "2026-10-17 08:00" --to "2026-10-17 18:00" --format csv
222
+
223
+ # export full-resolution images/stickers/GIFs plus manifest.ndjson
224
+ waidrop query --name "*" --last 24h --media-out ./waidrop-media
225
+
226
+ # multiple selectors / formats / output file
227
+ waidrop query --name "Alice*" --name "*Family*" --number +15550100 \
228
+ --from 2026-10-01 --to 2026-10-17 --format csv --out october.csv
229
+
230
+ # direct targeting
231
+ waidrop query --chat 0123456789abcdef --jid 15550100@c.us --last 2w
232
+
233
+ # per-chat conversation chunks for an analysis window
234
+ waidrop context --from 2026-10-01 --to 2026-10-17 --format text
235
+ waidrop context --name "Alice*" --last 6h --context-before 30m \
236
+ --max-chars 12000 --format text
237
+
238
+ # context chunks plus exported images/stickers/GIFs and their local paths
239
+ waidrop context --last 6h --media-out ./waidrop-media --format text
240
+ ```
241
+
242
+ ### Bounds
243
+
244
+ `--from` / `--to` accept, in local time (or `--tz`):
245
+
246
+ | Input | Meaning |
247
+ |---|---|
248
+ | `2026-10-01` | date precision: `from` = 00:00; `to` includes the whole day |
249
+ | `2026-10-01T14` | hour precision: to includes `14:00–14:59:59.999` |
250
+ | `2026-10-01T14:30` | minute precision: to includes `14:30–14:30:59.999` |
251
+ | `2026-10-01T14:30:45` | second precision |
252
+
253
+ `--from` is required unless `--last` is used. `--to` defaults to now.
254
+ `--last` accepts `m` (minutes), `h` (hours), `d` (days), `w` (weeks) and cannot be
255
+ combined with `--from`/`--to`.
256
+
257
+ With **no selectors**, `query` and `context` cover **all chats** (e.g.
258
+ `--last 1h`). Chats whose `firstSeen`/`lastSeen` cannot overlap the window are
259
+ skipped, and only part objects whose `[firstTs, lastTs]` interval can overlap
260
+ the window are downloaded (legacy parts without `lastTs` use a start-anchor
261
+ heuristic). `--max-parts` still caps the selected parts. `--context-before`
262
+ expands the fetched window and therefore counts toward `--max-parts`.
263
+
264
+ ### Output
265
+
266
+ - `--format ndjson` (default): archive records, one JSON object per line.
267
+ - `--format text`: `2026-10-17 12:00 ← Alice / Alice: message…`
268
+ - `--format csv`: `msgId,ts,chatName,chatPhone,senderName,direction,type,text`
269
+ - `--out FILE` writes to a file with mode `0600`; progress goes to stderr
270
+ (`--quiet` silences it).
271
+ - `--media-out DIR` downloads and decodes (or decrypts) full-resolution media
272
+ referenced by the selected records into `DIR`, plus `DIR/manifest.ndjson`
273
+ (override with `--media-manifest`). Files are written `0600`, directory
274
+ `0700`, and names are derived from the timestamp and message id only.
275
+ `--media-max-bytes` (default 25 MiB) skips larger objects;
276
+ `--media-fail-fast` aborts on the first decode/download error. Media records
277
+ whose status is not `stored` are reported as skipped.
278
+
279
+ Text output escapes control characters. CSV output prefixes cells that start
280
+ with `=`, `+`, `-`, `@`, tab or carriage return with `'` to reduce spreadsheet
281
+ formula injection. CSV files still contain untrusted chat data; open them with
282
+ care.
283
+
284
+ ### Context output
285
+
286
+ `context` returns conversation-oriented chunks instead of flat records:
287
+
288
+ - `--format ndjson` (default): one JSON object per chat chunk, with `chat`,
289
+ `window`, `part`/`parts`, `contextBeforeMs`, `oversized` and the full message
290
+ records (`inWindow` marks messages inside the analysis window).
291
+ - `--format text`: delimited per-chat blocks with `=== CHAT … ===` /
292
+ `=== END CHAT (i/n) ===`; newlines inside messages are escaped as `\n`.
293
+ - `--context-before DURATION` includes earlier messages as context (default `0`).
294
+ Those messages appear in the chunk but are marked `inWindow: false` and
295
+ `[context]` in text output.
296
+ - `--max-chars N` splits a chat into `part i/n` at message boundaries when its
297
+ rendered message lines exceed `N` characters (default `0` = one chunk per
298
+ chat); headers/footers are not counted. A single oversized message is kept
299
+ whole in its own part and flagged `oversized: true`.
300
+ - `--media-out DIR` decodes or decrypts full-resolution images, stickers and GIFs
301
+ referenced by the emitted chunks into `DIR` and adds a `mediaExport` object to each
302
+ NDJSON media message:
303
+ `{ "status": "exported", "file": "/abs/path/...jpg", "error": null }`.
304
+ Paths are absolute. Text output appends `(file: "…")` for exported media and
305
+ `(media: <status>)` or `(media: not exported)` otherwise. The manifest defaults
306
+ to `DIR/manifest.ndjson`; `--media-max-bytes` and `--media-fail-fast` behave
307
+ like `query`. Media from `--context-before` messages is included.
308
+ - Chats with no messages inside the analysis window are omitted, even if they
309
+ have context-only messages.
310
+
311
+ Exit codes: `0` ok, `2` usage/config error, `3` no matched chats / no messages in
312
+ window, `4` `--max-parts` guard tripped, `5` Dropbox/network/archive read error.
313
+
314
+ ## Running on a headless host
315
+
316
+ The CLI auto-refreshes access tokens from the stored refresh token, so no manual
317
+ rotation is needed. Run `waidrop auth` once on the host (or copy the
318
+ credentials file). Then store the archive key in the environment file:
319
+
320
+ ```sh
321
+ waidrop config
322
+ ```
323
+
324
+ It prompts for the key without echoing it, then for the account alias. On a
325
+ rerun, values already in the env file are offered as defaults: press Enter to
326
+ keep the existing key (shown as `[keep existing]`, never printed) or the
327
+ existing alias. It writes `~/.config/waidrop/env` with mode `0600` (directory
328
+ `0700`). Use `--account work` to set a non-primary alias, `--env-file PATH` for
329
+ a custom location, or set `WAIDROP_KEY` / `WAIDROP_ACCOUNT` to skip the
330
+ corresponding prompt. The file contains:
331
+
332
+ ```sh
333
+ # ~/.config/waidrop/env (must be 0600)
334
+ WAIDROP_KEY=<base64 archive key from the extension>
335
+ WAIDROP_ACCOUNT=primary
336
+ ```
337
+
338
+ On Windows the default is `%APPDATA%\waidrop\env`. On macOS and Linux the file
339
+ must not be readable or writable by group or others; the CLI and MCP server
340
+ reject insecure files and read only `WAIDROP_*` keys. `chats`, `query`, and
341
+ `context` load the file automatically, so nothing needs to be exported in your
342
+ shell; explicit flags and shell environment variables take precedence. The file
343
+ next to a custom `--credentials-file` is used when one is passed.
344
+
345
+ A cron or agent wrapper can still source the file (`set -a; .
346
+ ~/.config/waidrop/env; set +a`) before running other tools:
347
+
348
+ ```sh
349
+ waidrop context --last 6h --context-before 30m --max-chars 12000 --format text
350
+ ```
351
+
352
+ Health check:
353
+
354
+ ```sh
355
+ waidrop auth --status --json # exit 0 = ok, 2 = missing scopes
356
+ ```
357
+
358
+ If the refresh token is ever revoked, re-run `waidrop auth` on the host.
359
+ Rotate the archive key only with a re-encryption plan (key loss means unreadable
360
+ history). Never put access tokens in env files or cron lines; the credentials
361
+ file handles them.
362
+
363
+ ## MCP server (optional)
364
+
365
+ Install `waidrop-cli[mcp]` to expose a local, read-only MCP stdio server:
366
+
367
+ ```sh
368
+ pip install "waidrop-cli[mcp]"
369
+ waidrop-mcp --print-setup
370
+ ```
371
+
372
+ The server exposes `list_chats` and `get_context`, backed by the same archive
373
+ reader as the CLI. It works with any MCP-compatible client and does not contact
374
+ an AI service; selected text is returned only to the connected client. See
375
+ [`docs/mcp.md`](https://github.com/thabiger/waidrop-cli/blob/main/docs/mcp.md).
376
+
377
+ ## Security and privacy
378
+
379
+ - The CLI never uploads archive content and has no telemetry. Archives are
380
+ decrypted in memory.
381
+ - The optional MCP server is also local and read-only. It returns selected
382
+ archive text to the connected MCP client over stdio; it does not send content
383
+ to any AI service itself. A cloud-backed client may transmit that data.
384
+ - Dropbox credentials are stored in `~/.config/waidrop/credentials.json`
385
+ (`0600`; parent `0700`). The refresh token grants access to the archive, so
386
+ protect the file.
387
+ - Output files (`--out`, `--media-out`, manifests) are written with private
388
+ permissions. Remove them when they are no longer needed.
389
+ - `waidrop auth --revoke` revokes Dropbox access and removes local
390
+ credentials. If the remote revoke fails, local credentials are kept.
391
+ - Text output escapes terminal control characters. CSV output reduces
392
+ spreadsheet formula injection but remains untrusted data.
393
+ - Report vulnerabilities using the process in [SECURITY.md](SECURITY.md).
394
+
395
+ **Disclaimer:** this project is not affiliated with WhatsApp or Meta. Use it
396
+ only for conversations you are authorized to access. Archiving may violate
397
+ WhatsApp's Terms of Service; use at your own risk. The software is provided
398
+ without warranty under the Apache-2.0 license.
399
+
400
+ ## Troubleshooting
401
+
402
+ - **`missing_scope`**: enable the listed scope in the Dropbox App Console →
403
+ Permissions → Submit, then re-authorize. Existing tokens do not gain scopes.
404
+ - **`invalid_access_token`**: token revoked/expired; re-authorize with
405
+ `waidrop auth`.
406
+ - **`chat index could not be decrypted` / `cannot decrypt …`**: wrong archive key
407
+ for the archive.
408
+ - **`plaintext archives are no longer supported`**: re-export the archive with
409
+ encryption enabled.
410
+ - **`archive is encrypted; encryption key required`**: provide `--key` or
411
+ `WAIDROP_KEY`.
412
+ - **`archive format marker is invalid` / `unsupported archive format`**: verify
413
+ `_format.json` or update `waidrop-cli`.
414
+ - **`chat directory is empty`**: nothing has been uploaded yet (connect the
415
+ extension and upload once).
416
+ - **No chats found**: if the archive was created with a different Dropbox app
417
+ key, pass `--dropbox-app-key <old-key>`.
418
+ - **Dates look shifted by a day**: `dt=` is the capturing browser's local date;
419
+ the CLI pads ±1 day and filters by exact `ts`, so this is handled
420
+ automatically — ensure `--tz` matches how you want bounds interpreted.
421
+
422
+ ## Limitations
423
+
424
+ - **LID chats** (`@lid`) have no phone number in the jid; number search works only
425
+ when the archive recovered `chatPhone`. Otherwise select by name.
426
+ - **Phone formats** should include the country code; digits are compared.
427
+ - **Names are snapshots** inside message records; `chats` shows the latest name
428
+ from the archive index.
429
+ - **DOM-only records with no `chatId`** are grouped by `chatName` in `context`
430
+ output. Duplicate names cannot be mapped reliably, so they remain separate
431
+ name-only chats with `hash: null`.
432
+ - **Only `stored` media can be exported.** `context --media-out` reports
433
+ `not_downloaded`, `pending`, `view_once`, `too_large` and failed records as
434
+ media messages without files. Capture is passive by default: only media
435
+ WhatsApp already downloaded is stored; `not_downloaded` records have only the
436
+ preview. Video, audio and documents remain metadata/placeholders. Records
437
+ written before media capture cannot be backfilled from the archive.
438
+ - **Exported media files are unencrypted.** `context --media-out` writes
439
+ full-resolution files to `DIR`; keep it private (files are `0600`, directory
440
+ `0700`) and remove it after analysis if it is no longer needed.
441
+
442
+ ## Development
443
+
444
+ ```sh
445
+ uv sync
446
+ uv run pytest -q # MCP server tests skip without the extra
447
+ uv sync --extra mcp
448
+ uv run pytest -q # includes the MCP server tests
449
+ uv run ruff check .
450
+ uv run ruff format --check .
451
+ uv build
452
+ uvx twine check dist/*
453
+ ```
454
+
455
+ Tests run against a local fake Dropbox server (stdlib `http.server`) with
456
+ encrypted fixtures and the shared cross-language crypto vector. No Dropbox
457
+ account is needed.
458
+
459
+ The crypto contract is shared with the extension. Do not change the envelope
460
+ magic, version bytes, HKDF salt, or key derivation without updating both
461
+ projects.
462
+
463
+ ## Release
464
+
465
+ See [RELEASING.md](RELEASING.md).
466
+
467
+ ## Contributing
468
+
469
+ See [CONTRIBUTING.md](CONTRIBUTING.md).
470
+
471
+ ## Changelog
472
+
473
+ See [CHANGELOG.md](CHANGELOG.md).
474
+
475
+ ## License
476
+
477
+ Apache-2.0. See [LICENSE](LICENSE) and [NOTICE](NOTICE).
@@ -0,0 +1,25 @@
1
+ waidrop_cli/__init__.py,sha256=T5eM1fyR9uOuX6V2W9XRLSWtPpn3rkluhq9uYhSs-sg,63
2
+ waidrop_cli/__main__.py,sha256=MHKZ_ae3fSLGTLUUMOx15fWdeOnJSHhq-zslRP5F5Lc,79
3
+ waidrop_cli/archive.py,sha256=MiSL6QFCxFPDGps08oHW_mlPq3DEPduVsf_77xBSqcI,3345
4
+ waidrop_cli/auth.py,sha256=fkYHCouiuPvxLIBRV33rf2b8wNFHZatephxn-UZuUQU,10534
5
+ waidrop_cli/auth_flow.py,sha256=zc26yZ5gAZ9s-hu1Uq-hIhAq-VApoYYcDCYYuZFXd1M,5988
6
+ waidrop_cli/chats.py,sha256=kLYtpBRYsiU-_XmMEEdQ11DrzBIsVlhd5BrEnj1Q3j0,5713
7
+ waidrop_cli/cli.py,sha256=BBe0DWnozOTdNE45a88_j5f3zLTaXvoyZD3MbJCr1kQ,26217
8
+ waidrop_cli/config.py,sha256=3DMDOg4sQLfboX1rMfXkGsTjLCwrAzIWztsHMYatAZw,11453
9
+ waidrop_cli/context.py,sha256=7yUR8KDfX4_Gp78Pud_ItHSouL7B6lRFbW0WXx2Bwwg,11580
10
+ waidrop_cli/crypto.py,sha256=PaMfHF93J_TmiQyYLMWHUty5E6EfnL1gDcy4YSXqwpQ,4492
11
+ waidrop_cli/dropbox.py,sha256=hR-O017eJOzanLfNiO4F_UyrHZI50na7Er85HrrXXmo,8598
12
+ waidrop_cli/env_file.py,sha256=O90RoNW2rAbii79BwWKhwuzqpPedlNpPY9-WAj1Y4mw,4026
13
+ waidrop_cli/errors.py,sha256=mlQAYGfSRTP4NYy6J-HLJ-Z36jdWLG-duxjlFXC9hb8,290
14
+ waidrop_cli/fetch.py,sha256=FETwyw44bXFg-kIO1tiS-Jr7bqh8bKBUTlprW7HjISA,7439
15
+ waidrop_cli/mcp_cli.py,sha256=wsbBTRhXjDwvkboRByaPBb_2uhm7bZx8sCEgRmNb6xw,8647
16
+ waidrop_cli/mcp_config.py,sha256=IJdbdPxHnhi2zJd4_Nyy1yvsXh1V8IN86_xO45E6Wz8,6398
17
+ waidrop_cli/mcp_server.py,sha256=DNsYZdkq5bJWWdcptLUXeK-SB8QOJ3lIs0Ppih5q5aw,12115
18
+ waidrop_cli/media.py,sha256=rEF-QHJGIOt2Xow5y_LLGefbau_5SAJ4_tcSSvzhQzA,6339
19
+ waidrop_cli/output.py,sha256=OINDpBj4-x5XB0231yRZKlSPT8YidBdm7ArE9FCg7wI,4845
20
+ waidrop_cli-1.0.0.dist-info/METADATA,sha256=D8JnhBszj33eJWWZBkT2XyXcUNtc3AMuPzd_eyc2PG0,19757
21
+ waidrop_cli-1.0.0.dist-info/WHEEL,sha256=2iZrJkDIkeDh0k9SikKMqFuRP-ua6mb4Ir1AsER4BEw,87
22
+ waidrop_cli-1.0.0.dist-info/entry_points.txt,sha256=mNoPwOhcwMmRiy30pb_on7EoE1xuHxQqyKrx3HLXIVY,91
23
+ waidrop_cli-1.0.0.dist-info/licenses/LICENSE,sha256=g4gAaap9osgEeDUzOcL0DaNkbx8hx4pXI7jrP8UTFp4,11344
24
+ waidrop_cli-1.0.0.dist-info/licenses/NOTICE,sha256=FofoWe_SMwTXTivZALOciXvlepyMCe_BK2_xWEmUCqE,197
25
+ waidrop_cli-1.0.0.dist-info/RECORD,,
@@ -0,0 +1,4 @@
1
+ Wheel-Version: 1.0
2
+ Generator: hatchling 1.33.0
3
+ Root-Is-Purelib: true
4
+ Tag: py3-none-any
@@ -0,0 +1,3 @@
1
+ [console_scripts]
2
+ waidrop = waidrop_cli.cli:main
3
+ waidrop-mcp = waidrop_cli.mcp_server:main