3838
3939 from typing_extensions import Self
4040
41+ from libtmux ._internal .command_runner import CommandRunner
4142 from libtmux ._internal .types import StrPath
4243
4344 DashLiteral : TypeAlias = t .Literal ["-" ]
@@ -64,6 +65,8 @@ class Server(EnvironmentMixin):
6465 socket_path : str, optional
6566 config_file : str, optional
6667 colors : str, optional
68+ command_runner : CommandRunner, optional
69+ Custom command execution engine. Defaults to subprocess-based runner.
6770 on_init : callable, optional
6871 socket_name_factory : callable, optional
6972
@@ -124,13 +127,15 @@ def __init__(
124127 socket_path : str | pathlib .Path | None = None ,
125128 config_file : str | None = None ,
126129 colors : int | None = None ,
130+ command_runner : CommandRunner | None = None ,
127131 on_init : t .Callable [[Server ], None ] | None = None ,
128132 socket_name_factory : t .Callable [[], str ] | None = None ,
129133 ** kwargs : t .Any ,
130134 ) -> None :
131135 EnvironmentMixin .__init__ (self , "-g" )
132136 self ._windows : list [WindowDict ] = []
133137 self ._panes : list [PaneDict ] = []
138+ self ._command_runner = command_runner
134139
135140 if socket_path is not None :
136141 self .socket_path = socket_path
@@ -188,6 +193,39 @@ def __exit__(
188193 if self .is_alive ():
189194 self .kill ()
190195
196+ @property
197+ def command_runner (self ) -> CommandRunner :
198+ """Get or lazily initialize the command runner.
199+
200+ Returns
201+ -------
202+ CommandRunner
203+ The command execution engine for this server
204+
205+ Examples
206+ --------
207+ >>> server = Server(socket_name="default")
208+ >>> assert server.command_runner is not None
209+ >>> type(server.command_runner).__name__
210+ 'SubprocessCommandRunner'
211+ """
212+ if self ._command_runner is None :
213+ from libtmux ._internal .engines import SubprocessCommandRunner
214+
215+ self ._command_runner = SubprocessCommandRunner ()
216+ return self ._command_runner
217+
218+ @command_runner .setter
219+ def command_runner (self , value : CommandRunner ) -> None :
220+ """Set the command runner.
221+
222+ Parameters
223+ ----------
224+ value : CommandRunner
225+ New command execution engine
226+ """
227+ self ._command_runner = value
228+
191229 def is_alive (self ) -> bool :
192230 """Return True if tmux server alive.
193231
@@ -298,7 +336,9 @@ def cmd(
298336
299337 cmd_args = ["-t" , str (target ), * args ] if target is not None else [* args ]
300338
301- return tmux_cmd (* svr_args , * cmd_args )
339+ # Convert all arguments to strings for the command runner
340+ all_args = [str (arg ) for arg in [* svr_args , * cmd_args ]]
341+ return self .command_runner .run (* all_args )
302342
303343 @property
304344 def attached_sessions (self ) -> list [Session ]:
0 commit comments