feat(diagnostics): render the session as a real terminal - #25
Merged
Conversation
診断面のセッション出力が制御コードの羅列になって読めない問題の修正。 原因は精度ではなく方式。従来は制御シーケンスを除去して行を追記する行指向の 扱いをしていたが、Claude Code はフルスクリーンの TUI であり、カーソル移動・ 画面消去・部分再描画・代替スクリーンバッファを前提に出力する。行の連なりでは ないため、除去して追記すると再描画の断片が積み上がるだけになる。行指向の 表示器で TUI を映そうとしていること自体が誤りだった。 xterm.js + addon-fit に置き換えた。liplus-desktop で実績のある構成で、依存も その二つに留めている。pty-data は terminal.write、キー入力は onData から write_pty、リサイズは fit + ResizeObserver から resize_pty。Ctrl+V は webview が native paste を端末へ渡さないため clipboard plugin で橋渡しする。 これに伴い、制御シーケンス除去のコードと専用キーボタン(Enter / 矢印 / Esc / Ctrl+C)を削除した。端末が直接キーを受けるため不要になった。 仕様上の位置づけを docs で明示した。却下されている設計は「アプリが CLI の出力を 解析して発言を取り出す」ものであり、端末表示はそれに当たらない。部屋に並ぶ 発言は channel notification と say_to_room からのみ来る。端末は表示器であって 情報源ではない。会話面に端末を置かないことは維持している。 従来の一文は「ターミナルエミュレータを置かない制約と衝突しない」と書いており、 出力解析の禁止と端末表示の禁止を混同しうる形だった。axis を分けて書き直した。 #24
smileygames
commented
Aug 21, 2026
smileygames
left a comment
Member
Author
There was a problem hiding this comment.
AI self-review (execution_mode = auto)
受け入れ条件の照合(issue #24 完了条件)
| 条件 | 結果 | 根拠 |
|---|---|---|
| CLI の TUI が崩れずに表示される | 実装済 / 実機未確認 | xterm.js が制御シーケンスを解釈する。実際の描画は Master の実機でのみ確認できる |
| 端末へ直接キー入力でき、確認プロンプトに答えられる | 実装済 / 実機未確認 | terminal.onData → write_pty。Ctrl+V は clipboard plugin 経由 |
| ウィンドウのリサイズが CLI 側へ伝わる | 実装済 / 実機未確認 | fitAddon + ResizeObserver → resize_pty。起動時も端末の実サイズを start_session へ渡す |
| 制御シーケンス除去のコードと専用キーボタンが削除されている | pass | session-log / session-keys / session-input への参照がリポジトリ全体で 0 件。CSI / OSC パターンと行バッファも削除 |
| 部屋のメッセージ経路が channel 由来のみであることが docs で読み取れる | pass | docs/0-requirements.md に却下設計と採用設計を並べて明示 |
制約の照合
- 会話面に端末を置かない: pass。
#roomはroom-messageのみを描画し、端末は#diagnostics配下。 - 部屋のメッセージ経路を変更しない: pass。
appendMessageの入力はroom-messageイベントのみで、端末出力を読む箇所は存在しない。 - 依存は 2 つのみ: pass。
@xterm/xtermと@xterm/addon-fit。clipboard plugin は既存の依存で、capability もclipboard-manager:allow-read-textが既に入っている。
仕様条項の書き換えについて
docs/0-requirements.md の該当箇所は、私が #18 で書いた「ターミナルエミュレータを置かない制約と衝突しない」という一文だった。この書き方は、出力解析の禁止と端末表示の禁止を一つの語で括っており、読み手によってはどちらの禁止とも取れる。制約節そのものには「ターミナルエミュレータを置かない」条項は無く、あるのは出力解析を情報源にしないという条項のみ。
したがって今回の変更は制約の緩和ではなく、緩い記述を axis ごとに分けたもの。#10 の issue 本文には制約として書いていたため、そこからの変更であることは明示した。
検証
- CI 全ステップ pass(
npm run build/sidecar:check/sidecar:test/cargo check/cargo test8 pass) - バンドルサイズは 7KB → 341KB。xterm.js の分。
scope deviation
なし。
次の期待
execution_mode = auto のため人間レビューゲートなし。CI green(CI pass / check pass 1m50s)。self-review pass により squash merge へ進む。
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Closes #24
原因
精度ではなく方式の問題だった。従来は制御シーケンスを除去して行を追記する行指向の扱いをしていたが、Claude Code はフルスクリーンの TUI であり、カーソル移動・画面消去・部分再描画・代替スクリーンバッファを前提に出力する。行の連なりではないため、除去して追記すると再描画の断片が積み上がるだけになる。
除去の精度を上げても直らない。行指向の表示器で TUI を映そうとしていること自体が誤り。
変更内容
xterm.js + addon-fit に置き換えた(liplus-desktop で実績のある構成、依存はその二つのみ)。
pty-data-{id}→terminal.writeterminal.onData→write_ptyfitAddon+ResizeObserver→resize_ptyCtrl+V→ clipboard plugin →write_pty削除したもの: 制御シーケンス除去のコード、専用キーボタン(Enter / ↑ / ↓ / Esc / Ctrl+C)、行バッファ。端末が直接キーを受けるため不要になった。
起動時は端末の実サイズを
start_sessionに渡すようにした。CLI の最初の描画が、持っていないウィンドウ幅で組まれることを避けるため。仕様との関係
却下されている設計と、今回やったことは別物である。
stream_parser.rsのモデル)。部屋に並ぶものの出所が channel ではなくなる。部屋に並ぶ発言は channel notification と
say_to_roomからのみ来る。端末は表示器であって情報源ではない。会話面(#room)に端末を置かないことは維持している。従来
docs/0-requirements.mdにあった一文は「ターミナルエミュレータを置かない制約と衝突しない」と書いており、出力解析の禁止と端末表示の禁止を混同しうる形だった。axis を分けて書き直した。検証
npm run build/npm run sidecar:check/npm run sidecar:test(pass 1 / fail 0)cargo check --target x86_64-pc-windows-gnurelease type
minor — user/system observable な表示方式の変更で、依存の追加を伴う。