Skip to content

Instantly share code, notes, and snippets.

@wkronmiller
Created July 22, 2025 12:09
Show Gist options
  • Save wkronmiller/ab7797a469539c24c4a7938f29bf79d0 to your computer and use it in GitHub Desktop.
Save wkronmiller/ab7797a469539c24c4a7938f29bf79d0 to your computer and use it in GitHub Desktop.
Parses OpenAI Export conversations.json into Markdown
import fs from 'node:fs';
const conversations = JSON.parse(fs.readFileSync('conversations.json', 'utf8'));
function unpackMapping(currentNode, mapping) {
const conversation = [];
let node = mapping[currentNode];
while (node) {
const message = node.message;
if(message) {
const role = message.author?.role;
const content = message.content?.parts?.join('\n');
conversation.unshift({ role, content });
}
node = mapping[node.parent];
}
return conversation;
}
function formatConversation(conversation) {
return conversation.filter(({ role }) => role !== 'system').map(({ role, content }) => {
return `${role}: ${content}`;
}).join('\n\n');
}
function unpackConversation({ id, title, create_time, update_time, mapping, current_node, ...rest }) {
const conversation = formatConversation(unpackMapping(current_node, mapping));
if(conversation.length === 0) {
console.log('empty', mapping);
return;
}
const doc = `## ${title}\n\n` +
`**ID:** ${id}\n` +
`**Created:** ${new Date(create_time * 1000).toLocaleString()}\n` +
`**Updated:** ${new Date(update_time * 1000).toLocaleString()}\n\n` +
`${conversation}\n\n`;
return { id, doc };
}
const combined = []
await Promise.all(conversations.map(async conversation => {
const { id, doc } = unpackConversation(conversation);
await fs.promises.writeFile(`./conversations/${id}.md`, doc, 'utf8');
console.log(`Saved conversation ${id} to file.`);
combined.push(doc);
}));
await fs.promises.writeFile('./conversations-combined.md', combined.join('\n\n'), 'utf8')
console.log('Conversations unpacked and saved to files.')
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment