Skip to content

fix(claude): read ticked [✔] boxes in multi-select questions - #169

Open
Luke-Norland wants to merge 1 commit into
devswha:mainfrom
Luke-Norland:fix/claude-multiselect-tick
Open

Luke-Norland wants to merge 1 commit into
devswha:mainfrom
Luke-Norland:fix/claude-multiselect-tick

Conversation

@Luke-Norland

@Luke-Norland Luke-Norland commented Oct 6, 2026 •

Copy link
Copy Markdown

Bug

Claude Code draws a ticked multi-select option as [✔] (U+2714, heavy check mark). The Claude card parser in tmux-interactive-prompt.service.ts recognises [x], [X] and [✓] (U+2713), but not [✔]. That has three effects:

  • checkedOptionIndices stays empty, so answerMultiSelect never unticks a box that was ticked in the terminal. Claude receives that box as well as the choice made in the chat card.
  • The label keeps the prefix ("[✔] Apple"), so the card shows the bracket. The prompt id is hashed from the labels, so it also changes whenever a box is ticked or unticked.
  • If every option is ticked, no row matches the multi-select detection. The question is then treated as single-select.

Reproduce

  1. In a Claude Code pane (checked on 2.1.291, default renderer, 64x31), ask for an AskUserQuestion with multiSelect: true and the options Apple, Banana, Cherry and Date.
  2. In the terminal, press Enter on Apple. The row now reads 1. [✔] Apple.
  3. Open the card in ChatMux. Apple is not shown as checked, and its label reads [✔] Apple.
  4. Select Banana and Date in the card and submit.

On main the response is 200 {"action":"selected"}, and Claude's tool_result is "Which fruits do you want?"="Apple, Banana, Date".

Fix

Accept ✔ wherever [x], [X] and [✓] are already accepted on this path: the checked test and the label strip in parseNumberedRows, and the multi-select detection in parseClaudeQuestion. [ ] stays unchecked. Nothing else changes.

Tests

New file server/modules/providers/tests/claude-multiselect.test.ts, with one fixture: a real capture-pane -p -e -N -S -80 capture of the question with Apple ticked in the terminal (fixtures/claude-multiselect/pretick.joined.ansi).

  • A [✔] row reads as checked: checkedChoiceNumbers: [1], and the labels are Apple, Banana, Cherry, Date.
  • Answering Banana + Date sends Enter, Down, Enter, Down, Down, Enter, Right, Enter. Replaying those keys from the captured state ends with exactly {Banana, Date} ticked.
  • On the same capture, [x], [X] and [✓] still parse as before: Apple checked, clean labels and the same prompt id.
  • The prompt id is the same with Apple ticked and unticked.
  • With all four options ticked, the question is still a multi-select.

On main all five fail. The only failure in the [x]/[X]/[✓] test is the id comparison with the [✔] capture; its other assertions already pass there. With the fix all five pass. The existing tmux-interactive-prompt.service.test.ts passes unchanged (14/14).

If ✔ is removed from the checked test only, 4 of the 5 new tests fail.

npm run typecheck and eslint on the touched files are clean.

End to end

These runs used a real Claude Code 2.1.291 in a private tmux server (64x31, default renderer) and a dev server from this branch. The card was read and answered through POST /api/providers/sessions/external/interactive and /respond. Between runs the pane got /clear and clear-history.

Run Code Pane state Card shows Answer tool_result
1 main Apple ticked checked [], label [✔] Apple Banana, Date "Apple, Banana, Date"
2 this branch Apple ticked checked [1], label Apple Banana, Date "Banana, Date"
3 this branch nothing ticked checked [] Apple, Cherry "Apple, Cherry"

Every answer returned 200 {"action":"selected"}.

Scope

The transcript-ask path (tmux-ask-selection.service.ts) does not handle multi-select questions, so only the card path is affected. The OMP/GJC glyph rows (☐/☑) are unchanged.

Summary by CodeRabbit

  • Bug Fixes
    • Claude multi-select prompts now recognize checked options marked with [✔] and display their labels without the marker.
    • Answers correctly update preselected choices, including unticking options that were already selected.
    • Multi-select detection works when all options are checked, while existing checkbox markers remain supported.

Claude Code draws a ticked multi-select option as `[✔]` (U+2714). The
card parser only recognised `[x]`, `[X]` and `[✓]`, so a box ticked in
the terminal read as unticked and its label kept the `[✔]` prefix.

When the user then answered from the chat card, the key plan never
toggled that box off. With Apple ticked in the pane, answering
Banana + Date from the card returned 200 and Claude received
"Apple, Banana, Date". The leftover prefix also changed the prompt id
whenever a box was ticked or unticked.

Accept `✔` wherever `[x]`, `[X]` and `[✓]` are accepted on this path:
the checked test, the label strip and the multi-select detection.
`[ ]` stays unchecked.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@coderabbitai

coderabbitai Bot commented Oct 6, 2026 •

Copy link
Copy Markdown

Review in Change Stack →

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration
  • Configuration used: defaults
  • Review profile: CHILL
  • Plan: Advanced
  • Run ID: a8ccb7b3-c331-4fb2-8f16-d15a908865a3
📥 Commits

Reviewing files that changed from the base of the PR and between b258b57 and 1a16044.

📒 Files selected for processing (3)
  • server/modules/providers/services/tmux-interactive-prompt.service.ts
  • server/modules/providers/tests/claude-multiselect.test.ts
  • server/modules/providers/tests/fixtures/claude-multiselect/pretick.joined.ansi

Included review availability: This review used your included allowance. Your plan provides up to 10 included reviews per hour; 8 remain after this review.


📝 Walkthrough

Walkthrough

The Claude prompt parser now recognizes [✔] as a checked option and as evidence of a multi-select prompt. Tests cover parsing, selection behavior, compatibility with other checkbox markers, and prompt ID stability.

Changes

Claude multi-select parsing

Layer / File(s) Summary
Recognize and test checked options
server/modules/providers/services/tmux-interactive-prompt.service.ts, server/modules/providers/tests/claude-multiselect.test.ts, server/modules/providers/tests/fixtures/claude-multiselect/pretick.joined.ansi
The parser recognizes [✔] as a checked option and as evidence of a multi-select prompt. Tests use a captured pane to check clean labels, prechecked options, marker compatibility, selection behavior, and prompt ID stability.

Priority: ⬇️ Low

Estimated code review effort: 2 (Simple) | ~10 minutes

Change: Bug fix

Merge Risk: ⚪ Minimal · up to 1a160

This change makes Claude multi-select cards read ticked [✔] boxes correctly. No merge-blocking risk was found.

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 25.00% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 4 functions across 2 files. (1 skipped: 1… Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly describes the main change: Claude multi-select parsing now recognizes ticked [✔] boxes.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Full details: Docstring Coverage

Explanation

Docstring coverage is 25.00% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 4 functions across 2 files. (1 skipped: 1 unsupported.)

  • Fix all pre-merge checks with AI
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create a new PR
  • Autopilot · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

Warning

Some tools did not complete. Review the errors below.

🔧 ESLint

If the error stems from missing dependencies, add them to the package.json file. For unrecoverable errors (e.g., due to private dependencies), disable the tool in the CodeRabbit configuration.

ESLint install timed out. The project may have too many dependencies for the sandbox.


Comment @coderabbitai help to get the list of available commands.

This branch has not been deployed

No deployments
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.

1 participant