Skip to main content
ClaudeWave
Skill132 repo starsupdated yesterday

converting-files

This Claude Code skill converts files between formats by automatically routing to the correct engine, pandoc for markup conversions, LibreOffice for Office-to-PDF conversions, ImageMagick for image transformations, and ffmpeg for audio and video work. Use it when you need to change a file's format (for example, DOCX to PDF, MP4 to GIF, or Markdown to DOCX), but not for editing content within those files or extracting data from them.

Install in Claude Code
Copy
git clone --depth 1 https://github.com/oaustegard/claude-skills /tmp/converting-files && cp -r /tmp/converting-files/converting-files ~/.claude/skills/converting-files
Then start a new Claude Code session; the skill loads automatically.

SKILL.md

# converting-files

Four conversion engines are already in this container — `pandoc`, `libreoffice`
(headless), ImageMagick's `convert`, and `ffmpeg`. The hard part isn't running
them; it's picking the right one. pandoc mangles a real `.docx` into PDF;
LibreOffice is the tool for that. pandoc is *better* than LibreOffice for
`md → docx`. Neither touches `mp4 → gif`. This skill encodes that routing so the
choice isn't re-derived (often wrongly) each time.

`scripts/convert.py` is a dispatcher over those four binaries, not a new engine.
Use it for the common cases; drop to the raw engine when you need flags it
doesn't pass through.

## Is this the right skill?

| You want to… | Use instead |
| --- | --- |
| Change a file's **format** (ext A → ext B) | **this skill** |
| Edit/author a Word/PPT/Excel/PDF's **content** | `docx` / `pptx` / `xlsx` / `pdf` skills |
| Read a file already shown in context | just read it — no conversion |
| Extract text/tables *from* a PDF | `pdf-reading` skill |
| Fill or merge PDFs | `pdf` skill |

Format change = here. Content change = a content skill. A `docx → pdf` is a
format change; "fix the grammar in this docx" is not.

## Engine routing (the actual content of this skill)

Source family → target family decides the engine. The dispatcher applies this;
the table is here so the reasoning is auditable and so you can call the engine
directly when needed.

| From → To | Engine | Why |
| --- | --- | --- |
| markup → markup (md, html, rst, latex, org, epub, rtf, ipynb…) | **pandoc** | what it's built for |
| markup → Office (md → docx/pptx/odt) | **pandoc** | cleaner than LibreOffice from markup |
| Office → markup (docx/odt/pptx → md/html…) | **pandoc** | reads modern OOXML well |
| **Office → PDF** (docx/pptx/xlsx → pdf) | **LibreOffice** | preserves layout; pandoc mangles it |
| Office ↔ Office, or **legacy** (.doc/.ppt/.xls) anything | **LibreOffice** | pandoc can't read legacy binary formats at all |
| markup → PDF (md → pdf) | **pandoc** (+pdflatex/xelatex) | lighter than LibreOffice for plain markup |
| image ↔ image (png, jpg, gif, webp, tiff, heic, svg…) | **ImageMagick** | `convert in out` |
| image → PDF | **ImageMagick** | |
| audio ↔ audio (mp3, wav, flac, ogg, aac, m4a, opus…) | **ffmpeg** | |
| video ↔ video, **mp4 → gif**, gif → mp4 | **ffmpeg** | gif-from-video is an ffmpeg job, not ImageMagick |

`gif` lives in both image and video worlds: `png → gif` is ImageMagick (still
image), `mp4 → gif` is ffmpeg (animation). The dispatcher handles the split by
the *source* family.

## Usage

```bash
# Plan only — print engine + reason + exact command, run nothing. Do this first
# on an unfamiliar pair to confirm the route before committing.
python3 /mnt/skills/user/converting-files/scripts/convert.py --plan in.docx out.pdf

# Convert.
python3 /mnt/skills/user/converting-files/scripts/convert.py in.docx out.pdf
python3 /mnt/skills/user/converting-files/scripts/convert.py notes.md notes.docx
python3 /mnt/skills/user/converting-files/scripts/convert.py clip.mp4 clip.gif

# Pass engine flags through (everything after OUTPUT goes to the engine):
python3 .../convert.py photo.png photo.jpg -quality 85         # ImageMagick
python3 .../convert.py song.wav song.mp3 -b:a 192k             # ffmpeg
python3 .../convert.py paper.md paper.pdf --pdf-engine=xelatex # pandoc

# Force a specific engine if you disagree with the route:
python3 .../convert.py weird.docx weird.md --engine pandoc
```

Exit codes: `0` ok, `2` no route exists, `3` engine failed (stderr tail
printed), `4` bad args / missing input.

## Batch

The dispatcher is one file at a time by design — batch is a shell loop so each
file's failure is visible:

```bash
for f in *.png; do
  python3 /mnt/skills/user/converting-files/scripts/convert.py "$f" "${f%.png}.webp" || echo "FAILED: $f"
done
```

## Gotchas (the things that cost a re-run)

- **LibreOffice names the output itself** — it writes `<input-stem>.<ext>` into
  `--outdir`, ignoring your chosen filename. The dispatcher renames to your
  `OUTPUT` after. If you call `libreoffice` raw, expect the input-stem name.
- **LibreOffice headless is single-instance.** Two concurrent `--headless` calls
  collide on the user profile and one silently does nothing. Run them serially
  (the batch loop above is serial — fine).
- **markup → pdf needs a LaTeX engine.** `pdflatex`/`xelatex` are present, but
  exotic Unicode wants `--pdf-engine=xelatex`. If LaTeX chokes on the content,
  route through `docx` first: `md → docx` (pandoc) then `docx → pdf` (LibreOffice).
- **ImageMagick here is IM6** (`convert`, not `magick`). Policy may block some
  formats; if `convert` refuses a PDF/PS op, that's the `/etc/ImageMagick-6/policy.xml`
  security policy, not a missing codec.
- **markup → jira emits heading anchors.** `md → jira` works (both are pandoc
  formats), but headings come out as `h1. {anchor:slug}Title` — pandoc materializing
  the auto-generated heading ID. Suppress with
  `--engine pandoc ... -f markdown-auto_identifiers` (pass the format-with-extension
  yourself, since the dispatcher infers a bare `markdown`).
- **`--plan` lies about nothing but runs nothing** — it can't tell you the
  *content* will survive (e.g. a pptx → md drops all layout). Plan checks the
  route; only a real run checks the result.

## Why not VERT (or any web converter) as the skill

VERT (vert.sh) is a Svelte/WASM **browser app** wrapping these same engines
(libvips, ffmpeg.wasm, Pandoc-wasm) for a human at a tab who wants local privacy.
There's no library or CLI to import — the app *is* the UI. In-container we
already have the native binaries with full filesystem access and no browser
memory ceiling, so the WASM wrappers would be strictly slower and weaker. VERT is
a good *recommendation to a person*; it's the wrong shape for a skill. This skill
is the in-container equivalent of what VERT does in a tab.
accessing-github-reposSkill

GitHub repository access in containerized environments using REST API and credential detection. Use when git clone fails, or when accessing private repos/writing files via API.

api-credentialsSkill

Securely manages API credentials for multiple providers (Anthropic Claude, Google Gemini, GitHub). Use when skills need to access stored API keys for external service invocations.

asking-questionsSkill

Guidance for asking clarifying questions when user requests are ambiguous, have multiple valid approaches, or require critical decisions. Use when implementation choices exist that could significantly affect outcomes.

assessing-impactSkill

>-

bm25Skill

>-

browsing-blueskySkill

Browse Bluesky content via API and firehose - search posts, fetch user activity, sample trending topics, read feeds and lists, analyze and categorize accounts. Supports authenticated access for personalized feeds. Use for Bluesky research, user monitoring, trend analysis, feed reading, firehose sampling, account categorization.

building-github-indexSkill

Generate progressive disclosure indexes for GitHub repositories to use as Claude project knowledge. Use when setting up projects referencing external documentation, creating searchable indexes of technical blogs or knowledge bases, combining multiple repos into one index, or when user mentions "index", "github repo", "project knowledge", or "documentation reference".

categorizing-bsky-accountsSkill

Analyze and categorize Bluesky accounts by topic using keyword extraction. Use when users mention Bluesky account analysis, following/follower lists, topic discovery, account curation, or network analysis.