Converts PDF, DOCX, XLSX, PPTX, HTML, CSV, and other files to Markdown using the @covoyage/file2md CLI (@covoyage/file2md). Use when the user needs office do...
Documents
iwork2md
Try itConvert Apple iWork documents (Pages .pages, Numbers .numbers, Keynote .key) into Markdown. Use whenever the user wants to read, extract, or translate the content of an iWork file into text/markdown, for example 'convert this .pages file to markdown', 'extract text from a Numbers sheet', 'read a Keynote file', or 'open a .key/.numbers/.pages and turn it into markdown'. Handles the iWork '13+ format (bundle containing Index.zip with .iwa files that wrap Snappy-framed Protobuf) with no third-party dependencies.
What it does
Convert Apple iWork documents (Pages .pages, Numbers .numbers, Keynote .key) into Markdown. Use whenever the user wants to read, extract, or translate the content of an iWork file into text/markdown, for example 'convert this .pages file to markdown', 'extract text from a Numbers sheet', 'read a Keynote file', or 'open a .key/.numbers/.pages and turn it into markdown'. Handles the iWork '13+ format (bundle containing Index.zip with .iwa files that wrap Snappy-framed Protobuf) with no third-party dependencies.
The skill document
iwork2md — iWork (.pages / .numbers / .key) to Markdown
Convert Apple Pages / Numbers / Keynote documents to Markdown. The parser is in
scripts/iwa.py (pure stdlib); the converter CLI is scripts/iwork2md.py.
When to use
- User provides a
.pages,.numbers, or.keyfile and wants its text, tables, or slides as Markdown (or just to read the content). - User asks to "extract text / convert / translate / open" an iWork file.
- Do NOT use for: password-protected/encrypted iWork docs (unsupported), or for reconstructing exact visual layout (not the goal).
How to run
# Write a .md next to the source (auto-named)
python3 scripts/iwork2md.py path/to/Doc.pages
# Explicit output path
python3 scripts/iwork2md.py Doc.numbers out.md
# Print to stdout
python3 scripts/iwork2md.py Doc.key --stdout
# Debug: dump every recovered text fragment
python3 scripts/iwork2md.py Doc.numbers --texts
# List embedded media (images/video)
python3 scripts/iwork2md.py Doc.pages --media
From inside a chat, invoke with exec (or tell the user to run it). The script
is dependency-free (Python 3.8+, stdlib only: zipfile, struct, io,
plistlib).
What it does
- Opens the bundle ZIP; finds
Index.zip(or.iwafiles directly underIndex/). - For each
.iwa: removes the iWork Snappy framing (chunk type + 3-byte LE length, no stream-id, no CRC), then raw-Snappy-decompresses the body. - Parses the Protobuf container (
varint len + ArchiveInfo {identifier, message_infos[]}then payloads), and generically walks every message to collect UTF-8 string fields — recovering ~100% of readable content without needing the app-specific schema map (TSPRegistry). - Renders Markdown: document title (from
Metadata/Properties.plistor first heading), an embedded-media list, reconstructed Numbers tables (rows stored as"a | b | c"become proper markdown tables, deduped across mirrored components), a body block (largest multi-line text), and remaining text fragments.
Key facts you need (so you don't re-derive them)
- iWork
.iwaSnappy framing is non-standard: type byte0x00, 3-byte LE length, then a raw Snappy block (NOT an official framed stream). No stream-identifier chunk, no CRC. (iwa.iwa_unframe) - Raw Snappy: uncompressed-length varint, then LZ77 (literals + copies). Copies
have 1/2/4-byte offsets. (
iwa.snappy_decompress) - Payload
typeids map to schemas inside the iWork binaries and vary by app/version — Protobuf is not self-describing, so we decode generically by string fields. Seereferences/FORMAT.mdfor the full spec and limits. - Numbers table rows serialize as a single
"cell | cell | cell"string per row → the CLI groups consecutive such rows into a markdown table.
Output quality & limits
- ✅ Recovers all text, Numbers table structure, slide text, media inventory.
- ❌ No exact layout/fonts/colors/merged-cell geometry/charts/shapes.
- ❌ Encrypted (password-locked) documents are not readable.
- If a user needs perfect structural fidelity, note that it requires extracting the TSPRegistry type map for their iWork version; the generic walker here is the reliable, dependency-free fallback.
Testing / validating
scripts/test_iwa.py round-trips a synthetic .iwa (encoder + parser) to prove
the Snappy framing, raw-Snappy copy path, and Protobuf container logic. Run:
python3 scripts/test_iwa.py.
Related skills
Convert Word (.doc, .docx), PowerPoint (.ppt, .pptx), Excel (.xls, .xlsx), OpenDocument (.odt, .ods, .odp), RTF, EPUB, CSV, and PDF files to GitHub-Flavored Markdown. Use when a task needs the contents of an office document, spreadsheet, presentation, ebook, or PDF you cannot read directly.
Convert unstructured documents into LLM-ready structured data. Supports PDF, Word, PPT, and images; extracts paragraphs, formulas, tables, charts, and other...
Convert Markdown to DOCX, PDF, PPTX, XLSX, JSON and more from the command line.
Use when a NON-multimodal agent (a text-only LLM backend that cannot read attachments) receives a document — PDF, Word (docx), PowerPoint (pptx), Excel (xlsx...
Convert supported documents into Markdown for agent-side reading, with local output and optional image-preserving packages.