You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Web-based dashboard for managing Git worktrees with integrated terminals and AI agent support. Create, monitor, and interact with multiple isolated development environments — each running its own AI coding agent (Claude or Codex), backend, and frontend.
3
+
Web dashboard for [workmux](https://github.com/raine/workmux). Provides a browser UI with embedded terminals, PR status monitoring, and CI integration on top of workmux's worktree + tmux orchestration.
4
+
5
+
## What is workmux?
6
+
7
+
[workmux](https://github.com/raine/workmux) is a CLI tool that orchestrates git worktrees and tmux. It pairs each worktree with a tmux window, provisions files (copy/symlink), runs lifecycle hooks, and has first-class AI agent support. A single `workmux add` creates the worktree, opens a tmux window with configured panes, and starts your agent. `workmux merge` merges the branch, deletes the worktree, closes the window, and cleans up branches.
8
+
9
+
workmux is configured via `.workmux.yaml` in the project root. See the [workmux README](https://github.com/raine/workmux) for full documentation.
10
+
11
+
## What wmdev adds
12
+
13
+
wmdev is a web UI that wraps workmux. It delegates core worktree lifecycle operations to the `workmux` CLI and adds browser-based features on top:
# 3. Create a .wmdev.yaml in your project root (see Configuration below)
42
+
# 3. Set up your project
43
+
cd /path/to/your/project
44
+
workmux init # creates .workmux.yaml with sensible defaults
45
+
46
+
# 4. (Optional) Create a .wmdev.yaml for dashboard-specific config
47
+
# See Configuration below
17
48
18
-
#4. Start the dashboard from your project directory
49
+
#5. Start the dashboard
19
50
wmdev # UI on http://localhost:5111
20
-
wmdev --port 8080 #or pick a custom port
51
+
wmdev --port 8080 # custom port
21
52
```
22
53
23
54
## Configuration
24
55
25
-
wmdev reads a `.wmdev.yaml` file from the project root. This single file controls services, profiles, and Docker sandbox settings.
56
+
wmdev uses two config files in the project root:
26
57
27
-
### Full schema
58
+
-**`.workmux.yaml`** — workmux's own config. Controls worktree directory, pane layout, agent selection, file provisioning, lifecycle hooks, merge strategy, and more. See the [workmux docs](https://github.com/raine/workmux).
59
+
-**`.wmdev.yaml`** — dashboard-specific config. Controls service health checks, worktree profiles, linked repos for PR monitoring, and Docker sandbox settings.
60
+
61
+
### `.wmdev.yaml` schema
28
62
29
63
```yaml
30
64
# Services to monitor — each maps a display name to a port env var.
31
-
# The dashboard polls these ports to show health status.
65
+
# The dashboard polls these ports and shows health status badges.
32
66
services:
33
67
- name: string # Display name (e.g. "BE", "FE")
34
-
portEnv: string # Env var holding the port number (e.g. "BACKEND_PORT")
68
+
portEnv: string # Env var holding the port (e.g. "BACKEND_PORT")
35
69
36
-
# Profiles define what runs inside a worktree.
70
+
# Profiles define the environment when creating a worktree via the dashboard.
37
71
profiles:
38
72
default: # Required — used when no profile is specified
39
-
name: string # Profile identifier (e.g. "full")
40
-
systemPrompt: string # (optional) Instructions sent to the AI agent.
41
-
# Supports ${VAR} placeholders expanded from env.
73
+
name: string # Profile identifier
74
+
systemPrompt: string # (optional) Instructions for the AI agent.
75
+
# Supports ${VAR} placeholders expanded from .env.local.
42
76
envPassthrough: string[] # (optional) Env vars to pass to the agent process
| `linkedRepos[].alias` | string | no | Short label for the UI (defaults to repo name) |
157
+
158
+
### Auto-generated branch names
159
+
160
+
If your `.workmux.yaml` has `auto_name.model` configured, the create-worktree dialog will automatically generate a branch name from the prompt using that LLM. This is a workmux feature — wmdev detects it and enables the UI flow accordingly.
112
161
113
162
## Architecture
114
163
@@ -127,57 +176,48 @@ Browser (localhost:5111)
127
176
lifecycle) access) containers)
128
177
```
129
178
130
-
**Backend** — Bun/TypeScript HTTP + WebSocket server (`backend/src/server.ts`). Two interfaces:
179
+
**Backend** — Bun/TypeScript HTTP + WebSocket server (`backend/src/server.ts`):
131
180
132
-
- **REST API** (`/api/*`) — CRUD for worktrees. Wraps the `workmux` CLI to create/remove/merge worktrees. For sandbox profiles, manages Docker containers directly with published ports. The `GET /api/worktrees` endpoint enriches each worktree with its directory, assigned ports, and service healthstatus.
181
+
- **REST API** (`/api/*`) — CRUD for worktrees. Wraps the `workmux` CLI to create/remove/merge worktrees. Enriches each worktree with directory, assigned ports, service health, PR status, and agent state.
133
182
- **WebSocket** (`/ws/*`) — Bidirectional terminal bridge between xterm.js in the browser and tmux sessions on the server.
134
183
135
-
**Frontend** — Svelte 5 SPA with Tailwind CSS and xterm.js (`frontend/src/`). Two-panel UI: worktree list sidebar + embedded terminal. Polls the REST API for status updates. Responsive layout with mobile pane navigation.
184
+
**Frontend** — Svelte 5 SPA with Tailwind CSS and xterm.js (`frontend/src/`). Two-panel layout: worktree sidebar + embedded terminal. Polls the REST API for status updates. Responsive with mobile pane navigation.
136
185
137
186
### Terminal streaming
138
187
139
-
The WebSocket provides a bidirectional bridge between xterm.js in the browser and a tmux session on the server:
When a worktree is selected, the frontend opens a WebSocket to `/ws/<worktree>` and sends an initial `resize` message with the terminal dimensions. The backend then:
192
+
When a worktree is selected, the frontend opens a WebSocket to `/ws/<worktree>`. The backend spawns a PTY via `script` and attaches to a **grouped tmux session** — a separate view into the same windows. This allows the dashboard and a real terminal to view the same worktree simultaneously.
146
193
147
-
1. Spawns `script -q -c "... tmux attach-session ..." /dev/null` — allocates a real PTY for proper terminal escape sequences.
148
-
2. Creates a **grouped tmux session**, which is a separate view into the same windows. This allows the dashboard and a real terminal to view the same worktree simultaneously.
149
-
3. Streams PTY stdout over the WebSocket as `{ type: "output" }` messages.
150
-
4. Writes keystrokes from `{ type: "input" }` messages to the PTY's stdin.
151
-
5. Handles `resize` events by calling `tmux resize-window`.
152
-
153
-
Output is buffered in a scrollback array (up to 5000 chunks) so reconnecting clients receive recent history immediately.
194
+
Output is buffered (up to 1 MB) so reconnecting clients receive recent history immediately.
154
195
155
196
### Worktree profiles
156
197
157
-
When creating a worktree, you pick a profile that determines the environment:
158
-
159
198
| Profile | What it does |
160
199
|---------|-------------|
161
-
| `default` | Delegates to workmux — uses the pane layout and commands defined in your `.workmux.yaml` project config. wmdev doesn't manage panes or processes for this profile; workmux handles it all. |
162
-
| `sandbox` | Managed entirely by wmdev, decoupled from workmux. wmdev launches a Docker container, sets up agent + shell panes, and publishes service ports directly with `docker run -p`. |
200
+
| `default` | Delegates to workmux — uses the pane layout and commands from `.workmux.yaml`. wmdev doesn't manage panes or processes; workmux handles it all. |
201
+
| `sandbox` | Managed by wmdev. Launches a Docker container, sets up agent + shell panes, and publishes service ports via `docker run -p`. |
163
202
164
203
### Docker sandbox containers
165
204
166
205
For sandbox profiles, wmdev manages Docker containers directly:
167
206
168
-
1. **Launch** — `docker run -d -p <ports>` with the configured image, mounts, and env vars
169
-
2. **Mounts** — Worktree dir (rw), main repo `.git` (ro), Claude config, plus any `extraMounts`
170
-
3. **Environment** — All `.env.local` vars + `envPassthrough` vars + `HOME`, `TERM`, `IS_SANDBOX=1`
171
-
4. **Cleanup** — Containers are removed when the worktree is removed or merged
207
+
1. **Launch** — `docker run -d -p <ports>` with the configured image, mounts, and env vars. Runs as the host user (`--user uid:gid`) so file ownership matches.
208
+
2. **Mounts** — Worktree dir (rw), main repo `.git` (rw), main repo root (ro), `~/.claude`, plus any `extraMounts`. Conditionally mounts `~/.gitconfig`, `~/.ssh`, `~/.config/gh` if they exist.
209
+
3. **Environment** — All `.env.local` vars + `envPassthrough` vars + `HOME`, `TERM`, `IS_SANDBOX=1`.
210
+
4. **Cleanup** — Containers are removed when the worktree is removed or merged.
172
211
173
212
## Prerequisites
174
213
175
214
| Tool | Min version | Purpose |
176
215
|------|-------------|---------|
177
-
| [**bun**](https://bun.sh) | >1.3.5 | Runtime for backend and frontend |
0 commit comments