
Research
SANDWORM_MODE: Shai-Hulud-Style npm Worm Hijacks CI Workflows and Poisons AI Toolchains
An emerging npm supply chain attack that infects repos, steals CI secrets, and targets developer AI toolchains for further compromise.
running-process
Advanced tools
A modern subprocess.Popen wrapper with improved process management, real-time output streaming, and enhanced lifecycle control.
from running_process import RunningProcess
# Simple command execution with real-time output
process = RunningProcess(["echo", "Hello World"])
for line in process:
print(f"Output: {line}")
# Check exit code
if process.wait() != 0:
print("Command failed!")
from running_process import RunningProcess
from pathlib import Path
# Advanced configuration
process = RunningProcess(
command=["python", "long_script.py"],
cwd=Path("./scripts"),
timeout=300, # 5 minute timeout
enable_stack_trace=True, # Debug hanging processes
check=True, # Raise exception on non-zero exit
)
# Process output as it arrives
while process.is_running():
try:
line = process.get_next_line(timeout=1.0)
print(f"[{process.elapsed_time:.1f}s] {line}")
except TimeoutError:
print("No output for 1 second...")
continue
# Wait for completion
exit_code = process.wait()
from running_process import RunningProcess, TimeDeltaFormatter
# Use built-in time delta formatter
formatter = TimeDeltaFormatter()
process = RunningProcess(
["gcc", "-v", "main.c"],
output_formatter=formatter
)
# Implement custom formatter
class TimestampFormatter:
def begin(self): pass
def end(self): pass
def transform(self, line: str) -> str:
from datetime import datetime
timestamp = datetime.now().strftime("%H:%M:%S")
return f"[{timestamp}] {line}"
process = RunningProcess(["make"], output_formatter=TimestampFormatter())
from running_process import RunningProcessManager
# Access the global process registry
manager = RunningProcessManager.get_instance()
# List all active processes
for proc_id, process in manager.get_all_processes():
print(f"Process {proc_id}: {process.command_str}")
# Clean up finished processes
manager.cleanup_finished_processes()
pip install running_process
This package includes psutil as a required dependency for process tree management functionality.
The library follows a layered design with these core components:
# Clone the repository
git clone https://github.com/yourusername/running-process.git
cd running-process
# Activate development environment (requires git-bash on Windows)
. ./activate.sh
# Run all tests
./test
# Run with coverage
uv run pytest --cov=running_process tests/
# Run complete linting suite
./lint
# Individual tools
uv run ruff check --fix src tests
uv run black src tests
uv run pyright src tests
The main class for managing subprocess execution:
class RunningProcess:
def __init__(
self,
command: str | list[str],
cwd: Path | None = None,
check: bool = False,
auto_run: bool = True,
shell: bool | None = None,
timeout: int | None = None,
enable_stack_trace: bool = False,
on_complete: Callable[[], None] | None = None,
output_formatter: OutputFormatter | None = None,
) -> None: ...
def get_next_line(self, timeout: float | None = None) -> str | EndOfStream: ...
def wait(self, timeout: float | None = None) -> int: ...
def kill(self) -> None: ...
def is_running(self) -> bool: ...
def drain_stdout(self) -> list[str]: ...
get_next_line(timeout): Get the next line of output with optional timeoutwait(timeout): Wait for process completion, returns exit codekill(): Terminate the process (and process tree if psutil available)is_running(): Check if process is still executingdrain_stdout(): Get all currently available output linesInternal threaded reader that drains process stdout/stderr:
class ProcessOutputReader:
def __init__(
self,
proc: subprocess.Popen[Any],
shutdown: threading.Event,
output_formatter: OutputFormatter | None,
on_output: Callable[[str | EndOfStream], None],
on_end: Callable[[], None],
) -> None: ...
def run(self) -> None: ... # Thread entry point
class OutputFormatter(Protocol):
def begin(self) -> None: ...
def transform(self, line: str) -> str: ...
def end(self) -> None: ...
Built-in implementations:
NullOutputFormatter: No-op formatter (default)TimeDeltaFormatter: Adds elapsed time prefix to each lineBSD 3-Clause License
./test && ./lintFor bug reports and feature requests, please use the GitHub Issues page.
FAQs
A modern subprocess.Popen wrapper with improved process management
We found that running-process demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 1 open source maintainer collaborating on the project.
Did you know?

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Research
An emerging npm supply chain attack that infects repos, steals CI secrets, and targets developer AI toolchains for further compromise.

Company News
Socket is proud to join the OpenJS Foundation as a Silver Member, deepening our commitment to the long-term health and security of the JavaScript ecosystem.

Security News
npm now links to Socket's security analysis on every package page. Here's what you'll find when you click through.