Repository navigation
feat(session-ui): add run button for shell code blocks - #59810
mtabaresdev wants to merge 1 commit into
Conversation
Add play button to shell code blocks in markdown that executes commands via session.shell API. Both run and copy buttons are now always visible (no hover required). Shell output auto-expands at both group and content levels when executed from the run button. Changes: - Add RunMarkdownCommand capability type to markdown context - Create run button with play icon and spinner states - Add isRunnableCode() helper to check shell/bash/sh/zsh/fish languages - Wire runCommand prop through MarkdownProvider to app - Auto-expand tool groups containing shell messages - Auto-expand shell message content by default - Add unit tests for runnable language detection - Add i18n keys for run/running states Co-Authored-By: Claude Sonnet 4.5 <[email protected]>
|
This PR doesn't fully meet our contributing guidelines and PR template. What needs to be fixed:
Please edit this PR description to address the above within 72 hours, or it will be automatically closed. If you believe this was flagged incorrectly, please let a maintainer know. |
There was a problem hiding this comment.
The run button works: I tested it in a Playwright component spec using the markdown fixture's new runCommand option, and unit tests and tsc -b pass. A few things should change before this merges.
Public API is unchanged. RunMarkdownCommand and the runCommand prop on MarkdownProvider are internal to session-ui, and the PR only calls the existing session.shell endpoint.
Concerns, most important first (details inline):
- Partial commands can run. The button is added to code blocks that are still streaming. I clicked it on an unfinished ```bash block and it ran the half-written command.
- One click runs model-written text, with no confirmation. It goes through the same
session.shellpath as typing a command in the composer, so no permission check applies. Please add an explicit confirmation, or get a maintainer to agree that one click is acceptable. - Shell output now always opens, for every shell call. The
session-timeline-row.tsxchanges apply to all shell tool calls and shell messages, not only ones started from the run button, and they override the user's "collapsed" timeline setting. This is outside the feature; please drop it, or limit it to commands started from the button. - The copy button is now always visible. This is a separate visual change, and it touches the same CSS as #59159.
Smaller points:
- The
controller.tsxedit changes nothing:detailscan only be"collapsed"or"expanded", so!== "collapsed"means the same as=== "expanded". It can be dropped. - The new
playicon has exactly the same path as the existingoutline-videoicon.
|
|
||
| if (wrapper instanceof HTMLElement) applyCodeMetadata(wrapper, block.language) | ||
|
|
||
| if (wrapper instanceof HTMLElement) syncRunButton(wrapper, canRun && isRunnableCode(block.language), runLabels) |
There was a problem hiding this comment.
This adds the run button whether or not the block is complete, so it shows up while a fenced block is still streaming. I checked this in a component spec: with streaming on and the text ```bash\nrm -rf /tmp/build (fence not closed), clicking the button sent the partial command to runCommand. The model could still be adding arguments or more lines. Please only enable it once block.complete is true, here and in the new-wrapper path below.
| if (!sessionID) return | ||
|
|
||
| try { | ||
| await serverSDK.api.session.shell({ sessionID, command }) |
There was a problem hiding this comment.
session.shell is the user shell path, the same one the composer's shell mode uses, so no permission check applies. With this button, a single click runs whatever the model wrote, in the user's working directory. In shell mode the user at least types or submits the command. Please add a confirmation step, for example showing the command and asking to confirm, or get explicit maintainer agreement that one click is acceptable. Also, nothing here deals with the agent being busy or the session being archived.
|
|
||
| const key = () => `context:${row().group.key}` | ||
|
|
||
| // Auto-expand groups containing shell messages (unless explicitly closed by the user) |
There was a problem hiding this comment.
This (and the tool.name === "shell" changes in toolDefaultOpen and contentDefaultOpen below) opens every context group that contains a shell part, and every agent shell tool call, by default. It also returns before the timeline-detail shell.details setting is checked, so users who chose "collapsed" will see these expanded anyway. The description says output expands when run from the button, but this applies to every shell call. Please drop this, or limit it to commands started from the run button.
| (input.timelineDetail().shell.placement === "hidden" && | ||
| (value?.status === "timeout" || (value?.status === "exited" && value.exit !== undefined && value.exit !== 0))) | ||
| ) | ||
| // Always expand shell messages by default (user can still collapse them manually) |
There was a problem hiding this comment.
This now always returns true when timelineDetail is set, so the user's shell.details: "collapsed" setting no longer has any effect on shell messages. That's a regression for anyone who collapsed them on purpose.
| @@ -348,17 +348,28 @@ | |||
| position: absolute; | |||
There was a problem hiding this comment.
Removing the hover-to-reveal opacity rules makes the copy button visible on every code block. That's a design change separate from the run button, and it overlaps with #59159, which also changes how the copy button is shown. Please keep it out of this PR, or show the run button the same way the copy button is shown today.
|
This pull request has been automatically closed because it was not updated to meet our contributing guidelines within the 72-hour window. Feel free to open a new pull request that follows our guidelines. |


Summary
Adds a play button to shell code blocks in markdown that executes commands via the session.shell API, similar to Claude's interface.
Changes
RunMarkdownCommandcapability to markdown contextrunCommandthrough app tosession.shellAPITest plan
bun test packages/session-ui- tests passbun typecheckin affected packages - all passbun run dev:web- play button works, output expands🤖 Generated with Claude Code