skills/anentrypoint/gm-cc/process-management

process-management

SKILL.md

Process Management — PM2

All applications MUST run through PM2. Direct invocations (node, bun, python) are forbidden for any process that produces output or has a lifecycle.

Installation (First Time Only)

Check if PM2 is installed:

pm2 --version

If command not found, install globally:

npm install -g pm2

Verify installation:

pm2 --version        # should print version number
pm2 ping             # should respond "pong"

Pre-Start Check (MANDATORY)

Before starting any process, check what is already running:

pm2 jlist
  • online → already running, use pm2 logs <name> to observe
  • stopped → use pm2 restart <name>
  • Not in list → proceed to start

Never start a duplicate process. Always check first.

Start a Process

# CLI (quick)
pm2 start app.js --name myapp --watch --no-autorestart

# With interpreter
pm2 start script.py --interpreter python3 --name worker --watch --no-autorestart

# From ecosystem config (preferred for reproducibility)
pm2 start ecosystem.config.cjs

Ecosystem Config (Standard Template)

autorestart: false — process stops on crash, no automatic recovery watch: true — restarts on file changes in watched directories only

// ecosystem.config.cjs
module.exports = {
  apps: [{
    name: "myapp",
    script: "src/index.js",
    watch: ["src", "config"],
    watch_delay: 1000,
    autorestart: false,
    ignore_watch: [
      "node_modules",
      ".git",
      "logs",
      "*.log",
      ".pm2",
      "public",
      "uploads"
    ],
    watch_options: {
      followSymlinks: false,
      usePolling: false
    },
    log_date_format: "YYYY-MM-DD HH:mm:ss",
    out_file: "./logs/out.log",
    error_file: "./logs/error.log"
  }]
};

Log Viewing

pm2 logs <name>                      # stream live (Ctrl+C to stop)
pm2 logs <name> --lines 100          # last 100 lines then stream
pm2 logs <name> --err                # errors only
pm2 logs <name> --out                # stdout only
pm2 logs <name> --nostream --lines 200  # dump without follow
pm2 logs --json                      # structured JSON output
pm2 flush                            # clear all log files

Log files: ~/.pm2/logs/<name>-out.log / <name>-error.log Windows path: C:\Users\<user>\.pm2\logs\

Lifecycle Management

pm2 list                    # view all processes and status
pm2 jlist                   # JSON output for scripting
pm2 info <name>             # detailed process info
pm2 stop <name>             # stop (keeps in list)
pm2 restart <name>          # restart
pm2 delete <name>           # stop + remove from list
pm2 delete all              # remove all processes
pm2 ping                    # check if PM2 daemon is alive

When work is complete: always pm2 delete <name> to clean up orphaned processes.

Stopping a watched process: pm2 stop while watch is active restarts on next file change. To fully halt: pm2 delete <name> (removes it entirely).

Windows vs Linux

File Watching

Environment Config
Linux native usePolling: false (inotify kernel events)
WSL watching /mnt/c/... usePolling: true, interval: 1000
Windows native usePolling: false (ReadDirectoryChangesW)
Network / NFS / Docker volumes usePolling: true, interval: 1000

Linux inotify exhaustion fix (symptom: watch silently stops working):

echo fs.inotify.max_user_watches=524288 | sudo tee -a /etc/sysctl.conf && sudo sysctl -p

Windows: npm Scripts and .cmd Wrappers

PM2 cannot spawn .cmd shims (npm, npx, etc.) directly — they require cmd.exe.

// ecosystem.config.cjs — Windows npm script
{
  name: "myapp",
  script: "npm",
  args: "start",
  interpreter: "cmd",
  interpreter_args: "/c"
}

For globally installed CLIs, find the real .js entry point:

# Linux/macOS
cat "$(which myapp)" | head -5

# Windows PowerShell
Get-Command myapp | Select-Object -ExpandProperty Source

Point script at the resolved .js file — never at the .cmd wrapper.

Terminal Suppression on Windows (CRITICAL)

All code that spawns subprocesses MUST use windowsHide: true to prevent popup windows.

// ❌ WRONG - will show popup windows on Windows
spawn('node', ['script.js']);

// ✅ CORRECT - hides windows, safe for all platforms
spawn('node', ['script.js'], { windowsHide: true });

Applies to all subprocess execution:

  • child_process.spawn(){ windowsHide: true }
  • child_process.exec(){ windowsHide: true }
  • child_process.execFile(){ windowsHide: true }
  • child_process.fork(){ silent: true } (alternative for fork)

PM2-started processes automatically hide windows. Code-spawned subprocesses must explicitly set this. Forgetting creates visible popups during automation—unacceptable UX.

Windows 11+ wmic Error

PM2 uses wmic for process stats — removed in Windows 11+. Symptom: Error: spawn wmic ENOENT in ~/.pm2/pm2.log. Fix: npm install -g pm2@latest. App processes continue working despite the error.

Persistence on Reboot

Platform Method
Linux pm2 startup && pm2 save (auto-detects systemd/upstart/openrc)
Windows pm2-installer (Windows Service)
pm2 save        # snapshot current process list to ~/.pm2/dump.pm2
pm2 resurrect   # restore saved list after manual daemon restart
Weekly Installs
14
GitHub Stars
10
First Seen
13 days ago
Installed on
opencode14
gemini-cli14
antigravity14
github-copilot14
codex14
amp14