Conversational Markdown Format
Every conversation you have is valuable, whether with an LLM or with other people. It contains decisions, explanations, code, and context that you may need again. But most tools lock these conversations into proprietary formats, vendor-specific exports, or bloated JSON that nobody wants to read.
CMF (Conversational Markdown Format) is a simple, open standard that puts your conversations back in your hands.
CMF defines a straightforward convention for representing conversations in markdown. Any chat application that supports the format can read and write CMF files, making conversations truly portable across tools and vendors.
CMF files are valid markdown. Open them in any text editor, markdown viewer, or note-taking app and they just work. Search with grep, diff with git, edit by hand. No special tools required.
Why Plain Text?
Plain text is the universal interface. CMF files work with grep, sed, awk, and every other Unix tool. Track changes with git. Search across hundreds of conversations with ripgrep. Process them programmatically, feed them to other models, or move them between clients and agents. Your conversations stay portable across tools, vendors, and time.
For example, generate a report from past conversations with a single command:
cat project-*.cmf | claude -p "Summarize the key decisions made"
Chat Clients as File Editors
The vision for CMF is simple: chat applications should operate as file editors. When you start a conversation, the client creates a CMF file. When you send a message, it appends to that file. When the other party responds, it appends to that file. The file is the conversation.
If every chat client—whether CLI, desktop app, or web interface—reads and writes the same CMF format, conversations become truly portable. Start a chat in one tool, continue it in another. Switch clients without losing history. Your conversations live in your filesystem, not in someone else's database.
And while the tooling here focuses on LLM conversations, CMF works for any dialogue. Human-to-human chats, interview transcripts, support tickets, meeting notes—any conversation with turns can be expressed as CMF.
This also means you can edit conversations by hand. Fix a typo, redact sensitive information, or merge two related chats—it's just text.
Format
User messages are blockquotes (>). Everything else is assistant content. That's it.
CMF
> What is 2+2?
The answer is 4.
> Thanks!
You're welcome.
JSON (OpenAI Chat)
[
{"role": "user", "content": "What is 2+2?"},
{"role": "assistant", "content": "The answer is 4."},
{"role": "user", "content": "Thanks!"},
{"role": "assistant", "content": "You're welcome."}
]
Rules
- User lines start with
>in column 1 - Multi-user chats use
> @username:prefix - Assistant content is everything between user blocks
- Indent blockquotes (
> text) to escape them in assistant content - Files use
.cmfextension — CMF is valid CommonMark
Reference Implementation
The CLI and Rust library below are reference implementations. Use them directly, or build your own parser—the format is simple enough to implement in an afternoon.
CLI
# Install
git clone https://github.com/Sector-F-Labs/conversational-markdown-format.git
cargo install --path conversational-markdown-format
# Detect CMF and count turns
cmf detect conversation.cmf
# Check conformance (silent on success)
cmf check conversation.cmf
# Convert to OpenAI Chat Completions format
cmf to-openai-chat conversation.cmf
# Convert to OpenAI Responses API format
cmf to-openai-responses conversation.cmf
Design Choices
- Blockquotes for users — Natural fit: blockquotes already mean "quoted speech" in writing
- No metadata required — A conversation is just turns. Everything else is optional.
- Valid CommonMark — CMF files render correctly in GitHub, Obsidian, VS Code, anywhere
- Escaping via indent — Need a blockquote in assistant content? Just indent it one space.
Rust Library
use cmf::Document;
let doc = Document::parse(input);
for turn in &doc.turns {
println!("User: {}", turn.user.content);
println!("Assistant: {}", turn.assistant);
}
// Convert to OpenAI formats
let messages = doc.to_openai_chat();
let responses = doc.to_openai_responses();
License
BSD-3-Clause — GitHub