Skip to content
lpm vs PM2

A PM2 alternative for local development — and what to keep PM2 for.

PM2 is a production supervisor that also watches files in dev. lpm is the Mac workspace around your local stack: one pane per service, a switcher across repos, and copies for parallel agents.

If both columns describe you, that is the normal case — run both.

Every pm2 verb, mapped

The short answer

Can you use PM2 for local development?

Yes. pm2-dev and --watch restart your app on file change, and if PM2 already runs production, one config for both is a real reason to stay.

What PM2 does not give you locally is a pane per service you can read and search, a switcher across projects, or a second copy of the stack for a parallel agent. It is a supervisor, not a workspace. lpm is the workspace, and it is additive: it supervises nothing in production and it never wraps PM2. Keep ecosystem.config.js for the server; for the laptop, declare those same services to lpm — kept to yourself in your own project file, or committed as a .lpm.yml so a teammate gets the same set.

Same two services, both tools
pm2 start ecosystem.config.js --only "web,api"
lpm start myapp --profile dev

PM2

Keep PM2

You deploy Node and need cluster mode across cores, restart-on-crash with backoff, boot persistence, and zero-downtime reload.

lpm

Add lpm

You want every service in its own live pane, a switcher across projects, and copies of the stack for parallel agents.

Both

Run both

ecosystem.config.js on the server, .lpm.yml on the laptop. They never nest and they never fight.

Process lifetime

Close the app. Your dev servers keep running.

The reason people reach for PM2 locally is that a dev server tied to a terminal window dies with the window. lpm's services do not run in the app — they run outside it, so quitting lpm is not pm2 stop. Relaunch and every pane is still there, still labelled, still streaming.

Survives closing the app
Yeslpm
YesPM2
Survives a reboot
Nolpm

no equivalent to pm2 startup and pm2 save; you start the project again

YesPM2
Survives a crash
Nolpm

the service stays down; its pane keeps the last output

YesPM2

with backoff

Two of those three go to PM2. That is the honest shape of this comparison — lpm is built for the loop you are in, not the box you left running.

Facts checked . The six rows PM2 wins are cited individually, because they are the reason to keep it. lpm's own rows were re-checked against the app source the same day.

How it compares

PM2 and lpm, row by row

Six of these rows go to PM2. Each one is a production problem — cluster mode, crash recovery, boot persistence — rather than a local-dev one.

  • Services keep running after you close the app
    lpm
    Yes
    PM2
    Yes
  • Every service in its own live pane instead of one log stream
    lpm
    Yes
    PM2
    pm2 logs
  • Switch between projects visually
    lpm
    Yes
    PM2
    No
  • Checks declared ports before starting and names the holder
    lpm
    ask, free, or fail
    PM2
    No
  • Declares service start order
    lpm
    dependsOn
    PM2
    No
  • Named service subsets
    lpm
    profiles
    PM2
    --only
  • Wait for a port or a service from a script
    lpm
    lpm wait --port 3000
    PM2
    No
  • Copy the whole stack for a second agent
    lpm
    up to 50 worktrees or standalone copies
    PM2
    No
  • Runs Claude Code and Codex in panes beside the services
    lpm
    Yes
    PM2
    No
  • Runs Node, Python, shell commands and binaries
    lpm
    Yes
    PM2
    Yes
  • Cluster mode across CPU cores with load balancing
    lpm
    No
    PM2
    Yes
  • Auto-restart on crash with backoff and memory limits
    lpm
    stays down; the pane keeps its last output
    PM2
    Yes
  • Comes back after a reboot (pm2 startup / pm2 save)
    lpm
    No
    PM2
    Yes
  • Zero-downtime reload on deploy
    lpm
    No
    PM2
    Yes
  • Log files and rotation
    lpm
    live scrollback only
    PM2
    pm2-logrotate
  • CPU and memory dashboard
    lpm
    No
    PM2
    pm2 monit, PM2 Plus
  • Scriptable from a shell, with JSON for the caller
    lpm
    lpm CLI, --json on nearly every verb
    PM2
    pm2 CLI

There is no logs directory. lpm logs api --lines 500 reads that service pane's scrollback, so what you get back is always current — and when the pane goes, the history goes with it. For output you can still read next week, PM2's log files plus pm2-logrotate remain the right tool.

Muscle memory

Every pm2 verb, and what it is here

The verbs line up almost one to one. Two of them have no lpm equivalent, and three lpm verbs have no pm2 original.

  • pm2

    pm2 start ecosystem.config.js

    lpm

    lpm start myapp
  • pm2

    pm2 start … --only web

    lpm

    lpm start myapp --profile dev
  • pm2

    pm2 list

    lpm

    lpm list
  • pm2

    pm2 show web

    lpm

    lpm project myapp
  • pm2

    pm2 logs web --lines 200

    lpm

    lpm logs web --lines 200
  • pm2

    pm2 restart web

    lpm

    lpm service web restart
  • pm2

    pm2 stop all

    lpm

    lpm stop myapp
  • pm2

    pm2 monit

    lpm

    no equivalent

    lpm shows panes, not resource graphs

  • pm2

    pm2 startup / pm2 save

    lpm

    no equivalent
  • pm2

    —

    lpm

    lpm wait --port 3000 --timeout 60

    hold a script until the port is listening

  • pm2

    —

    lpm

    lpm duplicate myapp -n 3 --run claude --prompt "…"

    three copies, each running its own agent

  • pm2

    —

    lpm

    lpm worktree myapp -n 3

    three linked Git worktrees instead — untracked files like .env and node_modules stay behind

lpm start and lpm stop, and any lpm service web restart, need the app up: the panes belong to it, so a shell with lpm quit gets “lpm app is not running” instead. Reading is looser — lpm logs, lpm list and lpm wait --port inspect the services themselves. The exception on that side is lpm status: agent status is the app's to report, so it says there is no live status until lpm is up again. Every row above is also a line an agent can run for you.

Side by side

ecosystem.config.js to .lpm.yml

The same two services, declared twice. Nothing here replaces the ecosystem file — it stays on the server.

ecosystem.config.js
module.exports = {
  apps: [
    { name: "web", script: "npm", args: "run dev" },
    { name: "api", script: "./bin/api", env: { PORT: 4000 } },
  ],
};
.lpm.yml
services:
  web: npm run dev
  api:
    cmd: ./bin/api
    port: 4000
    env:
      PORT: "4000"
    dependsOn: [web]
profiles:
  dev: [web, api]
  • Each apps[] entry's name plus script/args becomes one services: key and its command — a service with no options is one line.
  • dependsOn sets start order, which ecosystem.config.js has no field for. It orders starts; it does not wait for readiness — that is lpm wait --port.
  • port: is what lpm checks for conflicts and what lpm wait watches. The port your service actually binds still comes from your command or env:.

Each field on the right — cmd, port, env, dependsOn and profiles — has its own entry in the config reference.

See it

The CLI, driven by an agent

The same verbs above, called by Claude Code — a fresh tab opens in lpm with the output.

Honest take

When PM2 is the right tool, and when lpm is

Both run multiple processes. PM2 is strongest as a supervisor and also offers local watch mode; lpm specializes in an interactive multi-project Mac workspace. And if both columns describe you, that is the normal case.

Pick lpm

You're in the dev loop — multiple projects, mixed stacks, or AI agents running in parallel.

  • You switch between several local projects a day and want a visual switcher instead of terminal tabs.
  • Your stack is not just Node: a Go binary, a Python worker, a Rails server and a docker compose up sit in one config, each with its own pane. Add the folder and lpm writes the service list from your package.json, Procfile, Gemfile or go.mod — the dev script run by the package manager the repo declares or locks, framework ports included — and suggests Makefile or justfile targets as buttons.
  • You want each service in its own live pane in a native macOS app, not one interleaved log stream.
  • You run Claude Code and Codex in parallel and want each session's output and status visible at once.
  • You want to duplicate a project so a second agent works on its own checkout instead of the files you are editing. Both copies still reach the same database and the same ports — lpm names the process already holding one before a project starts.
Pick PM2

You need deployment supervision or already rely on PM2's local watch workflow.

  • You deploy Node to production or staging and need cluster mode across CPU cores with load balancing.
  • You need auto-restart on crash with exponential backoff, memory limits, and graceful reloads.
  • You need pm2 startup + pm2 save so the app comes back after a reboot.
  • You need log rotation, centralized log files, and integrations like PM2 Plus / Keymetrics for monitoring.
  • You want pm2-dev or --watch to restart a local application when its files change.
See it in action

One project, several copies, an agent in each

A short video: duplicate a project so each agent has its own copy.

lpm is a macOS app with a multi-pane terminal workspace. Open this page on your computer to try the interactive demo.

Get lpm for MacOr check your Macs from your iPhone
FAQ

Keeping PM2, or moving off it

  • Can I use lpm in production instead of PM2?
    No, and that is not the pitch. lpm is a local dev-workflow tool. PM2 is production-first, with cluster mode, crash recovery, boot persistence, and zero-downtime reloads; it also provides pm2-dev and watch mode for local development. If you are deploying an app to a server, use PM2. If you want a visual workspace around local services and agents, use lpm.
  • Does lpm cluster Node processes across cores like PM2?
    No. Cluster mode is a production concern — PM2 forks your Node app across CPU cores and load-balances between workers so a single box serves more traffic. lpm doesn't do that. In dev you usually want one instance of each service so logs and debugger breakpoints map to a single process. If you need clustering, that is a signal you want PM2 in front of your app, not lpm.
  • Do my services keep running if I quit lpm?
    Yes. They run outside the app, so closing the window leaves them up and relaunching finds them again. A reboot is the exception — there is no pm2 startup equivalent, so you start the project again.
  • Can I run PM2 inside lpm?
    You can: a service's command is just a shell line, so pm2-runtime start ecosystem.config.js runs in a pane like anything else. Most people do not, because you would then have two things deciding whether a process is alive. Point lpm at the same commands your ecosystem file runs and skip the layer.
  • Should I run PM2 and tmux together, or neither?
    PM2 restarts what dies; tmux holds a detached session until you attach to it again. Neither one stands in for the other, so running both is a fair answer — one supervises, one keeps the window. If the pair is only there to give you a single workspace, that overlap is the job lpm does, with no tmux underneath it.
  • Can I keep PM2 for production and use lpm locally?
    Yes. Keep ecosystem.config.js and PM2 in your deployment workflow, then add the repo to lpm for the laptop: it lists the dev commands it finds, and you keep the ones you actively develop against. Supervision stays with PM2, and local development gets lpm's service panes, project switcher, and parallel-agent copies.

Keep PM2 for supervision. Add lpm for the workspace.

MIT-licensed, free, no account. PM2 stays where it belongs — on the server. lpm takes the laptop: a pane per service, a switcher across projects, and copies of the stack for Claude Code and Codex.Not installing today? Drop the .lpm.yml above into the repo, beside your ecosystem.config.js. Point lpm at that folder whenever you get to it — the services are already declared, and anything lpm also detects there is yours to prune.