Agent chat: right-click the prompt rail to move it to the right edge
Summary
Leo's words (2026-10-22):
also we can add an option for moving it the right.. maybe specifically right clicking that area (and as a toggle) it can happen
yo where'd the scrolling thing on the left go? we had this then a session fucked it up and now it's gone? plus the option to show it left or right? default on, default left? option for minimap like vscode on the other side?
Leo-ask: ask-e3f329a69d
Leo-ask: ask-61fa57a17a
This PR covers "the option to show it left or right" and "default left": a right-click toggle and the agentPane.display.rail.side setting, left by default.
Right-clicking the agent chat's prompt rail (or, in a narrow pane, its hover strip) opens the shared context menu with one item, Move to Right Edge. Once the rail is on the right the item reads Move to Left Edge. The choice is saved in agentPane.display.rail.side (left or right), so it persists and applies to every chat pane. It is also in Settings > Appearance > Agent Chat > Prompt Rail Side, the palette, cmux settings and MCP (the key is in AgentPaneDisplaySettingsSchema.keys, which is agent-settable).
Rebuilt on the current rail (#26641 pins it to the pane edge with a token inset and a live hover strip; #26520 lets its list scroll). The right rail is the left one mirrored, per design spec leo-workspace design/session-rail.md (right-edge section added in teamleaderleo/leo-workspace#1745):
- It uses the same pane-edge inset as the left rail (
useRailPlacement), counted from the right edge, and compresses the same way. - Its ticks are mirrored so they grow from the pane edge toward the text.
- When it would overlap the text it hides at rest and keeps the same live hover strip, at the right edge.
- The preview card opens on the rail's left:
card.right == rail.left. - The full-height map follows the same edge.
- When the VS Code minimap (
agentPane.display.vscodeMinimap, off by default) is on, it already holds the right edge. The right rail then sits on its inner side: the minimap's 56 px plus its 10 px edge further in, with its strip starting there. It never lies under the minimap (review finding at8788145). - The left rail is unchanged. Moving back to the left removes the key.
- Like the left rail, it does not follow Session Info. A floating Session Info panel draws over it where they overlap.
The menu is the shared ui/ContextMenu (the native menu in the app), so it opens on the click with no fade. Its host keeps its layout box. An earlier head used display: contents there and WebKit trailed the card by a pixel.
The defaults snapshot (schemas/defaults/cmux-next.json) is bot-only, so this PR no longer commits it. The new default is left, which keeps today's behavior. The defaults guard passes on the review receipt.
.github/design-surfaces.json now maps threadMinimap/ to the session-rail spec, which already existed but had no entry in the map.
Overlap: #26635, #27197, #25766 and #28494 touch the rail files too. This PR is based on current feat-cmux-next and adds only the side switch.
Gallery: agent-pane.thread-minimap-narrow
Testing
All at head 8c6cb2893d94a6e60e140b0ec52a9f31a6e30a8a (base 0dd8fd01109da brought in; it still merges cleanly with the tip), on the fleet (cmux-ci test, Linux, Chromium and WebKit):
bun run check(Oxlint, Oxfmt, type check, layers, catalog keys): pass.webviews/test/thread-minimap-side.test.tsx(rebuilt): 6 pass. For the compact rail and the full-height map, a right-click and then Move to Right Edge puts the rail at the same 10 px pane-edge inset from the right, the host gets["agentPane.display.rail.side", "right"], and the card anchors at the pane's right edge. Move to Left Edge brings it back and writesnull. A hostdisplayevent moves it too, and an unknown value means left. In a 300 px pane the rail hides at rest on either edge and keeps its strip on that edge. With the VS Code minimap on, the right rail is atright: 76px, its strip atright: 66px, and the left rail stays at 10 px.thread-minimap-left-rail-stays.test.ts(browser): 26 pass, 0 fail, including the new right-edge test at 1600, 1084 and 760 px on both engines. It checks the right inset equals the left inset formula, the strip sits at the right edge, the rail hides at 760 only, the strip reveals it, andcard.right == rail.leftwithin 1 px. Every existing left-rail test is unchanged and passes.- Every other
thread-minimap-*jsdom suite, plususeRailPlacement.dom.test.tsx,thread-minimap-settingand the threechat-minimapsuites: all pass, exceptthread-minimap-motion's click-glide sample (progress(40) < 0.12). That one is a base flake: run 3 times, base0dd8fd01109daand this head each went fail, pass, pass, with the same assertion. tests/test_pr_design_spec_check.py: 10 pass (the newsession-railmap entry).- Swift:
cmux-ci compile-check --package CmuxNextpassed at4f1c2437406(the settings schema row). No Swift changed after it. prepush-gate.py: no new violations.
Observed / Not run
Observed: the runs above, and the gallery stills below (looked at each one).
Not run: a live tagged build. I did not check the palette row, cmux settings get|set agentPane.display.rail.side or MCP settings_set by hand. The key is in AgentPaneDisplaySettingsSchema, whose keys are all agent-settable.
Changelog
Added: Right-click the agent chat's prompt rail to move it to the right edge of the chat, and back
Screenshots
Gallery agent-pane.thread-minimap-narrow (Linux Chromium, 2x, synthetic data), hovering the first tick. Before is the left rail, the default, which this PR leaves as it is. After is the rail moved to the right edge with the right-click menu.
800 px pane (the rail sits beside the text):
| Before: left (default) | After: right edge | |
|---|---|---|
| Light | ![]() | ![]() |
| Dark | ![]() | ![]() |
160 px pane (the rail is hidden at rest; hovering the edge strip reveals it over the text):
| Before: left (default) | After: right edge | |
|---|---|---|
| Light | ![]() | ![]() |
| Dark | ![]() | ![]() |
No capture: the change is in the agent chat's webview (the prompt rail), plus one settings schema row. Its stills come from the Linux gallery above, per the repo rule that webview screenshots come from the gallery. There is no native AppKit view to capture.
Viewed after image: yes
Visual verdict: SHIP. The right rail matches the left one: same inset and tick look, and the card opens toward the text with its right edge on the rail's left. Nothing repeats per row and the menu has one item. It fits at 160 px.
Agent session: agent session
🤖 Generated with Claude Code







