morphconv 1.0.2__tar.gz → 1.0.3__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.
Files changed (45) hide show
  1. {morphconv-1.0.2 → morphconv-1.0.3}/LICENSE +1 -1
  2. morphconv-1.0.3/PKG-INFO +330 -0
  3. morphconv-1.0.3/README.md +286 -0
  4. {morphconv-1.0.2 → morphconv-1.0.3}/morph/cli.py +167 -5
  5. {morphconv-1.0.2 → morphconv-1.0.3}/morph/converters/images.py +2 -0
  6. {morphconv-1.0.2 → morphconv-1.0.3}/morph/converters/web.py +1 -1
  7. {morphconv-1.0.2 → morphconv-1.0.3}/morph/deps.py +15 -9
  8. {morphconv-1.0.2 → morphconv-1.0.3}/morph/history.py +60 -0
  9. morphconv-1.0.3/morphconv.egg-info/PKG-INFO +330 -0
  10. {morphconv-1.0.2 → morphconv-1.0.3}/morphconv.egg-info/requires.txt +11 -3
  11. {morphconv-1.0.2 → morphconv-1.0.3}/pyproject.toml +12 -4
  12. morphconv-1.0.2/PKG-INFO +0 -396
  13. morphconv-1.0.2/README.md +0 -357
  14. morphconv-1.0.2/morphconv.egg-info/PKG-INFO +0 -396
  15. {morphconv-1.0.2 → morphconv-1.0.3}/morph/__init__.py +0 -0
  16. {morphconv-1.0.2 → morphconv-1.0.3}/morph/batch.py +0 -0
  17. {morphconv-1.0.2 → morphconv-1.0.3}/morph/converters/__init__.py +0 -0
  18. {morphconv-1.0.2 → morphconv-1.0.3}/morph/converters/archives.py +0 -0
  19. {morphconv-1.0.2 → morphconv-1.0.3}/morph/converters/audio.py +0 -0
  20. {morphconv-1.0.2 → morphconv-1.0.3}/morph/converters/csv_json.py +0 -0
  21. {morphconv-1.0.2 → morphconv-1.0.3}/morph/converters/csv_to_xlsx.py +0 -0
  22. {morphconv-1.0.2 → morphconv-1.0.3}/morph/converters/documents.py +0 -0
  23. {morphconv-1.0.2 → morphconv-1.0.3}/morph/converters/ebooks.py +0 -0
  24. {morphconv-1.0.2 → morphconv-1.0.3}/morph/converters/fonts.py +0 -0
  25. {morphconv-1.0.2 → morphconv-1.0.3}/morph/converters/json_yaml.py +0 -0
  26. {morphconv-1.0.2 → morphconv-1.0.3}/morph/converters/models_3d.py +0 -0
  27. {morphconv-1.0.2 → morphconv-1.0.3}/morph/converters/ocr.py +0 -0
  28. {morphconv-1.0.2 → morphconv-1.0.3}/morph/converters/pandas_extra.py +0 -0
  29. {morphconv-1.0.2 → morphconv-1.0.3}/morph/converters/svg.py +0 -0
  30. {morphconv-1.0.2 → morphconv-1.0.3}/morph/converters/video.py +0 -0
  31. {morphconv-1.0.2 → morphconv-1.0.3}/morph/converters/vtracer_converter.py +0 -0
  32. {morphconv-1.0.2 → morphconv-1.0.3}/morph/converters/xlsx_to_csv.py +0 -0
  33. {morphconv-1.0.2 → morphconv-1.0.3}/morph/ffmpeg_utils.py +0 -0
  34. {morphconv-1.0.2 → morphconv-1.0.3}/morph/progress.py +0 -0
  35. {morphconv-1.0.2 → morphconv-1.0.3}/morph/registry.py +0 -0
  36. {morphconv-1.0.2 → morphconv-1.0.3}/morph/tui.py +0 -0
  37. {morphconv-1.0.2 → morphconv-1.0.3}/morphconv.egg-info/SOURCES.txt +0 -0
  38. {morphconv-1.0.2 → morphconv-1.0.3}/morphconv.egg-info/dependency_links.txt +0 -0
  39. {morphconv-1.0.2 → morphconv-1.0.3}/morphconv.egg-info/entry_points.txt +0 -0
  40. {morphconv-1.0.2 → morphconv-1.0.3}/morphconv.egg-info/top_level.txt +0 -0
  41. {morphconv-1.0.2 → morphconv-1.0.3}/setup.cfg +0 -0
  42. {morphconv-1.0.2 → morphconv-1.0.3}/tests/test_cli.py +0 -0
  43. {morphconv-1.0.2 → morphconv-1.0.3}/tests/test_converters.py +0 -0
  44. {morphconv-1.0.2 → morphconv-1.0.3}/tests/test_registry.py +0 -0
  45. {morphconv-1.0.2 → morphconv-1.0.3}/tests/test_web.py +0 -0
@@ -1,6 +1,6 @@
1
1
  MIT License
2
2
 
3
- Copyright (c) 2026 morph contributors
3
+ Copyright (c) 2026 Hariharen S S
4
4
 
5
5
  Permission is hereby granted, free of charge, to any person obtaining a copy
6
6
  of this software and associated documentation files (the "Software"), to deal
@@ -0,0 +1,330 @@
1
+ Metadata-Version: 2.4
2
+ Name: morphconv
3
+ Version: 1.0.3
4
+ Summary: morph — convert anything to anything, from the CLI
5
+ License: MIT
6
+ Requires-Python: >=3.10
7
+ Description-Content-Type: text/markdown
8
+ License-File: LICENSE
9
+ Requires-Dist: pandas>=2.2.0
10
+ Requires-Dist: openpyxl>=3.1.2
11
+ Requires-Dist: xlsxwriter>=3.2.0
12
+ Requires-Dist: xlrd>=2.0.1
13
+ Requires-Dist: pyarrow>=15.0.0
14
+ Requires-Dist: odfpy>=1.4.1
15
+ Requires-Dist: lxml>=5.1.0
16
+ Requires-Dist: SQLAlchemy>=2.0.0
17
+ Requires-Dist: rich>=13.7.0
18
+ Requires-Dist: typer>=0.12.0
19
+ Requires-Dist: chardet>=5.2.0
20
+ Requires-Dist: python-dateutil>=2.9.0
21
+ Requires-Dist: click>=8.1.7
22
+ Requires-Dist: pyyaml>=6.0.1
23
+ Requires-Dist: textual>=0.60.0
24
+ Requires-Dist: Pillow>=10.0.0
25
+ Requires-Dist: pillow-heif>=0.15.0
26
+ Requires-Dist: pillow-avif-plugin>=1.4.3
27
+ Requires-Dist: cairosvg>=2.7.1
28
+ Requires-Dist: fonttools[woff]>=4.50.0
29
+ Requires-Dist: pytesseract>=0.3.10
30
+ Requires-Dist: trafilatura>=1.8.0
31
+ Requires-Dist: vtracer>=0.6.0
32
+ Requires-Dist: yt-dlp>=2024.03.10
33
+ Provides-Extra: dev
34
+ Requires-Dist: pytest>=8.0.0; extra == "dev"
35
+ Requires-Dist: pytest-mock>=3.12.0; extra == "dev"
36
+ Provides-Extra: 3d
37
+ Requires-Dist: bpy>=5.0.0; python_version < "3.13" and extra == "3d"
38
+ Provides-Extra: web
39
+ Requires-Dist: crawl4ai>=0.4.0; extra == "web"
40
+ Requires-Dist: playwright>=1.40.0; extra == "web"
41
+ Provides-Extra: all
42
+ Requires-Dist: morphconv[3d,web]; extra == "all"
43
+ Dynamic: license-file
44
+
45
+ <div align="center">
46
+
47
+ # 🦋 MORPH
48
+
49
+ **The Universal File Converter for the Command Line.**
50
+
51
+ *One command. No format-specific tools to remember. No cloud upload. No API keys.*
52
+ *Convert anything, to anything.*
53
+
54
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](LICENSE)
55
+ [![Python 3.10+](https://img.shields.io/badge/python-3.10%2B-blue.svg)](https://www.python.org/downloads/)
56
+ [![Built with Typer](https://img.shields.io/badge/CLI-Typer-6C47FF.svg)](https://typer.tiangolo.com/)
57
+ [![Powered by Rich](https://img.shields.io/badge/output-Rich-8A2BE2.svg)](https://github.com/Textualize/rich)
58
+ [![TUI: Textual](https://img.shields.io/badge/TUI-Textual-4B0082.svg)](https://textual.textualize.io/)
59
+
60
+ ```bash
61
+ morph report.docx report.pdf
62
+ morph data.csv data.xlsx --table-style TableStyleMedium2 --header-bg 2E7D32
63
+ morph logo.png logo.svg --mode spline
64
+ morph batch '*.mp4' mp3 --workers 4
65
+ ```
66
+
67
+ </div>
68
+
69
+ ---
70
+
71
+ ## ⚡ Why `morph` exists
72
+
73
+ `ffmpeg` converts media. `pandoc` converts documents. `ImageMagick` converts images. Each is an incredible piece of software, but using them together is a nightmare of different flag dialects, mental models, and obscure syntax errors.
74
+
75
+ **`morph` doesn't reinvent codecs or file formats — it orchestrates the best tool for each job behind a single, predictable, and beautiful interface.**
76
+
77
+ Whether you are rendering a 3D `.blend` file to a `.png`, scraping a Wikipedia article into a Markdown file, vectorizing a `.jpg` into an `.svg`, or converting a batch of `.csv` files to `.parquet`, `morph` calculates the route, fetches the dependencies, and executes the job.
78
+
79
+ ## ✨ Features
80
+
81
+ - **One Universal Verb.** `morph <input> <output>`. That's it. Omit the output, and `morph` acts as a wizard, presenting you with an interactive menu of all possible destination formats.
82
+ - **Undo.** Made a mistake? Convert a massive 1,000-file directory by accident? Just type `morph undo` and watch it instantly delete the generated files and revert your history.
83
+ - **Smart Multi-Hop Graph Routing.** No direct `csv → yaml` converter? `morph` automatically finds the `csv → json → yaml` route. When crossing wild paradigms (e.g. Markdown → SQLite), `morph` explicitly hints its logic (like `extracts tabular data only`).
84
+ - **Contextual Intelligence.** Run `morph data.csv data.xlsx --help` and you'll *only* see flags relevant to that specific pair (like `--table-style` or `--freeze-cols`). Run it on a video file, and you'll see bitrate and framerate controls instead.
85
+ - **Output Verification.** Pass the `--verify` flag to calculate and display the exact SHA-256 checksum of the resulting file right alongside the success message.
86
+ - **Transparent Remote Downloads.** Pass any `http://` link and `morph` handles the rest. It uses `trafilatura` to scrape web articles into clean Markdown, or `yt-dlp` to natively download high-quality media (`morph <url> --audio`).
87
+ - **Batch Processing Engine.** `morph batch '*.mp4' mp3` converts files concurrently with a live progress table, smart skip logic (`--newer-only`, `--skip-existing`), and output structure mirroring.
88
+ - **Interactive TUI.** Type `morph` with no arguments to launch a stunning, keyboard-driven Textual UI. Navigate your filesystem, preview conversion options, and watch live progress bars without touching your mouse.
89
+ - **Automated Dependency Management.** Missing `ffmpeg` or `pandoc`? `morph` detects your OS and package manager (brew/apt/winget/etc.), shows you the exact install command, and asks before running it. Massive dependencies (like 3D rendering engines) are cleanly isolated as optional extras!
90
+ - **Pluggable Architecture.** Drop a Python script in `morph/converters/`, add a `@register` decorator, and it's instantly live in the routing graph.
91
+ - **Local-First & Private.** No cloud uploads. No API keys. Everything runs on your machine.
92
+
93
+ ---
94
+
95
+ ## 📦 Installation
96
+
97
+ `morph` is natively distributed across all major operating systems. You do not need Python installed to use the standalone binaries!
98
+
99
+ ### Windows
100
+ ```powershell
101
+ # via Winget (Recommended)
102
+ winget install hariharen.morph
103
+
104
+ # via Scoop
105
+ scoop bucket add morph https://github.com/hariharen9/scoop-bucket.git
106
+ scoop install morph
107
+ ```
108
+
109
+ ### macOS & Linux
110
+ ```bash
111
+ # via Homebrew
112
+ brew tap hariharen9/homebrew-tap
113
+ brew install morph
114
+ ```
115
+
116
+ ### Python Ecosystem (PyPI)
117
+ If you prefer managing via `pip` (or `pipx`), install it globally:
118
+ ```bash
119
+ pipx install morphconv
120
+ ```
121
+
122
+ ### Development (Source)
123
+ ```bash
124
+ git clone https://github.com/hariharen9/morph.git
125
+ cd morph
126
+ pip install -e .
127
+ ```
128
+
129
+ `morph` relies on native Python libraries for data, web, and archives. For massive specialized packages, `morph` uses optional extras to keep your base installation blazing fast. If you need them, simply install them:
130
+ ```bash
131
+ pip install -e ".[3d]" # Installs bpy (Blender) for 3D conversions
132
+ pip install -e ".[web]" # Installs crawl4ai and playwright for heavy JS rendering
133
+ ```
134
+
135
+ For domain-specific external binaries (e.g., `ffmpeg`, `pandoc`), you don't need to install these upfront — `morph` will intelligently prompt you to install them the first time they are needed.
136
+
137
+ To see your current system dependencies at any time:
138
+ ```bash
139
+ morph deps
140
+ ```
141
+
142
+ ---
143
+
144
+ ## 🚀 Quickstart & Real-World Examples
145
+
146
+ ### 📊 Data Processing
147
+ Switch between analytical formats effortlessly.
148
+
149
+ ```bash
150
+ morph data.csv data.xlsx
151
+ morph data.json data.yaml
152
+ morph database.sqlite data.csv
153
+ ```
154
+
155
+ ### 📄 Documents & Ebooks
156
+ ```bash
157
+ morph notes.md notes.docx
158
+ morph report.docx report.pdf
159
+ morph book.epub book.mobi
160
+ ```
161
+
162
+ ### 🖼️ Images & Vectorization
163
+ Raster conversions, plus advanced raster-to-vector tracing.
164
+
165
+ ```bash
166
+ # Standard image processing
167
+ morph photo.png photo.webp --quality 80 --resize 1200x
168
+ morph icon.png icon.ico
169
+
170
+ # Raster to Vector (via vtracer)
171
+ morph logo.png logo.svg --mode spline --hierarchical stacked
172
+ ```
173
+
174
+ ### 🎬 Audio & Video (via `ffmpeg`)
175
+ Media manipulation with real-time progress bars parsed directly from ffmpeg.
176
+
177
+ ```bash
178
+ morph song.wav song.mp3 --bitrate 192k
179
+ morph clip.mp4 clip.gif --fps 10 --width 480
180
+ morph clip.mkv clip.mp3 # Extract audio
181
+ ```
182
+
183
+ ### 🌐 Web & Remote Files
184
+ Fetch data directly from the internet and transform it locally in one step. `morph` natively embeds `yt-dlp` to download almost any media from the web.
185
+
186
+ ```bash
187
+ # Natively download video from YouTube, Twitter, etc.
188
+ morph https://youtube.com/watch?v=... video.mp4
189
+
190
+ # Extract audio only from a remote video with metadata embedded
191
+ morph https://youtube.com/watch?v=... audio.mp3 --audio
192
+
193
+ # Scrape an article into clean Markdown (via trafilatura)
194
+ morph https://en.wikipedia.org/wiki/Graph_theory graph_theory.md
195
+
196
+ # Download a remote CSV and style it as an Excel workbook natively
197
+ morph https://raw.githubusercontent.com/owid/covid-19-data/master/public/data/latest/owid-covid-latest.csv covid.xlsx --table-style TableStyleMedium2
198
+
199
+ # Scrape a JavaScript-heavy page (requires morphconv[web])
200
+ morph https://example.com/dynamic-article doc.pdf --js
201
+ ```
202
+
203
+ ### 🧊 3D Models & Rendering (Powered by Blender/`bpy`)
204
+ Seamlessly convert between 3D formats, or utilize headless rendering to generate images of your models.
205
+
206
+ ```bash
207
+ # Format conversion
208
+ morph character.fbx character.glb
209
+ morph scene.obj scene.blend
210
+
211
+ # Headless 3D rendering (automatically places lights and cameras)
212
+ morph character.gltf character.png
213
+ ```
214
+
215
+ ---
216
+
217
+ ## 🏎️ Batch Operations
218
+
219
+ Convert hundreds of files concurrently with a beautiful terminal dashboard.
220
+
221
+ ```bash
222
+ # All MP4s to MP3 using 4 parallel workers
223
+ morph batch '*.mp4' mp3 --workers 4
224
+
225
+ # Recursively convert a whole directory and mirror its structure in an output folder
226
+ morph batch ./raw_footage/ mp3 --recursive --out-dir ./audio_only/ --mirror
227
+
228
+ # Skip files that have already been converted
229
+ morph batch '*.flac' mp3 --skip-existing
230
+ ```
231
+
232
+ During batch conversions, `morph` displays a live status table:
233
+
234
+ ```text
235
+ ╭─ morph batch — 8 files → mp3 ─────────────────────────────────────╮
236
+ │ Status File Time Size │
237
+ │ ✓ done concert_01.flac 0:00:04 8.3MB → 4.1MB │
238
+ │ ✓ done concert_02.flac 0:00:03 7.9MB → 3.8MB │
239
+ │ ▶ converting… concert_03.flac 0:00:01 │
240
+ │ · waiting concert_04.wav │
241
+ │ │
242
+ │ Overall ████████░░░░░░░░ 2/8 [0:00:07] │
243
+ ╰──────────────────────────────────────────────────────────────────────╯
244
+ ```
245
+
246
+ ---
247
+
248
+ ## 🗂️ Supported Formats
249
+
250
+ | Domain | Formats | Backend |
251
+ |---|---|---|
252
+ | **Data** | `csv`, `xlsx`, `json`, `yaml`, `parquet`, `feather`, `ods`, `xml`, `html`, `sqlite` | Native (`pandas` / `openpyxl`) |
253
+ | **Documents** | `md`, `html`, `docx`, `odt`, `rtf`, `epub`, `latex`, `rst`, `txt`, `ipynb`, `pptx`, `adoc`, `org`, `opml`, `man`, `pdf`* | `pandoc` |
254
+ | **Images (Raster)** | `png`, `jpg/jpeg`, `webp`, `bmp`, `gif`, `tiff`, `ico`, `heic`, `avif`, `icns`, `pdf` | `Pillow` / `cairosvg` |
255
+ | **Vectorization** | `png`/`jpg`/etc. → `svg` | `vtracer` |
256
+ | **3D Models** | `obj`, `stl`, `fbx`, `gltf`, `glb`, `blend`, `any → png` (Render) | `bpy` (Blender) |
257
+ | **Web Extraction** | `url` → `md`, `txt`, `xml`, `html` | `trafilatura` / `crawl4ai` |
258
+ | **Audio** | `mp3`, `wav`, `flac`, `ogg`, `aac`, `m4a`, `opus`, `wma` | `ffmpeg` |
259
+ | **Video** | `mp4`, `mkv`, `mov`, `webm`, `avi`, `flv`, `wmv`, `mpeg` | `ffmpeg` |
260
+ | **Ebooks** | `epub`, `mobi`, `azw3` | `ebook-convert` |
261
+ | **Fonts** | `ttf`, `otf`, `woff`, `woff2` | `fontTools` |
262
+ | **OCR** | `png`, `jpg`, `webp`, `pdf`, etc. → `txt` | `tesseract` |
263
+ | **Archives** | `zip`, `tar`, `tar.gz`, `tar.bz2`, `tar.xz` | Python stdlib |
264
+
265
+ *\* Note: PDF is an output-only format for documents. Extracting structured text back out of a PDF is handled via the OCR pipeline.*
266
+
267
+ ---
268
+
269
+ ## 🛠️ Architecture & Under the Hood
270
+
271
+ The magic of `morph` lies in its modular graph architecture.
272
+
273
+ ```text
274
+ morph/
275
+ ├── cli.py # Command dispatch (run, batch, formats, history, deps)
276
+ ├── registry.py # BFS Routing graph & registration logic
277
+ ├── tui.py # Textual keyboard-driven TUI
278
+ └── converters/
279
+ ├── __init__.py # Auto-discovers all modules
280
+ ├── documents.py # pandoc engine
281
+ ├── images.py # Pillow engine
282
+ ├── models_3d.py # Blender/bpy engine
283
+ ├── web.py # trafilatura / crawl4ai engine
284
+ └── vtracer_converter.py # Raster-to-SVG vectorization
285
+ ```
286
+
287
+ ### Adding a new conversion is trivial
288
+
289
+ Drop a file in `morph/converters/` and use the `@register` decorator. No central registry, no CLI parsers to update.
290
+
291
+ ```python
292
+ from pathlib import Path
293
+ from ..registry import ConversionResult, OptionSpec, register
294
+
295
+ @register("foo", "bar", backend="mytool", family="image")
296
+ def foo_to_bar(input_path: Path, output_path: Path, **kwargs) -> ConversionResult:
297
+ # Do the conversion...
298
+ return ConversionResult(output=output_path)
299
+ ```
300
+
301
+ Because of `morph`'s graph routing, once `foo → bar` is registered, if a path exists from `bar → baz`, `morph` immediately knows how to convert `foo → baz`.
302
+
303
+ ---
304
+
305
+ ## 📜 History & Transparency
306
+
307
+ Every conversion is automatically logged. You can review your execution history at any time.
308
+
309
+ ```bash
310
+ morph history
311
+ ```
312
+
313
+ ```text
314
+ ┌──────────┬──────┬──────┬────────────────┬────────┬────────────┐
315
+ │ When │ From │ To │ File │ Mode │ Status │
316
+ ├──────────┼──────┼──────┼────────────────┼────────┼────────────┤
317
+ │ 2m ago │ md │ docx │ README.md │ single │ ✓ 1.8s │
318
+ │ 1h ago │ mp4 │ mp3 │ intro.mp4 │ batch │ ✓ 4.2s │
319
+ └──────────┴──────┴──────┴────────────────┴────────┴────────────┘
320
+ ```
321
+
322
+ ---
323
+
324
+ ## 🤝 Contributing
325
+
326
+ PRs are highly encouraged! If you are adding a new conversion, simply add the file in the `converters/` directory.
327
+
328
+ ## ⚖️ License
329
+
330
+ Released under the [MIT License](LICENSE).
@@ -0,0 +1,286 @@
1
+ <div align="center">
2
+
3
+ # 🦋 MORPH
4
+
5
+ **The Universal File Converter for the Command Line.**
6
+
7
+ *One command. No format-specific tools to remember. No cloud upload. No API keys.*
8
+ *Convert anything, to anything.*
9
+
10
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](LICENSE)
11
+ [![Python 3.10+](https://img.shields.io/badge/python-3.10%2B-blue.svg)](https://www.python.org/downloads/)
12
+ [![Built with Typer](https://img.shields.io/badge/CLI-Typer-6C47FF.svg)](https://typer.tiangolo.com/)
13
+ [![Powered by Rich](https://img.shields.io/badge/output-Rich-8A2BE2.svg)](https://github.com/Textualize/rich)
14
+ [![TUI: Textual](https://img.shields.io/badge/TUI-Textual-4B0082.svg)](https://textual.textualize.io/)
15
+
16
+ ```bash
17
+ morph report.docx report.pdf
18
+ morph data.csv data.xlsx --table-style TableStyleMedium2 --header-bg 2E7D32
19
+ morph logo.png logo.svg --mode spline
20
+ morph batch '*.mp4' mp3 --workers 4
21
+ ```
22
+
23
+ </div>
24
+
25
+ ---
26
+
27
+ ## ⚡ Why `morph` exists
28
+
29
+ `ffmpeg` converts media. `pandoc` converts documents. `ImageMagick` converts images. Each is an incredible piece of software, but using them together is a nightmare of different flag dialects, mental models, and obscure syntax errors.
30
+
31
+ **`morph` doesn't reinvent codecs or file formats — it orchestrates the best tool for each job behind a single, predictable, and beautiful interface.**
32
+
33
+ Whether you are rendering a 3D `.blend` file to a `.png`, scraping a Wikipedia article into a Markdown file, vectorizing a `.jpg` into an `.svg`, or converting a batch of `.csv` files to `.parquet`, `morph` calculates the route, fetches the dependencies, and executes the job.
34
+
35
+ ## ✨ Features
36
+
37
+ - **One Universal Verb.** `morph <input> <output>`. That's it. Omit the output, and `morph` acts as a wizard, presenting you with an interactive menu of all possible destination formats.
38
+ - **Undo.** Made a mistake? Convert a massive 1,000-file directory by accident? Just type `morph undo` and watch it instantly delete the generated files and revert your history.
39
+ - **Smart Multi-Hop Graph Routing.** No direct `csv → yaml` converter? `morph` automatically finds the `csv → json → yaml` route. When crossing wild paradigms (e.g. Markdown → SQLite), `morph` explicitly hints its logic (like `extracts tabular data only`).
40
+ - **Contextual Intelligence.** Run `morph data.csv data.xlsx --help` and you'll *only* see flags relevant to that specific pair (like `--table-style` or `--freeze-cols`). Run it on a video file, and you'll see bitrate and framerate controls instead.
41
+ - **Output Verification.** Pass the `--verify` flag to calculate and display the exact SHA-256 checksum of the resulting file right alongside the success message.
42
+ - **Transparent Remote Downloads.** Pass any `http://` link and `morph` handles the rest. It uses `trafilatura` to scrape web articles into clean Markdown, or `yt-dlp` to natively download high-quality media (`morph <url> --audio`).
43
+ - **Batch Processing Engine.** `morph batch '*.mp4' mp3` converts files concurrently with a live progress table, smart skip logic (`--newer-only`, `--skip-existing`), and output structure mirroring.
44
+ - **Interactive TUI.** Type `morph` with no arguments to launch a stunning, keyboard-driven Textual UI. Navigate your filesystem, preview conversion options, and watch live progress bars without touching your mouse.
45
+ - **Automated Dependency Management.** Missing `ffmpeg` or `pandoc`? `morph` detects your OS and package manager (brew/apt/winget/etc.), shows you the exact install command, and asks before running it. Massive dependencies (like 3D rendering engines) are cleanly isolated as optional extras!
46
+ - **Pluggable Architecture.** Drop a Python script in `morph/converters/`, add a `@register` decorator, and it's instantly live in the routing graph.
47
+ - **Local-First & Private.** No cloud uploads. No API keys. Everything runs on your machine.
48
+
49
+ ---
50
+
51
+ ## 📦 Installation
52
+
53
+ `morph` is natively distributed across all major operating systems. You do not need Python installed to use the standalone binaries!
54
+
55
+ ### Windows
56
+ ```powershell
57
+ # via Winget (Recommended)
58
+ winget install hariharen.morph
59
+
60
+ # via Scoop
61
+ scoop bucket add morph https://github.com/hariharen9/scoop-bucket.git
62
+ scoop install morph
63
+ ```
64
+
65
+ ### macOS & Linux
66
+ ```bash
67
+ # via Homebrew
68
+ brew tap hariharen9/homebrew-tap
69
+ brew install morph
70
+ ```
71
+
72
+ ### Python Ecosystem (PyPI)
73
+ If you prefer managing via `pip` (or `pipx`), install it globally:
74
+ ```bash
75
+ pipx install morphconv
76
+ ```
77
+
78
+ ### Development (Source)
79
+ ```bash
80
+ git clone https://github.com/hariharen9/morph.git
81
+ cd morph
82
+ pip install -e .
83
+ ```
84
+
85
+ `morph` relies on native Python libraries for data, web, and archives. For massive specialized packages, `morph` uses optional extras to keep your base installation blazing fast. If you need them, simply install them:
86
+ ```bash
87
+ pip install -e ".[3d]" # Installs bpy (Blender) for 3D conversions
88
+ pip install -e ".[web]" # Installs crawl4ai and playwright for heavy JS rendering
89
+ ```
90
+
91
+ For domain-specific external binaries (e.g., `ffmpeg`, `pandoc`), you don't need to install these upfront — `morph` will intelligently prompt you to install them the first time they are needed.
92
+
93
+ To see your current system dependencies at any time:
94
+ ```bash
95
+ morph deps
96
+ ```
97
+
98
+ ---
99
+
100
+ ## 🚀 Quickstart & Real-World Examples
101
+
102
+ ### 📊 Data Processing
103
+ Switch between analytical formats effortlessly.
104
+
105
+ ```bash
106
+ morph data.csv data.xlsx
107
+ morph data.json data.yaml
108
+ morph database.sqlite data.csv
109
+ ```
110
+
111
+ ### 📄 Documents & Ebooks
112
+ ```bash
113
+ morph notes.md notes.docx
114
+ morph report.docx report.pdf
115
+ morph book.epub book.mobi
116
+ ```
117
+
118
+ ### 🖼️ Images & Vectorization
119
+ Raster conversions, plus advanced raster-to-vector tracing.
120
+
121
+ ```bash
122
+ # Standard image processing
123
+ morph photo.png photo.webp --quality 80 --resize 1200x
124
+ morph icon.png icon.ico
125
+
126
+ # Raster to Vector (via vtracer)
127
+ morph logo.png logo.svg --mode spline --hierarchical stacked
128
+ ```
129
+
130
+ ### 🎬 Audio & Video (via `ffmpeg`)
131
+ Media manipulation with real-time progress bars parsed directly from ffmpeg.
132
+
133
+ ```bash
134
+ morph song.wav song.mp3 --bitrate 192k
135
+ morph clip.mp4 clip.gif --fps 10 --width 480
136
+ morph clip.mkv clip.mp3 # Extract audio
137
+ ```
138
+
139
+ ### 🌐 Web & Remote Files
140
+ Fetch data directly from the internet and transform it locally in one step. `morph` natively embeds `yt-dlp` to download almost any media from the web.
141
+
142
+ ```bash
143
+ # Natively download video from YouTube, Twitter, etc.
144
+ morph https://youtube.com/watch?v=... video.mp4
145
+
146
+ # Extract audio only from a remote video with metadata embedded
147
+ morph https://youtube.com/watch?v=... audio.mp3 --audio
148
+
149
+ # Scrape an article into clean Markdown (via trafilatura)
150
+ morph https://en.wikipedia.org/wiki/Graph_theory graph_theory.md
151
+
152
+ # Download a remote CSV and style it as an Excel workbook natively
153
+ morph https://raw.githubusercontent.com/owid/covid-19-data/master/public/data/latest/owid-covid-latest.csv covid.xlsx --table-style TableStyleMedium2
154
+
155
+ # Scrape a JavaScript-heavy page (requires morphconv[web])
156
+ morph https://example.com/dynamic-article doc.pdf --js
157
+ ```
158
+
159
+ ### 🧊 3D Models & Rendering (Powered by Blender/`bpy`)
160
+ Seamlessly convert between 3D formats, or utilize headless rendering to generate images of your models.
161
+
162
+ ```bash
163
+ # Format conversion
164
+ morph character.fbx character.glb
165
+ morph scene.obj scene.blend
166
+
167
+ # Headless 3D rendering (automatically places lights and cameras)
168
+ morph character.gltf character.png
169
+ ```
170
+
171
+ ---
172
+
173
+ ## 🏎️ Batch Operations
174
+
175
+ Convert hundreds of files concurrently with a beautiful terminal dashboard.
176
+
177
+ ```bash
178
+ # All MP4s to MP3 using 4 parallel workers
179
+ morph batch '*.mp4' mp3 --workers 4
180
+
181
+ # Recursively convert a whole directory and mirror its structure in an output folder
182
+ morph batch ./raw_footage/ mp3 --recursive --out-dir ./audio_only/ --mirror
183
+
184
+ # Skip files that have already been converted
185
+ morph batch '*.flac' mp3 --skip-existing
186
+ ```
187
+
188
+ During batch conversions, `morph` displays a live status table:
189
+
190
+ ```text
191
+ ╭─ morph batch — 8 files → mp3 ─────────────────────────────────────╮
192
+ │ Status File Time Size │
193
+ │ ✓ done concert_01.flac 0:00:04 8.3MB → 4.1MB │
194
+ │ ✓ done concert_02.flac 0:00:03 7.9MB → 3.8MB │
195
+ │ ▶ converting… concert_03.flac 0:00:01 │
196
+ │ · waiting concert_04.wav │
197
+ │ │
198
+ │ Overall ████████░░░░░░░░ 2/8 [0:00:07] │
199
+ ╰──────────────────────────────────────────────────────────────────────╯
200
+ ```
201
+
202
+ ---
203
+
204
+ ## 🗂️ Supported Formats
205
+
206
+ | Domain | Formats | Backend |
207
+ |---|---|---|
208
+ | **Data** | `csv`, `xlsx`, `json`, `yaml`, `parquet`, `feather`, `ods`, `xml`, `html`, `sqlite` | Native (`pandas` / `openpyxl`) |
209
+ | **Documents** | `md`, `html`, `docx`, `odt`, `rtf`, `epub`, `latex`, `rst`, `txt`, `ipynb`, `pptx`, `adoc`, `org`, `opml`, `man`, `pdf`* | `pandoc` |
210
+ | **Images (Raster)** | `png`, `jpg/jpeg`, `webp`, `bmp`, `gif`, `tiff`, `ico`, `heic`, `avif`, `icns`, `pdf` | `Pillow` / `cairosvg` |
211
+ | **Vectorization** | `png`/`jpg`/etc. → `svg` | `vtracer` |
212
+ | **3D Models** | `obj`, `stl`, `fbx`, `gltf`, `glb`, `blend`, `any → png` (Render) | `bpy` (Blender) |
213
+ | **Web Extraction** | `url` → `md`, `txt`, `xml`, `html` | `trafilatura` / `crawl4ai` |
214
+ | **Audio** | `mp3`, `wav`, `flac`, `ogg`, `aac`, `m4a`, `opus`, `wma` | `ffmpeg` |
215
+ | **Video** | `mp4`, `mkv`, `mov`, `webm`, `avi`, `flv`, `wmv`, `mpeg` | `ffmpeg` |
216
+ | **Ebooks** | `epub`, `mobi`, `azw3` | `ebook-convert` |
217
+ | **Fonts** | `ttf`, `otf`, `woff`, `woff2` | `fontTools` |
218
+ | **OCR** | `png`, `jpg`, `webp`, `pdf`, etc. → `txt` | `tesseract` |
219
+ | **Archives** | `zip`, `tar`, `tar.gz`, `tar.bz2`, `tar.xz` | Python stdlib |
220
+
221
+ *\* Note: PDF is an output-only format for documents. Extracting structured text back out of a PDF is handled via the OCR pipeline.*
222
+
223
+ ---
224
+
225
+ ## 🛠️ Architecture & Under the Hood
226
+
227
+ The magic of `morph` lies in its modular graph architecture.
228
+
229
+ ```text
230
+ morph/
231
+ ├── cli.py # Command dispatch (run, batch, formats, history, deps)
232
+ ├── registry.py # BFS Routing graph & registration logic
233
+ ├── tui.py # Textual keyboard-driven TUI
234
+ └── converters/
235
+ ├── __init__.py # Auto-discovers all modules
236
+ ├── documents.py # pandoc engine
237
+ ├── images.py # Pillow engine
238
+ ├── models_3d.py # Blender/bpy engine
239
+ ├── web.py # trafilatura / crawl4ai engine
240
+ └── vtracer_converter.py # Raster-to-SVG vectorization
241
+ ```
242
+
243
+ ### Adding a new conversion is trivial
244
+
245
+ Drop a file in `morph/converters/` and use the `@register` decorator. No central registry, no CLI parsers to update.
246
+
247
+ ```python
248
+ from pathlib import Path
249
+ from ..registry import ConversionResult, OptionSpec, register
250
+
251
+ @register("foo", "bar", backend="mytool", family="image")
252
+ def foo_to_bar(input_path: Path, output_path: Path, **kwargs) -> ConversionResult:
253
+ # Do the conversion...
254
+ return ConversionResult(output=output_path)
255
+ ```
256
+
257
+ Because of `morph`'s graph routing, once `foo → bar` is registered, if a path exists from `bar → baz`, `morph` immediately knows how to convert `foo → baz`.
258
+
259
+ ---
260
+
261
+ ## 📜 History & Transparency
262
+
263
+ Every conversion is automatically logged. You can review your execution history at any time.
264
+
265
+ ```bash
266
+ morph history
267
+ ```
268
+
269
+ ```text
270
+ ┌──────────┬──────┬──────┬────────────────┬────────┬────────────┐
271
+ │ When │ From │ To │ File │ Mode │ Status │
272
+ ├──────────┼──────┼──────┼────────────────┼────────┼────────────┤
273
+ │ 2m ago │ md │ docx │ README.md │ single │ ✓ 1.8s │
274
+ │ 1h ago │ mp4 │ mp3 │ intro.mp4 │ batch │ ✓ 4.2s │
275
+ └──────────┴──────┴──────┴────────────────┴────────┴────────────┘
276
+ ```
277
+
278
+ ---
279
+
280
+ ## 🤝 Contributing
281
+
282
+ PRs are highly encouraged! If you are adding a new conversion, simply add the file in the `converters/` directory.
283
+
284
+ ## ⚖️ License
285
+
286
+ Released under the [MIT License](LICENSE).