<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: doremi</title>
    <description>The latest articles on DEV Community by doremi (@doremi).</description>
    <link>https://dev.to/doremi</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3894458%2F259a0fdb-4eef-4362-9b76-8a965087a214.png</url>
      <title>DEV Community: doremi</title>
      <link>https://dev.to/doremi</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/doremi"/>
    <language>en</language>
    <item>
      <title>Why Copying Code from AI Chat Tools Still Breaks Your Indentation (And How to Fix It)</title>
      <dc:creator>doremi</dc:creator>
      <pubDate>Sun, 26 Apr 2026 13:38:57 +0000</pubDate>
      <link>https://dev.to/doremi/why-copying-code-from-ai-chat-tools-still-breaks-your-indentation-and-how-to-fix-it-3ee6</link>
      <guid>https://dev.to/doremi/why-copying-code-from-ai-chat-tools-still-breaks-your-indentation-and-how-to-fix-it-3ee6</guid>
      <description>&lt;p&gt;If you've ever copied a code block from ChatGPT or Claude and pasted it into your editor, you've probably seen this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# What ChatGPT shows you:
&lt;/span&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;process_data&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;items&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;list&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nb"&gt;dict&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;dict&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;item&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;items&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;item&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;active&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
            &lt;span class="n"&gt;key&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;item&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;category&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
            &lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;setdefault&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;key&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;[]).&lt;/span&gt;&lt;span class="nf"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;item&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;value&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;result&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# What ends up in your clipboard:
&lt;/span&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;process_data&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;items&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;list&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nb"&gt;dict&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;dict&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;
        &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;item&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;items&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;item&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;active&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
                &lt;span class="n"&gt;key&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;item&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;category&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
                    &lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;setdefault&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;key&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;[]).&lt;/span&gt;&lt;span class="nf"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;item&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;value&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;result&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Tabs became spaces. Spaces became tabs. The whole thing is a mess. And if you're working with nested code — callbacks, decorators, class methods — it gets exponentially worse.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Technical Root Cause
&lt;/h2&gt;

&lt;p&gt;AI chat interfaces render code blocks using &lt;code&gt;&amp;lt;pre&amp;gt;&amp;lt;code&amp;gt;&lt;/code&gt; elements with CSS for styling. The syntax highlighting is applied via CSS classes (Prism.js, Highlight.js, or custom). When you select and copy:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;The browser's clipboard API&lt;/strong&gt; tries to serialize the selection&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;It includes CSS-computed styles&lt;/strong&gt; as rich text&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Most target apps&lt;/strong&gt; (VS Code, IDEs, terminals) expect plain text&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The mismatch&lt;/strong&gt; causes indentation corruption&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Here's the kicker: the underlying text in the DOM is usually correct. It's the &lt;em&gt;clipboard serialization&lt;/em&gt; that breaks things. Different browsers handle this differently too — Chrome, Firefox, and Safari all have slightly different clipboard behavior.&lt;/p&gt;

&lt;h2&gt;
  
  
  I Tested 5 Approaches
&lt;/h2&gt;

&lt;h3&gt;
  
  
  1. Direct Copy-Paste
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Result&lt;/strong&gt;: Fails ~60% of the time with nested code&lt;br&gt;
&lt;strong&gt;Why&lt;/strong&gt;: Clipboard serialization corrupts whitespace&lt;/p&gt;
&lt;h3&gt;
  
  
  2. "View Source" in DevTools
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Result&lt;/strong&gt;: Works but tedious&lt;br&gt;
&lt;strong&gt;Why&lt;/strong&gt;: You get the raw text but have to manually extract it&lt;/p&gt;
&lt;h3&gt;
  
  
  3. ChatGPT's Share Link
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Result&lt;/strong&gt;: Preserves formatting but read-only&lt;br&gt;
&lt;strong&gt;Why&lt;/strong&gt;: It's a rendered webpage, not a code export&lt;/p&gt;
&lt;h3&gt;
  
  
  4. Export to Markdown
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Result&lt;/strong&gt;: Best option for developers&lt;br&gt;
&lt;strong&gt;Why&lt;/strong&gt;: Markdown preserves code fences with language tags. Clean, portable, editor-friendly.&lt;/p&gt;
&lt;h3&gt;
  
  
  5. Export to PDF with Syntax Highlighting
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Result&lt;/strong&gt;: Good for documentation, not for reuse&lt;br&gt;
&lt;strong&gt;Why&lt;/strong&gt;: Visual fidelity is high but you can't edit the code&lt;/p&gt;
&lt;h2&gt;
  
  
  The Solution I Settled On
&lt;/h2&gt;

&lt;p&gt;I started using a Chrome extension that handles multi-platform AI export (ChatGPT, Claude, Gemini, DeepSeek, Grok). The Markdown export is what I use 90% of the time:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Code blocks&lt;/strong&gt; come out with proper language tags and indentation&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;No formatting corruption&lt;/strong&gt; — it's plain text with markdown syntax&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Works with Obsidian, VS Code, any editor&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Batch export&lt;/strong&gt; — I can grab an entire conversation at once&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The extension is called XWX AI Chat Exporter. It's free (PDF has a daily limit, but Markdown is unlimited). I'm not affiliated with the devs — just a user who got tired of fixing broken indentation.&lt;/p&gt;
&lt;h2&gt;
  
  
  Bonus: My Obsidian Integration
&lt;/h2&gt;

&lt;p&gt;Since I'm exporting to Markdown anyway, I piped everything into Obsidian:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;AI Conversations/
├── 2026-04/
│   ├── 2026-04-21-system-design.md
│   ├── 2026-04-20-api-refactor.md
│   └── 2026-04-19-auth-architecture.md
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Each exported file gets:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Frontmatter with date, AI platform, and topic tags&lt;/li&gt;
&lt;li&gt;Proper code fences with language identifiers&lt;/li&gt;
&lt;li&gt;Preserved headings for the conversation structure&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This turns AI conversations into a searchable knowledge base. When I need to find "that conversation about rate limiting strategies," I just search my vault instead of scrolling through ChatGPT history.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Real Issue
&lt;/h2&gt;

&lt;p&gt;This whole problem shouldn't exist. AI chat tools are used by millions of developers who need to copy code reliably. The fact that the default copy-paste still breaks indentation in 2026 is... not great.&lt;/p&gt;

&lt;p&gt;Until the platforms fix it properly (they should just offer a "Copy as plain text" button that actually works), extensions and workarounds are your best bet.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What's your approach?&lt;/strong&gt; Do you deal with broken formatting, or have you found a workflow that works?&lt;/p&gt;

</description>
      <category>tools</category>
      <category>webdev</category>
    </item>
  </channel>
</rss>
