[FEATURE] /curly option: context-aware curly/straight character handling in Write/Edit

Resolved 💬 4 comments Opened Mar 6, 2026 by ArtKoKo Closed Apr 4, 2026

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

Write/Edit tools normalize all curly typographic characters to straight ASCII before writing to disk:

  • ‘ (U+2018) → ' (U+0027)
  • ’ (U+2019) → ' (U+0027)
  • “ (U+201C) → " (U+0022)
  • ” (U+201D) → " (U+0022)

This solves a real bug (the model occasionally generates curly quotes in code, breaking parsers — see #29786, #31071). But it creates a symmetrical problem: legitimate curly characters in textual content (documentation, Markdown, changelogs, multilingual prose) are silently corrupted.

15 open/closed issues document both sides of this problem: #1599, #14355, #15920, #29699, #1716, #29786, #1986, #16879, #11148, #23945, #1828, #2516, #18422, #6094, #31071.

Proposed Solution

A /curly command that replaces blind normalization with context-aware verification.

Core rule

A curly character inside a straight delimiter is textual content (valid). A curly character used as a delimiter is a syntax error (invalid).

The agent analyzes each delimiter level independently (shell → language → regex) and only normalizes curly characters in delimiter position.

Two modes

| Mode | Command | When uncertain | Use case |
|------|---------|----------------|----------|
| safe | /curly safe | Straight (favor code) | Code-heavy projects |
| lazy | /curly lazy | Curly (favor typography) | Documentation, multilingual content |

Examples

Valid – curly inside straight delimiters (preserved):

const msg = 'Don’t stop'    // straight ' delimiters, curly ’ content
grep -r "l’utilisateur" docs/   // straight " delimiters, curly ’ content

Invalid – curly as delimiter (normalized to straight):

const msg = ’Don’t stop’    // curly ’ as delimiter → SyntaxError → fixed

Technical cost

The verification agent is lightweight:

  • Only triggered when curly characters are detected (minority case)
  • Local syntactic analysis (no external request)
  • Negligible overhead vs Write/Edit execution time

Alternative Solutions

Current community workarounds:

  • Placeholder substitution + perl (__RCURLY__\x{2019}) — requires post-processing after every Write/Edit
  • Python hex-level writing – bypasses Write/Edit entirely via python3 -c
  • Hooks (e.g. uedit) – cannot distinguish code delimiters from text content without semantic context

All workarounds are fragile, labor-intensive, and produce disproportionate machine resource usage. Writing the detailed proposal document itself required ~15 Edit calls, ~30 xxd verifications, and ~20 Python hex-level fixes — for a single Markdown file.

We have packaged these workarounds as reusable Claude Code skills (attached as zip archives):

  • en.zip — English skills: typo-curly (placeholder + perl), fix-unicode (\uXXXX → UTF-8, includes Python script), unicode-exact (Python hex-level bypass)
  • fr.zip — French skills: typo-courbe, fix-unicode, unicode-exact

These skills work but their very existence proves the point: users should not need 3 layered workarounds to preserve standard Unicode characters in text files.

A detailed proposal with hex-verified examples (JavaScript, bash, regex, nested delimiters) is also attached: PROPOSAL.en.md.

Priority

High - Significant impact on productivity

Feature Category

File operations

Use Case Example

  1. User works on a project with mixed code and multilingual documentation
  2. User runs /curly safe at session start
  3. User asks Claude to edit a JavaScript file → curly quotes in code are normalized (safe)
  4. User asks Claude to edit a French/English README → curly apostrophes in prose are preserved
  5. No placeholders, no perl, no hex verification needed

Additional Context

Attached files:

  • PROPOSAL.en.md – detailed proposal with hex-verified examples (JavaScript, bash, regex, nested delimiters)
  • en.zip – English Claude Code skills (workarounds)
  • fr.zip – French Claude Code skills (workarounds)

This proposal does not challenge the current normalization – it offers an opt-in alternative for users who also work with typographic content.

View original on GitHub ↗

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