Our review
Create, validate, query, update, and convert EPUB files using local CLI tools, targeting EPUB 3 standard.
Strengths
- Leverages powerful local tools (pandoc, epubcheck) with no cloud dependency
- Comprehensive EPUB 3 validation and conversion to/from many formats
- Ability to inspect and modify EPUB metadata and internal structure
Limitations
- Requires manual installation of pandoc, epubcheck, and other dependencies
- Only works with local files, no native cloud integration
- Conversion from other formats limited to pandoc's supported inputs
Use when you need to produce a standards-compliant EPUB 3 from Markdown or HTML, or validate/fix existing EPUB files.
Avoid for Kindle-only formats (MOBI/AZW3) or general file conversion that doesn't involve EPUB.
Security analysis
SafeThe skill uses only local, well-known CLI tools (pandoc, epubcheck, unzip, Python, uv) with no destructive or exfiltrating commands. All operations are standard EPUB file manipulations and validations. No obfuscated payloads, network requests, or dangerous shell commands are suggested.
No concerns found
Examples
Create an EPUB 3 file from my notes.md using pandoc with -t epub3, include a cover image cover.jpg and a metadata file metadata.yamlValidate the file book.epub using epubcheck with --json output and show any errorsConvert this EPUB 2 file old.epub to EPUB 3 using pandoc with -t epub3name: epub description: > Use local CLI tools to create, validate, query, update, and convert EPUB files. All output targets EPUB 3 (the current W3C standard, EPUB 3.3). Use when the user mentions EPUB, e-book, ebook, "create an epub", "validate epub", "check epub", "epub metadata", "convert to epub", "convert from epub", "update epub", "modify epub", "inspect epub", "epub table of contents", "epub cover", "upgrade epub", "epub version", "epub 3", or any task involving .epub files. Also trigger when the user wants to package HTML or Markdown content as an e-book, extract content from an EPUB, fix EPUB validation errors, or convert an older EPUB 2 file to EPUB 3. Do NOT use for PDF-only workflows, Kindle-only formats (MOBI/AZW3), or general file conversion that does not involve EPUB. allowed-tools:
- Read
- Write
- Edit
- Bash
- Glob
- Grep
EPUB Skill
Work with EPUB files using local command-line tools. All operations target EPUB 3 (the current W3C standard, EPUB 3.3). EPUB files are ZIP archives containing XHTML5 content, metadata, and navigation documents.
When working with older EPUB 2 files, convert them to EPUB 3 — see the conversion section below.
Prerequisites
Check tool availability before proceeding. Run epubcheck --help and pandoc --help to
confirm available options — these tools evolve and their capabilities should be verified rather
than assumed.
- pandoc — create and convert EPUBs (required; install via
brew install pandoc). Supports three EPUB output formats:epub(defaults to EPUB 3),epub2, andepub3. Always use-t epub3explicitly to ensure EPUB 3 output. - epubcheck — validate EPUB conformance (recommended; install via
brew install epubcheck). Validates against EPUB 3 by default. Supports JSON output (--json), profile-based validation (--profile), and individual file validation (--mode). - unzip / zipinfo — inspect EPUB internals (built-in on macOS)
- Python 3 — run helper scripts for metadata extraction and modification
- uv — runs
epub_metadata.py; itsrdflibdependency is declared inline (PEP 723) and provisioned automatically byuv run(install viabrew install uv)
If a required tool is missing, inform the user and provide the install command.
EPUB 3 Requirements
EPUB 3 content must meet these requirements (epubcheck enforces all of them):
- Package document (OPF) version attribute must be
"3.0" - Navigation document — an XHTML file with
properties="nav"in the manifest, containing a<nav epub:type="toc">element. This replaces the EPUB 2 NCX as the required navigation mechanism (NCX may be included for backward compatibility but is not required). - Content documents use XHTML5 (not XHTML 1.1), with
xmlns="http://www.w3.org/1999/xhtml" - Required metadata —
dc:identifier,dc:title,dc:language, and a<meta property="dcterms:modified">timestamp - Manifest items may use
propertiesattribute for semantic roles (nav,cover-image,mathml,svg,scripted, etc.)
Read references/epub-structure.md for the full EPUB 3 structure specification.
Core Operations
1. Create an EPUB 3
Use pandoc with -t epub3 to create EPUB 3 files from Markdown, HTML, or other supported formats.
# Basic creation from Markdown
pandoc input.md -t epub3 -o output.epub
# With metadata — keep metadata in a file (see the YAML example below), not
# inline --metadata flags. A file is reusable and version-controllable, avoids
# shell-quoting bugs in titles and descriptions, and is the only practical way
# to express lists (multiple authors, subjects) or an identifier with a scheme.
pandoc input.md -t epub3 -o output.epub --metadata-file=metadata.yaml
# With cover image, CSS, and table of contents
# --toc generates an EPUB 3 nav document from headings in the source
# --toc-depth controls how many heading levels appear (default: 3)
pandoc input.md -t epub3 -o output.epub \
--epub-cover-image=cover.jpg \
--css=style.css \
--toc --toc-depth=2
# From multiple source files (chapters)
# --split-level=N splits output into separate XHTML files at heading level N
# (older pandoc spells this --epub-chapter-level; run `pandoc --help` if unsure)
# --top-level-division=chapter treats top-level headings as chapters (vs. sections or parts)
pandoc ch01.md ch02.md ch03.md -t epub3 -o output.epub \
--metadata-file=metadata.yaml \
--epub-cover-image=cover.jpg \
--toc \
--split-level=1 \
--top-level-division=chapter
Define the metadata in a YAML file. Pandoc maps these fields to the EPUB's Dublin
Core metadata in the OPF — including lists (each author becomes a dc:creator
with a role, each subject a dc:subject) and an identifier with a scheme,
none of which can be expressed with repeated --metadata flags:
---
title: Book Title
author:
- First Author
- Second Author
date: 2026-01-01
lang: en-US
publisher: Publisher Name
rights: All rights reserved
subject:
- Fiction
- Adventure
identifier:
- scheme: ISBN
text: 978-0-000-00000-0
description: A brief description of the book.
---
Pass it with --metadata-file=metadata.yaml. Pandoc adds the required
dcterms:modified timestamp automatically.
2. Validate an EPUB
Use epubcheck to validate against the EPUB 3 specification:
# Full validation (EPUB 3 by default)
epubcheck book.epub
# Machine-readable JSON output for programmatic analysis
epubcheck book.epub --json results.json
# Validate with usage information (shows EPUB features used)
epubcheck book.epub --usage
# Fail on warnings too (stricter validation)
epubcheck book.epub --failonwarnings
Always validate after creating or modifying an EPUB. When fixing validation errors, parse the output systematically — fix errors before warnings, and re-validate after each round of fixes.
Common EPUB 3 validation issues:
- Missing
dcterms:modified— Add<meta property="dcterms:modified">to metadata - Missing nav document — Ensure an XHTML file with
properties="nav"exists in the manifest - Missing alt text — Add
altattributes to all<img>tags - Invalid XHTML5 — Ensure all tags are properly closed and content is well-formed XML
- Missing required metadata — Add
dc:identifier,dc:title,dc:languageto the OPF
3. Query EPUB Contents
EPUBs are ZIP archives. Inspect them directly:
# List all files in the EPUB
zipinfo -1 book.epub
# Extract the OPF (package) file to read metadata and check EPUB version
unzip -p book.epub OEBPS/content.opf 2>/dev/null || unzip -p book.epub content.opf 2>/dev/null
# Extract the EPUB 3 navigation document
unzip -p book.epub OEBPS/toc.xhtml 2>/dev/null
# Extract a specific chapter
unzip -p book.epub OEBPS/ch01.xhtml
For structured metadata extraction (including version detection), use the helper script:
uv run --no-project scripts/epub_metadata.py book.epub
The script reports the EPUB version, which is useful for identifying files that need conversion
to EPUB 3. Add --json for machine-readable JSON-LD output with Dublin Core vocabulary (dc:
and dcterms: terms):
# Full output (metadata, manifest, spine, TOC, file list)
uv run --no-project scripts/epub_metadata.py book.epub --json
# Concise summary (metadata + version only) — prefer this to manage context window
uv run --no-project "$SKILL_DIR/epub_metadata.py" book.epub --json \
| jq '{metadata, version, toc_type, file_count}'
# Full output to file for round-trip editing
uv run --no-project "$SKILL_DIR/epub_metadata.py" book.epub --json > metadata.json
Prefer jq filtering or file redirect over raw --json output to keep the context window
manageable. The full output includes manifest, spine, and file list which are rarely needed
for metadata operations.
Use pandoc to convert an EPUB back to readable text:
# Extract as Markdown
pandoc book.epub -t markdown -o output.md
# Extract as plain text
pandoc book.epub -t plain -o output.txt
# Extract as HTML
pandoc book.epub -t html -o output.html
4. Update an EPUB
EPUBs can be modified by extracting, editing, and repackaging:
# Use the helper script for metadata updates
python3 scripts/epub_update.py book.epub --title "New Title" --author "New Author"
# Round-trip: extract metadata as JSON-LD, edit, and apply back
uv run --no-project scripts/epub_metadata.py book.epub --json > meta.json
# ... edit meta.json ...
python3 scripts/epub_update.py book.epub --metadata-file meta.json
# CLI flags override file values
python3 scripts/epub_update.py book.epub --metadata-file meta.json --title "Override Title"
# Manual approach: extract, edit, repack
mkdir -p epub_work && cd epub_work
unzip ../book.epub
# ... edit files ...
# Repack (mimetype must be first, uncompressed)
zip -X0 ../updated.epub mimetype
zip -Xr9D ../updated.epub * -x mimetype
The repackaging order matters — mimetype must be the first entry and stored without compression.
5. Convert To/From EPUB 3
Use pandoc for format conversion. Always use -t epub3 when outputting EPUB.
# EPUB to other formats
pandoc book.epub -o book.pdf
pandoc book.epub -o book.docx
pandoc book.epub -o book.html
# Other formats to EPUB 3
pandoc document.docx -t epub3 -o book.epub
pandoc page.html -t epub3 -o book.epub
pandoc paper.tex -t epub3 -o book.epub
6. Convert EPUB 2 to EPUB 3
Pandoc reads EPUB 2 files natively and can output EPUB 3, handling the structural conversion automatically — upgrading the navigation from NCX to an XHTML nav document, converting content from XHTML 1.1 to XHTML5, and adding the required EPUB 3 metadata.
# Convert EPUB 2 to EPUB 3 (always work on a copy)
pandoc old_book.epub -t epub3 -o new_book.epub
# Regenerate the EPUB 3 nav document from headings (useful if the original TOC is sparse)
pandoc old_book.epub -t epub3 -o new_book.epub \
--toc --toc-depth=2
# Override metadata when the input is an EPUB: do NOT pass metadata to pandoc.
# Pandoc keeps the metadata embedded in an EPUB source — a --metadata-file is
# ignored entirely, and inline --metadata only partially applies (title changes,
# language does not). Convert the structure with pandoc first, then edit metadata
# with epub_update.py, which rewrites the OPF directly.
pandoc old_book.epub -t epub3 -o new_book.epub
python3 scripts/epub_update.py new_book.epub --title "Updated Title" --language en-GB
# epub_update.py also accepts --metadata-file for a saved set of fields (see Update).
After conversion, always validate the result:
epubcheck new_book.epub
If epubcheck reports errors, fix them and re-validate. Common post-conversion issues:
- Deprecated attributes — Remove EPUB 2-era attributes that are not valid in EPUB 3
(e.g.,
alignon elements — use CSS instead) - NCX-only navigation — Pandoc should generate the EPUB 3 nav document automatically,
but verify it exists in the output (
zipinfo -1 new_book.epub | grep -i nav) - Missing
dcterms:modified— Pandoc adds this, but if updating metadata manually, ensure it is present - Empty
<dc:date>— Converting from an EPUB can leave an empty<dc:date>element (pandoc drops the source's date value), which epubcheck rejects asRSC-005. Set a valid date —python3 scripts/epub_update.py new_book.epub --date 2026-01-01— or remove the element entirely, sincedc:dateis optional in EPUB 3.
For batch conversion of multiple files:
for f in *.epub; do
pandoc "$f" -t epub3 -o "epub3_${f}"
epubcheck "epub3_${f}"
done
Detecting EPUB Version
Before converting, check whether a file is already EPUB 3:
# Quick version check via the OPF package document
unzip -p book.epub OEBPS/content.opf 2>/dev/null | grep -o 'version="[^"]*"'
# Or use the metadata script for a full report
uv run --no-project scripts/epub_metadata.py book.epub
If the version is "3.0" or higher, conversion is not needed — just validate with epubcheck.
Helper Scripts
Two Python helper scripts are bundled in the scripts/ directory of this skill.
epub_metadata.py declares its rdflib dependency inline (PEP 723), so running it with
uv run provisions rdflib automatically — no separate install. epub_update.py uses only
the Python 3 standard library, so it runs under plain python3.
scripts/epub_metadata.py <file.epub> [--json]— Extract and display all metadata, TOC structure, spine order, and manifest contents from an EPUB file. Reports the EPUB version. With--json, outputs JSON-LD using Dublin Core vocabulary.scripts/epub_update.py <file.epub> [options]— Modify EPUB metadata, replace the cover image, or inject/remove files. Accepts--metadata-filefor JSON-LD input (as produced byepub_metadata.py --json). Run with--helpfor full usage.
When running these scripts, use the full path relative to this skill's installation directory. Locate the skill directory first:
# Find the skill directory
SKILL_DIR=$(find ~/.claude -path "*/skill-epub/scripts" -type d 2>/dev/null | head -1)
# Run a script
uv run --no-project "$SKILL_DIR/epub_metadata.py" book.epub
EPUB Structure Reference
Read references/epub-structure.md for detailed information about the EPUB 3 format internals,
including the container layout, OPF package document, navigation documents, and content
document requirements.
Workflow Guidelines
- Always use
-t epub3when creating or converting EPUBs with pandoc. - When creating or converting into EPUB from Markdown, HTML, etc., pass metadata to
pandoc through a
--metadata-file(YAML), never inline--metadataflags — a file is reusable and auditable, sidesteps shell-quoting issues, and is the only clean way to express multi-valued fields (several authors or subjects) and an identifier with a scheme. To change the metadata of an existing EPUB, useepub_update.py(which also takes a--metadata-file); pandoc does not reliably override metadata embedded in an EPUB input. - Always validate after creating or modifying an EPUB with
epubcheck. - When encountering an EPUB 2 file, convert it to EPUB 3 using pandoc before further processing.
- When the user provides content to convert, prefer Markdown as the intermediate format — pandoc handles it cleanly.
- For multi-chapter books, recommend one Markdown file per chapter with a metadata YAML file.
- When modifying an existing EPUB, always work on a copy — never modify the original in place.
- If an EPUB fails validation, use
epubcheck book.epub --json results.jsonfor structured error output, then fix issues systematically starting with errors before warnings.
Content Repurposer
Content
Transforms a single piece of content into platform-adapted publications.
SEO Blog Post Writer
Content
Writes SEO-optimized blog posts with proper structure and keywords.
YouTube Script Writer
Content
Writes engaging YouTube scripts with hooks, structure, and retention.