Skip to content

feat(diagnostics): render the session as a real terminal - #25

Merged
smileygames merged 1 commit into
mainfrom
issue-24-terminal
Aug 21, 2026
Merged

feat(diagnostics): render the session as a real terminal#25
smileygames merged 1 commit into
mainfrom
issue-24-terminal

Conversation

@smileygames

Copy link
Copy Markdown
Member

Closes #24

原因

精度ではなく方式の問題だった。従来は制御シーケンスを除去して行を追記する行指向の扱いをしていたが、Claude Code はフルスクリーンの TUI であり、カーソル移動・画面消去・部分再描画・代替スクリーンバッファを前提に出力する。行の連なりではないため、除去して追記すると再描画の断片が積み上がるだけになる。

除去の精度を上げても直らない。行指向の表示器で TUI を映そうとしていること自体が誤り。

変更内容

xterm.js + addon-fit に置き換えた(liplus-desktop で実績のある構成、依存はその二つのみ)。

経路 実装
CLI → 画面 pty-data-{id}terminal.write
キー入力 → CLI terminal.onDatawrite_pty
リサイズ fitAddon + ResizeObserverresize_pty
貼り付け Ctrl+V → clipboard plugin → write_pty

削除したもの: 制御シーケンス除去のコード、専用キーボタン(Enter / ↑ / ↓ / Esc / Ctrl+C)、行バッファ。端末が直接キーを受けるため不要になった。

起動時は端末の実サイズを start_session に渡すようにした。CLI の最初の描画が、持っていないウィンドウ幅で組まれることを避けるため。

仕様との関係

却下されている設計と、今回やったことは別物である。

  • 却下: アプリが CLI の出力を解析して発言を取り出す(liplus-desktop の stream_parser.rs のモデル)。部屋に並ぶものの出所が channel ではなくなる。
  • 採用: 起動した CLI をそのまま映す。解析しない。部屋のメッセージ経路には一切関与しない。

部屋に並ぶ発言は 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-gnu
  • 実際の TUI が崩れずに映ることは Master の実機でのみ確認できる

release type

minor — user/system observable な表示方式の変更で、依存の追加を伴う。

診断面のセッション出力が制御コードの羅列になって読めない問題の修正。

原因は精度ではなく方式。従来は制御シーケンスを除去して行を追記する行指向の
扱いをしていたが、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 smileygames linked an issue Aug 21, 2026 that may be closed by this pull request

@smileygames smileygames left a comment

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

AI self-review (execution_mode = auto)

受け入れ条件の照合(issue #24 完了条件)

条件 結果 根拠
CLI の TUI が崩れずに表示される 実装済 / 実機未確認 xterm.js が制御シーケンスを解釈する。実際の描画は Master の実機でのみ確認できる
端末へ直接キー入力でき、確認プロンプトに答えられる 実装済 / 実機未確認 terminal.onDatawrite_pty。Ctrl+V は clipboard plugin 経由
ウィンドウのリサイズが CLI 側へ伝わる 実装済 / 実機未確認 fitAddon + ResizeObserverresize_pty。起動時も端末の実サイズを start_session へ渡す
制御シーケンス除去のコードと専用キーボタンが削除されている pass session-log / session-keys / session-input への参照がリポジトリ全体で 0 件。CSI / OSC パターンと行バッファも削除
部屋のメッセージ経路が channel 由来のみであることが docs で読み取れる pass docs/0-requirements.md に却下設計と採用設計を並べて明示

制約の照合

  • 会話面に端末を置かない: pass。#roomroom-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 test 8 pass)
  • バンドルサイズは 7KB → 341KB。xterm.js の分。

scope deviation

なし。

次の期待

execution_mode = auto のため人間レビューゲートなし。CI green(CI pass / check pass 1m50s)。self-review pass により squash merge へ進む。

@smileygames
smileygames merged commit 56041d3 into main Aug 21, 2026
2 checks passed
@smileygames
smileygames deleted the issue-24-terminal branch August 21, 2026 10:16
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.

feat(diagnostics): render the session as a real terminal

1 participant