Summary
ConsoleUi.ColorizeKind (src/CodeIndex/Cli/ConsoleUi.cs:818-841) emits ANSI escape codes conditionally on ShouldUseInteractiveConsole(). That helper's check is !Console.IsOutputRedirected && !Console.Out.Encoding.Equals(Encoding.Unicode). The UTF-16 check defends against test StringWriter capture, but in some container/test environments Console.Out ends up wrapped in a custom encoder that passes both gates, allowing ANSI codes to leak into --json output. Any JSON parser then chokes on "\x1b[36mclass\x1b[0m" strings.
Where
src/CodeIndex/Cli/ConsoleUi.cs:843-851 (ShouldUseInteractiveConsole heuristic)
src/CodeIndex/Cli/ConsoleUi.cs:818-841 (ColorizeKind output)
src/CodeIndex/Cli/QueryCommandRunner.cs:837 (one of many call sites)
Suggested approach
- Thread
options.Json into ColorizeKind so JSON-mode callers always receive unstyled text.
- Alternatively, set a thread-local
ColorMode in ProgramRunner after argument parsing and consult it before any styled output.
- In
--json paths, never invoke ColorizeKind at all (skip styling entirely).
- Add a unit test that calls
ColorizeKind under JSON mode and asserts no \x1b byte appears.
- Add an end-to-end test piping
--json output through JsonDocument.Parse to catch regressions.
- Document the JSON-mode invariant in
DEVELOPER_GUIDE.md.
Summary
ConsoleUi.ColorizeKind(src/CodeIndex/Cli/ConsoleUi.cs:818-841) emits ANSI escape codes conditionally onShouldUseInteractiveConsole(). That helper's check is!Console.IsOutputRedirected && !Console.Out.Encoding.Equals(Encoding.Unicode). The UTF-16 check defends against testStringWritercapture, but in some container/test environmentsConsole.Outends up wrapped in a custom encoder that passes both gates, allowing ANSI codes to leak into--jsonoutput. Any JSON parser then chokes on"\x1b[36mclass\x1b[0m"strings.Where
src/CodeIndex/Cli/ConsoleUi.cs:843-851(ShouldUseInteractiveConsole heuristic)src/CodeIndex/Cli/ConsoleUi.cs:818-841(ColorizeKind output)src/CodeIndex/Cli/QueryCommandRunner.cs:837(one of many call sites)Suggested approach
options.JsonintoColorizeKindso JSON-mode callers always receive unstyled text.ColorModeinProgramRunnerafter argument parsing and consult it before any styled output.--jsonpaths, never invokeColorizeKindat all (skip styling entirely).ColorizeKindunder JSON mode and asserts no\x1bbyte appears.--jsonoutput throughJsonDocument.Parseto catch regressions.DEVELOPER_GUIDE.md.