diff --git a/executorlib/standalone/slurm_command.py b/executorlib/standalone/slurm_command.py
new file mode 100644
index 00000000..f9f4f8db
--- /dev/null
+++ b/executorlib/standalone/slurm_command.py
@@ -0,0 +1,51 @@
+from typing import Optional
+
+SLURM_COMMAND = "srun"
+
+
+def generate_slurm_command(
+    cores: int,
+    cwd: Optional[str],
+    threads_per_core: int = 1,
+    gpus_per_core: int = 0,
+    num_nodes: Optional[int] = None,
+    exclusive: bool = False,
+    openmpi_oversubscribe: bool = False,
+    slurm_cmd_args: Optional[list[str]] = None,
+    pmi_mode: Optional[str] = None,
+) -> list[str]:
+    """
+    Generate the command list for the SLURM interface.
+
+    Args:
+        cores (int): The number of cores.
+        cwd (str): The current working directory.
+        threads_per_core (int, optional): The number of threads per core. Defaults to 1.
+        gpus_per_core (int, optional): The number of GPUs per core. Defaults to 0.
+        num_nodes (int, optional): The number of compute nodes to use for executing the task. Defaults to None.
+        exclusive (bool): Whether to exclusively reserve the compute nodes, or allow sharing compute notes. Defaults to False.
+        openmpi_oversubscribe (bool, optional): Whether to oversubscribe the cores. Defaults to False.
+        slurm_cmd_args (list[str], optional): Additional command line arguments. Defaults to [].
+        pmi_mode (str): PMI interface to use (OpenMPI v5 requires pmix) default is None
+
+    Returns:
+        list[str]: The generated command list.
+    """
+    command_prepend_lst = [SLURM_COMMAND, "-n", str(cores)]
+    if cwd is not None:
+        command_prepend_lst += ["-D", cwd]
+    if pmi_mode is not None:
+        command_prepend_lst += ["--mpi=" + pmi_mode]
+    if num_nodes is not None:
+        command_prepend_lst += ["-N", str(num_nodes)]
+    if threads_per_core > 1:
+        command_prepend_lst += ["--cpus-per-task=" + str(threads_per_core)]
+    if gpus_per_core > 0:
+        command_prepend_lst += ["--gpus-per-task=" + str(gpus_per_core)]
+    if exclusive:
+        command_prepend_lst += ["--exact"]
+    if openmpi_oversubscribe:
+        command_prepend_lst += ["--oversubscribe"]
+    if slurm_cmd_args is not None and len(slurm_cmd_args) > 0:
+        command_prepend_lst += slurm_cmd_args
+    return command_prepend_lst
diff --git a/executorlib/task_scheduler/interactive/slurmspawner.py b/executorlib/task_scheduler/interactive/slurmspawner.py
index b6490657..e6bb58f3 100644
--- a/executorlib/task_scheduler/interactive/slurmspawner.py
+++ b/executorlib/task_scheduler/interactive/slurmspawner.py
@@ -2,8 +2,7 @@
 from typing import Optional
 
 from executorlib.standalone.interactive.spawner import SubprocessSpawner
-
-SLURM_COMMAND = "srun"
+from executorlib.standalone.slurm_command import generate_slurm_command
 
 
 def validate_max_workers(max_workers: int, cores: int, threads_per_core: int):
@@ -83,51 +82,3 @@ def generate_command(self, command_lst: list[str]) -> list[str]:
         return super().generate_command(
             command_lst=command_prepend_lst + command_lst,
         )
-
-
-def generate_slurm_command(
-    cores: int,
-    cwd: Optional[str],
-    threads_per_core: int = 1,
-    gpus_per_core: int = 0,
-    num_nodes: Optional[int] = None,
-    exclusive: bool = False,
-    openmpi_oversubscribe: bool = False,
-    slurm_cmd_args: Optional[list[str]] = None,
-    pmi_mode: Optional[str] = None,
-) -> list[str]:
-    """
-    Generate the command list for the SLURM interface.
-
-    Args:
-        cores (int): The number of cores.
-        cwd (str): The current working directory.
-        threads_per_core (int, optional): The number of threads per core. Defaults to 1.
-        gpus_per_core (int, optional): The number of GPUs per core. Defaults to 0.
-        num_nodes (int, optional): The number of compute nodes to use for executing the task. Defaults to None.
-        exclusive (bool): Whether to exclusively reserve the compute nodes, or allow sharing compute notes. Defaults to False.
-        openmpi_oversubscribe (bool, optional): Whether to oversubscribe the cores. Defaults to False.
-        slurm_cmd_args (list[str], optional): Additional command line arguments. Defaults to [].
-        pmi_mode (str): PMI interface to use (OpenMPI v5 requires pmix) default is None
-
-    Returns:
-        list[str]: The generated command list.
-    """
-    command_prepend_lst = [SLURM_COMMAND, "-n", str(cores)]
-    if cwd is not None:
-        command_prepend_lst += ["-D", cwd]
-    if pmi_mode is not None:
-        command_prepend_lst += ["--mpi=" + pmi_mode]
-    if num_nodes is not None:
-        command_prepend_lst += ["-N", str(num_nodes)]
-    if threads_per_core > 1:
-        command_prepend_lst += ["--cpus-per-task=" + str(threads_per_core)]
-    if gpus_per_core > 0:
-        command_prepend_lst += ["--gpus-per-task=" + str(gpus_per_core)]
-    if exclusive:
-        command_prepend_lst += ["--exact"]
-    if openmpi_oversubscribe:
-        command_prepend_lst += ["--oversubscribe"]
-    if slurm_cmd_args is not None and len(slurm_cmd_args) > 0:
-        command_prepend_lst += slurm_cmd_args
-    return command_prepend_lst
diff --git a/executorlib/task_scheduler/worker/__init__.py b/executorlib/task_scheduler/worker/__init__.py
new file mode 100644
index 00000000..e69de29b
diff --git a/executorlib/task_scheduler/worker/spawner.py b/executorlib/task_scheduler/worker/spawner.py
new file mode 100644
index 00000000..af615126
--- /dev/null
+++ b/executorlib/task_scheduler/worker/spawner.py
@@ -0,0 +1,119 @@
+from typing import Optional
+
+from pysqa import QueueAdapter
+
+from executorlib.standalone.interactive.spawner import BaseSpawner
+from executorlib.standalone.scheduler import pysqa_execute_command, terminate_with_pysqa
+
+
+class PysqaSpawner(BaseSpawner):
+    def __init__(
+        self,
+        cwd: Optional[str] = None,
+        cores: int = 1,
+        openmpi_oversubscribe: bool = False,
+        threads_per_core: int = 1,
+        config_directory: Optional[str] = None,
+        backend: Optional[str] = None,
+        submission_kwargs: Optional[dict] = None,
+    ):
+        """
+        Subprocess interface implementation.
+
+        Args:
+            cwd (str, optional): The current working directory. Defaults to None.
+            cores (int, optional): The number of cores to use. Defaults to 1.
+            threads_per_core (int, optional): The number of threads per core. Defaults to 1.
+            openmpi_oversubscribe (bool, optional): Whether to oversubscribe the cores. Defaults to False.
+        """
+        super().__init__(
+            cwd=cwd,
+            cores=cores,
+            openmpi_oversubscribe=openmpi_oversubscribe,
+        )
+        self._process: Optional[int] = None
+        self._threads_per_core = threads_per_core
+        self._config_directory = config_directory
+        self._backend = backend
+        self._submission_kwargs = submission_kwargs
+
+    def bootup(
+        self,
+        command_lst: list[str],
+    ):
+        """
+        Method to start the subprocess interface.
+
+        Args:
+            command_lst (list[str]): The command list to execute.
+        """
+        qa = QueueAdapter(
+            directory=self._config_directory,
+            queue_type=self._backend,
+            execute_command=pysqa_execute_command,
+        )
+        self._process = qa.submit_job(
+            command=" ".join(self.generate_command(command_lst=command_lst)),
+            working_directory=self._cwd,
+            cores=self._cores,
+            **self._submission_kwargs,
+        )
+
+    def generate_command(self, command_lst: list[str]) -> list[str]:
+        """
+        Method to generate the command list.
+
+        Args:
+            command_lst (list[str]): The command list.
+
+        Returns:
+            list[str]: The generated command list.
+        """
+        if self._cores > 1 and self._backend is None:
+            command_prepend = ["mpiexec", "-n", str(self._cores)]
+        elif self._cores > 1 and self._backend == "slurm":
+            command_prepend = ["srun", "-n", str(self._cores)]
+        elif self._cores > 1 and self._backend == "flux":
+            command_prepend = ["flux", "run", "-n", str(self._cores)]
+        elif self._cores > 1:
+            raise ValueError(
+                f"backend should be None, slurm or flux, not {self._backend}"
+            )
+        else:
+            command_prepend = []
+        return command_prepend + command_lst
+
+    def shutdown(self, wait: bool = True):
+        """
+        Method to shutdown the subprocess interface.
+
+        Args:
+            wait (bool, optional): Whether to wait for the interface to shutdown. Defaults to True.
+        """
+        if self._process is not None:
+            terminate_with_pysqa(
+                queue_id=self._process,
+                config_directory=self._config_directory,
+                backend=self._backend,
+            )
+        self._process = None
+
+    def poll(self) -> bool:
+        """
+        Method to check if the subprocess interface is running.
+
+        Returns:
+            bool: True if the interface is running, False otherwise.
+        """
+        qa = QueueAdapter(
+            directory=self._config_directory,
+            queue_type=self._backend,
+            execute_command=pysqa_execute_command,
+        )
+        if self._process is not None:
+            return qa.get_status_of_job(process_id=self._process) in [
+                "running",
+                "pending",
+            ]
+        else:
+            return False
diff --git a/tests/test_interactive_slurmspawner.py b/tests/test_interactive_slurmspawner.py
index 2617b9e9..bb04ad34 100644
--- a/tests/test_interactive_slurmspawner.py
+++ b/tests/test_interactive_slurmspawner.py
@@ -1,5 +1,5 @@
 import unittest
-from executorlib.task_scheduler.interactive.slurmspawner import generate_slurm_command
+from executorlib.standalone.slurm_command import generate_slurm_command
 
 try:
     from executorlib.standalone.scheduler import pysqa_execute_command
