Skip to content

Commit fda4451

Browse files
centdixclaude
andauthored
docs: polish README for user-facing clarity (#73)
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
1 parent e8e60ee commit fda4451

1 file changed

Lines changed: 60 additions & 181 deletions

File tree

README.md

Lines changed: 60 additions & 181 deletions
Original file line numberDiff line numberDiff line change
@@ -1,35 +1,42 @@
11
# wmdev
22

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.
3+
A web dashboard for managing parallel AI coding agents. Built on top of [workmux](https://github.com/raine/workmux), which handles git worktrees and tmux orchestration — wmdev adds a browser UI with embedded terminals, live status tracking, and CI integration.
44

55
https://github.com/user-attachments/assets/fa13366d-e758-4221-94bf-13a5738bf7e7
66

7-
## What is workmux?
7+
## Features
88

9-
[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.
9+
### Embedded Terminals
1010

11-
workmux is configured via `.workmux.yaml` in the project root. See the [workmux README](https://github.com/raine/workmux) for full documentation.
11+
<!-- gif -->
1212

13-
## What wmdev adds
13+
View and interact with your agents directly in the browser. Each worktree gets its own terminal session, streamed live via WebSocket. You can watch agents work, send prompts, and switch between worktrees instantly — no need to juggle tmux windows manually.
1414

15-
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:
15+
### PR & CI Status
1616

17-
| Responsibility | Handled by |
18-
|---|---|
19-
| Create/remove/merge worktrees | **workmux** (wmdev calls `workmux add`, `workmux rm`, `workmux merge`) |
20-
| Pane layout and agent launch (default profile) | **workmux** (uses `.workmux.yaml` pane config) |
21-
| Open/focus a worktree's tmux window | **workmux** (`workmux open`) |
22-
| List worktrees and agent status | **workmux** (`workmux list`, `workmux status`) |
23-
| File provisioning and lifecycle hooks | **workmux** (`.workmux.yaml` `files` and `post_create`) |
24-
| Port allocation for worktree services | **wmdev** (when `portStart` is set in `.wmdev.yaml`) or **workmux** (via `post_create` hook) |
25-
| Browser terminal (xterm.js ↔ tmux) | **wmdev** |
26-
| Service health monitoring (port polling) | **wmdev** |
27-
| PR status tracking and badges | **wmdev** (polls `gh pr list`) |
28-
| CI check status and failed log viewing | **wmdev** (calls `gh run view`) |
29-
| Send prompts / PR comments to agents | **wmdev** (via `tmux load-buffer`) |
30-
| Docker sandbox container lifecycle | **wmdev** (manages `docker run/rm` directly) |
17+
<!-- gif -->
3118

32-
## Quick start
19+
See pull request status, CI check results, and failed log output right next to each worktree. No more switching to GitHub to check if your agent's PR passed CI.
20+
21+
### Create & Manage Worktrees
22+
23+
<!-- gif -->
24+
25+
Spin up new worktrees with one click. Pick a profile, type a prompt, and wmdev creates the worktree, starts the agent, and begins streaming output. Merge or remove worktrees when you're done.
26+
27+
### Service Health Monitoring
28+
29+
<!-- gif -->
30+
31+
Track dev server ports across worktrees. wmdev polls configured services and shows live health badges so you know which worktrees have their servers running.
32+
33+
### Docker Sandbox Mode
34+
35+
<!-- gif -->
36+
37+
Run agents in isolated Docker containers for untrusted or experimental work. wmdev manages the container lifecycle, port forwarding, and volume mounts automatically.
38+
39+
## Quick Start
3340

3441
```bash
3542
# 1. Install prerequisites
@@ -42,78 +49,21 @@ bun install -g wmdev
4249

4350
# 3. Set up your project
4451
cd /path/to/your/project
45-
workmux init # creates .workmux.yaml with sensible defaults
46-
47-
# 4. (Optional) Create a .wmdev.yaml for dashboard-specific config
48-
# See Configuration below
52+
wmdev init # creates .workmux.yaml and .wmdev.yaml
4953

50-
# 5. Start the dashboard
51-
wmdev # UI on http://localhost:5111
52-
wmdev --port 8080 # custom port
54+
# 4. Start the dashboard
55+
wmdev # opens on http://localhost:5111
5356
```
5457

5558
## Configuration
5659

5760
wmdev uses two config files in the project root:
5861

59-
- **`.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).
60-
- **`.wmdev.yaml`** — dashboard-specific config. Controls service health checks, worktree profiles, linked repos for PR monitoring, and Docker sandbox settings.
61-
62-
### `.wmdev.yaml` schema
63-
64-
```yaml
65-
# Project name displayed in the sidebar header and browser tab title.
66-
# Falls back to "Dashboard" if omitted.
67-
name: string
68-
69-
# Services to monitor — each maps a display name to a port env var.
70-
# The dashboard polls these ports and shows health status badges.
71-
# When portStart is set, wmdev auto-allocates ports for new worktrees
72-
# and writes them to .env.local (no post_create hook needed).
73-
services:
74-
- name: string # Display name (e.g. "BE", "FE")
75-
portEnv: string # Env var holding the port (e.g. "BACKEND_PORT")
76-
portStart: number # (optional) Base port for slot 0 (e.g. 5111)
77-
portStep: number # (optional) Increment per worktree slot (default: 1)
78-
79-
# Profiles define the environment when creating a worktree via the dashboard.
80-
profiles:
81-
default: # Required — used when no profile is specified
82-
name: string # Profile identifier
83-
systemPrompt: string # (optional) Instructions for the AI agent.
84-
# Supports ${VAR} placeholders expanded from .env.local.
85-
envPassthrough: string[] # (optional) Env vars to pass to the agent process
86-
87-
sandbox: # (optional) Docker-based sandboxed profile
88-
name: string # Profile identifier
89-
image: string # Docker image name (must be pre-built)
90-
systemPrompt: string # (optional) Agent instructions (supports ${VAR})
91-
envPassthrough: string[] # (optional) Host env vars forwarded into the container
92-
extraMounts: # (optional) Additional bind mounts
93-
- hostPath: string # Host path (supports ~ for $HOME)
94-
guestPath: string # (optional) Mount point inside container (defaults to hostPath)
95-
writable: boolean # (optional) true = read-write, false/omit = read-only
96-
97-
# Monitor PRs from other GitHub repos and show their status alongside
98-
# worktree branches that share the same branch name.
99-
linkedRepos:
100-
- repo: string # GitHub repo slug (e.g. "org/repo")
101-
alias: string # (optional) Short label shown in the UI
102-
```
103-
104-
### Defaults
105-
106-
If `.wmdev.yaml` is missing or empty:
62+
- **`.workmux.yaml`** — Controls worktree directory, pane layout, agent selection, and lifecycle hooks. See the [workmux docs](https://github.com/raine/workmux).
63+
- **`.wmdev.yaml`** — Dashboard-specific config: service health checks, profiles, linked repos, and Docker sandbox settings.
10764

108-
```yaml
109-
services: []
110-
profiles:
111-
default:
112-
name: default
113-
linkedRepos: []
114-
```
115-
116-
### Example
65+
<details>
66+
<summary><strong>.wmdev.yaml example</strong></summary>
11767

11868
```yaml
11969
name: My Project
@@ -151,89 +101,34 @@ linkedRepos:
151101
alias: svc
152102
```
153103
154-
### Parameter reference
104+
</details>
105+
106+
<details>
107+
<summary><strong>.wmdev.yaml full schema</strong></summary>
155108
156109
| Parameter | Type | Required | Description |
157110
|-----------|------|----------|-------------|
158-
| `name` | string | no | Project name shown in the sidebar header and browser tab title. Defaults to "Dashboard" |
111+
| `name` | string | no | Project name shown in sidebar and browser tab |
159112
| `services[].name` | string | yes | Display name shown in the dashboard |
160-
| `services[].portEnv` | string | yes | Env var containing the service port (read from each worktree's `.env.local`) |
161-
| `services[].portStart` | number | no | Base port for slot 0. When set, wmdev auto-allocates ports for new worktrees |
162-
| `services[].portStep` | number | no | Port increment per worktree slot (default: `1`). Slot 0 is reserved for main |
113+
| `services[].portEnv` | string | yes | Env var containing the service port |
114+
| `services[].portStart` | number | no | Base port for auto-allocation |
115+
| `services[].portStep` | number | no | Port increment per worktree slot (default: `1`) |
163116
| `profiles.default.name` | string | yes | Identifier for the default profile |
164-
| `profiles.default.systemPrompt` | string | no | System prompt for the agent; `${VAR}` placeholders expanded at runtime |
165-
| `profiles.default.envPassthrough` | string[] | no | Env vars passed through to the agent process |
117+
| `profiles.default.systemPrompt` | string | no | Agent system prompt; `${VAR}` placeholders expanded at runtime |
118+
| `profiles.default.envPassthrough` | string[] | no | Env vars passed to the agent process |
166119
| `profiles.sandbox.name` | string | yes (if used) | Identifier for the sandbox profile |
167120
| `profiles.sandbox.image` | string | yes (if used) | Docker image for containers |
168-
| `profiles.sandbox.systemPrompt` | string | no | System prompt for sandbox agents; `${VAR}` placeholders expanded at runtime |
169-
| `profiles.sandbox.envPassthrough` | string[] | no | Host env vars forwarded into the Docker container |
121+
| `profiles.sandbox.systemPrompt` | string | no | Agent system prompt for sandbox |
122+
| `profiles.sandbox.envPassthrough` | string[] | no | Host env vars forwarded into the container |
170123
| `profiles.sandbox.extraMounts[].hostPath` | string | yes | Host path to mount (`~` expands to `$HOME`) |
171124
| `profiles.sandbox.extraMounts[].guestPath` | string | no | Container mount path (defaults to `hostPath`) |
172125
| `profiles.sandbox.extraMounts[].writable` | boolean | no | `true` for read-write; omit or `false` for read-only |
173126
| `linkedRepos[].repo` | string | yes | GitHub repo slug (e.g. `org/repo`) |
174-
| `linkedRepos[].alias` | string | no | Short label for the UI (defaults to repo name) |
127+
| `linkedRepos[].alias` | string | no | Short label for the UI |
175128

176-
### Auto-generated branch names
129+
</details>
177130

178-
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.
179-
180-
## Architecture
181-
182-
<p align="center">
183-
<img src="docs/architecture.svg" alt="Architecture diagram" />
184-
</p>
185-
186-
**Backend** — Bun/TypeScript HTTP + WebSocket server (`backend/src/server.ts`):
187-
188-
- **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.
189-
- **WebSocket** (`/ws/*`) — Bidirectional terminal bridge between xterm.js in the browser and tmux sessions on the server.
190-
191-
**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.
192-
193-
### Terminal streaming
194-
195-
<p align="center">
196-
<img src="docs/terminal-streaming.svg" alt="Terminal streaming diagram" />
197-
</p>
198-
199-
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.
200-
201-
Output is buffered (up to 1 MB) so reconnecting clients receive recent history immediately.
202-
203-
### Worktree profiles
204-
205-
| Profile | What it does |
206-
|---------|-------------|
207-
| `default` | Delegates to workmux — uses the pane layout and commands from `.workmux.yaml`. wmdev doesn't manage panes or processes; workmux handles it all. |
208-
| `sandbox` | Managed by wmdev. Launches a Docker container, sets up agent + shell panes, and publishes service ports via `docker run -p`. |
209-
210-
### Docker sandbox containers
211-
212-
For sandbox profiles, wmdev manages Docker containers directly:
213-
214-
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.
215-
2. **Mounts** — Worktree dir (rw), main repo `.git` (rw), main repo root (ro), `~/.claude` (dir) and `~/.claude.json` (settings file), plus any `extraMounts`. Conditionally mounts `~/.gitconfig`, `~/.ssh`, `~/.config/gh` if they exist.
216-
3. **Environment** — All `.env.local` vars + `envPassthrough` vars + `HOME`, `TERM`, `IS_SANDBOX=1`.
217-
4. **Cleanup** — Containers are removed when the worktree is removed or merged.
218-
219-
## Prerequisites
220-
221-
| Tool | Min version | Purpose |
222-
|------|-------------|---------|
223-
| [**bun**](https://bun.sh) | 1.3.5+ | Runtime for backend and frontend |
224-
| [**workmux**](https://github.com/raine/workmux) | latest | Worktree + tmux orchestration |
225-
| **tmux** | 3.x | Terminal multiplexer |
226-
| **git** | 2.x | Worktree management |
227-
| **gh** | 2.x | PR and CI status (optional — needed for PR badges and CI logs) |
228-
| **docker** | 28+ | Only needed for sandbox profile |
229-
230-
## Environment variables
231-
232-
| Variable | Default | Description |
233-
|----------|---------|-------------|
234-
| `BACKEND_PORT` | `5111` | Backend API port (also configurable via `--port`) |
235-
236-
## Keyboard shortcuts
131+
## Keyboard Shortcuts
237132

238133
| Shortcut | Action |
239134
|----------|--------|
@@ -242,35 +137,19 @@ For sandbox profiles, wmdev manages Docker containers directly:
242137
| `Cmd+M` | Merge selected worktree |
243138
| `Cmd+D` | Remove selected worktree |
244139

245-
## API
246-
247-
| Method | Endpoint | Description |
248-
|--------|----------|-------------|
249-
| `GET` | `/api/config` | Load dashboard config |
250-
| `GET` | `/api/worktrees` | List all worktrees with status, ports, service health, and PR data |
251-
| `POST` | `/api/worktrees` | Create a worktree (`{ branch?, profile?, agent?, prompt? }`) |
252-
| `DELETE` | `/api/worktrees/:name` | Remove a worktree |
253-
| `POST` | `/api/worktrees/:name/open` | Open/focus a worktree's tmux window |
254-
| `POST` | `/api/worktrees/:name/merge` | Merge worktree into main + cleanup |
255-
| `GET` | `/api/worktrees/:name/status` | Get agent status for a worktree |
256-
| `POST` | `/api/worktrees/:name/send` | Send a prompt to the agent's tmux pane |
257-
| `GET` | `/api/ci-logs/:runId` | Fetch failed CI run logs |
258-
| `WS` | `/ws/:worktree` | Terminal WebSocket (xterm.js ↔ tmux) |
140+
## Prerequisites
141+
142+
| Tool | Purpose |
143+
|------|---------|
144+
| [**bun**](https://bun.sh) | Runtime |
145+
| [**workmux**](https://github.com/raine/workmux) | Worktree + tmux orchestration |
146+
| **tmux** | Terminal multiplexer |
147+
| **git** | Worktree management |
148+
| **gh** | PR and CI status (optional) |
149+
| **docker** | Sandbox profile only (optional) |
259150

260151
## Development
261152

262153
```bash
263154
./dev.sh # backend + frontend with hot reload, UI on :5112
264155
```
265-
266-
Or start them separately:
267-
268-
```bash
269-
# Terminal 1: backend (auto-reloads on save)
270-
cd backend && bun run dev
271-
272-
# Terminal 2: frontend (Vite dev server)
273-
cd frontend && bun run dev
274-
```
275-
276-
The frontend dev server runs on port `5112` and proxies `/api/*` and `/ws/*` to the backend on `5111`.

0 commit comments

Comments
 (0)