Skip to content

fix(cli): ASCII glyph fallback for Windows console mojibake (#168)#178

Merged
colbymchenry merged 1 commit into
mainfrom
fix/windows-mojibake-168
May 19, 2026
Merged

fix(cli): ASCII glyph fallback for Windows console mojibake (#168)#178
colbymchenry merged 1 commit into
mainfrom
fix/windows-mojibake-168

Conversation

@colbymchenry
Copy link
Copy Markdown
Owner

Summary

  • Add src/ui/glyphs.ts with supportsUnicode() detection and matched Unicode / ASCII glyph sets
  • Route shimmer-worker and CLI output (✓✗ℹ⚠, │ ◆ — █ ░, tree chars, banner separators) through getGlyphs()
  • Default to ASCII on Windows and Linux kernel consoles, Unicode everywhere else
  • Escape hatches: CODEGRAPH_UNICODE=1 to opt into Unicode (e.g. pwsh 7 with UTF-8), CODEGRAPH_ASCII=1 to force ASCII

Why

#168 reports garbled output during codegraph index on Windows PowerShell:

鋍?[0m 鉒?[0m Scanning files 鈥?6 found
鋍?[0m 鉒?[0m Parsing code 鈥?done
鋍?[0m 鉒?[0m Resolving refs

The shimmer progress renderer writes from a worker thread via fs.writeSync(1, …) to keep the animation smooth while the main thread is blocked in SQLite — see the existing comment in shimmer-worker.ts. That path bypasses Node's TTY-aware UTF-8→codepage conversion on Windows, so glyphs like │ ◆ — were emitted as raw UTF-8 bytes and reinterpreted by the console's active OEM codepage (CP437, CP936, …), producing the mojibake above. Clack output rendered fine in the same screenshot because clack writes through process.stdout.write, which Node TTY-encodes correctly.

Why not #174

#174 was on the right track but didn't touch src/ui/shimmer-worker.ts — which is the actual source of the mojibake in the issue's screenshot. It also swapped glyphs unconditionally, degrading the macOS/Linux experience. This PR builds on the same idea (ASCII markers) but adds detection so non-Windows terminals keep the Unicode rendering, and extends coverage to every glyph in the CLI/installer/shimmer.

@Bortlesboat — thank you for the initial PR, credited in the CHANGELOG entry.

Test plan

  • npx vitest run __tests__/glyphs.test.ts — 13 new tests pinning detection + glyph contract
  • npm test — all 590 tests pass (no regressions in node-version-check, installer, mcp-initialize)
  • npm run build — clean tsc
  • Local smoke (macOS): default run shows │ ◆ — glyphs; CODEGRAPH_ASCII=1 switches to | * - ASCII fallback
  • @colbymchenry confirm on Windows PowerShell after merge

Closes #168

🤖 Generated with Claude Code

The shimmer progress renderer writes from a worker thread via
`fs.writeSync(1, ...)` to keep the animation smooth while the main
thread is busy in SQLite. That path bypasses Node's TTY-aware
UTF-8->codepage conversion on Windows, so glyphs like `|`/`<>`/`-`
were emitted as raw UTF-8 bytes and reinterpreted by the console's
OEM codepage (CP437, CP936, ...), producing strings like
`鋍?[0m 鉒?[0m Scanning files 鈥?N found`.

Add `src/ui/glyphs.ts` with `supportsUnicode()` detection plus
matched Unicode + ASCII glyph sets, and route all CLI/shimmer
output through `getGlyphs()`. Defaults: ASCII on Windows and on
Linux kernel consoles (`TERM=linux`), Unicode everywhere else.
`CODEGRAPH_UNICODE=1` and `CODEGRAPH_ASCII=1` are escape hatches.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Terminal output garbled/mojibake on Windows (PowerShell) during codegraph index

1 participant