run_shell_command
-
Run a shell command in a pane, wait for it to finish, and report its exit status with retained output. This is the tool for “run this and tell me if it worked”. Output is the pane’s raw output stream, not the rendered screen. Output is a bounded tail; check truncated before treating it as complete. The shell prompt is not included, and a line redrawn in place repeats; capture_pane shows the screen. The command runs in a subshell, so cd and export do not persist and invalid syntax completes with a nonzero status. Valid inherited Bash and zsh ERR and DEBUG traps remain visible to the command while parent-shell traps and options remain unchanged. It requires one configured input recipient and observes its mode, liveness, input-off state, attended-client state, cohort, inherited-caller relation, known POSIX shell, and resolved route before watcher setup and again before dispatch. A process-wide endpoint-and-pane reservation blocks other MCP pane input until the completion marker or pane closure is proved. The resolved tmux executable and socket path must contain no ASCII terminal-control bytes. The reservation serializes this MCP’s input, but tmux observations can still race with dispatch. The pane shell, tmux server, and configuration must be trusted. Reaching the deadline, cancelling, or an uncertain dispatch stops this request while its watcher keeps the reservation until completion is proved. To stop the command, send_keys with keys [“C-c”] alone passes the reservation, and the command reports completion when it ends; respawn_pane with kill_first replaces a program that ignores C-c and C-. Run a shell command in a pane with your user’s permissions.
- MCP request method
tools/callSendrun_shell_commandas the tool name, with the arguments below.
Arguments#
-
The command for the pane’s trusted POSIX-compatible shell.
Shell reserved words and special builtins must retain their standard meanings. The command runs inside a subshell, so several lines are fine and a bare
exitdoes not end the pane’s own shell. Invalid syntax is contained and completes with the shell’s nonzero status. Valid inherited Bash and zshERRandDEBUGtraps remain visible to the command while the pane’s parent-shell traps and options remain unchanged. -
The
%-prefixed pane to run in. -
How long to allow, in seconds. Defaults to 30, capped at 600.
- minimum
0
-
suppress_history? =false(boolean) #Whether to keep the command out of the shell’s history.
No other arguments are accepted.
Result#
Returns object
-
How many bytes that was, before any truncation.
- minimum
0
-
exit_status(integer | null) #The command’s exit status, when it completed.
Absent when the run did not complete, and when the command was killed by a signal rather than exiting.
- format
"int32"
-
How the run finished.
-
The retained tail of command output, stdout and stderr interleaved.
This is the raw output stream with escape sequences removed, not the rendered screen: a line redrawn in place, such as a progress bar, repeats. Check
truncatedbefore treating it as complete.capture_paneshows the screen. -
The pane the command ran in.
-
Whether the output was truncated from the front.
Types#
-
RunOutcome: "completed" | "deadline" | "pane_closed" | "cancelled" | "no_shell"type ¶ How a run finished.
Split from the wait outcomes rather than shared with them: a run cannot match a pattern and a wait cannot report a missing shell, and a vocabulary carrying both would have an agent checking for answers that never come.
Matches exactly one variant.
-
The command ran to completion and reported its status.
-
The time the caller allowed ran out.
This ends the waiting, not the command. The pane stays reserved for it until it ends, so other pane input is refused;
send_keyswith keys["C-c"]alone interrupts it. -
The pane stopped writing for good.
-
The client withdrew the request while the run was still going.
-
The pane never acknowledged the command.
The keys were sent but the opening sentinel never came back. That is what a pane looks like when it is not at a shell prompt: sitting in an editor or a REPL, or still running something an earlier call left behind. The text was typed into whatever is there.
The evidence is absence, so a deadline too short for the pane’s shell to have echoed anything yet looks the same. Read it as “nothing came back in the time allowed” and check the pane with
snapshot_panebefore concluding it is stuck.
-
Annotations#
destructiveHinttrueidempotentHintfalseopenWorldHinttruereadOnlyHintfalsetitle"Run Command In Pane"
Protocol data#
Use the complete advertised contract for validation and client integration.
Input schema
{"$schema": "https://json-schema.org/draft/2020-12/schema","additionalProperties": false,"properties": {"command": {"description": "The command for the pane's trusted POSIX-compatible shell.\n\nShell reserved words and special builtins must retain their standard\nmeanings. The command runs inside a subshell, so several lines are fine\nand a bare `exit` does not end the pane's own shell. Invalid syntax is\ncontained and completes with the shell's nonzero status. Valid inherited\nBash and zsh `ERR` and `DEBUG` traps remain visible to the command while\nthe pane's parent-shell traps and options remain unchanged.","type": "string"},"pane": {"description": "The `%`-prefixed pane to run in.","type": "string"},"seconds": {"description": "How long to allow, in seconds. Defaults to 30, capped at 600.","minimum": 0,"type": ["integer","null"]},"suppress_history": {"default": false,"description": "Whether to keep the command out of the shell's history.","type": "boolean"}},"required": ["pane","command"],"type": "object"}Output schema
{"$defs": {"RunOutcome": {"description": "How a run finished.\n\nSplit from the wait outcomes rather than shared with them: a run cannot\nmatch a pattern and a wait cannot report a missing shell, and a vocabulary\ncarrying both would have an agent checking for answers that never come.","oneOf": [{"const": "completed","description": "The command ran to completion and reported its status.","type": "string"},{"const": "deadline","description": "The time the caller allowed ran out.\n\nThis ends the waiting, not the command. The pane stays reserved for it\nuntil it ends, so other pane input is refused; `send_keys` with keys\n`[\"C-c\"]` alone interrupts it.","type": "string"},{"const": "pane_closed","description": "The pane stopped writing for good.","type": "string"},{"const": "cancelled","description": "The client withdrew the request while the run was still going.","type": "string"},{"const": "no_shell","description": "The pane never acknowledged the command.\n\nThe keys were sent but the opening sentinel never came back. That is\nwhat a pane looks like when it is not at a shell prompt: sitting in an\neditor or a REPL, or still running something an earlier call left\nbehind. The text was typed into whatever is there.\n\nThe evidence is absence, so a deadline too short for the pane's shell\nto have echoed anything yet looks the same. Read it as \"nothing came\nback in the time allowed\" and check the pane with `snapshot_pane`\nbefore concluding it is stuck.","type": "string"}]}},"$schema": "https://json-schema.org/draft/2020-12/schema","properties": {"bytes": {"description": "How many bytes that was, before any truncation.","minimum": 0,"type": "integer"},"exit_status": {"description": "The command's exit status, when it completed.\n\nAbsent when the run did not complete, and when the command was killed\nby a signal rather than exiting.","format": "int32","type": ["integer","null"]},"outcome": {"$ref": "#/$defs/RunOutcome","description": "How the run finished."},"output": {"description": "The retained tail of command output, stdout and stderr interleaved.\n\nThis is the raw output stream with escape sequences removed, not the\nrendered screen: a line redrawn in place, such as a progress bar,\nrepeats. Check `truncated` before treating it as complete.\n`capture_pane` shows the screen.","type": "string"},"pane": {"description": "The pane the command ran in.","type": "string"},"truncated": {"description": "Whether the output was truncated from the front.","type": "boolean"}},"required": ["pane","outcome","exit_status","output","bytes","truncated"],"type": "object"}