Background
Qwen Code's TUI already has a well-established, consistent glyph vocabulary built entirely from Unicode text symbols:
> user message prefix
✦ assistant message prefix
● / ○ / ◐ completed / unselected / in-progress (todos, selections)
✓ success / checked
↓ / ↑ token flow direction
⠋ ⠙ ⠹ … braille spinner frames (ink-spinner)
░ ▒ ▓ █ progress / shade blocks
Every one of these is a narrow (width=1) text symbol that renders predictably across terminals, fonts, and CI logs.
Problem
Scattered emoji are used as status indicators and break this consistency. Unlike the rest of the glyph set, emoji have real technical downsides in a TUI:
- Column misalignment — emoji render at width=2 (e.g.
💡 = width 2) while every other glyph is width=1, so indented blocks drift depending on which code path rendered them.
- Inconsistent environment rendering — the current thinking icon already encodes this pain: it branches into three different outputs (
💡 / ⟡ / ``) based on CI / `LANG`, so the same thinking line occupies a different number of columns depending on where it runs.
- Font fallback risk — cold Unicode-emoji-presentation characters can render as tofu (
□) on terminals without a color emoji font.
- Visual style mismatch — a single colored emoji among a sea of monochrome text glyphs looks like a foreign object.
A repo-wide scan (packages/cli/src + packages/core/src, excluding tests) turns up 30+ emoji usages. This issue scopes the two highest-traffic, semantically unambiguous ones; the rest are listed as follow-up cleanup.
Scope of this issue (first batch)
1. Thinking block icon — 💡 → ∴
packages/cli/src/ui/components/messages/ConversationMessages.tsx defines:
const isUtf8 = /utf-?8/i.test(process.env['LANG'] || process.env['LC_ALL'] || '');
export const THINKING_ICON =
!process.env['CI'] && isUtf8 ? '💡 ' : isUtf8 ? '⟡ ' : '';
This is the single most visible emoji in the TUI (shown on every model reasoning turn) and the only one that already needed a three-way fallback.
Replace with the mathematical therefore sign ∴ (U+2234, width=1):
- It "sits" on a wide base (two dots down, one up) — a stable, upright glyph.
- Semantically
∴ means "therefore / hence", which is exactly what a thinking block is: the reasoning that leads to a conclusion.
- Belongs to the same text-symbol family as
✦, ✓, ●, so it no longer reads as a foreign object.
This also lets us delete the entire isUtf8 / CI branch and collapse THINKING_ICON to a single constant — ∴ renders the same everywhere.
Affected render sites (same file): collapsed, pending, and expanded thinking titles; plus ThinkingViewer.tsx header (imports THINKING_ICON).
2. Summary success icon — ✅ → ✓
packages/cli/src/ui/components/messages/SummaryMessage.tsx:
return <Text color={Colors.AccentGreen}>✅</Text>;
ToolMessage already uses ✓ in success color for the exact same "operation succeeded" semantics. ✅ is a redundant, emoji variant of a glyph we already standardized on. Replace with ✓ to match ToolMessage exactly.
Why these two first
- Highest visibility — thinking shows on (almost) every turn; summary shows whenever
/chat summary runs. These are the glyphs users see most.
- Semantically unambiguous replacement —
∴ (therefore) and ✓ (success) are not stylistic guesses; they map 1:1 to the existing meaning.
- Zero new glyph families introduced —
∴ sits next to ✦ in the text-symbol family; ✓ is already in use. No risk of creating a new island.
Follow-up cleanup (not in this PR)
Emoji also appear in these locations and should be addressed in subsequent PRs to fully converge on text symbols:
Footer.tsx — 🔒 connection indicator
views/McpStatus.tsx — 🟢 🔴 🔄 💡 MCP server status
commands/ideCommand.ts — 🟢 🟡 🔴 IDE connection status
hooks/useContextualTips.ts — 💡 tip copy
hooks/useGeminiStream.ts — 🔎 🚫 💡 loading phrases
components/WelcomeBackDialog.tsx — 👋 🎯 📋 welcome copy
core/agents/runtime/agent-statistics.ts — 📋 🔧 🔁 🔢 🚀 💡 (verify whether these surface in TUI or are internal labels)
core/tools/artifact-tool.ts — 📄
core/tools/shell.ts — 🤖
For status indicators (green/yellow/red dots), the project already has ● / ◐ in the right colors, which directly replace 🟢 🟡 🔴.
Proposed glyph mapping (recap)
| Current |
Replacement |
Note |
💡 thinking |
∴ |
therefore sign; drops the 3-way fallback |
✅ summary success |
✓ |
matches existing ToolMessage success glyph |
中文说明
背景
Qwen Code 的 TUI 已经建立了一套完整、统一的纯文本符号体系,全部由 Unicode 文本符号构成:>(用户消息)、✦(助手消息)、● ○ ◐(todo/选择态)、✓(成功)、↓ ↑(token 流向)、盲文 spinner(⠋⠙⠹…)、明暗块(░▒▓█)。这些符号宽度都是 1,在各终端、字体、CI 日志里渲染一致。
问题
少数 emoji 作为状态指示器散落其中,破坏了这套一致性。emoji 在 TUI 里有真实的技术缺陷:
- 列对齐错位:emoji 渲染宽度为 2(如
💡 占 2 列),而其他符号都是 1,导致缩进块在不同代码路径下偏移。
- 环境表现不一致:现有 thinking icon 已经反映了这个痛点——它根据
CI/LANG 分支成三套输出(💡 /⟡ /空),同一条 thinking 行在不同环境占不同列宽。
- 字体回退风险:冷门 emoji 字符在没有彩色 emoji 字体的终端上会显示成豆腐块(
□)。
- 风格割裂:一个彩色 emoji 夹在一群单色文本符号里,像外来物。
全仓库扫描(packages/cli/src + packages/core/src,排除测试)发现 30+ 处 emoji。本 issue 先聚焦最高频、语义最明确的两处,其余列为后续清理。
本次范围
1. Thinking icon — 💡 → ∴
用数学符号 ∴(U+2234,宽 1,"所以/因此")替换。理由:形状端坐(底宽顶尖)、语义上"因此"正对应 thinking 的"推出结论的推理"、与 ✦ ✓ ● 同属文本符号族。同时可删除 isUtf8/CI 三分支判断,把 THINKING_ICON 收敛成单常量。
2. Summary 成功 icon — ✅ → ✓
ToolMessage 成功态已经用 ✓(success 色),✅ 是多余且语义重复的 emoji 变体。直接对齐 ✓。
为什么先做这两处
- 曝光最高:thinking 几乎每轮都出现,summary 在
/chat summary 时出现。
- 替换语义无歧义:
∴(因此)、✓(成功)与现有含义 1:1 对应。
- 不引入新符号族:
∴ 紧邻 ✦,✓ 已在用,不会制造新孤岛。
后续清理(不在本次 PR)
Footer.tsx 🔒、McpStatus.tsx 🟢🔴🔄💡、ideCommand.ts 🟢🟡🔴(状态点,项目已有 ● ◐ 可直接替换)
useContextualTips.ts 💡、useGeminiStream.ts 🔎🚫💡、WelcomeBackDialog.tsx 👋🎯📋(文案类)
core 层 agent-statistics.ts artifact-tool.ts shell.ts 的 emoji(需确认是 TUI 渲染还是内部标签)
Background
Qwen Code's TUI already has a well-established, consistent glyph vocabulary built entirely from Unicode text symbols:
>user message prefix✦assistant message prefix●/○/◐completed / unselected / in-progress (todos, selections)✓success / checked↓/↑token flow direction⠋ ⠙ ⠹ …braille spinner frames (ink-spinner)░ ▒ ▓ █progress / shade blocksEvery one of these is a narrow (width=1) text symbol that renders predictably across terminals, fonts, and CI logs.
Problem
Scattered emoji are used as status indicators and break this consistency. Unlike the rest of the glyph set, emoji have real technical downsides in a TUI:
💡= width 2) while every other glyph is width=1, so indented blocks drift depending on which code path rendered them.💡/⟡/ ``) based onCI/ `LANG`, so the same thinking line occupies a different number of columns depending on where it runs.□) on terminals without a color emoji font.A repo-wide scan (
packages/cli/src+packages/core/src, excluding tests) turns up 30+ emoji usages. This issue scopes the two highest-traffic, semantically unambiguous ones; the rest are listed as follow-up cleanup.Scope of this issue (first batch)
1. Thinking block icon —
💡→∴packages/cli/src/ui/components/messages/ConversationMessages.tsxdefines:This is the single most visible emoji in the TUI (shown on every model reasoning turn) and the only one that already needed a three-way fallback.
Replace with the mathematical therefore sign
∴(U+2234, width=1):∴means "therefore / hence", which is exactly what a thinking block is: the reasoning that leads to a conclusion.✦,✓,●, so it no longer reads as a foreign object.This also lets us delete the entire
isUtf8/CIbranch and collapseTHINKING_ICONto a single constant —∴renders the same everywhere.Affected render sites (same file): collapsed, pending, and expanded thinking titles; plus
ThinkingViewer.tsxheader (importsTHINKING_ICON).2. Summary success icon —
✅→✓packages/cli/src/ui/components/messages/SummaryMessage.tsx:ToolMessagealready uses✓in success color for the exact same "operation succeeded" semantics.✅is a redundant, emoji variant of a glyph we already standardized on. Replace with✓to matchToolMessageexactly.Why these two first
/chat summaryruns. These are the glyphs users see most.∴(therefore) and✓(success) are not stylistic guesses; they map 1:1 to the existing meaning.∴sits next to✦in the text-symbol family;✓is already in use. No risk of creating a new island.Follow-up cleanup (not in this PR)
Emoji also appear in these locations and should be addressed in subsequent PRs to fully converge on text symbols:
Footer.tsx—🔒connection indicatorviews/McpStatus.tsx—🟢🔴🔄💡MCP server statuscommands/ideCommand.ts—🟢🟡🔴IDE connection statushooks/useContextualTips.ts—💡tip copyhooks/useGeminiStream.ts—🔎🚫💡loading phrasescomponents/WelcomeBackDialog.tsx—👋🎯📋welcome copycore/agents/runtime/agent-statistics.ts—📋🔧🔁🔢🚀💡(verify whether these surface in TUI or are internal labels)core/tools/artifact-tool.ts—📄core/tools/shell.ts—🤖For status indicators (green/yellow/red dots), the project already has
●/◐in the right colors, which directly replace🟢🟡🔴.Proposed glyph mapping (recap)
💡thinking∴✅summary success✓ToolMessagesuccess glyph中文说明
背景
Qwen Code 的 TUI 已经建立了一套完整、统一的纯文本符号体系,全部由 Unicode 文本符号构成:
>(用户消息)、✦(助手消息)、● ○ ◐(todo/选择态)、✓(成功)、↓ ↑(token 流向)、盲文 spinner(⠋⠙⠹…)、明暗块(░▒▓█)。这些符号宽度都是 1,在各终端、字体、CI 日志里渲染一致。问题
少数 emoji 作为状态指示器散落其中,破坏了这套一致性。emoji 在 TUI 里有真实的技术缺陷:
💡占 2 列),而其他符号都是 1,导致缩进块在不同代码路径下偏移。CI/LANG分支成三套输出(💡/⟡/空),同一条 thinking 行在不同环境占不同列宽。□)。全仓库扫描(
packages/cli/src+packages/core/src,排除测试)发现 30+ 处 emoji。本 issue 先聚焦最高频、语义最明确的两处,其余列为后续清理。本次范围
1. Thinking icon —
💡→∴用数学符号
∴(U+2234,宽 1,"所以/因此")替换。理由:形状端坐(底宽顶尖)、语义上"因此"正对应 thinking 的"推出结论的推理"、与✦ ✓ ●同属文本符号族。同时可删除isUtf8/CI三分支判断,把THINKING_ICON收敛成单常量。2. Summary 成功 icon —
✅→✓ToolMessage成功态已经用✓(success 色),✅是多余且语义重复的 emoji 变体。直接对齐✓。为什么先做这两处
/chat summary时出现。∴(因此)、✓(成功)与现有含义 1:1 对应。∴紧邻✦,✓已在用,不会制造新孤岛。后续清理(不在本次 PR)
Footer.tsx🔒、McpStatus.tsx🟢🔴🔄💡、ideCommand.ts🟢🟡🔴(状态点,项目已有● ◐可直接替换)useContextualTips.ts💡、useGeminiStream.ts🔎🚫💡、WelcomeBackDialog.tsx👋🎯📋(文案类)core层agent-statistics.tsartifact-tool.tsshell.ts的 emoji(需确认是 TUI 渲染还是内部标签)