Star 历史趋势
数据来源: GitHub API · 生成自 Stargazers.cn
README.md

markit

Convert anything to markdown. PDF, DOCX, PPTX, XLSX, HTML, EPUB, Jupyter, RSS, images, audio, URLs, and more. Pluggable converters, built-in LLM providers for image description and audio transcription. Works as a CLI and as a library.

npm install -g markit-ai

Quick Start

# Documents markit report.pdf markit document.docx markit slides.pptx # Data markit data.csv markit config.json markit schema.yaml # Web markit https://example.com/article markit https://en.wikipedia.org/wiki/Markdown # Media (via LLMs. set OPENAI_API_KEY or ANTHROPIC_API_KEY) markit photo.jpg # EXIF metadata + AI description markit recording.mp3 # Audio metadata + transcription markit photo.jpg -p "Extract all text" # Custom instructions # Write to file markit report.pdf -o report.md # Pipe it markit report.pdf | pbcopy markit data.xlsx -q | napkin create "Imported Data"

Supported Formats

FormatExtensionsHow
PDF.pdfText extraction via unpdf
Word.docxmammoth → turndown, preserves headings/tables
PowerPoint.pptxXML parsing, slides + notes + tables
Excel.xlsxEach sheet → markdown table
HTML.html .htmturndown, scripts/styles stripped
EPUB.epubSpine-ordered chapters, metadata header
Jupyter.ipynbMarkdown cells + code + outputs
RSS/Atom.rss .atom .xmlFeed items with dates and content
CSV/TSV.csv .tsvMarkdown tables
JSON.jsonPretty-printed code block
YAML.yaml .ymlCode block
XML/SVG.xml .svgCode block
Images.jpg .png .gif .webpEXIF metadata + optional AI description
Audio.mp3 .wav .m4a .flacMetadata + optional AI transcription
ZIP.zipRecursive. converts each file inside
URLshttp:// https://Fetches with Accept: text/markdown
Wikipedia*.wikipedia.orgMain content extraction
Code.py .ts .go .rs ...Fenced code block
Plain text.txt .md .rst .logPass-through

Need more? Write a plugin.


AI Features

Images and audio get metadata extraction for free. For AI-powered descriptions and transcription, set an API key:

# OpenAI (default provider) export OPENAI_API_KEY=sk-... markit photo.jpg # Anthropic markit config set llm.provider anthropic export ANTHROPIC_API_KEY=sk-ant-... markit photo.jpg # Any OpenAI-compatible API (Ollama, Groq, Together, etc.) markit config set llm.apiBase http://localhost:11434/v1

Focus the AI on what matters:

markit receipt.jpg -p "List all line items with prices as a table" markit diagram.png -p "Describe the architecture and data flow" markit whiteboard.jpg -p "Extract all text verbatim"

Plugins

Extend markit with new formats, override builtins, or add LLM providers.

Install

markit plugin install npm:markit-plugin-dwg markit plugin install git:github.com/user/markit-plugin-ocr markit plugin install ./my-plugin.ts markit plugin list markit plugin remove dwg

Write a Plugin

A plugin is a function that receives an API and registers converters and/or providers:

import type { MarkitPluginAPI } from "markit-ai"; export default function(api: MarkitPluginAPI) { api.setName("cad"); api.setVersion("1.0.0"); // Register a converter for a new format api.registerConverter( { name: "dwg", accepts: (info) => [".dwg", ".dxf"].includes(info.extension || ""), convert: async (input, info) => { // Your conversion logic return { markdown: "..." }; }, }, // Optional: declare the format so it shows in `markit formats` { name: "AutoCAD", extensions: [".dwg", ".dxf"] }, ); }

Plugin converters run before builtins. so you can override any format:

export default function(api: MarkitPluginAPI) { api.setName("better-pdf"); // This replaces the built-in PDF converter api.registerConverter({ name: "pdf", accepts: (info) => info.extension === ".pdf", convert: async (input, info) => { // Your superior PDF extraction return { markdown: "..." }; }, }); }

Plugins can also register LLM providers:

api.registerProvider({ name: "gemini", envKeys: ["GOOGLE_API_KEY"], defaultBase: "https://generativelanguage.googleapis.com/v1beta", defaultModel: "gemini-2.0-flash", create: (config, prompt) => ({ describe: async (image, mime) => { /* ... */ }, }), });

For Agents

Every command supports --json. Raw markdown with -q.

markit report.pdf --json # Structured output for parsing markit report.pdf -q # Raw markdown, nothing else markit onboard # Add instructions to CLAUDE.md

SDK

markit is also a library:

import { Markit } from "markit-ai"; const markit = new Markit(); const { markdown } = await markit.convertFile("report.pdf"); const { markdown } = await markit.convertUrl("https://example.com"); const { markdown } = await markit.convert(buffer, { extension: ".docx" });

With AI features. pass plain functions, use any provider:

import OpenAI from "openai"; import { Markit } from "markit-ai"; const openai = new OpenAI(); const markit = new Markit({ describe: async (image, mime) => { const res = await openai.chat.completions.create({ model: "gpt-4.1-nano", messages: [{ role: "user", content: [ { type: "text", text: "Describe this image." }, { type: "image_url", image_url: { url: `data:${mime};base64,${image.toString("base64")}` } }, ]}], }); return res.choices[0].message.content ?? ""; }, transcribe: async (audio, mime) => { const res = await openai.audio.transcriptions.create({ model: "gpt-4o-mini-transcribe", file: new File([audio], "audio.mp3", { type: mime }), }); return res.text; }, });

Mix providers. Claude for vision, OpenAI for audio, whatever:

const markit = new Markit({ describe: async (image, mime) => { const res = await anthropic.messages.create({ model: "claude-haiku-4-5", messages: [{ role: "user", content: [ { type: "image", source: { type: "base64", media_type: mime, data: image.toString("base64") } }, { type: "text", text: "Describe this image." }, ]}], }); return res.content[0].text; }, transcribe: async (audio, mime) => { /* Whisper, Deepgram, AssemblyAI, ... */ }, });

Or use the built-in providers. no SDK needed:

import { Markit, createLlmFunctions, loadConfig } from "markit-ai"; const config = loadConfig(); // reads .markit/config.json + env vars const markit = new Markit(createLlmFunctions(config));

With plugins:

import { Markit, createLlmFunctions, loadConfig, loadAllPlugins } from "markit-ai"; const config = loadConfig(); const plugins = await loadAllPlugins(); const markit = new Markit(createLlmFunctions(config), plugins);

Configuration

markit init # Create .markit/config.json markit config show # Show resolved settings markit config get llm.model # Get a value markit config set llm.provider anthropic # Switch provider markit config set llm.apiKey sk-... # Set a value

.markit/config.json:

{ "llm": { "provider": "openai", "apiBase": "https://api.openai.com/v1", "apiKey": "sk-...", "model": "gpt-4.1-nano", "transcriptionModel": "gpt-4o-mini-transcribe" } }

Env vars override config. Each provider checks its own env vars first:

ProviderEnv varsDefault model
openaiOPENAI_API_KEY, MARKIT_API_KEYgpt-4.1-nano
anthropicANTHROPIC_API_KEY, MARKIT_API_KEYclaude-haiku-4-5

CLI Reference

markit <source> # Convert file or URL markit <source> -o output.md # Write to file markit <source> -p "instructions" # Custom AI prompt markit <source> --json # JSON output markit <source> -q # Raw markdown only cat file.pdf | markit - # Read from stdin markit formats # List supported formats markit init # Create .markit/ config markit config show # Show settings markit config get <key> # Get config value markit config set <key> <value> # Set config value markit plugin install <source> # Install plugin markit plugin list # List plugins markit plugin remove <name> # Remove plugin markit onboard # Add to CLAUDE.md

Development

bun install bun run dev -- report.pdf bun test bun run check

License

MIT

关于 About

🖍️ Convert anything to markdown. Mark it.

语言 Languages

TypeScript93.0%
Shell4.8%
JavaScript2.2%

提交活跃度 Commit Activity

代码提交热力图
过去 52 周的开发活跃度
66
Total Commits
峰值: 52次/周
Less
More

核心贡献者 Contributors