[FEATURE] Preserve Unicode characters exactly in Write/Edit tools (stop U+2019 → U+0027 conversion)

Resolved 💬 2 comments Opened Nov 30, 2025 by ArtKoKo Closed Nov 30, 2025

Preflight Checklist

  • [x] I have searched existing requests and this feature hasn't been requested yet
  • [x] This is a single feature request (not multiple features)

Problem Statement

Problem Statement

The Write and Edit tools in Claude Code automatically convert Unicode curved apostrophes (U+2019 ') to straight apostrophes (U+0027 '), preventing adherence to French typography standards and forcing developers to use bash workarounds (printf, cat, perl).

Example:

// Input (intended):
const msg = 'L’apostrophe courbe évite l’échappement'

// Output (actual after Write/Edit):
const msg = 'L'apostrophe courbe évite l'échappement'

Result:

  • U+2019 (') is silently converted to U+0027 (')
  • Backslash escaping required: \'
  • Typography quality degraded
  • Code readability reduced

This affects:

  • French software projects (millions of developers worldwide)
  • Multilingual documentation requiring proper Unicode
  • Typography-sensitive content (publishing, design)
  • Any project using non-ASCII Unicode characters properly

Impact

French Typography Standards Violated

The curved apostrophe (U+2019) has been the standard French typography since 1533 (Geoffroy Tory). It is the official Unicode recommendation for apostrophes in French.

The straight apostrophe (U+0027) is a mechanical limitation from 1860s typewriters, not a technical requirement in 2025.

Code Readability Degraded

With curved apostrophe (0 backslashes):

const msg = 'L'apostrophe courbe évite l'échappement'
const html = '<a href="#" title="C'est l'exemple">Link</a>'

With straight apostrophe (7 backslashes):

const msg = 'L\'apostrophe courbe évite l\'échappement'
const html = '<a href=\"#\" title=\"C\'est l\'exemple\">Link</a>'

Difference: 0 backslashes vs 7 backslashes in 2 lines of code.

Developer Workflow Disrupted

Current workarounds (none use Write/Edit tools):

  1. printf with explicit UTF-8:

``bash
printf "const msg = 'L\xe2\x80\x99apostrophe courbe'\n" > file.js
``

  1. cat with heredoc:

``bash
cat > file.js << 'EOF'
const msg = 'L'apostrophe courbe'
EOF
``

  1. perl post-processing:

``bash
perl -i -pe "s/'/\xe2\x80\x99/g" file.js
``

This defeats the purpose of having Write/Edit tools for seamless file operations.

Technical Validation

We tested curved apostrophes extensively with modern JavaScript:

| Test | Result |
|------|--------|
| Node.js v24 | ✅ Works perfectly |
| Strict mode | ✅ Works perfectly |
| ES6 modules | ✅ Fully compatible |
| ESLint 9.39 | ✅ No errors |

Conclusion: Modern JavaScript fully supports U+2019. The conversion is unnecessary.

Comparison with Industry

| Tool | UTF-8 Behavior |
|------|----------------|
| VS Code | Preserves exactly ✅ |
| vim/nano | Preserves exactly ✅ |
| git | Preserves exactly ✅ |
| Claude Write/Edit | Converts U+2019 → U+0027 ❌ |

Industry standard: Preserve user input exactly.

Proposed Solution

Remove the normalization layer that converts U+2019 → U+0027 in Write/Edit tools.

Rationale:

  • Developers explicitly choose characters
  • UTF-8 is the universal standard (98%+ of web since 2008)
  • Conversion breaks legitimate use cases (French, typography, linguistics)
  • Professional developers need precise control over file contents

Implementation suggestion:

# Current behavior (hypothesized):
def normalize_content(content):
    content = content.replace('\u2019', "'")  # U+2019 → U+0027
    return content

# Proposed behavior:
def normalize_content(content, preserve_unicode=True):
    if preserve_unicode:
        return content  # Preserve exactly as provided
    
    # Optional: Legacy normalization if needed
    content = content.replace('\u2019', "'")
    return content

Default: preserve_unicode=True (respect user input, industry standard)

Alternative Solutions

Option 1: Configuration Flag

Add optional parameter to Write/Edit tools:

Write({
  file_path: "file.js",
  content: "const msg = 'L'exemple'",
  preserve_unicode: true  // New flag
})

Pros: Backward compatible
Cons: Requires extra parameter, opt-in instead of opt-out

Option 2: Auto-detect Language Context

If file contains French diacritics (é, è, à, ç) or .md file with French content, preserve curved apostrophes.

Pros: Intelligent default
Cons: Complex heuristics, edge cases

Priority

High - Significant impact on productivity

Feature Category

File operations

Use Case Example

Scenario: French JavaScript project with proper typography standards

  1. Project uses curved apostrophes to avoid escaping (coding standard)
  2. Claude writes JavaScript file with French comments/strings
  3. Write tool converts all U+2019 → U+0027
  4. Developer must manually fix with perl -i -pe "s/'/\xe2\x80\x99/g" on every file

With this feature:

  1. Project uses curved apostrophes (coding standard)
  2. Claude writes JavaScript file with French comments/strings
  3. Write tool preserves U+2019 exactly
  4. ✅ File is correct, no manual intervention needed

Real-World Impact

Our project stats:

  • 50+ JavaScript modules with French documentation
  • ~15,000 lines of JSDoc comments in French
  • Every file affected by apostrophe conversion issue
  • Manual correction required for each file

Related Issues

This request is related but distinct from #12203 (UTF-8 BOM encoding):

  • #12203 requests encoding options (UTF-8 vs UTF-8 BOM for PowerShell 5.1)
  • This issue requests disabling character normalization (preserve U+2019 as-is)

Both highlight internationalization challenges in Claude Code.

Additional Context

This issue may affect other Unicode characters:

  • French guillemets: « » (U+00AB, U+00BB)
  • Em/En dashes: — – (U+2014, U+2013)
  • Ellipsis: (U+2026)
  • Ligatures: œ æ (U+0153, U+00E6)

We haven't tested these comprehensively, but if apostrophes are converted, these may be as well.

Supporting Documentation

We've created comprehensive documentation on this topic:

CURVED-APOSTROPHE.md

Full historical and technical analysis including:

  • History of apostrophes (1180-2025)
  • ASCII bias and missing characters (œ, é, etc.)
  • Deconstruction of "99.9% use straight apostrophes" argument
  • Technical tests (Node.js, ESLint validation)
  • Conclusion: "Normalization should not impoverish language"

Key excerpt:

The straight apostrophe (' U+0027) is a mechanical constraint from 1860s typewriters, not a technical requirement. In 2025, with UTF-8 universal, continuing to use ' instead of ' in French is equivalent to writing "oeuvre" instead of "œuvre" (1990s limitation) or "cafe" instead of "café" (1980s limitation). We've moved past these constraints. Why persist?

ANTHROPIC-GITHUB-ISSUE-DRAFT.md

Complete technical report with:

  • Problem description and verification
  • Impact analysis
  • Current workarounds
  • Proposed solutions
  • Industry comparison
  • Testing recommendations

Conclusion

We believe this is an unintended side effect of legacy ASCII-era thinking, not a deliberate choice.

Why this matters:

  • Claude Code is a professional development tool
  • Professional developers need precise control over file contents
  • UTF-8 has been the universal standard since 2008
  • Typography standards (especially for non-English languages) should be respected

This improvement would benefit:

  • French-speaking developers worldwide
  • Multilingual projects
  • Typography-conscious developers
  • Anyone working with proper Unicode characters

View original on GitHub ↗

This issue has 2 comments on GitHub. Read the full discussion on GitHub ↗