Local-first document-to-Markdown converter. File content is processed entirely in-process — nothing leaves your machine. Supports 8 input formats and 8 output flavours, with optional URL extraction and batch mode for premium users.
Key differentiator vs alternatives: Output flavours tailor Markdown to specific platforms (Slack *bold* vs GitHub **bold**, Confluence wiki markup, R Markdown, etc.). No other converter offers this.
bash
npm install -g formatferry
FormatExtensionNotesHTML.html, .htmWeb pages, snippetsWord.docxMicrosoft Word documentsPDF.pdfIncluding OCR for scanned documentsExcel.xlsxSpreadsheets with tablesCSV.csvComma-separated dataJSON.jsonStructured dataXML.xmlMarkup and data feedsPowerPoint.pptxSlide content
Use the -f / --flavour flag to select output format:
github (default) — GitHub Flavored Markdowncommonmark — Standard CommonMarkslack — Slack-compatible markdowndiscord — Discord-compatible markdownreddit — Reddit-compatible markdownconfluence — Confluence wiki markuprmarkdown — R Markdowncustom — Custom formatbash
# Convert a file
formatferry -i document.docx -o output.md
# Pipe HTML from stdin
echo '<h1>Hello</h1>' | formatferry
# Choose a flavour
formatferry -i notes.html -f slack -o notes.md
# Convert a PDF (includes OCR for scanned documents)
formatferry -i paper.pdf -o paper.md
# URL extraction (requires FORMATFERRY_API_KEY)
formatferry --url https://example.com/article -o article.md
# Batch convert (requires FORMATFERRY_LICENSE_KEY)
formatferry --batch "docs/**/*.docx" --output-dir ./markdown/
Both environment variables are optional. The CLI works for local file conversion with zero credentials.
VariableRequiredPurposeFORMATFERRY_API_KEYNoNeeded only for --url flag (URL extraction). Not needed for local file conversion.FORMATFERRY_LICENSE_KEYNoNeeded only for --batch mode (premium feature).
Set them via your shell profile or pass inline:
bash
FORMATFERRY_API_KEY=ff_xxxxx formatferry --url https://example.com/article
formatferry.vibingfun.com to check entitlement (cached for 24h, skippable with --offline)--url) is the only feature that sends content to a server — it fetches and processes the URL server-side--offline flag disables all network calls, falling back to cached or free-tier entitlementsDetermine input type:
-i <path>--url <url> (requires FORMATFERRY_API_KEY)--batch (requires FORMATFERRY_LICENSE_KEY)Execute conversion: bash
# Stdin (most common for agent use)
echo "$INPUT" | formatferry
# File
formatferry -i "$FILE_PATH" -o "$OUTPUT_PATH"
# URL
formatferry --url "$URL" -o output.md
Capture output:
-o <file> to write directly to fileReturn clean Markdown to user
Clean up temp files if created
IssueSolutionformatferry: command not foundInstall via npm install -g formatferry``node: command not foundInstall Node.js 18+ firstAPI rate limit hitWait 60s or use local file input instead of URLLarge file (>20MB PDF)Consider splitting before conversionInvalid URLVerify URL starts with http:// or https://Empty outputVerify input has content; check for HTML entity encoding issues
bash
# Test basic conversion
echo '<h1>Test</h1><p>Content</p>' | formatferry
# Verify no HTML tags remain
echo '<div>test</div>' | formatferry | grep -c '<.*>' || echo "Clean: 0 HTML tags"
# Test file conversion
echo '<p>File test</p>' > /tmp/test.html
formatferry -i /tmp/test.html