Convert anything. Locally. Privately.
A universal file converter CLI that runs entirely on your machine. No cloud uploads, no API calls, no telemetry. Your files never leave your computer.
- Single-command conversion:
filecraft convert input.pdf output.docx - Batch processing:
filecraft batch *.png --to webp - File inspection:
filecraft info document.pdf - Plugin system: Extend with custom converters
- Graceful degradation: Works with minimal deps, unlocks more formats as you install optional packages
- Progress bars: Rich terminal output (optional)
- Zero cloud dependency: Everything runs locally
# From source
pip install .
# With all optional converters
pip install ".[all]"
# Pick what you need
pip install ".[image]" # PNG, JPG, WEBP, GIF, BMP, ICO, AVIF
pip install ".[docs]" # PDF, DOCX, Markdown, HTML
pip install ".[data]" # YAML, TOML, CSV, Excel
pip install ".[rich]" # Beautiful terminal outputFor media conversions (audio/video), install ffmpeg system-wide:
# macOS
brew install ffmpeg
# Ubuntu/Debian
sudo apt install ffmpeg
# Arch
sudo pacman -S ffmpeg# Convert a single file
filecraft convert photo.png photo.webp
filecraft convert data.json data.yaml
filecraft convert report.md report.html
filecraft convert notebook.ipynb script.py
# Batch convert all PNGs to WebP
filecraft batch *.png --to webp
# Batch convert with output directory
filecraft batch reports/*.md --to html -o build/
# Inspect a file
filecraft info document.pdf
# List all available conversion pairs
filecraft formats| From \ To | DOCX | MD | HTML | TXT | |
|---|---|---|---|---|---|
| - | opt | opt | opt | opt | |
| DOCX | opt | - | opt | opt | opt |
| MD | opt | opt | - | yes | yes |
| HTML | opt | opt | yes | - | yes |
| TXT | opt | opt | yes | yes | - |
yes= works with zero optional dependenciesopt= requires optional packages (see install section)
| From \ To | PNG | JPG | WEBP | GIF | BMP | ICO | AVIF | SVG |
|---|---|---|---|---|---|---|---|---|
| PNG | - | yes | yes | yes | yes | yes | yes | embed |
| JPG | yes | - | yes | yes | yes | yes | yes | embed |
| WEBP | yes | yes | - | yes | yes | yes | yes | embed |
| GIF | yes | yes | yes | - | yes | yes | yes | embed |
| BMP | yes | yes | yes | yes | - | yes | yes | embed |
| ICO | yes | yes | yes | yes | yes | - | yes | embed |
| AVIF | yes | yes | yes | yes | yes | yes | - | embed |
| SVG | opt | opt | opt | opt | opt | opt | opt | - |
yes= requires Pillow (pip install ".[image]")embed= wraps raster as base64 data URI in SVGopt= SVG input requirescairosvg
| From \ To | JSON | YAML | TOML | CSV | XML | XLSX |
|---|---|---|---|---|---|---|
| JSON | - | opt | opt | yes | yes | opt |
| YAML | opt | - | opt | opt | opt | opt |
| TOML | opt | opt | - | opt | opt | - |
| CSV | yes | opt | opt | - | yes | opt |
| XML | yes | opt | opt | yes | - | - |
| XLSX | opt | opt | - | opt | - | - |
yes= stdlib only, always availableopt= requirespyyaml,toml/tomli, oropenpyxl
| From \ To | MP3 | WAV | OGG | FLAC | GIF |
|---|---|---|---|---|---|
| MP3 | - | yes | yes | yes | - |
| WAV | yes | - | yes | yes | - |
| OGG | yes | yes | - | yes | - |
| MP4 | yes | yes | yes | yes | yes |
| WEBM | yes | yes | yes | yes | yes |
| AVI | yes | yes | yes | yes | yes |
| From \ To | Python | Markdown |
|---|---|---|
| .ipynb | yes | yes |
| From \ To | ZIP | TAR.GZ | TAR.BZ2 | TAR.XZ | 7Z |
|---|---|---|---|---|---|
| ZIP | - | yes | yes | yes | opt |
| TAR.GZ | yes | - | yes | yes | opt |
| TAR.BZ2 | yes | yes | - | yes | opt |
| TAR.XZ | yes | yes | yes | - | opt |
| 7Z | opt | opt | opt | opt | - |
opt= requires7zcommand on PATH
$ filecraft info photo.png
Property Value
---------- --------------------------
Name photo.png
Path /home/user/photos/photo.png
Size 2.4 MB
Format png
MIME type image/png
Can convert to: avif, bmp, gif, ico, jpg, jpeg, svg, tiff, webpFileCraft supports custom converter plugins. A plugin is any Python module that uses the @register decorator:
# my_plugin.py
from filecraft.converter import register
from pathlib import Path
@register("custom", "txt")
def custom_to_txt(input_path: Path, output_path: Path) -> None:
data = input_path.read_bytes()
output_path.write_text(f"Converted {len(data)} bytes from .custom format")Load it at runtime:
filecraft convert input.custom output.txt --plugin my_pluginfrom filecraft.converter import register, register_pair
# Decorator style (one pair)
@register("src_fmt", "dst_fmt")
def my_converter(input_path: Path, output_path: Path) -> None:
...
# Decorator style (multiple pairs)
@register(["a", "b"], ["b", "a"])
def bidirectional(input_path: Path, output_path: Path) -> None:
...
# Imperative style
register_pair("x", "y", my_function)FileCraft runs locally with no network overhead. Typical conversion times on modern hardware:
| Operation | File Size | Time |
|---|---|---|
| PNG -> WEBP | 5 MB | ~0.3s |
| JSON -> YAML | 10 MB | ~0.5s |
| PDF -> TXT (50 pages) | 2 MB | ~1.2s |
| MP4 -> GIF (10s clip) | 20 MB | ~3s |
| Batch 100x PNG -> JPG | 500 MB total | ~8s |
Compare with online converters:
| FileCraft | Cloud Converter | |
|---|---|---|
| Upload time | 0s | 30-120s |
| Processing | 0.3s | 5-30s |
| Download | 0s | 10-60s |
| Privacy | 100% local | Files sent to server |
| Batch support | Native | Often limited/paid |
| Offline | Yes | No |
# Clone
git clone https://github.com/hzt/filecraft.git
cd filecraft
# Install in development mode with all deps
pip install -e ".[all]"
# Run tests
pytest
# Run a quick smoke test
filecraft formats- Python 3.10+
- Optional: Pillow, python-docx, pdfplumber, pyyaml, openpyxl, rich
- Optional: ffmpeg (system), 7z (system)
MIT License. See LICENSE for details.