[BUG] Spinner verbs partially render ANSI truecolor escape codes as literal text

Resolved 💬 2 comments Opened Apr 14, 2026 by cameronsjo Closed May 25, 2026

Preflight Checklist

  • [x] I have searched existing issues and this hasn't been reported yet
  • [x] This is a single bug report (please file separate reports for different bugs)
  • [x] 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 (\^[[38;2;R;G;Bm), the first escape code in each verb string partially renders as literal text. The ESC byte (\^[) 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 `\^[` (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 `\^[[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": [
      "🩺. \^[[38;2;231;111;81mt\^[[0m\^[[38;2;244;162;97mr\^[[0m\^[[38;2;255;214;102mu\^[[0m\^[[38;2;129;199;132ms\^[[0m\^[[38;2;100;210;199mt\^[[0m \^[[38;2;79;172;254mm\^[[0m\^[[38;2;129;140;248me\^[[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" />

View original on GitHub ↗

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