Manages processes
Project description
PMFlow
A lightweight CLI process manager. Spawn, monitor, and control long-running subprocesses from the terminal — with persistent state, process groups, log capture, and graceful lifecycle management.
pip install pmflow
Table of Contents
- Installation
- Quick Start
- State Storage
- Commands
- Config File (pmflow.yaml)
- Process Groups
- Error Codes
- Windows Notes
Installation
pip install pmflow
Windows: After installing, make sure the Python Scripts directory is on your PATH. Find it with:
pip show pmflow
The location will be something like C:\Users\<you>\AppData\Local\Programs\Python\Python3x\Scripts. Add that to your system PATH if pm is not found after install.
Quick Start
# Start a process
pm create "python app.py" --name api
# See what's running
pm ls
# See details for one process
pm info api
# Follow its logs
pm logs api --follow
# Gracefully stop it
pm stop api
# Start everything from a config file
pm up
State Storage
PMFlow stores process metadata in a JSON file in your user data directory:
| Platform | Location |
|---|---|
| Linux | ~/.local/share/pmflow/processes_state.json |
| macOS | ~/Library/Application Support/pmflow/processes_state.json |
| Windows | %APPDATA%\pmflow\processes_state.json |
State persists across terminal sessions and survives pip install --upgrade pmflow.
Commands
create / start
Start a new subprocess. start is an alias for create.
pm create "<command>" [OPTIONS]
pm start "<command>" [OPTIONS]
| Option | Short | Default | Description |
|---|---|---|---|
--name |
-n |
None | Human-readable name for the process |
--group |
-g |
auto | Group name (auto-generated for parent processes) |
--relation |
-r |
parent |
parent or child (see Process Groups) |
--foreground |
-f |
off | Block until the process exits (useful in .service files) |
--log-file |
-l |
None | File path to capture stdout and stderr |
--no-autostart |
off | Exclude from pm recreate bulk-restart |
|
--verbose |
-v |
off | Print the log file path after starting |
Examples:
# Basic
pm create "python server.py"
# Named process with log capture
pm create "uvicorn app:app --port 8000" --name api --log-file logs/api.log
# Child process in an existing group
pm create "celery -A tasks worker" --name worker --group backend --relation child
# Run in foreground (blocks)
pm create "pytest tests/" --foreground
Notes:
- Background processes are fully detached — they survive terminal close.
- A child process requires
--grouppointing to an existing parent group. - Each group may have only one parent.
ls / status
List all managed processes. status is an alias for ls.
pm ls [OPTIONS]
pm status [OPTIONS]
| Option | Short | Default | Description |
|---|---|---|---|
--json |
-j |
off | Output raw JSON instead of a table |
--group |
-g |
None | Filter by group name |
--running |
-r |
off | Show only running processes |
Examples:
pm ls
pm ls --running
pm ls --group backend
pm ls --json
pm ls --json --group backend
Status values:
| Status | Meaning |
|---|---|
running |
Process is alive |
paused |
Suspended with SIGSTOP |
stopped |
Exited cleanly (code 0) |
crashed |
Exited with non-zero code |
unknown |
PID gone, exit not tracked |
info
Show detailed information about a single process, looked up by name or PID.
pm info <name|pid>
Example output:
Name api
PID 12345
Status running
Command uvicorn app:app --host 0.0.0.0 --port 8000
Group backend
Relation parent
Autostart True
Log file logs/api.log
Created at 2026-06-27T09:14:32+00:00
Exited at —
Exit code —
Uptime 4h 22m
CPU 1.2%
Memory (RSS) 128.0 MB
logs
Print the log file for a process. The process must have been started with --log-file.
pm logs <name|pid> [OPTIONS]
| Option | Short | Default | Description |
|---|---|---|---|
--lines |
-n |
20 | Number of lines to show |
--follow |
-f |
off | Stream new output continuously (Ctrl+C to stop) |
Examples:
pm logs api
pm logs api --lines 100
pm logs api --follow
pm logs 12345 -n 50 -f
stop
Gracefully stop a process. Sends SIGTERM, waits for it to exit, then sends SIGKILL if it doesn't.
The process entry is kept in state after stopping (use pm kill to also remove it, or pm restart to bring it back up).
pm stop <name|pid> [OPTIONS]
| Option | Short | Default | Description |
|---|---|---|---|
--timeout |
-t |
10 | Seconds to wait before SIGKILL |
--force |
-F |
off | Skip SIGTERM and send SIGKILL immediately |
Examples:
pm stop api
pm stop api --timeout 30
pm stop api --force
pm stop 12345
After stopping, pm ls will show status stopped (clean exit) or crashed (non-zero exit code).
restart
Stop a process and immediately restart it with the same command, name, group, and log file.
pm restart <name|pid> [OPTIONS]
| Option | Short | Default | Description |
|---|---|---|---|
--timeout |
-t |
10 | Seconds before SIGKILL during the stop phase |
Example:
pm restart api
pm restart api --timeout 30
kill
Immediately terminate a process and remove it from state. For graceful shutdown, use pm stop instead.
pm kill <pid>
pm kill --group <name>
pm kill --all
| Option | Short | Description |
|---|---|---|
--group |
-g |
Kill all processes in a group |
--child |
-c |
(With --group) kill only child processes, spare the parent |
--all |
-a |
Kill and remove every managed process |
Examples:
pm kill 12345
pm kill --group backend
pm kill --group backend --child
pm kill --all
Killing a parent process automatically kills all its children.
pause / respawn
Suspend a process without terminating it, then resume it later.
pm pause <pid> # send SIGSTOP to the process and its children
pm respawn # resume all paused processes (SIGCONT)
Note: SIGSTOP/SIGCONT are Unix signals and are not available on Windows.
recreate
Restart all managed processes from their stored commands. Useful after a reboot when all PIDs are stale.
pm recreate
Spawns a new subprocess for each entry in state and updates the PIDs. Use pm cleanup first to remove any entries you don't want restarted.
cleanup
Remove all state entries whose process no longer exists. Useful after a reboot.
pm cleanup
up / down
Start or stop all processes defined in pmflow.yaml. See Config File.
pm up # start all processes from pmflow.yaml
pm down # stop all processes from pmflow.yaml
pm up --config path/to.yaml # use a different config file
pm down --config path/to.yaml
version
Print the installed version of pmflow.
pm version
# pmflow 1.3.0
Config File (pmflow.yaml)
Define all your processes in a pmflow.yaml file in your project directory, then use pm up / pm down to manage them all at once — similar to docker-compose.
version: 1
processes:
api:
command: uvicorn app:app --host 0.0.0.0 --port 8000
group: backend
relation: parent
log_file: logs/api.log
autostart: true
worker:
command: celery -A tasks worker --loglevel=info
group: backend
relation: child
log_file: logs/worker.log
autostart: true
scheduler:
command: celery -A tasks beat
group: backend
relation: child
log_file: logs/scheduler.log
autostart: false
Fields per process:
| Field | Required | Description |
|---|---|---|
command |
yes | Shell command to run |
group |
no | Group name (auto-generated if omitted for parent) |
relation |
no | parent (default) or child |
log_file |
no | Path to redirect stdout/stderr |
autostart |
no | Include in pm recreate (default: true) |
pm up starts parents before children so group validation passes.
Process Groups
Groups let you manage related processes together.
- Each group has exactly one parent process.
- A group can have many child processes.
- Killing or stopping a parent cascades to all its children.
# Start a parent (creates group "backend" automatically)
pm create "nginx" --name proxy --group backend
# Add children to the same group
pm create "python worker.py" --name worker --group backend --relation child
pm create "python beat.py" --name beat --group backend --relation child
# Inspect the group
pm ls --group backend
# Stop the whole group
pm kill --group backend
Error Codes
| Code | Trigger | Meaning |
|---|---|---|
| 800 | pm create |
Child process created without --group |
| 801 | pm create |
--group does not match any existing parent group |
| 802 | pm create |
A parent already exists for that group |
| 1000 | pm ls |
--group filter matched no processes |
| 1001 | pm stop, pm info, pm logs |
Name or PID not found in state |
| 1100 | pm kill |
No argument provided (need PID, --group, or --all) |
| 1200 | pm kill |
More than one of PID / --group / --all given |
| 1300 | pm logs |
Process has no log file configured |
| 1400 | pm up, pm down |
pmflow.yaml not found |
| 1401 | pm up, pm down |
pmflow.yaml is not valid YAML |
Windows Notes
pm pause/pm respawnuse SIGSTOP/SIGCONT which are not available on Windows. These commands will fail on Windows.pm stop --forceusesTerminateProcesson Windows, which is always immediate regardless of the--timeoutsetting.- Background processes use
DETACHED_PROCESS | CREATE_NEW_PROCESS_GROUPflags to survive terminal close. - Make sure the Python
Scriptsdirectory is on your PATH after installation (see Installation).
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file pmflow-1.3.0.tar.gz.
File metadata
- Download URL: pmflow-1.3.0.tar.gz
- Upload date:
- Size: 22.8 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.12.13
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
c7ac0b0d7c075b2b0cda19d14ac3516dcc3f6392650a6bef651b79db4704c7db
|
|
| MD5 |
2ebf1159f8e4245476cfa1c7148edaa9
|
|
| BLAKE2b-256 |
68e9ff9394d7c9e60506354a41ef7e7ff827db2b56b412065a8e9b521d008ab2
|
File details
Details for the file pmflow-1.3.0-py3-none-any.whl.
File metadata
- Download URL: pmflow-1.3.0-py3-none-any.whl
- Upload date:
- Size: 19.1 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.12.13
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
14791df73c069e308bfdf9a6e6bcf2da978700ebd93ac6a4f06f6c0406c80df7
|
|
| MD5 |
d5f52d8b0c142690e2e4f866b7bfc5a6
|
|
| BLAKE2b-256 |
eb7fe0a4bd54df7b8b19911f3358bb08a95f73e36a722ba20745741501e6b78f
|