epub2md CLI
Use this skill to operate on local EPUB files with epub2md instead of hand-rolling parsing logic.
Bundled script
For any conversion that writes files, use the bundled wrapper script:
/home/admin1/.agents/skills/epub2md-cli/scripts/run_epub2md.py
The wrapper exists to enforce a stable workspace layout and avoid epub2md 1.6.2 merge-path quirks.
One more epub2md 1.6.2 quirk: source filenames containing glob metacharacters such as [ ] ? or * can still be treated as patterns by epub2md, even when the shell path was quoted correctly. When that happens, keep the original EPUB in inputs/, but stage a temporary safe basename such as book.epub before calling raw epub2md, then copy the generated book/ directory into the expected workspace output folder.
What epub2md is good at
- Inspecting book metadata with
--info
- Inspecting table of contents and nesting with
--structure
- Listing sections/chapters with
--sections
- Converting an EPUB into chapter-by-chapter Markdown files
- Merging an EPUB into one Markdown file, preferably with an explicit output name
- Merging an existing Markdown directory with plain
--merge
- Downloading remote images referenced by the EPUB with
--localize
- Unzipping EPUB contents for inspection with
--unzip
- Batch conversion with quoted glob patterns like
"books/*.epub"
Prerequisites
Check the command first:
command -v epub2md
If it is missing and the environment allows installs, install it with npm:
npm install -g epub2md
If --localize is needed, make sure Node.js is at least 18.0.0.
Workspace layout
By default, write conversion jobs to:
/home/admin1/.agents/skills/epub2md-cli-workspace/{bookname}
Within that directory:
inputs/ contains the original EPUB file
outputs/ contains conversion results
outputs/split/ contains chapter-by-chapter Markdown output
outputs/merge/ contains merged Markdown output and related assets
outputs/inspect/ contains saved inspection results when the user explicitly asks for inspection output
Do not write conversion output next to the user's source EPUB unless they explicitly ask for a different layout.
Working style
-
Start from the user's real goal, not from the default conversion.
- If they only want metadata or structure, do not convert the book.
- Inspection is opt-in only. Do not run it unless the user explicitly asked to inspect the EPUB.
- If they want one final Markdown file from an EPUB, use merge mode.
- If they want chapter files, use split mode.
-
Confirm the source path before running commands.
- Prefer exact paths the user already gave you.
- If they referred to "that epub in this folder", discover it with shell tools such as
rg --files -g '*.epub'.
- Quote paths and glob patterns when they contain spaces or wildcard characters.
- Quoting is necessary but not sufficient when the EPUB basename itself contains
[ ] ? or *; epub2md may still interpret the basename as a glob internally.
-
If the user asked for conversion but did not specify the output shape, ask one short clarifying question before writing files.
- Ask whether they want
多个文件、只要 merge 文件、or 都转换.
- Do not guess between split and merge when the user clearly cares about the output form.
-
Use the wrapper script for any file-writing conversion task.
- Do not call
epub2md directly for split/merge/both output jobs unless the user explicitly asked for raw CLI invocation.
- The wrapper copies the original EPUB into
inputs/ and writes results into outputs/.
- The wrapper always uses a safe merge invocation and should not produce a stray
home/ directory.
- If conversion still fails with
No files found matching pattern: or a wrapper FileNotFoundError caused by a glob-like source basename, fall back to safe-basename staging: copy the EPUB into a temp directory as book.epub, run raw epub2md there, then copy the generated book/ directory back into outputs/merge/ or outputs/split/.
-
After the command finishes, report concrete outputs.
- Say which command you ran.
- Say where the generated files were written.
- Mention any limitations, such as remote images not being localized unless
--localize was used.
-
Treat --sections as an inspection tool, not a default user-facing output.
- In
epub2md 1.6.2, --sections prints very large objects with raw HTML.
- Use it when you need deep inspection.
- Summarize the findings for the user unless they explicitly asked for the raw dump.
Command selection
Inspect only
epub2md --info "/path/to/book.epub"
epub2md --structure "/path/to/book.epub"
epub2md --sections "/path/to/book.epub"
epub2md --unzip "/path/to/book.epub"
python3 /home/admin1/.agents/skills/epub2md-cli/scripts/run_epub2md.py \
--input "/path/to/book.epub" \
--mode inspect
python3 /home/admin1/.agents/skills/epub2md-cli/scripts/run_epub2md.py \
--input "/path/to/book.epub" \
--mode inspect \
--inspect-actions info structure sections
Use these only when the user explicitly wants to understand the book before deciding how to export it.
Convert into chapter Markdown files
python3 /home/admin1/.agents/skills/epub2md-cli/scripts/run_epub2md.py \
--input "/path/to/book.epub" \
--mode split
python3 /home/admin1/.agents/skills/epub2md-cli/scripts/run_epub2md.py \
--input "/path/to/book.epub" \
--mode split \
--autocorrect
Use --autocorrect when the user explicitly wants spacing or punctuation cleanup in the Markdown output.
Merge into one Markdown file
python3 /home/admin1/.agents/skills/epub2md-cli/scripts/run_epub2md.py \
--input "/path/to/book.epub" \
--mode merge
python3 /home/admin1/.agents/skills/epub2md-cli/scripts/run_epub2md.py \
--input "/path/to/book.epub" \
--mode merge \
--merge-name custom-name.md
Use the custom merged filename form when the user asks for a specific final filename.
Convert both split and merge outputs
python3 /home/admin1/.agents/skills/epub2md-cli/scripts/run_epub2md.py \
--input "/path/to/book.epub" \
--mode both
Localize remote images
python3 /home/admin1/.agents/skills/epub2md-cli/scripts/run_epub2md.py \
--input "/path/to/book.epub" \
--mode split \
--localize
python3 /home/admin1/.agents/skills/epub2md-cli/scripts/run_epub2md.py \
--input "/path/to/book.epub" \
--mode merge \
--merge-name custom-name.md \
--localize
Use this only when the user wants remote images downloaded into the output folder. Mention the Node.js >=18 requirement if needed.
Batch conversion
epub2md "books/*.epub"
epub2md --merge "books/*.epub"
Keep the glob quoted so epub2md receives the pattern directly.
This is a raw CLI fallback for explicit bulk-processing requests. It does not use the per-book workspace layout above. Prefer the bundled wrapper for normal single-book conversion jobs.
Fallback for glob-like EPUB filenames
Use this only when the source basename itself contains [ ] ? or * and the normal wrapper flow fails.
src="/path/to/Book [Annotated].epub"
book_name="Book [Annotated]"
book_dir="/home/admin1/.agents/skills/epub2md-cli-workspace/$book_name"
merge_dir="$book_dir/outputs/merge"
merge_name="$book_name-merged.md"
mkdir -p "$book_dir/inputs" "$merge_dir"
cp "$src" "$book_dir/inputs/"
tmpdir=$(mktemp -d "$book_dir/.manual-merge-XXXXXX")
cp "$src" "$tmpdir/book.epub"
cd "$tmpdir"
epub2md --merge="$merge_name" "book.epub"
cp -a "$tmpdir/book/." "$merge_dir/"
This preserves the normal workspace layout while avoiding epub2md's internal glob matching on the original basename.
Expected outputs
Use these expectations when explaining results:
- The original EPUB is copied to
.../{bookname}/inputs/{bookname}.epub
- Split output is written under
.../{bookname}/outputs/split/
- Merge output is written under
.../{bookname}/outputs/merge/
- Inspection output is written under
.../{bookname}/outputs/inspect/ only when the user asked for inspection
- Chapter Markdown files are typically written as numbered Markdown files
- Many chapter files are named like
NNN-title.md, but fallback names such as NNN-partXXXX.md can also appear
- Images are stored under an
images/ subdirectory inside the relevant output folder
- Merge mode defaults to
{bookname}-merged.md unless the user asked for another filename
Do not claim remote images were downloaded unless --localize was part of the command.
Known quirks
These were validated against epub2md 1.6.2:
--sections is often too verbose to show directly because it includes raw HTML payloads
- Plain
--merge on an absolute EPUB path can generate an awkward nested path and keep the .epub extension on the merged Markdown file
- The bundled wrapper avoids that behavior by never relying on plain
--merge for EPUB merge jobs
- EPUB basenames containing
[ ] ? or * can be interpreted as glob patterns by epub2md itself, even when shell quoting is correct
- The common symptom is
No files found matching pattern: from epub2md, or a wrapper FileNotFoundError because epub2md created book/ while the wrapper expected a directory named after the original book
- The practical workaround is to stage the source EPUB to a safe basename such as
book.epub, run epub2md from that temp directory, then copy the generated book/ contents back into the expected workspace output directory
Response format
Keep the response practical and concrete:
- State the action you took
- Show the exact
epub2md command you ran
- List the output path or paths created
- Mention blockers or caveats, if any
Examples
Example 1: convert to chapter files
User intent: "把 ~/Books/foo.epub 转成多个 markdown 章节。"
Good command:
python3 /home/admin1/.agents/skills/epub2md-cli/scripts/run_epub2md.py \
--input "$HOME/Books/foo.epub" \
--mode split
Example 2: merge and localize
User intent: "把 ~/Books/foo.epub 合成一个 markdown,并把远程图片下载到本地。"
Good command:
python3 /home/admin1/.agents/skills/epub2md-cli/scripts/run_epub2md.py \
--input "$HOME/Books/foo.epub" \
--mode merge \
--merge-name foo.md \
--localize
Example 3: user did not specify split or merge
User intent: "把这个 epub 转成 markdown。"
Good response:
要哪种输出:多个章节文件、只要一个 merge 文件,还是两种都要?
Example 4: inspect only
User intent: "先帮我看看这本书的目录结构,不要导出正文。"
Good command:
python3 /home/admin1/.agents/skills/epub2md-cli/scripts/run_epub2md.py \
--input "/path/to/book.epub" \
--mode inspect