TmuxDeck
A web dashboard for managing tmux sessions across Docker containers
Quick Start • Features • Shortcuts • Configuration • Contributing
Run AI coding agents, dev servers, and long-lived processes inside Docker containers. TmuxDeck gives you a single browser tab to manage all of them — create containers from templates, organize tmux sessions and windows, and interact through a real terminal powered by xterm.js.
If you run multiple Docker containers with tmux sessions inside them — for AI agents, development environments, build systems — you know the pain of docker exec-ing into each one and juggling terminal tabs. TmuxDeck replaces that workflow:
- One browser tab instead of a dozen terminal windows
- Instant switching between sessions with a connection pool (no reconnect delay)
- Fuzzy search across all containers, sessions, and windows (Ctrl+K)
- Drag-and-drop to reorder sessions and move windows between them
- Create containers from Dockerfile templates with one click
- Host tmux too — manage sessions on the host machine, not just containers
git clone https://github.com/msbrogli/tmuxdeck.git
cd tmuxdeck
cp .env.example .env
docker compose upOpen http://localhost:3000. The backend runs on port 8000 behind the nginx proxy.
The backend needs access to the Docker socket to manage containers. To also manage host tmux sessions, pass your UID:
HOST_UID=$(id -u) docker compose up# Backend (Python 3.12 + uv)
cd backend
uv sync
DATA_DIR=./data TEMPLATES_DIR=../docker/templates \
uv run uvicorn app.main:app --reload --host 0.0.0.0 --port 8000
# Frontend (in another terminal)
cd frontend
npm install
npm run devOpen http://localhost:5173 — Vite proxies /api/* and /ws/* to the backend automatically.
Want to explore the UI without Docker or a running backend?
cd frontend
npm install
VITE_USE_MOCK=true npm run devThis runs the full UI with simulated containers, sessions, and a mock terminal.
Full xterm.js terminal with ANSI color support, clickable links, and native tmux keybindings — Ctrl-B works as expected. Copy with Ctrl+Shift+C, paste with Ctrl+Shift+V (Cmd+C/V on Mac). Paste or drag-and-drop images directly into the terminal.
TmuxDeck keeps up to 8 WebSocket connections alive in the background (configurable 1-32) with LRU eviction. Switching between sessions is instant — no reconnect, no redraw delay.
Fuzzy search across every container, session, and window. Results are ranked by recency and match quality. Hover to preview, Enter to switch.
- Drag windows within a session to reorder (
tmux swap-window) - Drag windows onto another session to move them (
tmux move-window) - Drag session headers to reorder within a container (persisted in localStorage)
Assign Ctrl+1 through Ctrl+0 to any window. Digits follow their windows when you reorder. Ctrl+Alt+1-0 to assign or unassign.
Create containers from Dockerfile templates with real-time build log streaming. Start, stop, rename, or remove from the sidebar context menu. Double-click any name to rename inline.
Create and edit Dockerfile templates with Monaco editor syntax highlighting. Each template can define default environment variables and volume mounts. Ships with two templates:
- claude-worker — Node 20 + Claude Code CLI, ready for AI agent workflows
- basic-dev — Ubuntu 24.04 + build tools for general development
Not just Docker — TmuxDeck can manage tmux sessions on the host machine and on the machine running the backend. The special container IDs host and local appear in the sidebar alongside your Docker containers.
Optional PIN-based authentication protects the dashboard. No user management overhead — set a PIN in Settings and sessions last 7 days.
Bell and activity flags from tmux show as icons in the sidebar. When a process finishes or needs attention, you see it without switching.
When tmux mouse mode is enabled (which breaks browser text selection), TmuxDeck shows a warning banner with a one-click button to disable it.
| Shortcut | Action |
|---|---|
Ctrl+K |
Open session switcher (fuzzy search) |
Ctrl+H |
Show keyboard shortcuts |
Ctrl+1 - Ctrl+0 |
Jump to assigned window |
Ctrl+Alt+1 - Ctrl+Alt+0 |
Assign/unassign digit to current window |
Ctrl+Up / Ctrl+Down |
Previous / next window |
Esc Esc |
Deselect current session |
All tmux keybindings (Ctrl-B + w, Ctrl-B + c, etc.) pass through natively.
| Variable | Default | Description |
|---|---|---|
DATA_DIR |
/data |
Directory for settings and template data (JSON files) |
DOCKER_SOCKET |
/var/run/docker.sock |
Docker socket path |
CONTAINER_NAME_PREFIX |
tmuxdeck |
Prefix for managed container names |
TEMPLATES_DIR |
/app/docker/templates |
Path to seed Dockerfile templates |
HOST_TMUX_SOCKET |
(none) | Host tmux socket for host session access |
TELEGRAM_BOT_TOKEN |
(none) | Telegram bot token for text interaction |
TELEGRAM_ALLOWED_USERS |
(none) | Comma-separated Telegram user IDs |
- Default volume mounts — pre-fill when creating containers (e.g.
~/.claude:/root/.claude) - SSH key path — auto-mount SSH keys into containers for private repo access
- Terminal pool size — how many background connections to keep alive (1-32)
- Telegram bot — token and allowed users for text-based session interaction
Browser (React + xterm.js)
|
|--- REST /api/v1/* ---> FastAPI backend
|--- WS /ws/* ---> WebSocket terminal handler
|
|--- docker-py ---> Docker Engine
|--- docker exec ---> tmux inside containers
|--- tmux (local) ---> host/local sessions
| Layer | Technology |
|---|---|
| Backend | Python 3.12, FastAPI, docker-py |
| Frontend | React 18, TypeScript, Vite, Tailwind CSS |
| Terminal | xterm.js (fit + web-links addons) |
| Template editor | Monaco Editor |
| Data fetching | TanStack Query |
| Package managers | uv (backend), npm (frontend) |
| Deployment | Docker Compose, nginx |
tmuxdeck/
├── backend/ # Python 3.12 + FastAPI
│ ├── app/
│ │ ├── api/ # REST endpoints (auth, containers, sessions, templates, settings)
│ │ ├── ws/ # WebSocket terminal handler
│ │ ├── services/ # Docker manager, tmux manager
│ │ └── schemas/ # Pydantic request/response models
│ ├── tests/ # pytest test suite
│ └── pyproject.toml # Dependencies (managed with uv)
│
├── frontend/ # React 18 + TypeScript + Vite
│ └── src/
│ ├── components/ # Sidebar, Terminal, SessionSwitcher, ContainerNode, ...
│ ├── hooks/ # Terminal pool, keyboard shortcuts
│ ├── pages/ # MainPage, TemplatesPage, SettingsPage
│ ├── mocks/ # Mock API for development without backend
│ └── api/ # API client
│
├── docker/
│ └── templates/ # Bundled Dockerfile templates
├── docker-compose.yml
└── .env.example
| Method | Path | Description |
|---|---|---|
| GET | /api/v1/containers |
List all containers (Docker + host + local) |
| POST | /api/v1/containers |
Create container from template |
| GET | /api/v1/containers/{id} |
Get container details |
| PATCH | /api/v1/containers/{id} |
Rename container |
| DELETE | /api/v1/containers/{id} |
Remove container |
| POST | /api/v1/containers/{id}/start |
Start container |
| POST | /api/v1/containers/{id}/stop |
Stop container |
| Method | Path | Description |
|---|---|---|
| GET | /api/v1/containers/{id}/sessions |
List tmux sessions |
| POST | /api/v1/containers/{id}/sessions |
Create session |
| PATCH | /api/v1/containers/{id}/sessions/{sid} |
Rename session |
| DELETE | /api/v1/containers/{id}/sessions/{sid} |
Kill session |
| POST | .../sessions/{sid}/windows |
Create window |
| POST | .../sessions/{sid}/swap-windows |
Swap two windows |
| POST | .../sessions/{sid}/move-window |
Move window to another session |
Connect to WS /ws/terminal/{container_id}/{session_name}/{window_index} for an interactive terminal. Control messages: RESIZE:cols:rows, SCROLL:up:N, SCROLL:down:N, SELECT_WINDOW:index, DISABLE_MOUSE:.
| Method | Path | Description |
|---|---|---|
| GET/POST | /api/v1/templates |
List / create templates |
| GET/PUT/DELETE | /api/v1/templates/{id} |
Read / update / delete template |
| GET/POST | /api/v1/settings |
Get / update settings |
# Backend
cd backend
uv run pytest
# Frontend
cd frontend
npm test# Backend
cd backend
uv run ruff check app
uv run ruff format --check app
# Frontend
cd frontend
npm run lintdocker compose up --buildMIT
