Skip to content
lpm vs Docker Compose

A Docker Compose alternative for fast local dev on macOS.

Compose gives every machine the same stack, at the cost of a Linux VM, a shared filesystem and a container to create before anything runs. lpm reads the repo, lists the same processes, and runs them straight on the host, one live pane each.

Most people end up splitting it: app code native, stateful infrastructure still in compose.

See every compose command mapped

Facts checked . The file-sharing and rebuild rows were re-checked against Docker's current defaults, not the osxfs era; every lpm cell was re-read in the app source on the same date, after lpm began listing compose files as a service.

The short answer

Can you run a dev stack on macOS without Docker Compose?

Yes — for every service your Mac can run directly. Add the folder and lpm lists the processes it recognises — Rails, Django, a Next.js or Vite dev server, Go, and the compose file itself — then starts them together, each in its own live pane, with dependsOn for start order and profiles for subsets of the stack.

What you give up is the container boundary: no pinned image versions, no separate network namespace, and no guarantee that a teammate on Linux gets an identical stack. Which is why most people end up splitting it — application code native, stateful infrastructure still in compose, both started from the same window.

.lpm.yml
services:
  compose: docker compose up
  api:
    cmd: bin/rails s
    port: 3000
    dependsOn: [compose]
  web:
    cmd: npm run dev
    port: 5173
    dependsOn: [api]

profiles:
  backend: [compose, api]

Commit it at the repo root and a teammate who clones gets the same graph. lpm still adds what it detects when they add the folder, so they may find a double to delete. Keep the attached form — docker compose up, not -d — if you want the container output in an lpm pane. The config reference documents every field.

lpm

Run it natively

Each process gets its own pane. No image, no volume, no container to create — dependsOn for order, profiles for subsets.

Both

Drive compose from lpm

Keep Postgres, Redis or Kafka in containers. Adding the folder already makes docker compose up one lpm service, its output in a pane beside your native ones.

Docker Compose

Keep compose

Prod parity down to the image tag, a teammate whose laptop is not a Mac, or an image there is no native way to install. Five rows in the table go to Compose, and the description names them.

Migration

Every compose command, and what you type instead

You do not have to move the whole file. This is the mapping for the parts you do move.

  • docker compose

    docker compose up

    lpm

    lpm start

    every service in the default profile, one pane each

  • docker compose

    docker compose up web

    lpm

    lpm service web start
  • docker compose

    docker compose --profile full up

    lpm

    lpm start --profile full
  • docker compose

    docker compose down

    lpm

    lpm stop
  • docker compose

    docker compose ps

    lpm

    lpm project <name>

    services, terminals, actions, live status

  • docker compose

    docker compose ls

    lpm

    lpm list

    every project, its running state and service counts

  • docker compose

    docker compose logs -f web

    lpm

    lpm logs web

    prints that pane's recent output; the live follow is the pane itself

  • docker compose

    docker compose run --rm web bin/rails db:migrate

    lpm

    an action, or lpm run migrate
  • docker compose

    depends_on:

    lpm

    dependsOn:

    start order; cycles are rejected when the config is validated

  • docker compose

    healthcheck + condition: service_healthy

    lpm

    lpm wait --port 5432

    an explicit gate rather than a condition on the dependency

  • docker compose

    profiles:

    lpm

    profiles:

    same idea, same name

  • docker compose

    environment:

    lpm

    env:

    per service

  • docker compose

    ports: "3000:3000"

    lpm

    port: 3000 + portConflict: ask | free | fail

    not a mapping — the process binds the host port itself; declaring it lets lpm check the port first and name the process holding it

  • docker compose

    committed docker-compose.yml

    lpm

    committed .lpm.yml

    merged underneath each developer's own project file, which also holds what lpm detected when they added the folder

The lpm column splits in two. lpm start, lpm stop and a service restart are requests to the open lpm window — that is where the panes live, and closing it leaves the services you already started running. lpm list and lpm logs read those services with the window shut. Every field on the right — profiles, dependsOn, env and portConflict — is in the config reference.

How it compares

Docker Compose and lpm, row by row

Five rows go to Compose: container isolation, identical runtimes and a network namespace of its own outright, plus health-gated start order and pinned image versions on substance. Those five are why the split-stack setup below exists.

  • Starts a multi-service dev stack in one command
    lpm
    click Start, or lpm start with the app open
    Docker Compose
    Yes
  • Declares startup order between services
    lpm
    dependsOn
    Docker Compose
    order + health gate
  • Time from start to services listening
    lpm
    process start
    Docker Compose
    container create + start
  • Rebuild needed when dependencies change
    lpm
    reinstall
    Docker Compose
    image rebuild
  • Reads your source straight off the host filesystem
    lpm
    Yes
    Docker Compose
    through the VM's file sharing
  • Containerized service isolation
    lpm
    No
    Docker Compose
    Yes
  • Pins the exact service version the team runs
    lpm
    whatever is installed on the host
    Docker Compose
    pinned by image tag
  • Identical runtimes on every teammate's machine
    lpm
    No
    Docker Compose
    Yes
  • Own network namespace, so two projects can both use 5432
    lpm
    No
    Docker Compose
    Yes
  • A live pane per service, open the whole time you work
    lpm
    Yes
    Docker Compose
    docker compose logs, or a container's Logs tab in Docker Desktop
  • Checks a declared port before start and names what holds it
    lpm
    ask, free, or fail
    Docker Compose
    no pre-start check documented
  • Starts, stops and switches between many repos from one window
    lpm
    Yes
    Docker Compose
    docker compose ls lists them; switching means changing directory
  • Service graph committed to the repo
    lpm
    .lpm.yml
    Docker Compose
    docker-compose.yml
  • Turns your compose file into something it runs
    lpm
    adds docker compose up as a service when you add the folder
    Docker Compose
    that file is compose's own input
  • Your coding agent gets a tab next to the service panes
    lpm
    Claude Code and Codex report Working, Needs you or Done
    Docker Compose
    the agent runs in a terminal you open yourself
  • Free to use inside a large company
    lpm
    MIT, at any company size
    Docker Compose
    Compose is Apache-2.0; Docker Desktop needs a paid subscription above Docker's size threshold

Isolation is where the concessions above bite hardest, and this is the exact position when a second agent needs the same project: copy it and the copy edits its own files, so two agents never save over each other. Nothing else is namespaced — one host, one set of ports, one Postgres — and lpm checks a declared port before the project starts, then tells you which process is holding it. A linked worktree starts from the tracked files only: an ignored .env is not in it, and Node packages are installed only if you turn on Install dependencies. How the copies work.

The setup most people land on

Native where it is fast, containers where they earn it

There is no migration to finish. Compose keeps the services you want pinned; lpm runs the code you edit.

Native in lpm

Your Rails or Django server, the Next.js dev server, a Go binary, background workers, anything with a file watcher. Each is one service with a pane of its own; the watcher inside it picks up your edits, and if the process dies its last output stays in the pane until you start it again.

Left in compose

Postgres, Redis, Kafka, Elasticsearch, LocalStack, a vendor image nobody installs natively. lpm lists the compose file as one service in the attached form — compose: docker compose up, not -d — so its output lands in a pane next to the rest.

  1. 01

    Add the folder. lpm reads the manifests, lists the native services — with the framework's default port where there is one — and adds docker compose up as one more. Generate with AI in the config editor is there if you want a different first pass.

  2. 02

    Move the processes with file watchers out of the compose file and into services:, one at a time.

  3. 03

    Leave the rest as a single compose service and bring the project up with one click — or lpm start, with the window open.

See it

A subset of the stack, on demand

Compose profiles have a direct equivalent: named subsets you switch between from the header.

Honest take

When to keep compose, and when to go native

A friendly split. If your daily loop is native code running on your laptop, lpm leans in. If your daily loop depends on containerized infra matching prod, Compose still wins.

Pick lpm

Most of your stack runs fine as a host process, and you want to see each one.

  • You do most of your dev natively on macOS, and the file share into the VM still sits between your watcher and your disk.
  • You want your Rails server, Next.js frontend, worker, and a Redis process each in their own live pane.
  • You juggle several repos and would rather see which stack is up than remember which compose file you left running where.
  • You run Claude Code, Codex, Gemini CLI, or OpenCode in parallel on the same or adjacent codebases and want their output beside your services — with Claude Code and Codex also reporting Working, Needs you or Done on the tab.
  • You already have a docker-compose.yml — lpm can drive it as one service while you move the rest native.
  • Your production is not containers at all — a managed platform, a VPS, or serverless — so the parity compose buys you was never real.
Pick Docker Compose

You need prod parity, team reproducibility, or real container isolation for local dev.

  • Your production runs on containers and you want dev to match the exact Postgres, Redis, or Kafka versions.
  • Your team spans multiple operating systems and reproducible local infra matters more than startup speed.
  • You rely on complex service networking, named volumes, or health checks that Compose expresses cleanly.
  • You want strong isolation — each service in its own container, its own filesystem, its own network namespace.
  • Your CI, staging, and prod pipelines are container-based and your dev environment should stay in that ecosystem.
  • A service nobody sensibly installs natively — Kafka, Elasticsearch, ClickHouse, SQL Server, LocalStack, or a vendor image with no Homebrew formula.
  • Two projects need the same port at the same time; containers give each stack its own network namespace and lpm does not.
See it in action

Add a folder, and it becomes a project

A short video: pick a folder or clone a repo, and it joins the sidebar.

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

Switching from — or alongside — Docker Compose

  • Can I use lpm and Docker Compose together?
    Yes, and this is the common case. lpm runs compose up as one of your services alongside native processes, and lists it that way on its own when the folder has a compose file. So you can keep Postgres and Redis in containers for prod parity while running your Rails or Next.js app natively, and watch every pane — container logs included — in the same desktop app. They are not mutually exclusive. Use the attached form — docker compose up, not -d — if you want the container output in an lpm pane; a detached start hands you nothing to watch.
  • Does lpm replace Docker Compose?
    For some workflows, yes; for others, no. If you're a solo or small-team dev doing native work on macOS and Compose was mostly a way to launch a process tree, lpm covers that with per-service panes and multi-project switching. If you rely on Compose for prod-parity service versions, cross-OS team reproducibility, or container-first deploy pipelines, keep using Compose. lpm doesn't try to be a container runtime.
  • Why is Docker Compose slow on a Mac?
    Your containers run in a Linux VM and your source is shared into it. VirtioFS narrowed that gap a lot and it is the default now, but the shared path still sits between your file watcher and your disk, and every start has to create and start containers rather than just a process. Native processes read the disk directly.
  • Can lpm read my docker-compose.yml?
    Partly. When you add the folder, lpm notices docker-compose.yml (or compose.yaml) and lists compose: docker compose up as one service — the attached form, so the container output has a pane — next to the native services it found in the same pass. It does not parse the compose service graph. To split the infrastructure further, edit the list, or press Generate with AI in the config editor for a second draft from Claude Code, Codex, Gemini CLI or OpenCode.
  • Two projects need port 5432 — what happens without containers?
    One of them loses, and lpm tells you before it starts: it checks each declared port, names the process holding it, and either asks, frees it, or refuses to start depending on that service's portConflict setting. That is detection, not isolation. If you genuinely need both at once, that is a container's job.
  • Does lpm run on Linux or Windows?
    There is no Windows build, and no Linux desktop build either — the app itself is macOS only. A Linux machine can still be the host that runs your services and agent sessions, with the Mac window driving all of it.

Keep compose where it earns it. Run the rest on the host.

Add the folder, get a live pane per service, and docker compose up as one of those services when a container is the right answer. Free, open source, native macOS app.