DPMux Docs

Everything you need to install, customize, and automate DPMux.

Install

  1. Download DPMuxSetup.exe (~110 KB).
  2. Run it. The installer downloads the latest release, verifies its SHA-256, and installs to %LOCALAPPDATA%\DPMux — per-user, no administrator prompt, no wizard.
  3. DPMux launches automatically with Start-menu and Desktop shortcuts created, and the dpmux command available in any new terminal.

Requirements: Windows 10/11, x64. SmartScreen may warn on first run because the installer is not code-signed — choose More info → Run anyway.

# silent install / scripted install
> DPMuxSetup.exe --silent

# install from a different update channel
> DPMuxSetup.exe --url https://example.com/latest.json

Updates

DPMux updates itself like a browser: it checks the update channel on launch and every 4 hours, downloads new versions in the background, verifies them, and stages them next to the running version. When an update is ready you'll see a "Restart to update" toast — or apply it yourself:

> dpmux check-updates     # check + download now
> dpmux update-status     # idle | downloading | ready | uptodate ...
> dpmux update-restart    # apply a staged update

Versions install side by side (app-1.0.1, app-1.0.2, …); the previous version is kept so a bad update can be rolled back by deleting the newest folder. Set DPMUX_UPDATE_URL to point an install at a different channel.

Workspaces, panes & surfaces

  • Workspaces are the items in the left sidebar — one per task. Each shows its live title, a preview of recent output, working directories, an optional status pill and progress bar, and a notification ring when something needs you.
  • Groups are named collections of workspaces — switch with the header dropdown.
  • Panes split a workspace into tiles (right/down/left/up, drag the dividers to resize). Splitting never restarts the shells already running.
  • Surfaces are tabs inside a pane — each one a terminal or a browser. Close the last surface and the pane closes; close the last pane and the workspace closes.

The sidebar is resizable — drag its edge (180–440 px; the width is remembered). Drag it small and it snaps into a compact icon rail: each workspace becomes a tinted monogram tile with all the signals wrapped around the icon — the notification ring pulses around it, progress becomes a circular ring, the status pill becomes a colored corner dot (hover for the full text), unread keeps its dot. Double-click the edge to toggle expanded ↔ rail, or cycle expanded → rail → hidden with Ctrl+Shift+B (also scriptable: dpmux sidebar rail).

Sessions are restored on restart: layout, titles, working directories, and browser URLs come back — and since 1.4.0, so do the running shells themselves (see Detach).

Detach — sessions that survive everything

Your shells don't live inside the DPMux window. They live in a small background process, dpmux-ptyhost, that owns the consoles — so when the app exits, crashes, or restarts to apply an update, every shell keeps running. Relaunch DPMux and each workspace re-attaches to the same processes, scrollback included, tmux-style. A 40-minute agent run no longer dies with the window.

  • Survives: closing the window, app crashes, renderer reloads, and DPMux's own auto-updates (restart-to-update keeps the fleet running).
  • Doesn't survive: closing a pane/surface/workspace yourself — explicit closes kill the shell, exactly as you'd expect — and dpmux kill-server, log-off, or reboot.
> dpmux detach-status   # the host process + every shell it holds
> dpmux kill-server     # end the host and every shell in it (tmux-style)

Because shells outlive the window, closing DPMux no longer stops what's running in it — a build or agent left in a workspace keeps working in the background. Use dpmux kill-server (or close the panes first) when you want everything gone. Prefer the old behavior entirely? Set "detach": false in settings.json and restart.

The host exits on its own once it holds no shells and no app is connected. After an app update it is replaced the next time it's empty; an old host keeps serving a newer app in the meantime.

Keyboard shortcuts

Defaults below — every one is rebindable. Plain Ctrl combos still reach the shell (Ctrl+R history search etc.), matching Windows Terminal conventions.

ActionShortcut
New workspaceCtrl+Shift+T
Close surface / pane / workspaceCtrl+Shift+W
Split right / downCtrl+Shift+D / Ctrl+Shift+E
New browser surfaceCtrl+Shift+L
Next / previous workspaceCtrl+Tab / Ctrl+Shift+Tab
Jump to workspace 1–9Ctrl+Alt+1…9
Focus pane directionallyAlt+←↑↓→
Resize paneCtrl+Shift+←↑↓→
Find in terminalCtrl+Shift+F
Command paletteCtrl+Shift+P
Cycle sidebar (expanded / rail / hidden)Ctrl+Shift+B
New groupCtrl+Shift+N
Rename workspaceCtrl+Shift+R
Copy / pasteCtrl+Shift+C / Ctrl+Shift+V (right-click pastes)
Font zoomCtrl+= / Ctrl+- / Ctrl+0
FullscreenF11

Pane resize and font zoom need a terminal focused — while a browser pane has focus those keys belong to the page.

Configuration

Everything lives in %APPDATA%\DPMux\settings.json (create it via the command palette: Open settings file). Changes are hot-reloaded — save the file and the app re-themes live. Kebab-case keys, Ghostty-style:

{
  "theme": "catppuccin-mocha",
  "font-family": "JetBrains Mono",
  "font-size": 14,
  "line-height": 1.2,
  "cursor-style": "bar",            // block | bar | underline
  "cursor-blink": true,
  "scrollback-lines": 50000,
  "window-padding-x": 10,
  "window-padding-y": 8,
  "background": "#11111b",
  "accent-color": "#89b4fa",
  "palette": { "1": "#ff5555" },
  "keybind": ["ctrl+shift+o=split-right", "ctrl+shift+w=unbind"],
  "shell": "pwsh.exe",
  "shell-args": ["-NoLogo"],
  "working-directory": "D:\\projects",
  "detach": true                  // shells survive app restarts (see Detach)
}

Layering, later wins: defaults → your Ghostty config → settings.json → DPMUX_PIPE/DPMUX_SHELL env vars. Inspect the result with dpmux get-config; force a reload with dpmux reload-config. pipe-name changes need a restart; everything else applies live.

Themes & colors

Built-in themes: tokyo-night (default), catppuccin-mocha, dracula, gruvbox-dark, nord, one-dark. Names match Ghostty's, so a Ghostty theme = line maps directly.

Override any part of a theme with background, foreground, cursor-color, selection-background, accent-color (the UI accent: rings, selection, progress bars), and per-slot ANSI colors via palette (indexes 0–15, object or 16-element array).

Custom keybinds

Ghostty syntax — "combo=action" entries in the keybind array. Later entries win; unbind removes a default.

"keybind": [
  "ctrl+shift+o=split-right",
  "f5=reload-config",
  "ctrl+shift+w=unbind"
]

Actions: new-workspace, close-surface, split-right/down/left/up, new-browser-surface, command-palette, find, toggle-sidebar, new-group, rename-workspace, next-workspace, previous-workspace, workspace-1workspace-9, focus-pane-left/right/up/down, resize-pane-left/right/up/down, copy, paste, zoom-in/out/reset, fullscreen, reload-config, unbind.

Combo syntax: modifiers ctrl, alt, shift, meta/win; keys like t, f5, left, esc, plus, page_up.

Ghostty config inheritance

If ~/.config/ghostty/config (or %APPDATA%\ghostty\config) exists, DPMux reads its appearance keys automatically: font-family (repeats become a fallback list), font-size, theme, background, foreground, cursor-color, cursor-style, cursor-style-blink, selection-background, window-padding-x/y, and palette = N=#rrggbb lines. Ghostty keybind lines are not imported (different action names). Opt out with "use-ghostty-config": false.

The dpmux CLI

Installed automatically (since 1.0.3) — open any terminal and run dpmux. Inside a DPMux terminal, commands target the calling workspace/surface by default, so a script or agent can address its own tab without ids. Outside, they target the active workspace, or use --workspace/--pane/--surface with an id, title, or 1-based index.

# set up a labelled dev workspace with a browser beside it
> dpmux new-workspace --title "dev server" --cwd D:\proj --command "npm run dev"
> dpmux split-pane --dir right --url http://localhost:3000

# type into terminals, read what they printed
> dpmux send-text "git status" --workspace "dev server"
> dpmux capture-pane --lines 50

# everything responds with JSON when you add --json
> dpmux list-workspaces --all --json

dpmux help prints full usage; dpmux capabilities lists every command the app accepts, including tmux-compat aliases (new-window, send-keys, kill-pane, capture-pane, …).

Command reference

AreaCommands
Workspaceslist-workspaces current-workspace new-workspace close-workspace rename-workspace focus-workspace move-workspace mark-read mark-unread set-status set-progress
Groupslist-groups new-group rename-group focus-group close-group
Paneslist-panes split-pane close-pane focus-pane resize-pane flash-pane
Surfaceslist-surfaces new-surface close-surface focus-surface respawn
Terminal I/Osend-text send-keys capture-pane
Notificationsnotify notification-list notification-clear
Browsernavigate browser-back browser-forward browser-reload browser-eval browser-screenshot
Appping version capabilities dump activate screenshot sidebar events get-config reload-config check-updates update-status update-restart detach-status kill-server
AI agentsmcp mcp install mcp uninstall mcp print install-hooks claude install-hooks codex install-skill claude — see Claude Code / Codex setup
Fleetfleet-dispatch (alias dispatch) fleet-list fleet-review fleet-merge fleet-discard — see Fleet Dispatch
Researchresearch-dispatch (aliases research, scout) — parallel research agents, no worktree; see Research Dispatch
Blocksinstall-shell-integration list-blocks search-blocks (alias search) get-block bookmark-block block-stats workspace-blocks — see Command blocks
Librarylibrary list library run library show library rm — reusable workflows / prompts / env-sets; see Library
Privacyredact-preview — preview the local secret redaction applied to blocks (no upload)

Under the hood this is a named pipe (\\.\pipe\dpmux-<user>) speaking JSON lines — {"id":1,"cmd":"new-workspace","args":{…}} — so any language can drive DPMux directly. dpmux events subscribes the connection to a live event stream (notification.created, workspace.created, …). Socket commands never steal focus unless you pass --focus.

Notification rings

Rings are explicit — DPMux never guesses from output. Trigger them three ways:

1. From the CLI (or an agent hook)

> dpmux notify --title build "tests are green — ready for review"

2. With escape sequences from any program

# OSC 9 (simple), OSC 777 (title + body), OSC 99 (kitty) all work
> printf '\x1b]9;build finished\x07'
> printf '\x1b]777;notify;Build;tests are green\x07'

3. From PowerShell

> Write-Host "`e]9;deploy needs approval`a" -NoNewline

Effects: pulsing ring + unread marker on the workspace, a blue flash on the originating pane, the message shown under the workspace title, plus a desktop notification and taskbar flash when the window is in the background. Everything clears when you view the workspace. Add sidebar status with dpmux set-status "deploying" --color "#9ece6a" and dpmux set-progress 0.7.

Browser panes

Any pane can hold browser surfaces (Ctrl+Shift+L, or split-pane --url …). They're full Chromium webviews: address bar with search, back/forward, DevTools, and popups open as sibling tabs. Drive them from scripts:

> dpmux navigate http://localhost:3000
> dpmux browser-eval "document.title"
> dpmux browser-screenshot page.png

Command blocks & history

Since 2.0.0, DPMux can capture every command as a block — the command line plus its output, exit status, working directory and timing — the way Warp does. Turn it on once; it's driven by OSC 633 shell integration and only activates inside DPMux (a guarded snippet appended to your PowerShell $PROFILE / ~/.bashrc / ~/.zshrc):

> dpmux install-shell-integration            # PowerShell + bash + zsh (uninstall | status)

Then Ctrl+Shift+H opens a searchable history of the active terminal — jumps to a command, Ctrl+R re-runs it, Ctrl+B bookmarks it. The command palette searches your whole history, and scripts or agents can query it directly:

> dpmux search-blocks "docker run"     # ranked by relevance + recency
> dpmux get-block s12.4               # the full command + output for one block
> dpmux workspace-blocks              # HTML transcript of a workspace's commands, errors highlighted

Before a block is stored or shown it runs through a local secret-redaction pass — AWS / GitHub / OpenAI / Anthropic keys, bearer tokens, private keys, connection-string passwords, SECRET=… assignments. Nothing leaves your machine; preview exactly what it strips with dpmux redact-preview "…". Tune it under "blocks" and "redaction" in settings.json.

Workflow library

Save the setups you run constantly as reusable workflows, prompts, and env sets — JSON files under %APPDATA%\DPMux\library. A workflow is a list of steps that provisions a whole workspace layout in one command (each step's created ids thread into the next, so a split lands in the workspace just created):

> dpmux library list
> dpmux library run wf-dev-preview --command "npm run dev" --url http://localhost:5173

Run them from the command palette with a parameter form, or let an agent run one with the run_workflow MCP tool. A local Event log (command palette → "Show event log") shows DPMux's own event stream — the same frames dpmux events emits.

Claude Code setup

A few one-time commands turn DPMux into mission control for Claude Code (MCP + hooks since 1.2.0; fleet dispatch + the skill since 1.5.1):

> dpmux mcp install            # let Claude drive the terminal + dispatch fleets (MCP server, user scope)
> dpmux install-hooks claude   # live status pills + rings from every Claude session
> dpmux install-skill claude   # teach Claude when to dispatch a fleet vs. delegate in-process

What the MCP server gives Claude

With dpmux mcp install, Claude Code sessions get tools to operate the terminal they're running in — every tool defaults to the agent's own workspace and pane, so Claude can split a pane to run your dev server, open a real Chromium tab at localhost:3000, screenshot it to see its own UI change, and ring your workspace when it's done or blocked. The full tool list is in the MCP tool reference.

Since 1.5.1 that list includes the fleet_* tools, so Claude can dispatch its own fleet — parallel worktree agents you watch on the Fleet Board — with fleet_dispatch, then fleet_status, fleet_review, and fleet_merge / fleet_discard, instead of spawning invisible in-process sub-agents. Since 1.7.0 it can also dispatch research with research_dispatch — parallel web-search agents, no worktree — and tidy up with close_workspace.

For other MCP clients, dpmux mcp print emits the mcpServers JSON to paste into their config; dpmux mcp uninstall removes the registration.

What the hooks give you

dpmux install-hooks claude wires five Claude Code lifecycle hooks to the sidebar — the agent declares its own state, no output-scraping:

Claude Code eventWhat you see
Prompt submittedStatus pill working
Claude waits on you (permission or idle prompt)Pill needs input + notification ring, desktop alert, taskbar flash
Response finishedPill done + unread dot
Delegates to a sub-agent (the Agent/Task tool, since 1.5.1)Pill delegating ×N while sub-agents run, back to working as each finishes

Run five Claude sessions in five workspaces and the sidebar tells you at a glance which are grinding, which are blocked on you, and which finished while you were elsewhere.

The hooks are safe to keep installed globally: the dpmux claude-hook command no-ops outside DPMux terminals, never blocks or breaks a Claude session, and your existing hooks in ~/.claude/settings.json are preserved (a backup is written beside the file). Unwire any time with dpmux install-hooks claude --remove. Already-running Claude sessions pick the hooks up after a restart.

Letting Claude dispatch fleets

dpmux install-skill claude installs the /dpmux-dispatch skill, which teaches Claude when to fan work out to a fleet — real, isolated, visible, mergeable worktree agents — when to send out research instead (parallel findings, no worktree), and when to just use an in-process sub-agent, plus how to drive dispatch → review → merge through the fleet_* tools. It needs dpmux mcp install. Dispatched agents run asynchronously: Claude polls and reviews, and you approve every merge, so you stay in the loop. --remove uninstalls it.

No setup at all

Even without MCP or hooks, any agent inside a DPMux terminal can ring its own workspace — handy as a CLAUDE.md instruction:

> dpmux notify "done — tests are green"
> dpmux set-status "reviewing" --color "#bb9af7"

OpenAI Codex setup

The same ground-truth sidebar pills work for OpenAI Codex CLI sessions — one command (since 1.6.0):

> dpmux install-hooks codex   # live status pills from every Codex session

It registers three of Codex's lifecycle hooks in your user-level ~/.codex/config.toml (turning on features.hooks) — Codex declares its own state, no output-scraping:

Codex eventWhat you see
Prompt submitted (UserPromptSubmit)Status pill working
Waiting on you to approve a tool (PermissionRequest)Pill needs input + notification ring, desktop alert, taskbar flash
Turn finished (Stop)Pill done + unread dot

Run a Claude Code session and a Codex session side by side and the sidebar tells you the truth about both — which is grinding, which is blocked on you, which finished while you were elsewhere.

DPMux uses Codex's [hooks] engine, which delivers each event's payload on stdin — the agent's output never reaches a shell. The dpmux codex-hook command no-ops outside DPMux, a backup of config.toml is written beside it, and your own config is preserved. Needs a recent Codex (the hooks engine); restart Codex to pick the hooks up. Unwire any time with dpmux install-hooks codex --remove.

Fleet Dispatch

Run several agents on one repo in parallel, each isolated in its own git worktree on its own branch — with a diff-review gate before anything merges back (since 1.5.0).

> cd D:\proj
> dpmux dispatch "fix the navbar overlap" "add tests for auth" "update the docs"

Each task gets a fleet/<slug> branch + worktree (in a sibling <repo>.fleet\ folder), a workspace under a Fleet: sidebar group, and a Claude Code session started on the task. With hooks installed, the pills tell you at a glance who's working, who's blocked on you, and who's done — and with Detach, a dispatched fleet survives app restarts mid-run.

The Fleet Board

While a fleet runs, a mission-control card sits pinned at the top of the sidebar — visible no matter which group you're working in. One dot per agent, colored by live state (working / needs you / done); per-agent rows show the task, elapsed time, and live work metrics (+insertions −deletions · commits, refreshed every few seconds from the worktree). Hover a row for diff / merge / drop actions, click it to jump to that agent's workspace, and the card glows when anyone is blocked on you. dpmux fleet-stats exposes the same numbers to scripts.

The review gate

> dpmux fleet-review     # styled diff vs the base branch, in a review pane
> dpmux fleet-merge      # wip-commit -> squash-merge onto base -> cleanup
> dpmux fleet-discard    # drop the branch + worktree without merging
> dpmux fleet-list       # every dispatched workspace and its branch

Run them inside a fleet workspace's terminal (they self-target), or pass --workspace. fleet-merge commits any uncommitted agent work first (nothing is silently lost), refuses if your main repo is dirty or on a different branch than the fleet was cut from, and rolls back cleanly on conflicts. Each fleet lands as one squash commit: fleet: <task>.

The launch command is configurable — "fleet-command" in settings.json (default claude "{task}"; {task} is substituted and PowerShell-escaped). Point it at any agent CLI. Also in the command palette: Dispatch agent fleet… — tasks separated by ||, repo taken from the active terminal's cwd.

Research Dispatch

The git-free sibling of Fleet Dispatch: fan out several agents to research, deliberate, and search the web in parallel — for findings, not code, so there's no worktree, branch, or merge (since 1.7.0).

> dpmux research "compare Postgres vs SQLite for a local-first app" "what are people saying about Bun this month"

Each task gets its own workspace + terminal under a single Research sidebar group, running a real Claude (or Codex) session pointed at the question — told to lean on web search and the /last30days skill (if installed) for recent Reddit / X / HN / YouTube discussion, and to finish with a concise, well-sourced summary. No repo is required; up to 8 tasks per dispatch. Aliases: research, scout.

> dpmux capture-pane     # read a scout's findings back from its terminal
> dpmux close-workspace  # clear it away when you're done — nothing to merge

The launch command is configurable — "research-command" in settings.json (default claude "{task}"; {task} is substituted and PowerShell-escaped), mirroring "fleet-command". Claude and Codex can dispatch research themselves via the research_dispatch MCP tool.

MCP tool reference

The tools exposed by dpmux mcp. Targeting parameters (workspace_id, pane_id, surface_id) are always optional — they default to the workspace/pane the agent is running in via the DPMUX_* env vars.

ToolWhat it does
list_workspacesEvery workspace with status, pills, progress, paths — the place to find ids
list_surfacesTerminal/browser tabs of a workspace (find browser surface ids)
new_workspaceNew sidebar workspace with optional title, cwd, command
split_paneSplit (right/left/down/up) into a new terminal — or a browser when url is set
send_textType a line into a terminal (with or without Enter)
send_keysSpecial keys: Enter, Escape, C-c, arrows, … for prompts and TUIs
read_paneRead a terminal's recent output
search_blocksSearch the command history — prior commands with output, exit, cwd, timing
list_blocksRecent command blocks for a workspace/surface (newest first, or only bookmarked)
get_blockOne block in full — the command line and its complete output
review_workspace_blocksOpen an HTML transcript of a workspace's commands (status, timing, output) for a human to read
list_workflowsList the library — saved workflows / prompts / env-sets and their parameters
run_workflowRun a library object by id — provisions a workspace layout, expands a prompt, or applies an env-set
open_browserOpen a Chromium tab in a pane at a URL (dev server, docs, anything)
navigatePoint an existing browser surface at a new URL
browser_evalRun JavaScript in the page and get the result
browser_screenshotScreenshot the page — returned as an image the agent can see
screenshot_appScreenshot the whole DPMux window, returned as an image
notifyRing the workspace (+ desktop notification, taskbar flash)
set_statusSet the sidebar status pill (text + color)
set_progressShow a progress bar on the workspace card (0..1, or clear)
fleet_dispatchDispatch a fleet — one worktree agent per task, on the Fleet Board
fleet_statusLive per-agent metrics: branch, +ins/−del, commits, status
fleet_reviewOpen the diff-vs-base review pane for a fleet agent
fleet_mergeSquash-merge a fleet agent's branch onto base, then close + clean up
fleet_discardDrop a fleet agent's branch + worktree without merging
research_dispatchDispatch parallel research agents — one workspace per task, no worktree/repo (findings, not code)
close_workspaceClose a workspace + its terminals — e.g. clear a research agent once you've read its findings

The server is a thin bridge to the same named-pipe API the CLI uses, so anything an MCP tool can do, a script can do too — see the command reference.

Where things live

PathWhat
%LOCALAPPDATA%\DPMux\The app: launcher (DPMux.exe), versioned app-x.y.z folders, bin\dpmux.cmd CLI shim, Uninstall.exe
%APPDATA%\DPMux\settings.jsonYour configuration (hot-reloaded)
%APPDATA%\DPMux\session.jsonSaved layout/session (restored on launch)
\\.\pipe\dpmux-<user>The automation socket (override: DPMUX_PIPE)

Env vars inside every DPMux terminal: DPMUX_PIPE, DPMUX_WORKSPACE_ID, DPMUX_PANE_ID, DPMUX_SURFACE_ID, TERM_PROGRAM=DPMux.

Uninstall

Use Settings → Apps & features → DPMux, or run %LOCALAPPDATA%\DPMux\Uninstall.exe --uninstall (add --silent to skip the prompt). This removes the app, shortcuts, PATH entry, and registry entries. Your settings and sessions in %APPDATA%\DPMux are kept — delete that folder too for a full wipe.

FAQ

Does plain Ctrl+C / Ctrl+R / Ctrl+W reach my shell?

Yes. App shortcuts use Ctrl+Shift (Windows Terminal convention); plain Ctrl combos go to the shell untouched.

Which shell does DPMux use?

PowerShell 7 if installed, otherwise Windows PowerShell. Override with "shell"/"shell-args" in settings.json (cmd, nushell, git-bash, WSL via wsl.exe — anything with a console works).

Why does splitting a pane not restart my process?

Panes are repositioned, never recreated — running shells, scrollback, and browser pages survive splits, closes, and resizes.

Can I run two independent instances?

Yes — set DPMUX_PIPE=some-name before launching. That instance gets its own socket and an isolated settings/session directory under %APPDATA%\DPMux\instances\.

The `dpmux` command isn't found

Open a new terminal (PATH changes don't reach existing ones), and launch DPMux at least once after installing or updating to 1.0.3+ — the launcher provisions the CLI shim. Inside DPMux's own terminals the CLI is always available, no PATH setup needed.

Running `dpmux` opened another DPMux window instead of the CLI

That was a 1.0.2/1.0.3 bug (the app launcher could shadow the CLI shim on PATH, and a second instance could slip past the single-instance lock). Fixed in 1.0.4 — update via Check for updates in the command palette and restart. If a stray extra window is open, just close it.

Is this the same as tmux on Linux?

No — DPMux is a Windows GUI terminal inspired by cmux. The CLI borrows tmux verbs (send-keys, capture-pane, split-window…) so existing muscle memory and scripts adapt easily.

Is the source available?

Not currently — DPMux is proprietary and free to use. The update channel (dpmux-updates) is public so installs can verify and fetch releases.