Skip to content

Markdown Converter

claude_conversation_extractor.markdown_converter

Convert conversations to markdown format.

MarkdownConverter

Converts Claude conversations to markdown format.

Source code in src/claude_conversation_extractor/markdown_converter.py
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
class MarkdownConverter:
    """Converts Claude conversations to markdown format."""

    def __init__(self, conversation: Conversation):
        """Initialize with a conversation to convert.

        Args:
            conversation: The conversation to convert to markdown
        """
        self.conversation = conversation

    def convert(self) -> str:
        """Convert the conversation to markdown.

        Returns:
            The conversation formatted as markdown
        """
        lines = []

        # Header
        lines.append(f"# {self.conversation.name or 'Untitled Conversation'}")
        lines.append("")

        # Metadata
        lines.append("## Conversation Details")
        lines.append(f"- **UUID**: `{self.conversation.uuid}`")
        lines.append(
            f"- **Created**: {self._format_timestamp(self.conversation.created_at)}"
        )
        lines.append(
            f"- **Updated**: {self._format_timestamp(self.conversation.updated_at)}"
        )
        lines.append(f"- **Account**: `{self.conversation.account.uuid}`")
        lines.append("")

        # Messages
        if self.conversation.chat_messages:
            lines.append("## Messages")
            lines.append("")

            for i, message in enumerate(self.conversation.chat_messages, 1):
                lines.extend(self._format_message(message, i))
                lines.append("")
        else:
            lines.append("## Messages")
            lines.append("")
            lines.append("*No messages in this conversation.*")

        return "\n".join(lines)

    def _format_message(self, message: ChatMessage, message_number: int) -> list[str]:
        """Format a single message as markdown.

        Args:
            message: The message to format
            message_number: Sequential number for the message

        Returns:
            List of markdown lines for the message
        """
        lines = []

        # Message header
        sender_emoji = "👤" if message.sender == "human" else "🤖"
        sender_name = "Human" if message.sender == "human" else "Claude"

        lines.append(f"### {sender_emoji} {sender_name} - Message {message_number}")
        lines.append(f"*{self._format_timestamp(message.created_at)}*")
        lines.append("")

        # Message content
        if message.content:
            for content_item in message.content:
                if content_item.type == "text" and content_item.text:
                    # Format the text content
                    formatted_text = self._format_text_content(content_item.text)
                    lines.append(formatted_text)
                    lines.append("")

        # Attachments and files
        if message.attachments:
            lines.append("**Attachments:**")
            for attachment in message.attachments:
                lines.extend(self._format_file_object(attachment))
            lines.append("")

        if message.files:
            lines.append("**Files:**")
            for file in message.files:
                lines.extend(self._format_file_object(file))
            lines.append("")

        return lines

    def _format_file_object(self, file_obj: FileObject) -> list[str]:
        """Format a file object as markdown.

        Args:
            file_obj: The file object to format

        Returns:
            List of markdown lines for the file
        """
        lines = []

        # Basic file info
        file_info = f"- **{file_obj.file_name}**"
        if file_obj.file_size:
            file_info += f" ({file_obj.file_size} bytes)"
        if file_obj.file_type:
            file_info += f" - {file_obj.file_type}"
        lines.append(file_info)

        # File content if available
        if file_obj.extracted_content:
            lines.append("")
            lines.append("```")
            lines.append(file_obj.extracted_content)
            lines.append("```")
            lines.append("")

        return lines

    def _format_text_content(self, text: str) -> str:
        """Format text content with proper markdown.

        Args:
            text: Raw text content

        Returns:
            Formatted markdown text
        """
        # Handle code blocks (if they exist in the text)
        # This is a simple implementation - could be enhanced for more complex formatting
        return text.strip()

    def _format_timestamp(self, timestamp: datetime) -> str:
        """Format timestamp for display.

        Args:
            timestamp: The timestamp to format

        Returns:
            Formatted timestamp string
        """
        return timestamp.strftime("%Y-%m-%d %H:%M:%S UTC")

    def save_to_file(self, output_path: str) -> None:
        """Convert and save the conversation to a markdown file.

        Args:
            output_path: Path where to save the markdown file
        """
        markdown_content = self.convert()

        with open(output_path, "w", encoding="utf-8") as f:
            f.write(markdown_content)

__init__

__init__(conversation)

Initialize with a conversation to convert.

Parameters:

Name Type Description Default
conversation Conversation

The conversation to convert to markdown

required
Source code in src/claude_conversation_extractor/markdown_converter.py
11
12
13
14
15
16
17
def __init__(self, conversation: Conversation):
    """Initialize with a conversation to convert.

    Args:
        conversation: The conversation to convert to markdown
    """
    self.conversation = conversation

convert

convert()

Convert the conversation to markdown.

Returns:

Type Description
str

The conversation formatted as markdown

Source code in src/claude_conversation_extractor/markdown_converter.py
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
def convert(self) -> str:
    """Convert the conversation to markdown.

    Returns:
        The conversation formatted as markdown
    """
    lines = []

    # Header
    lines.append(f"# {self.conversation.name or 'Untitled Conversation'}")
    lines.append("")

    # Metadata
    lines.append("## Conversation Details")
    lines.append(f"- **UUID**: `{self.conversation.uuid}`")
    lines.append(
        f"- **Created**: {self._format_timestamp(self.conversation.created_at)}"
    )
    lines.append(
        f"- **Updated**: {self._format_timestamp(self.conversation.updated_at)}"
    )
    lines.append(f"- **Account**: `{self.conversation.account.uuid}`")
    lines.append("")

    # Messages
    if self.conversation.chat_messages:
        lines.append("## Messages")
        lines.append("")

        for i, message in enumerate(self.conversation.chat_messages, 1):
            lines.extend(self._format_message(message, i))
            lines.append("")
    else:
        lines.append("## Messages")
        lines.append("")
        lines.append("*No messages in this conversation.*")

    return "\n".join(lines)

save_to_file

save_to_file(output_path)

Convert and save the conversation to a markdown file.

Parameters:

Name Type Description Default
output_path str

Path where to save the markdown file

required
Source code in src/claude_conversation_extractor/markdown_converter.py
155
156
157
158
159
160
161
162
163
164
def save_to_file(self, output_path: str) -> None:
    """Convert and save the conversation to a markdown file.

    Args:
        output_path: Path where to save the markdown file
    """
    markdown_content = self.convert()

    with open(output_path, "w", encoding="utf-8") as f:
        f.write(markdown_content)