Markdown to Confluence XML converter with bidirectional sync support for self-hosted Confluence Server/Data Center.
Converts Markdown to Confluence storage format XML and back. Supports pulling pages from Confluence, editing locally as Markdown, and pushing changes back — with template-aware embedding that preserves metadata tables, changelogs, and inline comment markers.
go install sourcecraft.dev/bigbes/markdown-to-confluence-xml@latest
The binary is named mdcx.
convert — Markdown to Confluence XMLmdcx convert input.md -o output.xml
cat input.md | mdcx convert > output.xml
embed — Embed Markdown into a Confluence XML templateConverts Markdown and inserts it between marker comments in an existing Confluence document, preserving everything outside the markers (metadata table, TOC, changelog, etc.).
mdcx embed input.md --template template.xml -o output.xml
The template must contain marker comments:
<!-- MD_CONTENT_START -->
<!-- MD_CONTENT_END -->
extract — Extract Markdown from Confluence XMLExtracts content between markers and converts back to Markdown.
mdcx extract input.xml -o output.md
mdcx extract input.xml --raw # output raw Confluence XML
pull — Pull a page from Confluencemdcx pull "https://confluence.example.com/pages/viewpage.action?pageId=12345" -o page.md
mdcx pull "https://confluence.example.com/display/TEAM/Page+Title" -o page.md
mdcx pull "https://confluence.example.com/display/TEAM/Page+Title" --raw -o page.xml
push — Push Markdown to a Confluence page# Replace entire page body
mdcx push "https://confluence.example.com/display/TEAM/Page+Title" page.md
# Template mode: replace only content between markers
mdcx push "https://confluence.example.com/display/TEAM/Page+Title" page.md --template
# With version message
mdcx push "https://confluence.example.com/display/TEAM/Page+Title" page.md -m "Updated intro section"
For pull and push, provide a Personal Access Token via:
--token flag, orCONFLUENCE_TOKEN environment variableexport CONFLUENCE_TOKEN="your-token-here"
mdcx pull "https://confluence.example.com/display/TEAM/RFC-42" -o rfc.md
export CONFLUENCE_TOKEN="..."
# Pull page to local Markdown
mdcx pull "https://confluence.example.com/display/TEAM/RFC-42" -o rfc.md
# Edit locally
vim rfc.md
# Push back, preserving template structure
mdcx push "https://confluence.example.com/display/TEAM/RFC-42" rfc.md --template -m "Updated requirements"
| Markdown | Confluence XML |
|---|---|
# Heading |
<h1> ... <h6> |
**bold** |
<strong> |
*italic* |
<em> |
~~strike~~ |
<del> |
`code` |
<code> |
| Fenced code blocks | <ac:structured-macro ac:name="code"> with CDATA |
- item / 1. item |
<ul>/<ol> with <li> |
| Nested lists | Nested <ul>/<ol> inside <li> |
- [x] task |
<ac:task-list> / <ac:task> |
[text](url) |
<a href="..."> |
 |
<ac:image><ri:url .../> |
> blockquote |
<ac:structured-macro ac:name="info"> (info panel) |
--- |
<hr/> |
| GFM tables | <table> with <th>/<td> wrapped in <p> |
| Inline comment markers | Preserved via <span data-inline-comment="ref"> in Markdown |
Confluence inline comments (<ac:inline-comment-marker ac:ref="UUID">) are preserved through round-trips. In Markdown they appear as:
<span data-inline-comment="b2f6ce98-4dc9-...">commented text</span>
This is converted back to proper <ac:inline-comment-marker> tags when pushing to Confluence.
MIT