Skip to content

Instantly share code, notes, and snippets.

@bquast
Created April 12, 2026 10:33
Show Gist options
  • Select an option

  • Save bquast/e26812c23bc4829531a465a00e86a160 to your computer and use it in GitHub Desktop.

Select an option

Save bquast/e26812c23bc4829531a465a00e86a160 to your computer and use it in GitHub Desktop.
Export Claude conversation to markdown
(() => {
const title = document.title.replace(' - Claude', '').trim();
const lines = [`# ${title}\n`];
// Grab every turn in the conversation
const turns = document.querySelectorAll('[data-testid="user-message"], .font-claude-response-body, .standard-markdown');
// Better approach: walk the full message list
// User messages
const userMsgs = [...document.querySelectorAll('[data-testid="user-message"]')];
// Claude responses — each lives inside a .standard-markdown container
const claudeMsgs = [...document.querySelectorAll('.standard-markdown')];
// Interleave by DOM order
const all = [
...userMsgs.map(el => ({ el, role: 'user' })),
...claudeMsgs.map(el => ({ el, role: 'claude' }))
].sort((a, b) => {
const pos = a.el.compareDocumentPosition(b.el);
return pos & Node.DOCUMENT_POSITION_FOLLOWING ? -1 : 1;
});
function nodeToMd(node, indent = '') {
if (node.nodeType === Node.TEXT_NODE) return node.textContent;
const tag = node.tagName?.toLowerCase();
const children = () => [...node.childNodes].map(n => nodeToMd(n, indent)).join('');
if (!tag) return children();
switch (tag) {
case 'p': return children() + '\n\n';
case 'br': return '\n';
case 'strong': case 'b': return `**${children()}**`;
case 'em': case 'i': return `*${children()}*`;
case 'code': return node.closest('pre') ? children() : `\`${children()}\``;
case 'pre': return '```\n' + node.textContent.trim() + '\n```\n\n';
case 'h1': return `# ${children()}\n\n`;
case 'h2': return `## ${children()}\n\n`;
case 'h3': return `### ${children()}\n\n`;
case 'h4': return `#### ${children()}\n\n`;
case 'ul': return [...node.children].map(li => `- ${nodeToMd(li, indent + ' ').trim()}`).join('\n') + '\n\n';
case 'ol': return [...node.children].map((li, i) => `${i+1}. ${nodeToMd(li, indent + ' ').trim()}`).join('\n') + '\n\n';
case 'li': return children();
case 'blockquote': return children().split('\n').map(l => `> ${l}`).join('\n') + '\n\n';
case 'a': return `[${children()}](${node.href})`;
case 'hr': return '---\n\n';
default: return children();
}
}
for (const { el, role } of all) {
if (role === 'user') {
const text = el.textContent.trim();
lines.push(`**You:** ${text}\n`);
} else {
const md = nodeToMd(el).trim();
lines.push(`**Claude:** ${md}\n`);
}
lines.push('---\n');
}
const output = lines.join('\n');
// Download as .md file
const blob = new Blob([output], { type: 'text/markdown' });
const url = URL.createObjectURL(blob);
const a = document.createElement('a');
a.href = url;
a.download = `${title.replace(/[^a-z0-9]/gi, '_').toLowerCase()}.md`;
a.click();
URL.revokeObjectURL(url);
console.log('✅ Exported:', a.download);
})();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment