[BUG] Edit tool cannot distinguish between straight and curved quotes in replacements
Environment
- Platform (select one):
- [x] Anthropic API
- [ ] AWS Bedrock
- [ ] Google Vertex AI
- [ ] Other:
- Claude CLI version: 1.0.21 (Claude Code)
- Operating System: Linux 5.15.167.4-microsoft-standard-WSL2
- Terminal: WSL2
Bug Description
The Edit tool fails to properly handle Unicode character replacements when characters are visually similar but have different byte representations. Specifically, the tool cannot distinguish between straight quotes (U+0027 ') and curved quotes (U+2018 ‘ and U+2019 ’), returning "No changes to make: old_string and new_string are exactly the same" even when hex dumps show the characters have different byte sequences.
Steps to Reproduce
- Create a file containing text with straight quotes around a placeholder:
'%s' - Attempt to use the Edit tool to replace the straight quotes with curved quotes:
‘%s’ - The Edit tool will claim no changes are needed despite the Unicode characters being different
- Verify with
hexdump -Cthat the characters have different byte representations:- Straight quotes:
27(U+0027) - Curved quotes:
e2 80 98(U+2018) ande2 80 99(U+2019)
- Straight quotes:
Expected Behavior
The Edit tool should successfully replace the straight quotes with curved quotes, recognizing that they are different Unicode characters despite visual similarity.
Actual Behavior
The Edit tool returns "No changes to make: old_string and new_string are exactly the same" and fails to perform the replacement, even though the characters are demonstrably different at the byte level.
Additional Context
This issue was discovered while trying to standardize quote usage in documentation. The problem prevents proper Unicode character normalization and could affect any scenario where visually similar but distinct Unicode characters need to be replaced. The hex dump evidence clearly shows the characters are different:
- Line with straight quotes:
27 25 73 27('%s') - Line with curved quotes:
e2 80 98 25 73 e2 80 99(‘%s’)
Same problem with different quotes: https://github.com/anthropics/claude-code/issues/8234
This issue has been inactive for 30 days. If the issue is still occurring, please comment to let us know. Otherwise, this issue will be automatically closed in 30 days for housekeeping purposes.
This is still occurring for me.
I will just add: I suspect that this is model (Sonnet) bug as opencode.ai with Sonnet has the same problem
This is really annoying. Claude Opus 4.5 can see the difference between ' (straight apostrophe) (U+0027) and ’ (curly apostrophe) (U+2019) when reading, but cannot write curly apostrophes - they get somehow always converted to straight apostrophes
As a workaround here is a simple SKILL.md file content that teach Claude how to write properly curly apostrophe via a placeholder then a sed command:
name: curly-apostrophe description: Auto-triggers when writing or editing text content that requires curly apostrophes. Teaches Claude to use placeholder and post-processing.
Curly Apostrophe Skill
Problem
Claude cannot directly write curly apostrophes (U+2019) through Write/Edit tools - they get converted to straight apostrophes (U+0027).
Solution
Use the placeholder __CURLY__ (double underscore + CURLY + double underscore), then post-process with bash.
Workflow
Step 1: Use Placeholder
When writing text that needs curly apostrophes, use __CURLY__ instead:
| Target text | Claude writes |
|---|---|
| don’t | don__CURLY__t |
| it’s | it__CURLY__s |
Step 2: Post-Process
After each Write or Edit operation on a file containing __CURLY__, IMMEDIATELY run:
CURLY=$'\u2019' && sed -i "s/__CURLY__/${CURLY}/g" <filepath>
Step 3: Verify (Optional)
Verify the replacement worked by checking for e2 80 99 bytes:
hexdump -C <filepath> | grep "e2 80 99"
Example
# Before (what Claude writes)
Don__CURLY__t forget to check the student__CURLY__s answer.
# After running sed command
Don’t forget to check the student’s answer.
Important Notes
- Always run sed immediately after Write/Edit - do not batch multiple files
- The placeholder
__CURLY__is case-sensitive - Works for any file type (.php, .html.twig, .md, .txt, etc.)
- The
$'\u2019'bash syntax outputs UTF-8 bytese2 80 99 - Do NOT run sed on this SKILL.md file - the placeholders here are documentation