Skip to content

fix(cli): make alt+t expand thinking on macOS Option-compose terminals - #5872

Merged
chiga0 merged 1 commit into
QwenLM:mainfrom
chiga0:fix/alt-t-thinking-macos-option
Jun 25, 2026
Merged

fix(cli): make alt+t expand thinking on macOS Option-compose terminals#5872
chiga0 merged 1 commit into
QwenLM:mainfrom
chiga0:fix/alt-t-thinking-macos-option

Conversation

@chiga0

@chiga0 chiga0 commented Jun 25, 2026

Copy link
Copy Markdown
Collaborator

What this PR does

Fixes the "expand thinking" shortcut (Alt+t) on macOS terminals that use the default "Option as compose character" mode — specifically iTerm2 (Normal mode) and VS Code's integrated terminal (without macOptionIsMeta). These terminals deliver Option+t as the dagger glyph (U+2020) with no modifier metadata, so the app can't tell Option was held — the shortcut silently typed into the prompt instead of toggling the thinking summary. The fix rewrites a lone to a synthetic Alt+t in the keypress pipeline, scoped to darwin only. Terminals that speak the Kitty keyboard protocol (e.g. Ghostty) already report a real Alt+t event and are unaffected.

Why it's needed

The thinking summary UI shows (alt+t to expand) but the shortcut only worked in Ghostty and terminals configured with "Option as Meta". Most macOS users on iTerm2 or VS Code — the two most popular terminals — would press Alt+t and get a inserted into their prompt instead. This makes the shortcut work everywhere without requiring users to reconfigure their terminal's Option key behavior.

Reviewer Test Plan

How to verify

  1. Open iTerm2 with default settings (Option key = Normal) or VS Code integrated terminal.
  2. Run qwen and trigger a response that shows the thinking summary (∴ Thought for Xs (alt+t to expand)).
  3. Press Option+t — the thinking block should expand/collapse. Previously it typed into the prompt.
  4. Confirm the same shortcut still works in Ghostty (no regression on Kitty protocol path).

Evidence (Before & After)

Before: Option+t in iTerm2/VS Code inserts into the prompt; thinking summary does not expand.
After: Option+t in iTerm2/VS Code toggles the thinking summary, matching Ghostty behavior.

Tested on

OS Status
🍏 macOS
🪟 Windows N/A
🐧 Linux N/A

Environment (optional)

iTerm2 (default Option=Normal), VS Code integrated terminal, Ghostty — all on macOS.

Risk & Scope

  • Main risk or tradeoff: A legitimate character typed via other means on macOS would also be rewritten to Alt+t. This is extremely unlikely in practice since is rarely typed in a terminal coding context.
  • Not validated / out of scope: Non-macOS platforms (the fix is scoped to darwin).
  • Breaking changes / migration notes: None.

Linked Issues

中文说明

本 PR 做了什么

修复了 macOS 终端在默认"Option 作为组合字符"模式下(iTerm2 的 Normal 模式和 VS Code 集成终端未开启 macOptionIsMeta 时),Alt+t 展开思考摘要快捷键无效的问题。这些终端将 Option+t 转换为匕首符号 (U+2020),且不携带修饰键信息,导致应用无法识别 Option 键被按下——快捷键会静默地将 输入到提示符中,而非展开思考摘要。修复方案是在按键管道中将单独的 重写为合成的 Alt+t,仅在 darwin 平台生效。使用 Kitty 键盘协议的终端(如 Ghostty)已经上报真实的 Alt+t 事件,不受影响。

为什么需要这个改动

思考摘要 UI 显示了 (alt+t to expand) 提示,但该快捷键只在 Ghostty 和配置了"Option as Meta"的终端中有效。大多数 macOS 用户使用 iTerm2 或 VS Code——这两个最流行的终端——按下 Alt+t 后只会在提示符中插入 。此修复让快捷键在所有终端中都能正常工作,无需用户修改终端的 Option 键配置。

审阅者测试计划

  1. 打开 iTerm2(默认设置,Option 键 = Normal)或 VS Code 集成终端。
  2. 运行 qwen,触发一个包含思考摘要的响应(∴ Thought for Xs (alt+t to expand))。
  3. Option+t——思考块应展开/折叠。此前会输入 到提示符中。
  4. 确认 Ghostty 中快捷键仍然正常(Kitty 协议路径无回归)。

测试环境

系统 状态
🍏 macOS
🪟 Windows N/A
🐧 Linux N/A

风险与范围

  • 主要风险:在 macOS 上通过其他方式输入的合法 字符也会被重写为 Alt+t。实际风险极低,因为终端编码场景中几乎不会输入
  • 未验证/不在范围内:非 macOS 平台(修复仅限于 darwin)。
  • 破坏性变更/迁移说明:无。

On macOS, terminals in the default "Option as compose character" mode
(iTerm2 "Normal", VS Code without macOptionIsMeta) turn Option+t into the
dagger glyph "†" (U+2020) with no modifier metadata, so the app cannot tell
Option was held — the "expand thinking" shortcut silently typed "†" into the
prompt instead of toggling. Terminals that speak the Kitty keyboard protocol
(e.g. Ghostty) report a real Alt+t event, which is why it already worked there.

Rewrite a lone "†" to a synthetic Alt+t in the keypress pipeline. This both
fires TOGGLE_THINKING_EXPANDED and, via the meta flag, stops the glyph from
being inserted into the input buffer, so it behaves exactly like Alt+t. Scoped
to darwin to avoid affecting legitimate "†" input on other platforms.

Generated with AI

Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>

@qwen-code-ci-bot qwen-code-ci-bot left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the PR! The technical approach looks solid — rewriting the compose glyph to a synthetic Alt+t in the keypress pipeline is a clean, minimal fix for a real macOS terminal pain point.

However, the PR body doesn't follow the PR template. A few required sections are missing:

  • Reviewer Test Plan (with How to verify, Evidence (Before & After), and Tested on table) — this is the most important missing piece. Maintainers use it to confirm the fix works before merging.
  • Risk & Scope — what are the tradeoffs, what's out of scope, any breaking changes?
  • Linked Issues — is there an open issue this closes?

Could you restructure the PR body to match the template? The technical content you've already written (root cause analysis, the fix, the test results) maps naturally onto the template sections.

中文说明

感谢贡献!技术方案本身很棒——在按键处理管道中将 组合字符改写为合成的 Alt+t,是解决 macOS 终端 Option 键编码问题的简洁方案。

但 PR 正文没有按照 PR 模板 来写,缺少几个必填部分:

  • Reviewer Test Plan(包含 How to verifyEvidence (Before & After)Tested on 表格)——这是最重要的缺失部分,维护者需要通过它来确认修复有效后再合并。
  • Risk & Scope——有哪些取舍?哪些不在范围内?是否有破坏性变更?
  • Linked Issues——是否有关联的 issue?

能否按模板重新组织 PR 正文?你已经写好的技术内容(根因分析、修复方案、测试结果)可以很自然地映射到模板的各个部分。

Qwen Code · qwen3.7-max

@chiga0 chiga0 left a comment

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Overview

Final Verdict: LGTM — Clean, surgical fix for a real macOS terminal pain point. The root cause analysis is thorough (Option-as-compose encoding difference, not a key-parsing bug), and the fix follows the existing alt+return normalization pattern already in the codebase.

Findings Summary

  • Critical/Major: 0 items
  • Minor: 0 items
  • Nit: 0 items

Key Observations

The fix is minimal and well-scoped: one glyph rewrite ( → Alt+t) in the keypress pipeline, guarded by process.platform === 'darwin' and !isPaste. Setting meta: true achieves both goals simultaneously — fires TOGGLE_THINKING_EXPANDED and prevents glyph insertion into the input buffer. Terminals that already work (Ghostty via Kitty protocol, Option-as-Meta via ESC t) never hit this branch.

Additional Audit Coverage

  • Paste mode guard: !isPaste correctly prevents in pasted content from being rewritten on macOS. Pasted dagger glyphs pass through unchanged.
  • Platform scoping: process.platform === 'darwin' is the correct check. Linux/Windows users typing (e.g., via compose key or character picker) are unaffected.
  • False positive risk: A macOS user deliberately typing into the prompt would have it intercepted. Extremely unlikely edge case, and the trade-off is well-justified — the (alt+t to expand) hint is now accurate on every terminal.
  • Precedent: Follows the exact same pattern as the existing alt+return normalization (key.name === 'return' && key.sequence === '\x1b\r' → key.meta = true) two lines above. Consistent with codebase conventions.
  • Test quality: Tests mock process.platform with Object.defineProperty + finally cleanup. Both positive (darwin rewrite) and negative (linux passthrough) paths covered. Test structure mirrors existing Kitty protocol tests.

This review was generated by QoderWork AI

@chiga0
chiga0 requested a review from qwen-code-ci-bot June 25, 2026 13:08
@chiga0

chiga0 commented Jun 25, 2026

Copy link
Copy Markdown
Collaborator Author

@qwen-code-ci-bot /triage

@yiliang114 yiliang114 left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM, looks ready to ship. ✅

@yiliang114

Copy link
Copy Markdown
Collaborator

@qwen-code /triage

@qwen-code-ci-bot qwen-code-ci-bot left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No review findings at blocker level. The → Alt+t rewrite is correctly placed and well-tested.

A few minor defensive suggestions for consideration (not blockers):

  • Modifier guard: Consider adding !key.ctrl && !key.shift && !key.meta to the rewrite condition. Compose-mode terminals deliver with all modifiers false, so this is consistent today, but the defensive check is cheap.
  • Name guard: Consider adding key.name === '' to assert the compose-character assumption explicitly.
  • Follow-up: The same compose-character problem affects Alt+m (Option+m → µ). Consider tracking this in a follow-up issue.

— qwen3.7-max via Qwen Code /review

@qwen-code-ci-bot

Copy link
Copy Markdown
Collaborator

Thanks for the PR, @chiga0!

Template looks good ✓ — all required sections present.

Direction: This fixes a real pain point. The alt+t shortcut is advertised in the UI as "(alt+t to expand)" but silently fails on the two most popular macOS terminals (iTerm2 default + VS Code integrated). Claude Code's own CHANGELOG has the exact same fix ("Fixed Alt+T (thinking toggle) not working on macOS terminals without 'Option as Meta' enabled"), so this is well-validated territory. Clearly aligned.

Approach: The scope is tight — one constant, one conditional block, two tests. The rewrite sits right next to the existing ESC+\r → meta+return workaround in KeypressContext, which is the natural home for it. No scope creep, no unrelated changes.

The acknowledged tradeoff (a legitimate typed on macOS would be consumed as Alt+t) is acceptable — dagger glyphs in terminal coding sessions are vanishingly rare, and users who need can paste it.

Moving on to code review. 🔍

中文说明

感谢贡献,@chiga0

模板完整 ✓

方向: 这修复了一个真实的痛点。UI 中展示了 (alt+t to expand) 快捷键,但在 macOS 最常用的两个终端(iTerm2 默认配置和 VS Code 集成终端)上完全不生效。Claude Code 自己的 CHANGELOG 里也有完全相同的修复记录("Fixed Alt+T (thinking toggle) not working on macOS terminals without 'Option as Meta' enabled"),方向已经充分验证。

方案: 范围控制得很好——一个常量、一个条件块、两个测试。改写逻辑放在 KeypressContext 里已有的 ESC+\r → meta+return 变通方案旁边,位置很自然。没有范围蔓延,没有无关改动。

已知的权衡(在 macOS 上合法输入的 会被当作 Alt+t 消费掉)可以接受——在终端编码场景中几乎不会用到匕首符号,需要 的用户可以通过粘贴输入。

进入代码审查 🔍

Qwen Code · qwen3.7-max

@qwen-code-ci-bot

Copy link
Copy Markdown
Collaborator

Code Review

Independent proposal (before reading the diff): To fix the macOS Option-as-compose-character issue for Alt+t, I would intercept the (U+2020) glyph in the keypress handler and rewrite it to a synthetic Alt+t event, scoped to darwin only. Place it in KeypressContext.tsx next to the existing ESC+\r → meta+return workaround, which is the same pattern. Add a constant for the glyph and tests for both platforms.

Comparison: The PR's approach matches this exactly. Two files, +115/-0, focused entirely on the one fix:

  • Constant OPTION_T_COMPOSED_GLYPH — well-named, with a thorough block comment explaining the terminal behavior that motivates it.
  • Rewrite logicprocess.platform === 'darwin' && !isPaste && key.sequence === '†' → set key.name = 't' and key.meta = true. The !isPaste guard prevents interference with paste events. The meta: true flag both triggers the TOGGLE_THINKING_EXPANDED binding and prevents the glyph from being inserted as text input (the text buffer skips printable input when meta/ctrl is set). Clean and correct.
  • Placement — right after the ESC+\rmeta+return rewrite, which is the exact same pattern. Follows existing conventions.
  • Tests — Two new tests: darwin rewrites to Alt+t ✓, linux leaves untouched ✓. Both use Object.defineProperty on process.platform with proper cleanup in finally. Correct mock pattern for the test infrastructure.

No critical bugs, no security concerns, no AGENTS.md violations. Every edit serves the stated goal — no drive-by refactors, no scope creep.

Reuse Check

The OPTION_T_COMPOSED_GLYPH constant and rewrite block are specific to this one keybinding workaround. No existing utility covers this. Nothing to reuse or extract.

Unit Test Results

Applied the PR patch on top of main and ran the test suite:

Test File Tests Status
KeypressContext.test.tsx (93 existing + 2 new) 95 ✅ All pass

TypeScript typecheck: clean, no errors.

Real-Scenario Testing (tmux)

Note: This fix is macOS-specific (process.platform === 'darwin'). The test environment is Linux, so the Alt+t rewrite cannot be triggered here. The tmux test below verifies the baseline: Alt+t works on Linux (terminals correctly send ESC+t), and the thinking summary UI with "(alt+t to expand)" is displayed properly.

Baseline: interactive mode with thinking prompt

  > what is the capital of France? think step by step

  ∴ Thought for 0s (alt+t to expand)

  ✦ Paris

After pressing Alt+t (thinking block expanded)

  > what is the capital of France? think step by step

  ∴ Thought for 0s (alt+t to collapse)
    The user is asking a simple geography question. No tools needed.

  ✦ Paris

The Alt+t shortcut correctly toggles the thinking block. On Linux this works natively; on macOS without this fix, Option+t would type instead. The PR's rewrite bridges that gap.

Verdict: Code is clean, tests pass, the fix is minimal and well-placed. The only thing this environment can't verify is the actual macOS terminal behavior — that requires a macOS reviewer to confirm.

中文说明

代码审查

独立方案(阅读 diff 前): 修复 macOS Option 组合字符模式下 Alt+t 的问题:在按键处理器中拦截 (U+2020)字符并重写为合成的 Alt+t 事件,仅限 darwin 平台。放在 KeypressContext.tsx 中已有的 ESC+\r → meta+return 变通方案旁边,模式完全一致。

对比: PR 的方案与此完全一致。两个文件,+115/-0,完全聚焦于这一个修复:

  • 常量 OPTION_T_COMPOSED_GLYPH — 命名清晰,附有详细的注释说明终端行为。
  • 重写逻辑process.platform === 'darwin' && !isPaste && key.sequence === '†' → 设置 key.name = 't'key.meta = true!isPaste 防止干扰粘贴事件。meta: true 既触发 TOGGLE_THINKING_EXPANDED 绑定,又阻止字符作为文本输入。
  • 位置 — 紧接在 ESC+\rmeta+return 重写之后,完全相同的模式。
  • 测试 — 两个新测试:darwin 将 重写为 Alt+t ✓,linux 保持 不变 ✓。

无关键 bug、无安全问题、无 AGENTS.md 违规。 每个编辑都服务于目标。

单测结果

将 PR 补丁应用到 main 上运行测试:95 个测试全部通过(93 个已有 + 2 个新增)。TypeScript 类型检查:无错误。

真实场景测试(tmux)

注意: 此修复仅限 macOS。测试环境为 Linux,无法触发 Alt+t 重写。tmux 测试验证了基线行为:Alt+t 在 Linux 上正常工作。

基线: 交互模式下思考摘要正常显示 "(alt+t to expand)"。
按 Alt+t 后: 思考块正确展开,提示变为 "(alt+t to collapse)"。

结论: 代码整洁、测试通过、修复最小且位置合理。唯一无法验证的是 macOS 终端的实际行为,需要 macOS 审阅者确认。

Qwen Code · qwen3.7-max

@qwen-code-ci-bot

Copy link
Copy Markdown
Collaborator

Stepping back: this is exactly the kind of PR you want to see from a community contributor. The root cause analysis is spot-on — macOS terminals in default "Option as compose character" mode silently convert Option+t to the dagger glyph , and the fix intercepts this at the right layer (the keypress pipeline, next to an identical workaround for ESC+\r).

The implementation matches my independent proposal exactly. One constant, one conditional block, two tests — 9 lines of production code that solve the problem without touching anything else. The !isPaste guard, the meta: true flag that both fires the binding and prevents text insertion, the darwin scope — all correct on inspection.

95 unit tests pass (93 existing + 2 new), typecheck is clean, and the tmux baseline on Linux confirms the Alt+t → thinking toggle path works correctly. The only gap is that we can't verify the actual macOS behavior from this Linux CI — a macOS reviewer needs to confirm that one.

The prior CHANGES_REQUESTED review was about template completeness — the author has since addressed that. Maintainer @yiliang114 has already approved.

If I had to maintain this in six months, I'd thank the author — the constant name and block comment tell the whole story of why this exists, so no one has to rediscover the terminal encoding rabbit hole.

Approving. ✅

中文说明

退一步看:这正是社区贡献者应该提交的 PR 类型。根因分析准确——macOS 终端在默认"Option 作为组合字符"模式下会将 Option+t 静默转换为匕首符号 ,修复在正确的层级(按键处理管道,紧挨着已有的 ESC+\r 变通方案)拦截了这个问题。

实现与我的独立方案完全一致。一个常量、一个条件块、两个测试——9 行生产代码解决问题,没有触及其他任何东西。!isPaste 守卫、meta: true 既触发绑定又阻止文本插入、darwin 作用域——检查后全部正确。

95 个单测通过(93 已有 + 2 新增),类型检查通过,Linux 上的 tmux 基线测试确认 Alt+t → 思考切换路径正常工作。唯一的限制是无法从这个 Linux CI 验证实际的 macOS 行为——需要 macOS 审阅者确认。

之前的 CHANGES_REQUESTED 评审是关于模板完整性的——作者已经解决了。维护者 @yiliang114 已经批准。

如果六个月后需要维护这个代码,我会感谢作者——常量名和注释块完整解释了为什么需要这个改动,不需要重新发现终端编码的问题。

批准 ✅

Qwen Code · qwen3.7-max

@qwen-code-ci-bot qwen-code-ci-bot left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM, looks ready to ship. ✅

@chiga0
chiga0 added this pull request to the merge queue Jun 25, 2026

@qwen-code-ci-bot qwen-code-ci-bot left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No review findings. Downgraded from Approve to Comment: CI still running.

The → Alt+t rewrite is correctly placed after all early-return paths, well-guarded with process.platform === 'darwin' and !isPaste, and the key object mutation follows the existing pattern (e.g. the return-key meta rewrite above). Tests cover both the darwin positive case and the linux negative case with proper platform restoration. The !key.meta insert guard in text-buffer.ts correctly prevents the stale key.sequence from leaking into the input buffer.

LGTM ✅

— qwen3.7-max via Qwen Code /review

Merged via the queue into QwenLM:main with commit ecdf470 Jun 25, 2026
64 checks passed
);
});

it('rewrites macOS composed Option+t glyph "†" to Alt+t', () => {

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[Suggestion] These two compose-glyph rewrite tests are placed inside describe('Enter key handling') but test macOS Option+t glyph rewriting, which is unrelated to Enter key handling. Moving them to their own describe('macOS compose-glyph rewrite') block would improve discoverability and match the file's convention of grouping tests by concern area (Escape, Tab/Backspace, paste mode, etc.).

— qwen3.7-max via Qwen Code /review

if (
process.platform === 'darwin' &&
!isPaste &&
key.sequence === OPTION_T_COMPOSED_GLYPH

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[Suggestion] Consider adding a key.name === '' guard to the condition, matching the pattern already used for the backslash handler (~line 869: key.sequence === '\\' && !key.name). This ensures the rewrite only fires when the terminal did not recognize the keypress (empty name), preventing edge cases where a kitty-protocol fall-through or buffer overflow path delivers a pre-decoded character with name: '†'.

Suggested change
key.sequence === OPTION_T_COMPOSED_GLYPH
process.platform === 'darwin' &&
!isPaste &&
key.name === '' &&
key.sequence === OPTION_T_COMPOSED_GLYPH

— qwen3.7-max via Qwen Code /review

@chiga0
chiga0 deleted the fix/alt-t-thinking-macos-option branch June 26, 2026 02:59
pull Bot pushed a commit to Stars1233/qwen-code that referenced this pull request Jun 26, 2026
Both the triage job and the PR-review job run the qwen agent directly on
the persistent self-hosted ECS pool with no per-run isolation. $HOME,
/tmp and the workspace are reused between runs, so a prior run's agent
session/memory (default ~/.qwen) or leftover draft comments
(/tmp/stage-*.md, which survive git clean) can bleed into the next run.

This surfaced on QwenLM#5874: its triage posted QwenLM#5872's review verbatim
(wrong author, wrong approver, wrong diff), while the same run's internal
stage actually exercised QwenLM#5874 — the PR id was correct, the agent state
was stale.

Point QWEN_HOME at a per-run $RUNNER_TEMP/qwen-home on the Qwen step and
reset it (plus /tmp/stage-*.md) in the pre-run cleanup, for both jobs.
QWEN_HOME relocates the entire global qwen dir (storage.ts), so this
isolates sessions/memory/temp without touching $HOME and disturbing
git/npm. The tmux-testing job is already container-isolated and unchanged.

Refs QwenLM#5882
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.

3 participants