// dev server groups for your terminal, your editor, and your agent

One command.
Full stack running.

Muster runs your API, frontend, and workers as one named group — and keeps hold of them. Start it from the terminal, the editor, or an AI agent; the logs survive the crash, the restart, and the closed window.

MIT licensed·No editor required·MCP server built in·CLI + TUI + daemon

muster — Visual Studio Code
Muster: FastAPI
Muster: Next.js
Muster: Worker
muster run full-stack
[muster] starting 3 services · layout: dedicated · order: parallel
INFO Uvicorn running on http://127.0.0.1:8000
INFO Application startup complete.
[muster] ready pattern matched on api → starting dependents
celery@dev ready. 4 workers online
▲ Next.js — ready on http://localhost:3000
[muster] full-stack · 3/3 services running

The problem

A dev server never exits.
Everything around it assumes otherwise.

Shells, task runners, and AI agents are all built around commands that start, do a thing, and finish. A dev server does none of that — it runs for hours, prints continuously, and only stops when something kills it. That single mismatch is where the whole day goes.

Your agent runs it, then hangs

Ask an agent to start the dev server and it waits for a command that will never return. Every major agent has hit this — and had to build a workaround for it.

“Fixed claude -p hanging forever after its final result when a backgrounded command never exits.” Claude Code changelog · same pattern in Codex, Cursor, Copilot

The logs die with the session

Close the terminal and the output goes with it. So the one question you actually want answered afterwards — why did it crash? — has nothing left to read.

“Background tasks are automatically cleaned up when Claude Code exits.” Claude Code documentation

Nothing keeps a handle on what's running

With no durable record of what it started, an agent starts it again — and collides with the port it bound itself a minute earlier.

“Claude keeps forgetting that it already started the dev server… started a second one even after it identified that the port… was already in use.” claude-code#9780

Watching output eats the context window

Dev servers are noisy by design. Every line an agent reads is budget it isn't spending on your code — and one stuck process can dominate an entire session.

Measured on one bug: ~50K tokens per 10 exchanges became 581K — 11.6× waste. claude-code#11716

None of this is any one tool's fault — it's what happens when a process that never ends meets tooling that expects one that does. Muster is the piece that holds the process. It starts your stack and returns immediately, keeps the logs on disk after everything exits, and hands both humans and agents the same typed handle on what's actually running.

How it works

Muster in three moves

Define once, commit it to the repo, and everyone on the team gets the same one-click stack.

01

Define your groups

Use the visual wizard — folder pickers, command suggestions, runtime detection — or write .vscode/muster.json by hand. Group your API, frontend, and workers with dependencies and delays.

02

Run the group

One click in the sidebar — or muster run full-stack from any terminal. Muster opens terminals in your chosen layout — dedicated, aggregated, or split — and starts everything in order.

03

Watch everything

Live status per service in the tree. Errors and warnings from every terminal collected into one Events panel — filter by severity, group, or date, and click to jump to the source.

Features

Everything a running stack needs

Terminal layouts

One terminal per service, everything multiplexed into a single pane, or split panes across the editor — per group, your call.

Ordered startup

Parallel or sequenced starts with dependsOn graphs and per-service delays. Your worker never boots before the broker again.

Ready detection

Gate dependents on a readyPattern regex in terminal output or an HTTP healthUrl check — not on hope.

Stacked commands

A commands list per service, chained with && — install, migrate, then serve, without cramming one string.

First-class ports

Declare port once: it becomes the PORT env var, substitutes ${port} anywhere, and Muster warns before launch if something's already listening.

Lifecycle hooks

preRun/postStop commands per group — connect the VPN, docker compose up, run migrations — narrated, with failures aborting the run.

🐍

Runtime aware

Explicit venv and nvm activation per service, with project auto-detection available as an opt-in setting — never forced on you.

Event monitoring

Configurable regex patterns scan every service's output plus VS Code diagnostics. One timeline, filterable, click-to-navigate.

🛡

Trust & safety

Blocked in untrusted workspaces. Only commands defined in config can run — no arbitrary shell. Your other terminals are never touched.

🗄

Logs that outlive the process

Every line is kept on disk as timestamped, greppable text. Stop the group, restart it, close the terminal — the crash you were reading is still there. Retention is per group: 7d, 48h, or none to keep it until you clear it.

Stop keeps your scrollback

Stopping interrupts the process and leaves the terminal, so a crash loop stays on screen to read. Restart reuses it and carries the history across a — restarted — divider instead of a blank screen.

Background daemon

muster daemon start hands your stack to a process that outlives the terminal that launched it — and the editor. Close everything; muster logs and every MCP tool still work.

Terminal native

The same stack, from any terminal

Run your stack with muster up — no VS Code required: it reads your config, supervises the processes itself, and opens this exact dashboard — status dots, per-service logs, hotkeys, mouse, command palette. Quit and the whole tree stops with it. When VS Code is open, the same CLI becomes a remote control for the extension; when piped or in CI it degrades to clean prefixed logs.

muster — dashboard
MUSTER ~/code/acme
Full Stack Dev (full-stack · dedicated) running
    FastAPI :8000 uvicorn main:app --reload
    Celery Worker celery -A app worker
    Next.js :3000 pnpm dev
  Workers Only (workers · aggregated) idle
    Indexer node jobs/indexer.js
: stop web  type an action · enter to run
stop full-stack/web
rrun sstop xrestart llogs /filter :commands qquit ↑↓/click select

Type what you want :

The command palette fuzzy-matches every live action — stop web finds stop full-stack/web. No keybindings to memorize.

Point and click

Click rows to select, click a service again for its logs, click the footer buttons to act, scroll to move. A TUI that behaves like a UI.

Create, run, remove

Scaffold config, create and delete groups (muster create), stop or restart a single service without touching its siblings, follow and filter logs — from the terminal or the sidebar tree.

Standalone, same dashboard

muster up needs no editor at all — the supervisor runs in your terminal with this same UI, an activity feed on the group row, and a quit that tears down every process. No orphans, ever.

MCP built in

Give your agent the stack, not a shell

Muster ships a native Model Context Protocol server. Agents in Claude Code, Cursor, Codex, and any MCP client can define, start, and read your groups through typed tools — no editor open, no arbitrary shell access, no watching a dev server swallow the conversation.

Tools

list_server_groupsread
get_group_statusread
get_service_logsread
describe_configread
create_server_groupconfig
add_service_to_groupconfig
run_server_groupconfirm
stop_server_groupconfirm
restart_server_groupconfirm

It never blocks. Starting a group hands it to Muster and returns immediately — the agent gets a status back instead of hanging on a process that never exits. Ask for logs when you actually need them.

Filtered, not firehosed. get_service_logs takes a severity and a substring, so an agent pulls the errors from api — a handful of lines — rather than pasting a megabyte of dev-server output into its context.

Scoped by design. Agents act only on IDs defined in your config; unknown ones are rejected. Defining a group only writes config. Anything that actually starts or stops a process waits for your OK — a prompt in the editor, or an explicit --allow-agent-actions when you run the daemon headless.

Works with no editor. The tools reach a running muster daemon or the VS Code extension, whichever is up:

muster daemon start --allow-agent-actions

Configuration

One file, whole team

A single muster.json in your repo defines the stack for everyone. Schema-validated, wizard-editable, diff-friendly.

  • JSON Schema autocomplete in VS Code
  • ${workspaceFolder}, ${env:VAR}, and ${port} substitution
  • Stacked commands, first-class ports, pre-run/post-stop hooks
  • Global profiles in ~/.config/muster, env files, shell prepends
.vscode/muster.json
{
  "groups": [{
    "id": "full-stack",
    "label": "Full Stack Dev",
    "layout": "dedicated",
    "hooks": { "preRun": ["docker compose up -d db"] },
    "services": [
      {
        "id": "api",
        "command": "uvicorn main:app --port ${port}",
        "port": 8000,
        "cwd": "${workspaceFolder}/backend",
        "readyPattern": "startup complete"
      },
      {
        "id": "worker",
        "command": "celery -A app worker",
        "dependsOn": ["api"]
      },
      {
        "id": "frontend",
        "commands": ["pnpm install", "pnpm dev"],
        "port": 3000,
        "cwd": "${workspaceFolder}/frontend"
      }
    ]
  }]
}

Install

Muster your stack

On the Marketplace and on npm today — pick whichever fits how you work.

VS Code Marketplace

LIVE

One-click install from the Extensions view — search for Muster, or:

$ code --install-extension muster.muster

View the listing ↗ · An Open VSX listing (Cursor, VSCodium) follows right after.

From source

TODAY

Clone, package, install — no build system beyond npm.

$ git clone https://github.com/berwinsingh/muster.git $ cd muster && npm install $ npm run package $ code --install-extension muster-0.1.10.vsix

Prefer the terminal? Add the CLI

LIVE

npm install -g puts muster and muster-mcp on your PATH in one command — no VS Code required. muster up runs your groups right in the terminal, dashboard and all.

$ npm install -g muster-cli

Already have the extension installed instead? It offers to install the CLI itself the first time it sees a config — one click, no npm required.

Where the CLI comes from

The extension carries the CLI inside its own extension folder, and the editor puts that folder in a different place depending on where your code lives. That's invisible on macOS and Windows, and the whole story on WSL — so it's worth thirty seconds.

macOS & Linux

NOTHING TO DO

Install the extension, and the first time it sees a config it offers to put muster on your PATH — one click. It lands in /usr/local/bin, or ~/.local/bin when that needs sudo.

extensions live in ~/.vscode/extensions

Windows

NOTHING TO DO

Same one-click offer, into %USERPROFILE%\.muster\bin. If a new terminal can't find muster, that directory isn't on your PATH yet:

> setx PATH "%PATH%;%USERPROFILE%\.muster\bin"
extensions live in %USERPROFILE%\.vscode\extensions

WSL, Remote SSH, devcontainers, Codespaces

READ THIS

These keep two separate sets of extensions — one for the editor's window, one for the machine your code is on. An extension installed on the Windows side is on a different filesystem from the shell you run muster in, so the install succeeds and the terminal sees nothing change.

Install it where the code is: open the folder in WSL first, then in the Extensions view use Install in WSL (or Install in Dev Container / Install in SSH). Then check which copy you actually got:

$ muster --version

It prints the version and the file it resolved. On WSL that path must start with /home/ — if it starts with /mnt/c/, or the command isn't found at all, you installed on the Windows side.

extensions live in ~/.vscode-server/extensions

Building from source?

ONE GOTCHA

npm link puts muster on your PATH pointing at your checkout — but a checkout with nothing built has no CLI to run, so it falls back to the installed extension's copy. You'd be editing one tree and running another. Build first:

$ npm install && npm run compile $ npm link $ muster --version

The last line should print a path inside your checkout. If it doesn't, muster says so on stderr rather than letting you debug a fix you already made.

Where the CLI comes from

The extension carries the CLI inside its own extension folder, and the editor puts that folder in a different place depending on where your code lives. That's invisible on macOS and Windows, and the whole story on WSL — so it's worth thirty seconds.

macOS & Linux

NOTHING TO DO

Install the extension, and the first time it sees a config it offers to put muster on your PATH — one click. It lands in /usr/local/bin, or ~/.local/bin when that needs sudo.

extensions live in ~/.vscode/extensions

Windows

NOTHING TO DO

Same one-click offer, into %USERPROFILE%\.muster\bin. If a new terminal can't find muster, that directory isn't on your PATH yet:

> setx PATH "%PATH%;%USERPROFILE%\.muster\bin"
extensions live in %USERPROFILE%\.vscode\extensions

WSL, Remote SSH, devcontainers, Codespaces

READ THIS

These keep two separate sets of extensions — one for the editor's window, one for the machine your code is on. An extension installed on the Windows side is on a different filesystem from the shell you run muster in, so the install succeeds and the terminal sees nothing change.

Install it where the code is: open the folder in WSL first, then in the Extensions view use Install in WSL (or Install in Dev Container / Install in SSH). Then check which copy you actually got:

$ muster --version

It prints the version and the file it resolved. On WSL that path must start with /home/ — if it starts with /mnt/c/, or the command isn't found at all, you installed on the Windows side.

extensions live in ~/.vscode-server/extensions

Building from source?

ONE GOTCHA

npm link puts muster on your PATH pointing at your checkout — but a checkout with nothing built has no CLI to run, so it falls back to the installed extension's copy. You'd be editing one tree and running another. Build first:

$ npm install && npm run compile $ npm link $ muster --version

The last line should print a path inside your checkout. If it doesn't, muster says so on stderr rather than letting you debug a fix you already made.

Connect your agent

Inside VS Code or Cursor with the extension installed, this is already wired up — see Agents above. From a terminal, or with no editor open at all, register muster-mcp with your client directly:

Claude Code

EASIEST

Install the repo as a plugin — registers the MCP server and the agent skill (the read → run → poll → stop workflow) in one step:

/plugin marketplace add berwinsingh/muster /plugin install muster@muster

Or register the server directly

$ claude mcp add muster -- muster-mcp

Verify with /mcp in a session — nine muster tools should list.

>_ Codex CLI

One command registers it:

$ codex mcp add muster -- muster-mcp

Or add to ~/.codex/config.toml

[mcp_servers.muster] command = "muster-mcp"

Cursor

Cursor doesn't read VS Code's MCP provider, so add it to .cursor/mcp.json (project) or ~/.cursor/mcp.json (global):

{ "mcpServers": { "muster": { "command": "muster-mcp" } } }

Then enable it under Settings → MCP.

Any other MCP client

Point it at the launcher — it finds the compiled server on its own, whether from an npm install -g or a checkout:

command: muster-mcp

From a repo checkout

$ node bin/muster-mcp.cjs
No editor required — the launcher reaches a standalone muster daemon or a running VS Code/Cursor extension, whichever answers. Headless, start the daemon with muster daemon start --allow-agent-actions first so run/stop/restart don't wait on a confirmation prompt nobody's there to click.

Product names and logos belong to their respective owners and are used here only to identify the clients Muster works with. Marks from Simple Icons (CC0).