stackdeck

Your agent made four worktrees. Something has to run them.

Making the worktree is the easy part, and several tools do it well. The part nobody covers is the hour after: four branches, four dev servers, ports you didn't choose, and no idea which are up or what they are printing. Stackdeck starts them, keeps them running, and streams their logs.

It works on the rest of your projects folder too: it finds every project, works out how to run each one, and boards them all — with every port on the machine, and an MCP server so an agent can drive the lot. One Node process, one HTML page, zero dependencies, bound to 127.0.0.1. It never talks to the internet.

npm i -g stackdeck && stackdeck

Just want to look? npx stackdeck runs it without installing anything.

Needs Node 18.13 or newer, on macOS or Linux (WSL2 included, though nobody has confirmed it yet). Then point it at your projects folder and press configure on anything it found.

Shop 2 of 3 up
api :3001 pnpm run dev main Kill Logs
feature/rate-limits :3002 pnpm run dev worktree Kill Logs
studio :5173 pnpm run dev main Start Logs
Data 1 of 2 up
postgres :5432 postgres -D /usr/local/var/postgres external Kill Logs
A drawing of the board, not a live one: two branches of the same repo running side by side, and a Postgres someone started in a terminal an hour ago.

What it does once the worktree exists

01

It runs them, and keeps running them

Every branch gets its own row, its own log stream and its own address. A branch runs beside your main checkout in its own git worktree, on a free port, with the main copy's .env — and if an agent already made a worktree for it, Stackdeck runs that one rather than fighting git over it. restart: on-failure backs off exponentially, and dependsOn starts a stack in order, waiting for each piece to be serving rather than merely spawned.

A worktree costs a checkout, not a gigabyte: node_modules, target and .venv are symlinked back at the main checkout rather than copied, and never anything git tracks — experimental, and new. With isolateDb — which is experimental, creates and drops real databases, and nobody has used it in anger yet — the branch gets its own copy of the Postgres database too, so an agent's migration cannot reach your main checkout's data.

02

Your agent can drive all of it

stackdeck mcp puts the board on MCP: list and start and stop services, run a branch in a worktree, read logs, see what is holding a port. Starting returns only once the service is actually serving, so an agent never has to guess with a sleep loop — the one thing every integration otherwise reimplements. MCP is an open standard, so point any client that speaks it at npx -y stackdeck mcp — nothing to install.

03

Visit it and it starts

Turn on start on demand and opening api.localhost boots the service, holding the request until it is ready. With idle stop it shuts down again once nothing has touched it for a while, so twenty configured services cost you nothing until you open one.

And the ports you never configured

The board knows the services you set up. The Ports panel knows the machine: everything listening, which of your services owns it, the command behind it, its directory and parent, and a two-click kill. It is how you find the dev server from three weeks ago sitting on :3000.

:3000 54211 node …/side-project/node_modules/.bin/next dev 22d kill
:5000 1113 ControlCenter — macOS AirPlay Receiver, not a dev server system kill
:8021 owned by root — Stackdeck runs as you and cannot see or kill it needs sudo
It never asks for sudo, so root-owned ports are listed and left alone rather than quietly missing. Operating system processes that run under your own account say so before you kill one.

Watch it work

Live logs with filtering, then a second branch of the same API started in a parallel worktree on its own port, then the whole board switched to a light theme.

It never talks to the internet

No telemetry, no analytics, no update checks, no accounts, no CDN. The page loads no external fonts, scripts or images. The daemon listens on 127.0.0.1 and the only connections it opens are to loopback ports of services you configured yourself. It all works on a plane, and you can check that claim in one command while it is running:

$ lsof -nP -a -p "$(lsof -ti tcp:8899 -sTCP:LISTEN)" -i
only 127.0.0.1 listeners, plus loopback connections to your own services

Asked by the port it listens on, not by process name: pgrep -f server.js matches your editor's helpers too.

This page is the same: nothing on it is loaded from anywhere but this repository.

There is a terminal board too

Same daemon, so the browser stays in sync with it. Navigate, start, kill, restart, filter, and stream logs in a split pane — and press p for the same port table.

$ stackdeck tui

 stackdeck  5 running · 12 stopped
 ─────────────────────────────────────────────────────────────────
 Shop  2/3 up
   api                   :3001   71760   pnpm run dev
     ⧉ feature/rate-limits :3002   71874   worktree
  ○ studio                :5173           pnpm run dev
 ─────────────────────────────────────────────────────────────────
 ↑↓ move  s start  x kill  r restart  ⏎ logs  / filter  p ports  o open  q quit

How this relates to other tools

Creating an isolated worktree is table stakes now. workz does it as a Rust CLI: symlinks node_modules, copies your .env, installs dependencies, and with --isolated hands out unique ports, database names and a COMPOSE_PROJECT_NAME. Then it exits, which is exactly right for a setup tool. Conductor, Claude Squad and Agent Deck are working the same problem from other angles; go and read them rather than taking my summary of it.

Stackdeck is the half that comes after setup. It starts what is in the worktree, supervises it, restarts it when it crashes, streams its logs, says which ports are taken across the whole machine, and exposes all of that to an agent over MCP. Where those tools hand you a provisioned directory, Stackdeck is what keeps watching it — a different job, not a better one.

They compose. Stackdeck finds worktrees through git worktree list, so it adopts whatever created them, wherever they are. Provision with workz --isolated, run the result with Stackdeck, and neither needs to know the other exists.

Install

npm the usual way

$ npm i -g stackdeck

Published with provenance, so npm can show you which commit and which GitHub Actions run built the tarball. npx stackdeck works too, but npx installs nothing: you get a throwaway copy each time and no stackdeck command on your PATH.

curl no npm needed

$ curl -fsSL https://beingmechon.github.io/stackdeck/install.sh | sh

Downloads the published tarball, checks it against the sha512 npm recorded at publish time, unpacks it into ~/.local/lib/stackdeck and symlinks one command. Nothing is compiled and nothing is fetched afterwards, because there are no dependencies to fetch. Pin a version with STACKDECK_VERSION=0.11.2, move it with STACKDECK_PREFIX=/opt, and remove it with the same script and -s -- --uninstall. Read it before you pipe it.

Homebrew macOS and Linuxbrew

$ brew install beingmechon/tap/stackdeck

From a personal tap rather than homebrew-core, which only takes projects with a track record. The formula installs the same npm tarball and depends on node.

What it costs you

About 300 KB on disk and one Node process. Two files you can read in an evening, which is the point for something that runs shell commands on your machine: the daemon is one server.js, the board is one index.html, and there is no build step and no dependency tree between you and either of them.

MIT licensed, and the spiritual successor to hotel, which has been unmaintained since 2019, with the git-awareness it never had.