Skip to content

Let the terminal viewer scroll - #174

Merged
lsk567 merged 7 commits into
mainfrom
fix/terminal-scroll
Aug 1, 2026
Merged

Let the terminal viewer scroll#174
lsk567 merged 7 commits into
mainfrom
fix/terminal-scroll

Conversation

@lsk567

@lsk567 lsk567 commented Aug 1, 2026

Copy link
Copy Markdown
Collaborator

The web terminal could not be scrolled.

A tmux client only forwards wheel events when the session asks for mouse tracking, and agent sessions are created without it. So the viewer received nothing to scroll with, and there was no way back through what an agent had already drawn.

Attaching now turns it on for that session. It is best effort — failing to set it costs scrolling, not the attachment.

Side effect worth knowing: with mouse tracking on, clicking and dragging inside the pane is handled by tmux (selection/copy-mode) rather than by the browser. That is the same behaviour as attaching from a terminal with mouse on, and it is what makes the wheel work.

Validation

  • cargo test --bin omar — 307 pass, including a new one that turns the option off, attaches, and asserts it comes back on, against real tmux
  • cargo fmt --all, cargo clippy --all-targets --all-features -- -D warnings

🤖 Generated with Claude Code

lsk567 and others added 5 commits July 25, 2026 19:40
A tmux client only forwards wheel events when the session asks for mouse
tracking, and agent sessions are created without it — so there was no
way to scroll back through what an agent had already drawn.

Attaching turns it on. Best effort: failing to set it costs scrolling,
not the attachment.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Copilot AI review requested due to automatic review settings August 1, 2026 16:23

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🟡 Not ready to approve

New tmux commands use non-exact -t session targets that can prefix-match and act on the wrong session, which should be fixed before merging.

Once you've addressed the issues Copilot identified, you can request another Copilot review.

This review doesn't count toward merge requirements. Sign up for the private preview to control whether Copilot approvals count.

Pull request overview

This PR makes web terminal attachments scrollable by enabling tmux mouse tracking on attach, ensuring wheel events are available for the viewer to scroll through pane history.

Changes:

  • Add a best-effort enable_mouse() helper that turns mouse on for the target tmux session.
  • Invoke mouse enabling during Attachment::open() before spawning tmux attach-session.
  • Add an integration test that creates a real tmux session with mouse off, attaches, and asserts the option becomes on.
File summaries
File Description
src/terminal.rs Enables tmux mouse tracking during attachment and adds a tmux-backed regression test to confirm the option is turned on.
Review details

Suppressed comments (2)

src/terminal.rs:316

  • This test uses tmux targets like -t session, which can prefix-match and may operate on an unintended session if another session shares the same prefix. Using an exact target (=name) here avoids accidentally killing or mutating the wrong session on a shared tmux server.
        let session = "omar-terminal-mouse-probe";
        let _ = tmux_command()
            .args(["kill-session", "-t", session])
            .output();
        let _guard = SessionGuard(session.to_string());

src/terminal.rs:341

  • show-options is also targeted with a prefix match; use the exact =name target computed earlier so the assertion is about the session created by this test.
        let reported = tmux_command()
            .args(["show-options", "-t", session, "-v", "mouse"])
            .output()
            .expect("tmux answers");
  • Files reviewed: 1/1 changed files
  • Comments generated: 1
  • Review effort level: Lite

We're testing this review assessment. Please use 👍 or 👎 to tell us if it's correct.

Comment thread src/terminal.rs
Comment on lines +75 to +79
fn enable_mouse(session: &str) {
let _ = tmux_command()
.args(["set-option", "-t", session, "mouse", "on"])
.output();
}
Review catch: tmux resolves `-t name` by prefix when nothing matches it
exactly. With sessions like `…-w` and `…-w2`, a lookup for one that had
gone would land silently on its neighbour — reading the wrong agent's
size, turning the wrong agent's mouse on, or attaching to it.

The suggested `=name` is right for `attach-session` and `kill-session`
and wrong for the rest: `display-message`, `set-option` and
`show-options` reject it with "no such session". They need the trailing
colon, `=name:`, which is what makes it the session's current window
rather than a window called `=name`. Both forms are helpers now, so the
distinction is stated once.

The test creates the neighbour, leaves the other absent, and asserts the
absent one neither reports a size nor attaches.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Copilot AI review requested due to automatic review settings August 1, 2026 17:15

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🟡 Not ready to approve

enable_mouse can permanently toggle session mouse tracking even when Attachment::open fails later, creating unexpected side effects without a successful attachment.

Once you've addressed the issues Copilot identified, you can request another Copilot review.

This review doesn't count toward merge requirements. Sign up for the private preview to control whether Copilot approvals count.

Review details

Suppressed comments (1)

src/terminal.rs:144

  • enable_mouse(&session) runs before several fallible steps (openpty, building/spawning the tmux attach command). If Attachment::open returns an error after enable_mouse succeeds, the session is left with mouse enabled even though no viewer attached, which can change interaction semantics unexpectedly. Consider moving the best-effort enable_mouse call to immediately after spawn_command succeeds so mouse tracking is only enabled when an attachment is actually created.
    pub fn open(prefix: &str, agent: &str) -> Result<Self> {
        let session = format!("{prefix}{}", flatten_agent_name(agent));
        let size = window_size(&session)?;
        enable_mouse(&session);

  • Files reviewed: 1/1 changed files
  • Comments generated: 0 new
  • Review effort level: Lite

We're testing this review assessment. Please use 👍 or 👎 to tell us if it's correct.

Review catch: `enable_mouse` ran before opening the pseudo-terminal and
spawning the attach, either of which can fail. An attempt that never
attached left the session with mouse tracking on — a change nobody asked
for, made on behalf of a viewer that does not exist.

It runs after the child is spawned now. The test points an attach at a
name that does not resolve and asserts the neighbouring session's option
is untouched.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Copilot AI review requested due to automatic review settings August 1, 2026 22:11

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🟡 Not ready to approve

enable_mouse is currently called before remaining fallible PTY setup (so open() can still error after mutating tmux state), and the new “failed attach” test doesn’t actually exercise the intended failure scenario.

Once you've addressed the issues Copilot identified, you can request another Copilot review.

This review doesn't count toward merge requirements. Sign up for the private preview to control whether Copilot approvals count.

Review details

Suppressed comments (2)

src/terminal.rs:176

  • enable_mouse(&session) is invoked before try_clone_reader() / take_writer() which can still return an error, so Attachment::open can fail while leaving the tmux session modified (mouse tracking enabled) despite the intent expressed in the preceding comment. Move the call to after the remaining fallible PTY setup so the mouse option is only changed when open() is definitely returning Ok.
        // Only now that a viewer really is attached: everything above can fail,
        // and a session left with mouse tracking on by an attempt that never
        // arrived is a change nobody asked for.
        enable_mouse(&session);

src/terminal.rs:356

  • This test sets mouse off on session = "omar-terminal-failed-attach" but then performs the failing attach against a different session name ("omar-terminal-does-not-exist"), so it doesn't actually exercise the intended invariant about leaving the attempted session unchanged on failure. Consider rewriting it to make the attempted (missing) session a prefix of a real neighbour session, so the test would catch any accidental tmux prefix resolution causing the neighbour's mouse option to be flipped.
        // A name that does not resolve: the attach fails before any viewer.
        assert!(Attachment::open("", "omar-terminal-does-not-exist").is_err());

  • Files reviewed: 1/1 changed files
  • Comments generated: 0 new
  • Review effort level: Lite

We're testing this review assessment. Please use 👍 or 👎 to tell us if it's correct.

@lsk567
lsk567 merged commit cba2624 into main Aug 1, 2026
15 checks passed
@lsk567
lsk567 deleted the fix/terminal-scroll branch August 1, 2026 22:21
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.

2 participants