Skip to content

Commit 372b57e

Browse files
committed
Server(feat[run_shell]): add run_shell() wrapping tmux run-shell
why: run-shell executes shell commands in the tmux server context, useful for background tasks and capturing command output programmatically. what: - Add Server.run_shell() with background (-b), delay (-d), capture (-C), target_pane (-t) parameters - Returns stdout when not in background mode, None otherwise - Add tests for basic command execution and background mode
1 parent 7a5132b commit 372b57e

2 files changed

Lines changed: 75 additions & 0 deletions

File tree

src/libtmux/server.py

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -423,6 +423,66 @@ def kill_session(self, target_session: str | int) -> Server:
423423

424424
return self
425425

426+
def run_shell(
427+
self,
428+
command: str,
429+
*,
430+
background: bool | None = None,
431+
delay: str | None = None,
432+
capture: bool | None = None,
433+
target_pane: str | None = None,
434+
) -> list[str] | None:
435+
"""Execute a shell command via ``$ tmux run-shell``.
436+
437+
Parameters
438+
----------
439+
command : str
440+
Shell command to execute.
441+
background : bool, optional
442+
Run in background (``-b`` flag).
443+
delay : str, optional
444+
Delay before execution (``-d`` flag).
445+
capture : bool, optional
446+
Capture output to the target pane (``-C`` flag).
447+
target_pane : str, optional
448+
Target pane for output (``-t`` flag).
449+
450+
Returns
451+
-------
452+
list[str] | None
453+
Command stdout if not running in background, None otherwise.
454+
455+
Examples
456+
--------
457+
>>> result = server.run_shell('echo hello')
458+
>>> 'hello' in (result or [])
459+
True
460+
"""
461+
tmux_args: tuple[str, ...] = ()
462+
463+
if background:
464+
tmux_args += ("-b",)
465+
466+
if delay is not None:
467+
tmux_args += ("-d", delay)
468+
469+
if capture:
470+
tmux_args += ("-C",)
471+
472+
if target_pane is not None:
473+
tmux_args += ("-t", target_pane)
474+
475+
tmux_args += (command,)
476+
477+
proc = self.cmd("run-shell", *tmux_args)
478+
479+
if proc.stderr:
480+
raise exc.LibTmuxException(proc.stderr)
481+
482+
if background:
483+
return None
484+
return proc.stdout
485+
426486
def switch_client(self, target_session: str) -> None:
427487
"""Switch tmux client.
428488

tests/test_server.py

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -460,6 +460,21 @@ def test_tmux_bin_invalid_path_raise_if_dead() -> None:
460460
s.raise_if_dead()
461461

462462

463+
def test_run_shell_basic(server: Server) -> None:
464+
"""Test Server.run_shell() executes command and returns output."""
465+
server.new_session(session_name="run_shell_test")
466+
result = server.run_shell("echo hello_from_run_shell")
467+
assert result is not None
468+
assert any("hello_from_run_shell" in line for line in result)
469+
470+
471+
def test_run_shell_background(server: Server) -> None:
472+
"""Test Server.run_shell() in background mode."""
473+
server.new_session(session_name="run_shell_bg_test")
474+
result = server.run_shell("echo bg_test", background=True)
475+
assert result is None
476+
477+
463478
def test_new_session_config_file(
464479
server: Server,
465480
tmp_path: pathlib.Path,

0 commit comments

Comments
 (0)