claude-code - 💡(How to fix) Fix [BUG] Spinner verbs partially render ANSI truecolor escape codes as literal text [1 comments, 2 participants]

Official PRs (…)
ON THIS PAGE

Recommended Tools

×6

Utilities matched from this issue’s tags and category — try them while you read without losing context.

GitHub issue graph ai analysis

Paste a GitHub issue URL. We fetch that issue, discover linked issues from bodies/comments/timeline, collect linked pull requests, and produce a structured English report.

The report is written in English Markdown for sharing and archival.

Helpful · Quick feedback

Loading…
GitHub stats
anthropics/claude-code#48120Fetched 2026-04-15 06:32:36
View on GitHub
Comments
1
Participants
2
Timeline
4
Reactions
0
Timeline (top)
labeled ×3commented ×1

When spinnerVerbs in settings.json contain ANSI truecolor escape sequences (\u001b[38;2;R;G;Bm), the first escape code in each verb string partially renders as literal text. The ESC byte (\u001b) is consumed, but the remaining CSI parameters ([38;2;R;G;Bm) leak into the visible spinner text.

Subsequent escape codes in the same string render correctly as colors.

Error Message

Error Messages/Logs

Root Cause

This likely occurs in Ink's text layout/measurement pass. The first ANSI escape at position 0 is partially parsed — the ESC byte is stripped but the CSI parameter string is left as literal text. Subsequent escapes are processed correctly, suggesting an off-by-one in the initial ANSI stripping logic.

The statusLine custom commands with preserveColors: true (via ccstatusline) handle truecolor ANSI correctly, so this appears specific to the spinner/verb rendering path.

Fix Action

Fix / Workaround

Workaround attempted: Prefixing with \u001b[0m (no-op reset) — did not resolve the issue.

Code Example

The first ANSI escape sequence leaks as literal text:


🩺  [38;2;240;113;195mtrust me, I'm the Doctor...


The `\u001b` (ESC byte) is consumed, but `[38;2;240;113;195m` appears as visible text. Colors render correctly for subsequent escape codes later in the same string.

**Workaround attempted:** Prefixing with `\u001b[0m` (no-op reset) — did not resolve the issue.

---

{
  "spinnerVerbs": {
    "mode": "replace",
    "verbs": [
      "🩺. \u001b[38;2;231;111;81mt\u001b[0m\u001b[38;2;244;162;97mr\u001b[0m\u001b[38;2;255;214;102mu\u001b[0m\u001b[38;2;129;199;132ms\u001b[0m\u001b[38;2;100;210;199mt\u001b[0m \u001b[38;2;79;172;254mm\u001b[0m\u001b[38;2;129;140;248me\u001b[0m"
    ]
  }
}
RAW_BUFFERClick to expand / collapse

Preflight Checklist

  • I have searched existing issues and this hasn't been reported yet
  • This is a single bug report (please file separate reports for different bugs)
  • I am using the latest version of Claude Code

What's Wrong?

Spinner verbs partially render ANSI truecolor escape codes as literal text

Summary

When spinnerVerbs in settings.json contain ANSI truecolor escape sequences (\u001b[38;2;R;G;Bm), the first escape code in each verb string partially renders as literal text. The ESC byte (\u001b) is consumed, but the remaining CSI parameters ([38;2;R;G;Bm) leak into the visible spinner text.

Subsequent escape codes in the same string render correctly as colors.

Steps to reproduce

Expected behavior

Environment

  • Claude Code version: latest (as of 2026-04-14)
  • Terminal: Ghostty (truecolor capable)
  • OS: macOS 15.4 (Darwin 25.4.0)
  • Shell: zsh

Analysis

This likely occurs in Ink's text layout/measurement pass. The first ANSI escape at position 0 is partially parsed — the ESC byte is stripped but the CSI parameter string is left as literal text. Subsequent escapes are processed correctly, suggesting an off-by-one in the initial ANSI stripping logic.

The statusLine custom commands with preserveColors: true (via ccstatusline) handle truecolor ANSI correctly, so this appears specific to the spinner/verb rendering path.

What Should Happen?

The spinner verb text renders with each character in a different color (truecolor ANSI), with no visible escape code artifacts.

Error Messages/Logs

The first ANSI escape sequence leaks as literal text:


🩺  [38;2;240;113;195mtrust me, I'm the Doctor...


The `\u001b` (ESC byte) is consumed, but `[38;2;240;113;195m` appears as visible text. Colors render correctly for subsequent escape codes later in the same string.

**Workaround attempted:** Prefixing with `\u001b[0m` (no-op reset) — did not resolve the issue.

Steps to Reproduce

  1. Add a spinner verb with embedded ANSI truecolor escapes to ~/.claude/settings.json:
{
  "spinnerVerbs": {
    "mode": "replace",
    "verbs": [
      "🩺. \u001b[38;2;231;111;81mt\u001b[0m\u001b[38;2;244;162;97mr\u001b[0m\u001b[38;2;255;214;102mu\u001b[0m\u001b[38;2;129;199;132ms\u001b[0m\u001b[38;2;100;210;199mt\u001b[0m \u001b[38;2;79;172;254mm\u001b[0m\u001b[38;2;129;140;248me\u001b[0m"
    ]
  }
}
  1. Start a Claude Code session
  2. Send a message and observe the spinner

Claude Model

Opus

Is this a regression?

I don't know

Last Working Version

No response

Claude Code Version

2.1.108

Platform

Anthropic API

Operating System

macOS

Terminal/Shell

Terminal.app (macOS)

Additional Information

<img width="932" height="280" alt="Image" src="https://github.com/user-attachments/assets/216ab661-b92a-4e63-8981-028116010f78" />

extent analysis

TL;DR

The issue can be fixed by adjusting the ANSI escape sequence parsing logic in the spinner verb rendering path to correctly handle the first escape code.

Guidance

  • Review the text layout and measurement pass in Ink to identify the off-by-one error in the initial ANSI stripping logic.
  • Verify that the statusLine custom commands with preserveColors: true are handling truecolor ANSI correctly, and apply similar logic to the spinner verb rendering path.
  • Test the spinner verb rendering with different ANSI truecolor escape sequences to ensure the fix is not specific to a particular sequence.
  • Consider adding additional logging or debugging statements to help identify the root cause of the issue.

Example

No code snippet is provided as the issue is related to the internal logic of the Claude Code and Ink libraries.

Notes

The issue appears to be specific to the spinner verb rendering path and may not be related to the statusLine custom commands. The workaround attempted by prefixing with \u001b[0m (no-op reset) did not resolve the issue.

Recommendation

Apply a workaround by modifying the spinner verb to avoid using ANSI truecolor escape sequences at the beginning of the string, until a permanent fix is available. This can be done by adding a non-ANSI character at the start of the string, such as a space.

Vote matrix · Quick signals

Works
Did the solution work? Tap to confirm.
Easy Fix
Was it a quick fix?
Time Saver
Did it save you time?
Blocking
Was it severely blocking?
Common Issue
Are others likely hitting this too?
Flaky / Intermittent
Is it intermittent?
Verified / Reproducible
Can you reproduce it reliably?
Loading…

Still need to ship something?

×6

Another batch ranked right after the header list — different links, same matching logic.

Back to top recommendations

TRENDING

claude-code - 💡(How to fix) Fix [BUG] Spinner verbs partially render ANSI truecolor escape codes as literal text [1 comments, 2 participants]