polytool 0.1.0__tar.gz

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,63 @@
1
+ # Python
2
+ __pycache__/
3
+ *.py[cod]
4
+ *$py.class
5
+ *.so
6
+ .Python
7
+ *.egg-info/
8
+ *.egg
9
+ build/
10
+ dist/
11
+ wheels/
12
+ .eggs/
13
+ pip-wheel-metadata/
14
+ share/python-wheels/
15
+
16
+ # Virtual envs
17
+ .venv/
18
+ venv/
19
+ env/
20
+ ENV/
21
+
22
+ # uv
23
+ .uv-cache/
24
+
25
+ # Tests / coverage
26
+ .pytest_cache/
27
+ .coverage
28
+ .coverage.*
29
+ htmlcov/
30
+ coverage.xml
31
+ .tox/
32
+ .nox/
33
+
34
+ # Type checkers
35
+ .mypy_cache/
36
+ .pyright/
37
+ .basedpyright/
38
+ .ruff_cache/
39
+
40
+ # Editors
41
+ .idea/
42
+ .vscode/
43
+ *.swp
44
+ *.swo
45
+
46
+ # OS
47
+ .DS_Store
48
+ Thumbs.db
49
+
50
+ # Local outputs from manual smoke tests
51
+ out.*
52
+ cutout.*
53
+ merged.pdf
54
+ pages/
55
+ qr.png
56
+ screen.png
57
+ page.png
58
+ *.gif
59
+ !tests/fixtures/*.gif
60
+
61
+ # Cache from heavy deps
62
+ .rembg/
63
+ .cache/
polytool-0.1.0/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 polytool contributors
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,258 @@
1
+ Metadata-Version: 2.4
2
+ Name: polytool
3
+ Version: 0.1.0
4
+ Summary: One-binary CLI bundling 26 everyday utilities — image/video/PDF conversion, background removal, OCR, QR codes, hashing, downloads, and more
5
+ Project-URL: Homepage, https://github.com/k6w/polytool
6
+ Project-URL: Repository, https://github.com/k6w/polytool
7
+ Project-URL: Issues, https://github.com/k6w/polytool/issues
8
+ Author: polytool contributors
9
+ License: MIT
10
+ License-File: LICENSE
11
+ Keywords: background-removal,cli,convert,ffmpeg,image,ocr,pdf,qr,swiss-army-knife,utility,video,yt-dlp
12
+ Classifier: Development Status :: 3 - Alpha
13
+ Classifier: Environment :: Console
14
+ Classifier: Intended Audience :: Developers
15
+ Classifier: Intended Audience :: End Users/Desktop
16
+ Classifier: License :: OSI Approved :: MIT License
17
+ Classifier: Operating System :: OS Independent
18
+ Classifier: Programming Language :: Python :: 3
19
+ Classifier: Programming Language :: Python :: 3.13
20
+ Classifier: Topic :: Multimedia :: Graphics
21
+ Classifier: Topic :: Utilities
22
+ Requires-Python: >=3.13
23
+ Requires-Dist: cron-descriptor>=1.4
24
+ Requires-Dist: croniter>=2
25
+ Requires-Dist: faker>=25
26
+ Requires-Dist: httpx>=0.27
27
+ Requires-Dist: markdown-it-py>=3
28
+ Requires-Dist: pint>=0.24
29
+ Requires-Dist: pyjwt>=2.8
30
+ Requires-Dist: pyperclip>=1.8
31
+ Requires-Dist: python-dateutil>=2.9
32
+ Requires-Dist: python-slugify>=8
33
+ Requires-Dist: rich>=13
34
+ Requires-Dist: ruamel-yaml>=0.18
35
+ Requires-Dist: segno>=1.6
36
+ Requires-Dist: tomli-w>=1.0
37
+ Requires-Dist: typer>=0.12
38
+ Requires-Dist: xmltodict>=0.13
39
+ Requires-Dist: xxhash>=3.4
40
+ Provides-Extra: ai
41
+ Requires-Dist: rembg[cpu]>=2.0; extra == 'ai'
42
+ Provides-Extra: archive
43
+ Requires-Dist: py7zr>=0.21; extra == 'archive'
44
+ Provides-Extra: dev
45
+ Requires-Dist: basedpyright>=1.13; extra == 'dev'
46
+ Requires-Dist: pre-commit>=3.7; extra == 'dev'
47
+ Requires-Dist: pytest-cov>=5; extra == 'dev'
48
+ Requires-Dist: pytest>=8; extra == 'dev'
49
+ Requires-Dist: ruff>=0.5; extra == 'dev'
50
+ Provides-Extra: dl
51
+ Requires-Dist: yt-dlp>=2024.5; extra == 'dl'
52
+ Provides-Extra: full
53
+ Requires-Dist: ascii-magic>=2; extra == 'full'
54
+ Requires-Dist: colorthief>=0.2; extra == 'full'
55
+ Requires-Dist: easyocr>=1.7; extra == 'full'
56
+ Requires-Dist: ffmpeg-python>=0.2; extra == 'full'
57
+ Requires-Dist: imageio-ffmpeg>=0.5; extra == 'full'
58
+ Requires-Dist: mss>=9; extra == 'full'
59
+ Requires-Dist: pdfplumber>=0.11; extra == 'full'
60
+ Requires-Dist: piexif>=1.1; extra == 'full'
61
+ Requires-Dist: pikepdf>=8; extra == 'full'
62
+ Requires-Dist: pillow-avif-plugin>=1.4; extra == 'full'
63
+ Requires-Dist: pillow-heif>=0.18; extra == 'full'
64
+ Requires-Dist: pillow>=10; extra == 'full'
65
+ Requires-Dist: playwright>=1.44; extra == 'full'
66
+ Requires-Dist: py7zr>=0.21; extra == 'full'
67
+ Requires-Dist: pymupdf>=1.24; extra == 'full'
68
+ Requires-Dist: pypdf>=4; extra == 'full'
69
+ Requires-Dist: pytesseract>=0.3; extra == 'full'
70
+ Requires-Dist: pyzbar>=0.1; extra == 'full'
71
+ Requires-Dist: rembg[cpu]>=2.0; extra == 'full'
72
+ Requires-Dist: resvg-py>=0.1; extra == 'full'
73
+ Requires-Dist: yt-dlp>=2024.5; extra == 'full'
74
+ Provides-Extra: img
75
+ Requires-Dist: ascii-magic>=2; extra == 'img'
76
+ Requires-Dist: colorthief>=0.2; extra == 'img'
77
+ Requires-Dist: piexif>=1.1; extra == 'img'
78
+ Requires-Dist: pillow-avif-plugin>=1.4; extra == 'img'
79
+ Requires-Dist: pillow-heif>=0.18; extra == 'img'
80
+ Requires-Dist: pillow>=10; extra == 'img'
81
+ Requires-Dist: resvg-py>=0.1; extra == 'img'
82
+ Provides-Extra: ocr
83
+ Requires-Dist: easyocr>=1.7; extra == 'ocr'
84
+ Requires-Dist: pytesseract>=0.3; extra == 'ocr'
85
+ Provides-Extra: pdf
86
+ Requires-Dist: pdfplumber>=0.11; extra == 'pdf'
87
+ Requires-Dist: pikepdf>=8; extra == 'pdf'
88
+ Requires-Dist: pymupdf>=1.24; extra == 'pdf'
89
+ Requires-Dist: pypdf>=4; extra == 'pdf'
90
+ Provides-Extra: qr-decode
91
+ Requires-Dist: pyzbar>=0.1; extra == 'qr-decode'
92
+ Provides-Extra: shot
93
+ Requires-Dist: mss>=9; extra == 'shot'
94
+ Requires-Dist: playwright>=1.44; extra == 'shot'
95
+ Provides-Extra: vid
96
+ Requires-Dist: ffmpeg-python>=0.2; extra == 'vid'
97
+ Requires-Dist: imageio-ffmpeg>=0.5; extra == 'vid'
98
+ Description-Content-Type: text/markdown
99
+
100
+ # polytool
101
+
102
+ > One CLI, 26 everyday utilities. Image format conversion, background removal, video/audio conversion, PDF tooling, OCR, QR codes, hashing, downloads, and more — all behind one binary called `pt`.
103
+
104
+ [![CI](https://github.com/k6w/polytool/actions/workflows/ci.yml/badge.svg)](https://github.com/k6w/polytool/actions/workflows/ci.yml)
105
+
106
+ ## Install
107
+
108
+ The fastest way (no Python prerequisite — `uv` brings its own):
109
+
110
+ ```powershell
111
+ # 1. install uv (Windows PowerShell)
112
+ irm https://astral.sh/uv/install.ps1 | iex
113
+
114
+ # 2. install polytool (slim — fast, ~80 MB)
115
+ uv tool install polytool
116
+
117
+ # or, install everything (image/video/PDF/yt-dlp/screenshots/AI background removal)
118
+ uv tool install 'polytool[full]'
119
+ ```
120
+
121
+ ```bash
122
+ # macOS / Linux
123
+ curl -LsSf https://astral.sh/uv/install.sh | sh
124
+ uv tool install 'polytool[full]'
125
+ ```
126
+
127
+ > **Note for PowerShell users:** quote `'polytool[full]'` — the brackets are shell glob characters.
128
+
129
+ After install, both `polytool` and the short alias `pt` are on your PATH.
130
+
131
+ ## Quick start
132
+
133
+ ```bash
134
+ pt qr gen "https://github.com/k6w/polytool" -o qr.png
135
+ pt img convert photo.heic -o photo.jpg
136
+ pt img bg-remove portrait.jpg # transparent PNG
137
+ pt vid gif clip.mp4 # animated gif
138
+ pt vid extract-audio movie.mp4 # mp3
139
+ pt pdf merge a.pdf b.pdf -o merged.pdf
140
+ pt pdf to-images doc.pdf --dpi 200
141
+ pt dl get 'https://www.youtube.com/watch?v=...'
142
+ pt enc hash sha256 release.zip
143
+ pt enc base64 encode README.md
144
+ pt data convert config.yaml --to json
145
+ pt gen password --length 32
146
+ pt gen uuid v7
147
+ pt color convert "#3366ff"
148
+ pt convert unit "100 km" --to mi
149
+ pt convert timestamp 1715200000
150
+ pt text slugify "Hello, World!"
151
+ pt cron explain "0 9 * * MON"
152
+ pt net http GET https://api.github.com
153
+ pt file dedupe ./Downloads
154
+ pt file archive ./project -o project.7z
155
+ ```
156
+
157
+ Run `pt --help` to see all groups, or `pt <group> --help` for any group's verbs (each verb's help has runnable Examples).
158
+
159
+ ## Documentation
160
+
161
+ Full reference for every verb, argument, and option lives in **[docs/](docs/README.md)**:
162
+
163
+ - **[Install guide](docs/install.md)** — slim vs full, all extras, Windows quoting
164
+ - **Per-group reference** — [img](docs/img.md) · [vid](docs/vid.md) · [pdf](docs/pdf.md) · [dl](docs/dl.md) · [shot](docs/shot.md) · [qr](docs/qr.md) · [data](docs/data.md) · [enc](docs/enc.md) · [text](docs/text.md) · [convert](docs/convert.md) · [color](docs/color.md) · [cron](docs/cron.md) · [file](docs/file.md) · [gen](docs/gen.md) · [net](docs/net.md) · [clip](docs/clip.md)
165
+ - **[Architecture](docs/architecture.md)** — package layout, lazy imports, error model, how to add a verb
166
+ - **[Troubleshooting](docs/troubleshooting.md)** — every common error with a fix
167
+
168
+ ## Feature reference (all 26 verbs)
169
+
170
+ | Group | Verbs |
171
+ |---|---|
172
+ | `pt img` | `convert` (png/jpg/webp/avif/heic/svg/bmp/tiff), `resize`, `compress`, `bg-remove`, `watermark`, `ascii`, `exif`, `palette`, `ocr` |
173
+ | `pt vid` | `convert`, `trim`, `extract-audio`, `gif` |
174
+ | `pt pdf` | `merge`, `split`, `compress`, `extract-text`, `to-images`, `from-images`, `ocr` |
175
+ | `pt dl` | `get` (yt-dlp wrapper, audio-only mode), `info` |
176
+ | `pt data` | `convert` (json↔yaml↔toml↔csv↔xml), `pretty`, `validate` |
177
+ | `pt enc` | `hash` (md5/sha1/sha256/sha512/blake2b/xxhash), `base64`, `url`, `html`, `jwt-decode`, `jwt-verify` |
178
+ | `pt qr` | `gen` (png/svg/pdf/eps/terminal), `wifi` (Wi-Fi join code), `decode` |
179
+ | `pt gen` | `password`, `uuid` (v1/v3/v4/v5/v7), `lorem` |
180
+ | `pt file` | `rename`, `dedupe`, `bigfiles`, `organize`, `archive` (zip/tar/tar.gz/7z) |
181
+ | `pt net` | `port-check`, `ip-info`, `http` |
182
+ | `pt clip` | `copy`, `paste` |
183
+ | `pt shot` | `screen`, `web` (Playwright), `install` |
184
+ | `pt color` | `convert` (hex/rgb/hsl/hsv/cmyk) |
185
+ | `pt convert` | `unit`, `timestamp`, `base` |
186
+ | `pt text` | `diff`, `wc`, `case` (snake/kebab/camel/pascal/...), `slugify`, `md-to-html`, `md-preview` |
187
+ | `pt cron` | `explain`, `next` |
188
+
189
+ ## Slim vs full install
190
+
191
+ The default install ships only lightweight utilities (data, enc, gen, color, convert, text, qr-gen, cron, net, clip, file). Heavy/optional features are grouped behind extras so you only pull what you need:
192
+
193
+ | Extra | Adds | Approx. size |
194
+ |---|---|---|
195
+ | `[img]` | Pillow + HEIC/AVIF/SVG plugins, EXIF, palette, ASCII, watermark | ~50 MB |
196
+ | `[vid]` | `ffmpeg-python` + bundled `ffmpeg` (auto-downloaded) | ~70 MB on first use |
197
+ | `[pdf]` | pypdf, pikepdf, pdfplumber, PyMuPDF | ~80 MB |
198
+ | `[dl]` | yt-dlp | ~10 MB |
199
+ | `[shot]` | mss, Playwright (Chromium installed via `pt shot install`) | ~150 MB |
200
+ | `[ai]` | rembg + ONNX runtime (170 MB U2-Net model on first run) | ~250 MB |
201
+ | `[ocr]` | pytesseract / easyocr (PyTorch) | ~1 GB if easyocr |
202
+ | `[qr-decode]` | pyzbar (system `libzbar` on Linux) | ~5 MB |
203
+ | `[archive]` | py7zr | ~5 MB |
204
+ | `[full]` | all of the above | ~1.5 GB |
205
+
206
+ Verbs that need an extra you haven't installed print a friendly hint:
207
+
208
+ ```
209
+ This command needs the 'ai' extra.
210
+ Install with: uv tool install 'polytool[ai]'
211
+ ```
212
+
213
+ ## Troubleshooting
214
+
215
+ ### `pt img convert *.svg` fails on Windows
216
+ We use `resvg-py` (a pre-built Rust wheel) instead of `cairosvg` precisely to avoid the Cairo DLL pain. Reinstall the `[img]` extra to pull it in.
217
+
218
+ ### `pt vid` wants ffmpeg
219
+ We prefer a system `ffmpeg` if it's on PATH, and fall back to `imageio-ffmpeg`'s bundled binary (auto-downloads ~70 MB on first call). Install ffmpeg system-wide with [`winget install ffmpeg`](https://learn.microsoft.com/windows/package-manager/) / `brew install ffmpeg` / `apt install ffmpeg` to skip the bundled download.
220
+
221
+ ### `pt img bg-remove` is downloading something
222
+ First run pulls the U2-Net ONNX model (~170 MB) into `~/.u2net/`. Set `U2NET_HOME` to relocate.
223
+
224
+ ### `pt qr decode` says pyzbar missing
225
+ On Linux, install the system library: `sudo apt-get install libzbar0` (Debian/Ubuntu) or `sudo dnf install zbar` (Fedora). Then reinstall `[qr-decode]`.
226
+
227
+ ### `pt shot web` fails on first run
228
+ Chromium isn't installed yet. Run `pt shot install` (which is shorthand for `python -m playwright install chromium`).
229
+
230
+ ### `pt img ocr` says Tesseract not found
231
+ The default `tesseract` engine needs the system Tesseract binary. Either install it (`winget install --id UB-Mannheim.TesseractOCR` on Windows, `brew install tesseract`, `apt install tesseract-ocr`) or pass `--engine easyocr` to use a self-contained PyTorch OCR.
232
+
233
+ ### Brackets in `uv tool install 'polytool[full]'`
234
+ PowerShell parses unquoted brackets — always wrap the spec in single quotes.
235
+
236
+ ## Contributing
237
+
238
+ ```bash
239
+ git clone https://github.com/k6w/polytool
240
+ cd polytool
241
+ uv sync --extra dev --extra img --extra vid --extra pdf --extra dl --extra shot --extra archive --extra qr-decode
242
+ uv run pre-commit install
243
+ uv run pytest
244
+ uv run ruff check .
245
+ ```
246
+
247
+ Conventional Commits required (`feat:`, `fix:`, `chore:`, `docs:`, `test:`, `ci:`, `build:`).
248
+
249
+ Each user-facing verb must:
250
+ - Include a runnable `Examples:` block in its `--help`.
251
+ - Read from path or stdin (`-`) where it's semantic.
252
+ - Default `--output` to next-to-source for files, stdout for text.
253
+ - Raise `PolytoolError(msg, hint=...)` on user errors (rendered as a red panel).
254
+ - Ship at least one happy-path and one error-path test.
255
+
256
+ ## License
257
+
258
+ MIT — see [LICENSE](LICENSE).
@@ -0,0 +1,159 @@
1
+ # polytool
2
+
3
+ > One CLI, 26 everyday utilities. Image format conversion, background removal, video/audio conversion, PDF tooling, OCR, QR codes, hashing, downloads, and more — all behind one binary called `pt`.
4
+
5
+ [![CI](https://github.com/k6w/polytool/actions/workflows/ci.yml/badge.svg)](https://github.com/k6w/polytool/actions/workflows/ci.yml)
6
+
7
+ ## Install
8
+
9
+ The fastest way (no Python prerequisite — `uv` brings its own):
10
+
11
+ ```powershell
12
+ # 1. install uv (Windows PowerShell)
13
+ irm https://astral.sh/uv/install.ps1 | iex
14
+
15
+ # 2. install polytool (slim — fast, ~80 MB)
16
+ uv tool install polytool
17
+
18
+ # or, install everything (image/video/PDF/yt-dlp/screenshots/AI background removal)
19
+ uv tool install 'polytool[full]'
20
+ ```
21
+
22
+ ```bash
23
+ # macOS / Linux
24
+ curl -LsSf https://astral.sh/uv/install.sh | sh
25
+ uv tool install 'polytool[full]'
26
+ ```
27
+
28
+ > **Note for PowerShell users:** quote `'polytool[full]'` — the brackets are shell glob characters.
29
+
30
+ After install, both `polytool` and the short alias `pt` are on your PATH.
31
+
32
+ ## Quick start
33
+
34
+ ```bash
35
+ pt qr gen "https://github.com/k6w/polytool" -o qr.png
36
+ pt img convert photo.heic -o photo.jpg
37
+ pt img bg-remove portrait.jpg # transparent PNG
38
+ pt vid gif clip.mp4 # animated gif
39
+ pt vid extract-audio movie.mp4 # mp3
40
+ pt pdf merge a.pdf b.pdf -o merged.pdf
41
+ pt pdf to-images doc.pdf --dpi 200
42
+ pt dl get 'https://www.youtube.com/watch?v=...'
43
+ pt enc hash sha256 release.zip
44
+ pt enc base64 encode README.md
45
+ pt data convert config.yaml --to json
46
+ pt gen password --length 32
47
+ pt gen uuid v7
48
+ pt color convert "#3366ff"
49
+ pt convert unit "100 km" --to mi
50
+ pt convert timestamp 1715200000
51
+ pt text slugify "Hello, World!"
52
+ pt cron explain "0 9 * * MON"
53
+ pt net http GET https://api.github.com
54
+ pt file dedupe ./Downloads
55
+ pt file archive ./project -o project.7z
56
+ ```
57
+
58
+ Run `pt --help` to see all groups, or `pt <group> --help` for any group's verbs (each verb's help has runnable Examples).
59
+
60
+ ## Documentation
61
+
62
+ Full reference for every verb, argument, and option lives in **[docs/](docs/README.md)**:
63
+
64
+ - **[Install guide](docs/install.md)** — slim vs full, all extras, Windows quoting
65
+ - **Per-group reference** — [img](docs/img.md) · [vid](docs/vid.md) · [pdf](docs/pdf.md) · [dl](docs/dl.md) · [shot](docs/shot.md) · [qr](docs/qr.md) · [data](docs/data.md) · [enc](docs/enc.md) · [text](docs/text.md) · [convert](docs/convert.md) · [color](docs/color.md) · [cron](docs/cron.md) · [file](docs/file.md) · [gen](docs/gen.md) · [net](docs/net.md) · [clip](docs/clip.md)
66
+ - **[Architecture](docs/architecture.md)** — package layout, lazy imports, error model, how to add a verb
67
+ - **[Troubleshooting](docs/troubleshooting.md)** — every common error with a fix
68
+
69
+ ## Feature reference (all 26 verbs)
70
+
71
+ | Group | Verbs |
72
+ |---|---|
73
+ | `pt img` | `convert` (png/jpg/webp/avif/heic/svg/bmp/tiff), `resize`, `compress`, `bg-remove`, `watermark`, `ascii`, `exif`, `palette`, `ocr` |
74
+ | `pt vid` | `convert`, `trim`, `extract-audio`, `gif` |
75
+ | `pt pdf` | `merge`, `split`, `compress`, `extract-text`, `to-images`, `from-images`, `ocr` |
76
+ | `pt dl` | `get` (yt-dlp wrapper, audio-only mode), `info` |
77
+ | `pt data` | `convert` (json↔yaml↔toml↔csv↔xml), `pretty`, `validate` |
78
+ | `pt enc` | `hash` (md5/sha1/sha256/sha512/blake2b/xxhash), `base64`, `url`, `html`, `jwt-decode`, `jwt-verify` |
79
+ | `pt qr` | `gen` (png/svg/pdf/eps/terminal), `wifi` (Wi-Fi join code), `decode` |
80
+ | `pt gen` | `password`, `uuid` (v1/v3/v4/v5/v7), `lorem` |
81
+ | `pt file` | `rename`, `dedupe`, `bigfiles`, `organize`, `archive` (zip/tar/tar.gz/7z) |
82
+ | `pt net` | `port-check`, `ip-info`, `http` |
83
+ | `pt clip` | `copy`, `paste` |
84
+ | `pt shot` | `screen`, `web` (Playwright), `install` |
85
+ | `pt color` | `convert` (hex/rgb/hsl/hsv/cmyk) |
86
+ | `pt convert` | `unit`, `timestamp`, `base` |
87
+ | `pt text` | `diff`, `wc`, `case` (snake/kebab/camel/pascal/...), `slugify`, `md-to-html`, `md-preview` |
88
+ | `pt cron` | `explain`, `next` |
89
+
90
+ ## Slim vs full install
91
+
92
+ The default install ships only lightweight utilities (data, enc, gen, color, convert, text, qr-gen, cron, net, clip, file). Heavy/optional features are grouped behind extras so you only pull what you need:
93
+
94
+ | Extra | Adds | Approx. size |
95
+ |---|---|---|
96
+ | `[img]` | Pillow + HEIC/AVIF/SVG plugins, EXIF, palette, ASCII, watermark | ~50 MB |
97
+ | `[vid]` | `ffmpeg-python` + bundled `ffmpeg` (auto-downloaded) | ~70 MB on first use |
98
+ | `[pdf]` | pypdf, pikepdf, pdfplumber, PyMuPDF | ~80 MB |
99
+ | `[dl]` | yt-dlp | ~10 MB |
100
+ | `[shot]` | mss, Playwright (Chromium installed via `pt shot install`) | ~150 MB |
101
+ | `[ai]` | rembg + ONNX runtime (170 MB U2-Net model on first run) | ~250 MB |
102
+ | `[ocr]` | pytesseract / easyocr (PyTorch) | ~1 GB if easyocr |
103
+ | `[qr-decode]` | pyzbar (system `libzbar` on Linux) | ~5 MB |
104
+ | `[archive]` | py7zr | ~5 MB |
105
+ | `[full]` | all of the above | ~1.5 GB |
106
+
107
+ Verbs that need an extra you haven't installed print a friendly hint:
108
+
109
+ ```
110
+ This command needs the 'ai' extra.
111
+ Install with: uv tool install 'polytool[ai]'
112
+ ```
113
+
114
+ ## Troubleshooting
115
+
116
+ ### `pt img convert *.svg` fails on Windows
117
+ We use `resvg-py` (a pre-built Rust wheel) instead of `cairosvg` precisely to avoid the Cairo DLL pain. Reinstall the `[img]` extra to pull it in.
118
+
119
+ ### `pt vid` wants ffmpeg
120
+ We prefer a system `ffmpeg` if it's on PATH, and fall back to `imageio-ffmpeg`'s bundled binary (auto-downloads ~70 MB on first call). Install ffmpeg system-wide with [`winget install ffmpeg`](https://learn.microsoft.com/windows/package-manager/) / `brew install ffmpeg` / `apt install ffmpeg` to skip the bundled download.
121
+
122
+ ### `pt img bg-remove` is downloading something
123
+ First run pulls the U2-Net ONNX model (~170 MB) into `~/.u2net/`. Set `U2NET_HOME` to relocate.
124
+
125
+ ### `pt qr decode` says pyzbar missing
126
+ On Linux, install the system library: `sudo apt-get install libzbar0` (Debian/Ubuntu) or `sudo dnf install zbar` (Fedora). Then reinstall `[qr-decode]`.
127
+
128
+ ### `pt shot web` fails on first run
129
+ Chromium isn't installed yet. Run `pt shot install` (which is shorthand for `python -m playwright install chromium`).
130
+
131
+ ### `pt img ocr` says Tesseract not found
132
+ The default `tesseract` engine needs the system Tesseract binary. Either install it (`winget install --id UB-Mannheim.TesseractOCR` on Windows, `brew install tesseract`, `apt install tesseract-ocr`) or pass `--engine easyocr` to use a self-contained PyTorch OCR.
133
+
134
+ ### Brackets in `uv tool install 'polytool[full]'`
135
+ PowerShell parses unquoted brackets — always wrap the spec in single quotes.
136
+
137
+ ## Contributing
138
+
139
+ ```bash
140
+ git clone https://github.com/k6w/polytool
141
+ cd polytool
142
+ uv sync --extra dev --extra img --extra vid --extra pdf --extra dl --extra shot --extra archive --extra qr-decode
143
+ uv run pre-commit install
144
+ uv run pytest
145
+ uv run ruff check .
146
+ ```
147
+
148
+ Conventional Commits required (`feat:`, `fix:`, `chore:`, `docs:`, `test:`, `ci:`, `build:`).
149
+
150
+ Each user-facing verb must:
151
+ - Include a runnable `Examples:` block in its `--help`.
152
+ - Read from path or stdin (`-`) where it's semantic.
153
+ - Default `--output` to next-to-source for files, stdout for text.
154
+ - Raise `PolytoolError(msg, hint=...)` on user errors (rendered as a red panel).
155
+ - Ship at least one happy-path and one error-path test.
156
+
157
+ ## License
158
+
159
+ MIT — see [LICENSE](LICENSE).
@@ -0,0 +1,80 @@
1
+ # polytool documentation
2
+
3
+ Detailed reference for every command in `polytool` (binary `pt`).
4
+
5
+ `pt` is built around 16 subcommand groups, each with one or more verbs (26 verbs in total). Every verb has its own page below — argument types, defaults, all flags, exit codes, and runnable examples.
6
+
7
+ ## Quick links
8
+
9
+ - **[Install](install.md)** — `uv tool install`, slim vs full, extras, Windows quoting
10
+ - **[Troubleshooting](troubleshooting.md)** — every common gotcha with a fix
11
+ - **[Architecture](architecture.md)** — package layout, lazy imports, error model
12
+
13
+ ## Subcommand groups
14
+
15
+ Tap a group to jump to its full reference.
16
+
17
+ ### Media
18
+
19
+ | Group | What it does |
20
+ |---|---|
21
+ | **[`pt img`](img.md)** | Image format conversion (HEIC, AVIF, SVG, ...), resize, compress, EXIF, palette, watermark, ASCII art, **background removal**, OCR |
22
+ | **[`pt vid`](vid.md)** | Convert video/audio, trim, extract audio, animated GIF |
23
+ | **[`pt pdf`](pdf.md)** | Merge, split, compress, extract text, render to images, build from images, OCR |
24
+ | **[`pt dl`](dl.md)** | Download from YouTube and 1000+ sites (yt-dlp wrapper, audio-only mode) |
25
+ | **[`pt shot`](shot.md)** | Screen capture and full-page web screenshots |
26
+ | **[`pt qr`](qr.md)** | Generate QR codes (PNG/SVG/PDF/EPS/terminal), Wi-Fi join codes, decode |
27
+
28
+ ### Text & data
29
+
30
+ | Group | What it does |
31
+ |---|---|
32
+ | **[`pt data`](data.md)** | Convert between JSON / YAML / TOML / CSV / XML; pretty-print; validate |
33
+ | **[`pt enc`](enc.md)** | Hash (sha*, xxhash, blake2b), base64, URL, HTML, JWT decode/verify |
34
+ | **[`pt text`](text.md)** | Diff, wc, case conversion, slugify, Markdown → HTML / preview |
35
+ | **[`pt convert`](convert.md)** | Unit conversion (pint), epoch ↔ ISO timestamp, number-base conversion |
36
+ | **[`pt color`](color.md)** | Color conversion (hex / rgb / hsl / hsv / cmyk) |
37
+ | **[`pt cron`](cron.md)** | Explain a cron expression in English; show next N firings |
38
+
39
+ ### System
40
+
41
+ | Group | What it does |
42
+ |---|---|
43
+ | **[`pt file`](file.md)** | Batch rename, find duplicates, list big files, organize, archive (zip/tar/7z) |
44
+ | **[`pt gen`](gen.md)** | Strong passwords, UUIDs (v1/v3/v4/v5/v7), lorem ipsum |
45
+ | **[`pt net`](net.md)** | Port reachability, IP geolocation, HTTP request (httpie-like) |
46
+ | **[`pt clip`](clip.md)** | Read/write the system clipboard |
47
+
48
+ ## Conventions used in these docs
49
+
50
+ - **`SOURCE`**, **`OUTPUT`** — uppercase = positional argument.
51
+ - **`--flag`**, **`-f`** — long and short option forms; both work.
52
+ - **`Default:`** — what happens when the option is omitted.
53
+ - **`Type:`** — `path`, `int`, `float`, `str`, `bool` (flag), or a closed `enum: a | b | c`.
54
+ - **`Required:`** — marked explicitly when not optional.
55
+ - **`Stdin:`** — every verb that accepts file input also accepts `-` (or omitting the path) to read stdin where it makes sense.
56
+ - **`Stdout:`** — verbs that produce text default to stdout when `--output` is omitted (you can pipe into other commands).
57
+ - **Exit codes** — `0` on success, `1` on user/data error (rendered as a red panel with a fix hint), `2` on argument parsing error (Typer default).
58
+
59
+ ## Global options
60
+
61
+ These work for every subcommand:
62
+
63
+ | Flag | Type | Default | Purpose |
64
+ |---|---|---|---|
65
+ | `--version`, `-V` | flag | — | Print the polytool version and exit. |
66
+ | `--help` | flag | — | Show help for the current group/verb. Every leaf verb's help includes a runnable `Examples:` block. |
67
+
68
+ ## How help is structured
69
+
70
+ ```
71
+ pt --help # top-level: lists 16 groups
72
+ pt <group> --help # lists verbs in that group
73
+ pt <group> <verb> --help # full verb reference (matches the .md page)
74
+ ```
75
+
76
+ ## Next steps
77
+
78
+ - Read **[install.md](install.md)** for the install paths and extras.
79
+ - Browse a group page above to see exact arguments and examples.
80
+ - Hit a problem? **[troubleshooting.md](troubleshooting.md)** has the answer for every common error.