[FEATURE] Preserve Unicode characters exactly in Write/Edit tools (stop U+2019 → U+0027 conversion)
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):
- printf with explicit UTF-8:
``bash``
printf "const msg = 'L\xe2\x80\x99apostrophe courbe'\n" > file.js
- cat with heredoc:
``bash``
cat > file.js << 'EOF'
const msg = 'L'apostrophe courbe'
EOF
- 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
- Project uses curved apostrophes to avoid escaping (coding standard)
- Claude writes JavaScript file with French comments/strings
- Write tool converts all U+2019 → U+0027
- Developer must manually fix with
perl -i -pe "s/'/\xe2\x80\x99/g"on every file
With this feature:
- Project uses curved apostrophes (coding standard)
- Claude writes JavaScript file with French comments/strings
- Write tool preserves U+2019 exactly
- ✅ 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
This issue has 2 comments on GitHub. Read the full discussion on GitHub ↗