Skip to content

feat: tell Sonara which question of Claude Code's question widget is on screen (#235) - #236

Merged
Maxaubert merged 2 commits into
mainfrom
feat/sonara-question-follow
Oct 16, 2026
Merged

Maxaubert merged 2 commits into
mainfrom
feat/sonara-question-follow

Conversation

@Maxaubert

Copy link
Copy Markdown
Owner

Summary

Closes #235. Prism Terminal side of Sonara #323 (plan: Maxaubert/Sonara docs/plans/2026-10-16-question-follow.md, approved by the owner 2026-10-16). Sonara side: Maxaubert/Sonara#327.

Claude Code tells its plugins nothing while the user moves between the questions of one AskUserQuestion, so Sonara could not read the question the user is on. The tab can see it:

  • core/renderer/questionWidget.ts reads the question under the widget's tab row (← ☐ Colour ☐ Size ✔ Submit →) off the visible rows: wrapped │ lines joined, and the "Review your answers" screen. Pure, tested on the screens a probe measured (Claude Code 2.1.301; 120 and 70 columns; one-line, wrapped, multi-select; typing an answer; review).
  • core/renderer/questionWatch.ts watches each session after output settles (150 ms) and reports a change once.
  • term:question carries it to main; core/main/sonaraLink.ts posts it to the Sonara on 127.0.0.1 named by its runtime.json. No Sonara: nothing is sent, and every failure is quiet.
  • PRISM_TAB_ID: every shell, warm or not, carries a random id (ptyEnv). Sonara's hook already reads it into the session's host tab, so the post names the tab. An inherited value is never kept.

This is a core change, so it ships to Prism too. Prism's host bridge (createTermApi, registerTermIpc) gets it with nothing to add, and termQuestion is optional on TermApi.

Tests

  • Unit: questionWidget (7), questionWatch (3), sonaraLink (3, a stand-in Sonara over HTTP), ptyEnv (tab id). npm test: 161 files, 2170 tests pass. Typecheck and lint are clean (only the existing warnings).
  • e2e sonaraQuestion (new): a stand-in program draws the widget and a stand-in Sonara records the posts: one per change of question, none for a redraw, the review last, always one tab id. All 10 checks pass.
  • Full npm run e2e: two older scenarios (launchSkeleton, restore) failed when another Claude session ran this repo's e2e at the same time (one app instance); restore passed alone afterwards.

PRIVACY.md (the localhost request), core/README.md (the contract). Core 0.41.0, app 0.54.0.

The owner tests before merge (a test copy of this build, beside Stable).

🤖 Generated with Claude Code

https://claude.ai/code/session_014cnwwWNiEmM5ghBD933h59

Maxaubert and others added 2 commits October 16, 2026 05:00
…on screen (#235)

Claude Code tells its plugins nothing while the user moves between the
questions of one AskUserQuestion, so Sonara (the text-to-speech reader)
could not read the question the user is on (Sonara #323; plan approved by
the owner 2026-10-16). The tab can:

- core/renderer/questionWidget.ts reads the question under the widget's
  tab row off the visible rows (wrapped "│" lines joined; the review
  screen), tested on the screens a probe measured (Claude Code 2.1.301,
  120 and 70 columns, one-line, wrapped, multi-select, typing, review).
- core/renderer/questionWatch.ts watches a session after output settles
  (150 ms) and reports a change once.
- term:question carries it to main; core/main/sonaraLink.ts posts it to
  the Sonara on 127.0.0.1 named by its runtime.json (SONARA_HOME, else
  %LOCALAPPDATA%\Sonara). No Sonara: nothing is sent; failures are quiet.
- Each shell, warm or not, carries a random PRISM_TAB_ID (ptyEnv); Sonara's
  hook reads it into the session's host tab, and the post names the tab by
  it. An inherited PRISM_TAB_ID is never kept.

Tests: questionWidget (7), questionWatch (3), sonaraLink (3), ptyEnv; e2e
sonaraQuestion (a stand-in widget and a stand-in Sonara: one post per
change, the review last, one tab id). PRIVACY.md (the localhost request),
core/README.md (the contract). Core 0.41.0, app 0.54.0.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_014cnwwWNiEmM5ghBD933h59
…0.41.0)

Both sides added to TerminalPanel's session setup (the question watch and the
agent copy watch); both kept. App 0.54.0 was taken on main by #237.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017XYVRPzvhLpPCr75uB6uaA
@Maxaubert
Maxaubert merged commit 12ed156 into main Oct 16, 2026
2 checks passed
github-actions Bot pushed a commit that referenced this pull request Oct 16, 2026
…on screen (#235) (#236)

Claude Code tells its plugins nothing while the user moves between the
questions of one AskUserQuestion, so Sonara (the text-to-speech reader)
could not read the question the user is on (Sonara #323; plan approved by
the owner 2026-10-16). The tab can:

- core/renderer/questionWidget.ts reads the question under the widget's
  tab row off the visible rows (wrapped "│" lines joined; the review
  screen), tested on the screens a probe measured (Claude Code 2.1.301,
  120 and 70 columns, one-line, wrapped, multi-select, typing, review).
- core/renderer/questionWatch.ts watches a session after output settles
  (150 ms) and reports a change once.
- term:question carries it to main; core/main/sonaraLink.ts posts it to
  the Sonara on 127.0.0.1 named by its runtime.json (SONARA_HOME, else
  %LOCALAPPDATA%\Sonara). No Sonara: nothing is sent; failures are quiet.
- Each shell, warm or not, carries a random PRISM_TAB_ID (ptyEnv); Sonara's
  hook reads it into the session's host tab, and the post names the tab by
  it. An inherited PRISM_TAB_ID is never kept.

Tests: questionWidget (7), questionWatch (3), sonaraLink (3), ptyEnv; e2e
sonaraQuestion (a stand-in widget and a stand-in Sonara: one post per
change, the review last, one tab id). PRIVACY.md (the localhost request),
core/README.md (the contract). Core 0.41.0, app 0.54.0.


Claude-Session: https://claude.ai/code/session_014cnwwWNiEmM5ghBD933h59

Co-authored-by: Claude Opus 5.5 <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.

Tell Sonara which question of Claude Code's question widget is on screen

1 participant