
File Converter
- 94 installs
- 4 repo stars
- Updated April 11, 2026
- 89jobrien/steve
file-converter is a Claude Code skill that converts files between document, data, and image formats by generating Python conversion code per request.
About
file-converter is a Claude Code skill that converts files between formats across documents, data files, and images. A developer uses it to turn Markdown into HTML, JSON into CSV, DOCX into PDF, or PNG into WebP, among other pairings. It generates Python conversion code dynamically and picks the appropriate library for each conversion.
- Converts documents, data files, and images between formats
- Generates Python conversion code dynamically per request
- Covers PDF/DOCX/Markdown, JSON/CSV/YAML/XML/TOML, and PNG/SVG/WebP
File Converter by the numbers
- 94 all-time installs (skills.sh)
- Ranked #332 of 688 Office & Documents skills by installs in the Skillselion catalog
- Data as of Jul 28, 2026 (Skillselion catalog sync)
file-converter capabilities & compatibility
- Capabilities
- file conversion · document conversion · image conversion
- Use cases
- pdf parsing · documentation
- Pricing
- Free
What file-converter says it does
This skill handles file format conversions across documents (PDF, DOCX, Markdown, HTML, TXT), data files (JSON, CSV, YAML, XML, TOML), and images (PNG, JPG, WebP, SVG, GIF).
Generate Python code dynamically for each conversion request, selecting appropriate libraries and handling edge cases.
npx skills add https://github.com/89jobrien/steve --skill file-converterAdd your badge
Show developers this skill is listed on Skillselion. Paste this into your README.
| Installs | 94 |
|---|---|
| repo stars | ★ 4 |
| Last updated | April 11, 2026 |
| Repository | 89jobrien/steve ↗ |
What it does
Convert files between document, data, and image formats using generated Python code.
Who is it for?
Developers who need to convert between document, data, or image formats using appropriate Python libraries.
Skip if: Bulk enterprise media pipelines or lossless conversions the underlying libraries cannot guarantee (for example PNG to SVG).
When should I use this skill?
You need to convert, transform, or export a file between two formats.
What you get
Produces working Python code that converts the source file to the target format with the recommended library.
- Python conversion script
- converted output file
By the numbers
- 3 conversion categories: documents, data files, images
- 3 bundled reference files for edge cases
Files
File Converter
Overview
Convert files between formats across three categories: documents, data files, and images. Generate Python code dynamically for each conversion request, selecting appropriate libraries and handling edge cases.
Conversion Categories
Documents
| From | To | Recommended Library |
|---|---|---|
| Markdown | HTML | markdown or mistune |
| HTML | Markdown | markdownify or html2text |
| HTML | weasyprint or pdfkit (requires wkhtmltopdf) | |
| Text | pypdf or pdfplumber | |
| DOCX | Markdown | mammoth |
| DOCX | docx2pdf (Windows/macOS) or LibreOffice CLI | |
| Markdown | Convert via HTML first, then to PDF |
Data Files
| From | To | Recommended Library |
|---|---|---|
| JSON | YAML | pyyaml |
| YAML | JSON | pyyaml |
| JSON | CSV | pandas or stdlib csv + json |
| CSV | JSON | pandas or stdlib csv + json |
| JSON | TOML | tomli/tomllib (read) + tomli-w (write) |
| XML | JSON | xmltodict |
| JSON | XML | dicttoxml or xmltodict.unparse |
Images
| From | To | Recommended Library |
|---|---|---|
| PNG/JPG/WebP/GIF | Any raster | Pillow (PIL) |
| SVG | PNG/JPG | cairosvg or svglib + reportlab |
| PNG | SVG | potrace (CLI) for tracing, limited fidelity |
Workflow
1. Identify source format (from file extension or user statement) 2. Identify target format 3. Check references/ for format-specific guidance 4. Generate conversion code using recommended library 5. Handle edge cases (encoding, transparency, nested structures) 6. Execute conversion and report results
Quick Patterns
Data: JSON to YAML
import json
import yaml
with open("input.json") as f:
data = json.load(f)
with open("output.yaml", "w") as f:
yaml.dump(data, f, default_flow_style=False, allow_unicode=True)Data: CSV to JSON
import csv
import json
with open("input.csv") as f:
reader = csv.DictReader(f)
data = list(reader)
with open("output.json", "w") as f:
json.dump(data, f, indent=2)Document: Markdown to HTML
import markdown
with open("input.md") as f:
md_content = f.read()
html = markdown.markdown(md_content, extensions=["tables", "fenced_code"])
with open("output.html", "w") as f:
f.write(html)Image: PNG to WebP
from PIL import Image
img = Image.open("input.png")
img.save("output.webp", "WEBP", quality=85)Image: SVG to PNG
import cairosvg
cairosvg.svg2png(url="input.svg", write_to="output.png", scale=2)Resources
Detailed guidance for complex conversions is in references/:
references/document-conversions.md- PDF handling, encoding issues, styling preservationreferences/data-conversions.md- Schema handling, type coercion, nested structuresreferences/image-conversions.md- Quality settings, transparency, color profiles
Consult these references when handling edge cases or when the user has specific quality/fidelity requirements.
Data Conversion Reference
Type Coercion
JSON to CSV
JSON types map to CSV strings. Handle carefully:
import csv
import json
def flatten_for_csv(data):
if isinstance(data, list) and all(isinstance(d, dict) for d in data):
return data
raise ValueError("CSV requires list of flat dictionaries")
with open("input.json") as f:
data = json.load(f)
flat_data = flatten_for_csv(data)
with open("output.csv", "w", newline="") as f:
if flat_data:
writer = csv.DictWriter(f, fieldnames=flat_data[0].keys())
writer.writeheader()
writer.writerows(flat_data)CSV to JSON
All CSV values are strings. Convert types explicitly:
import csv
import json
def infer_type(value):
if value == "":
return None
try:
return int(value)
except ValueError:
pass
try:
return float(value)
except ValueError:
pass
if value.lower() in ("true", "false"):
return value.lower() == "true"
return value
with open("input.csv") as f:
reader = csv.DictReader(f)
data = [{k: infer_type(v) for k, v in row.items()} for row in reader]
with open("output.json", "w") as f:
json.dump(data, f, indent=2)Nested Structures
Flattening Nested JSON for CSV
def flatten_dict(d, parent_key="", sep="_"):
items = []
for k, v in d.items():
new_key = f"{parent_key}{sep}{k}" if parent_key else k
if isinstance(v, dict):
items.extend(flatten_dict(v, new_key, sep).items())
elif isinstance(v, list):
items.append((new_key, json.dumps(v)))
else:
items.append((new_key, v))
return dict(items)XML Handling
xmltodict converts XML to OrderedDict:
import xmltodict
import json
with open("input.xml") as f:
data = xmltodict.parse(f.read())
with open("output.json", "w") as f:
json.dump(data, f, indent=2)Attributes become @attr, text becomes #text:
<item id="1">value</item>Becomes:
{"item": {"@id": "1", "#text": "value"}}YAML Specifics
Multi-document YAML
import yaml
with open("input.yaml") as f:
docs = list(yaml.safe_load_all(f))Preserving Order
import yaml
with open("input.yaml") as f:
data = yaml.safe_load(f)
with open("output.yaml", "w") as f:
yaml.dump(data, f, default_flow_style=False, sort_keys=False)TOML Handling
Python 3.11+ has tomllib built-in (read-only):
import tomllib
with open("input.toml", "rb") as f:
data = tomllib.load(f)For writing, use tomli-w:
import tomli_w
with open("output.toml", "wb") as f:
tomli_w.dump(data, f)Schema Considerations
When converting between formats, preserve these semantics:
| Source | Target | Watch For |
|---|---|---|
| JSON | YAML | Dates (JSON has no date type) |
| YAML | JSON | Anchors/aliases (not supported in JSON) |
| CSV | JSON | Header row naming, empty values |
| JSON | CSV | Nested objects, arrays |
| XML | JSON | Attributes vs elements, namespaces |
Document Conversion Reference
PDF Handling
Reading PDFs
pypdf (formerly PyPDF2):
- Best for: Simple text extraction, merging, splitting
- Limitation: Poor handling of complex layouts, tables
pdfplumber:
- Best for: Table extraction, precise text positioning
- Provides bounding boxes for text elements
import pdfplumber
with pdfplumber.open("input.pdf") as pdf:
for page in pdf.pages:
text = page.extract_text()
tables = page.extract_tables()Creating PDFs
weasyprint:
- Best for: HTML/CSS to PDF with good styling support
- Requires: Cairo graphics library
from weasyprint import HTML
HTML("input.html").write_pdf("output.pdf")reportlab:
- Best for: Programmatic PDF generation
- More control but more verbose
PDF Edge Cases
- Scanned PDFs: Contain images, not text. Use OCR (pytesseract + pdf2image)
- Encrypted PDFs: Must decrypt first with password
- Form fields: Use pypdf or pdfrw for filling forms
Encoding Issues
Text Files
Always specify encoding explicitly:
with open("input.txt", encoding="utf-8") as f:
content = f.read()Common encodings:
utf-8: Default for modern fileslatin-1/iso-8859-1: Legacy Windows/Europeancp1252: Windows Western Europeanutf-16: Some Windows exports
Detection when unknown:
import chardet
with open("input.txt", "rb") as f:
result = chardet.detect(f.read())
encoding = result["encoding"]DOCX Handling
Reading DOCX
python-docx:
- Full access to document structure
- Can read paragraphs, tables, images
mammoth:
- Best for converting to HTML/Markdown
- Semantic conversion (headings, lists preserved)
import mammoth
with open("input.docx", "rb") as f:
result = mammoth.convert_to_markdown(f)
markdown = result.valueDOCX to PDF
Platform-dependent options:
macOS/Windows - docx2pdf:
from docx2pdf import convert
convert("input.docx", "output.pdf")Linux - LibreOffice CLI:
libreoffice --headless --convert-to pdf input.docxStyling Preservation
When converting between formats, styling fidelity varies:
| Conversion | Styling Preserved |
|---|---|
| DOCX -> HTML | Partial (basic formatting) |
| DOCX -> Markdown | Minimal (headings, lists, bold/italic) |
| HTML -> PDF | Good (with weasyprint + CSS) |
| Markdown -> HTML | Full (via extensions) |
| PDF -> Text | None (text only) |
For maximum fidelity, prefer intermediate HTML with explicit CSS.
Image Conversion Reference
Quality Settings
JPEG Quality
Range: 1-100 (higher = better quality, larger file)
from PIL import Image
img = Image.open("input.png")
img = img.convert("RGB") # JPEG requires RGB, not RGBA
img.save("output.jpg", "JPEG", quality=85, optimize=True)Recommendations:
- 95: Near-lossless, large files
- 85: Good balance (default recommendation)
- 75: Noticeable compression, smaller files
- 60: Web thumbnails
WebP Quality
img.save("output.webp", "WEBP", quality=80, method=6)quality: 0-100 (80 recommended)method: 0-6 (compression effort, 6 = slowest/smallest)lossless=True: For lossless compression
PNG Optimization
PNG is lossless, but compression level affects file size:
img.save("output.png", "PNG", optimize=True, compress_level=9)Transparency Handling
RGBA to RGB (for JPEG)
from PIL import Image
img = Image.open("input.png")
if img.mode == "RGBA":
background = Image.new("RGB", img.size, (255, 255, 255))
background.paste(img, mask=img.split()[3])
img = background
img.save("output.jpg", "JPEG", quality=85)Preserving Transparency
Formats supporting transparency: PNG, WebP, GIF
img = Image.open("input.png")
img.save("output.webp", "WEBP", quality=80) # Preserves alphaColor Profiles
Converting Color Modes
from PIL import Image
img = Image.open("input.png")
if img.mode == "P": # Palette mode
img = img.convert("RGBA")
elif img.mode == "L": # Grayscale
img = img.convert("RGB")
elif img.mode == "CMYK":
img = img.convert("RGB")Preserving ICC Profiles
img = Image.open("input.jpg")
icc_profile = img.info.get("icc_profile")
img.save("output.jpg", "JPEG", quality=85, icc_profile=icc_profile)SVG Conversion
SVG to Raster (PNG/JPG)
cairosvg (recommended):
import cairosvg
cairosvg.svg2png(
url="input.svg",
write_to="output.png",
output_width=1024, # or use scale=2
)svglib + reportlab:
from svglib.svglib import svg2rlg
from reportlab.graphics import renderPM
drawing = svg2rlg("input.svg")
renderPM.drawToFile(drawing, "output.png", fmt="PNG")Raster to SVG (Tracing)
Limited fidelity - converts to vector paths:
potrace input.bmp -s -o output.svgFor photographs, this produces stylized results, not faithful reproduction.
Resizing
Maintain Aspect Ratio
from PIL import Image
img = Image.open("input.png")
img.thumbnail((800, 600), Image.Resampling.LANCZOS)
img.save("output.png")Exact Dimensions (with padding)
from PIL import Image
def resize_with_padding(img, target_size, fill_color=(255, 255, 255)):
img.thumbnail(target_size, Image.Resampling.LANCZOS)
new_img = Image.new("RGB", target_size, fill_color)
offset = ((target_size[0] - img.size[0]) // 2,
(target_size[1] - img.size[1]) // 2)
new_img.paste(img, offset)
return new_imgBatch Processing
from pathlib import Path
from PIL import Image
input_dir = Path("input_images")
output_dir = Path("output_images")
output_dir.mkdir(exist_ok=True)
for img_path in input_dir.glob("*.png"):
img = Image.open(img_path)
output_path = output_dir / f"{img_path.stem}.webp"
img.save(output_path, "WEBP", quality=80)GIF Handling
Extracting Frames
from PIL import Image
img = Image.open("input.gif")
frames = []
try:
while True:
frames.append(img.copy())
img.seek(img.tell() + 1)
except EOFError:
passCreating GIF from Images
from PIL import Image
images = [Image.open(f"frame_{i}.png") for i in range(10)]
images[0].save(
"output.gif",
save_all=True,
append_images=images[1:],
duration=100, # milliseconds per frame
loop=0 # 0 = infinite loop
)Related skills
FAQ
What formats does it support?
Documents (PDF, DOCX, Markdown, HTML, TXT), data files (JSON, CSV, YAML, XML, TOML), and images (PNG, JPG, WebP, SVG, GIF).
How does it convert files?
It generates Python code dynamically for each conversion request, selecting an appropriate library.