Skip to content

sttwister/devbench

Repository files navigation

Devbench

A development workbench for managing multiple AI coding agent and terminal sessions across projects. Think of it as a dashboard that organizes your Claude Code, Pi, Codex, and plain terminal sessions β€” all backed by tmux for persistence.

Node.js TypeScript React Electron


Features

πŸ—‚οΈ Project Management

  • Register projects by name and filesystem path
  • Optional browser URL per project for live-previewing web apps
  • Full CRUD β€” create, edit, and delete projects from the sidebar
  • Drag-and-drop reordering for projects and sessions in the sidebar

πŸ’» Session Types

  • Terminal β€” plain shell session
  • Claude Code β€” launches claude --dangerously-skip-permissions
  • Pi β€” launches the pi coding agent
  • Codex β€” launches codex

Each session runs inside a detached tmux session, so they survive page reloads, reconnects, and server restarts.

🎫 Source URL & Issue Tracking

  • Attach a source URL when creating or editing a session (Jira ticket, Linear issue, Sentry error, GitHub/GitLab issue, Slack thread)
  • Auto-detects source type and displays a labelled badge (e.g. PROJ-123 for Jira)
  • Issue and MR/PR links shown in the terminal header for quick access on any device
  • Edit session popup (Ctrl+Shift+E or via session context menu) to update source URL and manage MR/PR links

πŸ”Œ Live Terminal

  • Full terminal emulation in the browser via xterm.js
  • WebSocket connection streams I/O between the browser and tmux (via node-pty)
  • Resize support β€” terminal dimensions sync automatically
  • Sessions that exit from inside (e.g. exit, Ctrl+D) are detected and archived

πŸ€– Auto-Rename

Sessions start with a generic name like "Claude Code 1". Once meaningful activity is detected in the terminal, Devbench uses Claude Haiku to generate a short, descriptive kebab-case name based on the terminal content β€” so your sidebar stays readable even with many sessions.

🟒 Agent Status Tracking

  • Agent sessions (Claude Code, Pi, Codex) are monitored for activity
  • Status shows working (spinner) or waiting (idle) based on terminal content changes
  • Only the conversation/output area is tracked β€” input area keystrokes are ignored to avoid false positives

πŸ”— MR/PR Link Detection & Status

Terminal output is periodically scanned for merge request and pull request URLs from:

  • GitLab β€” /-/merge_requests/<id> and /merge_requests/new
  • GitHub β€” /pull/<id> and /pull/new/
  • Bitbucket β€” /pull-requests/<id>

Detected links appear as rich status badges on sessions in the sidebar:

  • API polling fetches live status from GitLab/GitHub (open, merged, closed, draft, approved, changes requested, pipeline status)
  • Badges are color-coded by state (green = approved, purple = merged, red = failed pipeline, etc.)
  • Configure API tokens in Settings (βš™οΈ button) to enable status polling

🌐 Browser Pane

  • Side-by-side browser panel for previewing your web app alongside the terminal
  • Electron mode: native WebContentsView with a real browser toolbar, tab bar (project URL + MR tabs), and URL navigation
  • Web mode: inline <iframe> with address bar, back/forward, reload, and a draggable split resizer
  • Reverse proxy β€” proxies HTTP dev server targets through the Devbench server to fix HTTPS mixed-content issues

🌿 GitButler Dashboard

  • Visual branch dashboard showing stacks, branches, commits, and uncommitted changes per project
  • MR/PR status badges on branches with linked reviews
  • Pull from upstream with one click (per-project or all projects at once)
  • Merge MRs/PRs directly from the dashboard via glab / gh CLIs with auto-merge support
  • Session linking β€” branches are matched to active sessions, with quick navigation
  • DB-backed cache with per-project background refresh for instant load times
  • Open per-project (Ctrl+Shift+D) or across all projects (Ctrl+Shift+F)

πŸ“± Mobile & PWA

  • Installable as a PWA β€” add to home screen on mobile for a native app experience
  • Mobile keyboard bar with Esc, Tab, Ctrl, Alt, arrow keys, and a git-commit-and-push button
  • Swipe gestures β€” swipe left/right to navigate between sessions
  • Touch scrolling for terminal content
  • Long-press to rename sessions on touch devices
  • Sidebar auto-closes on session creation for more screen space
  • Optimized terminal font size for mobile viewports
  • Native input with dictation and autofill support

⌨️ Keyboard Shortcuts

Shortcut Action
Ctrl+Shift+J Next session
Ctrl+Shift+K Previous session
Ctrl+Shift+N New session
Ctrl+Shift+R Rename session
Ctrl+Shift+X Kill session
Ctrl+Shift+A Archived sessions
Ctrl+Shift+B Toggle browser pane
Ctrl+Shift+T Toggle terminal session
Ctrl+Shift+G Git commit & push
Ctrl+Shift+D GitButler dashboard (project)
Ctrl+Shift+F GitButler dashboard (all projects)
Ctrl+Shift+L GitButler pull (in dashboard)
Ctrl+Shift+? Show shortcuts help

πŸ”„ Session Revival & Crash Recovery

  • Orphaned session detection β€” If the server restarts after a crash or power failure, sessions whose tmux died are marked orphaned (not archived), preserving them for revival
  • Agent session tracking β€” Claude Code and Pi sessions store their agent session IDs so conversations can be resumed after a crash
    • Claude: launched with --session-id <uuid> for deterministic resume
    • Pi: launched with --session <path> to persist conversation state
  • Revive orphaned sessions β€” Orphaned sessions appear dimmed in the sidebar with a πŸ”„ button; reviving creates a new tmux and resumes the agent conversation
  • Revive archived sessions β€” Open the archived sessions popup (Ctrl+Shift+A or the πŸ—„ button on a project header) to browse and revive previously closed sessions
  • Keyboard navigation β€” The archived sessions popup supports j/k to navigate, Enter to revive, Esc to close
  • Archive on kill β€” Killing a session archives it instead of deleting, so it can be recovered later; permanent delete is only available from the archived list

πŸ”„ WebSocket Auto-Reconnect

  • Terminal WebSocket connections automatically reconnect on disconnect
  • Active session is persisted in the URL, so refreshes and server restarts return you to the same session

πŸ›‘οΈ Health & Cleanup

  • On startup, sessions whose tmux died are kept as orphaned (revivable), not silently discarded
  • A periodic health check (every 10s) archives any sessions whose tmux process has disappeared (skips orphaned sessions)
  • Auto-rename and MR monitoring are restarted for surviving sessions on server boot

Architecture

devbench/
β”œβ”€β”€ shared/              # TypeScript types shared between client & server
β”‚   β”œβ”€β”€ types.ts             # Core types (Session, Project, MrStatus, AgentStatus)
β”‚   β”œβ”€β”€ session-config.ts    # Session type definitions & icons
β”‚   β”œβ”€β”€ gitbutler-types.ts   # GitButler CLI output types & dashboard models
β”‚   β”œβ”€β”€ mr-labels.ts         # MR badge status labels & formatting
β”‚   └── source-utils.ts      # Source URL detection (Jira, Linear, Sentry, etc.)
β”œβ”€β”€ server/              # Node.js backend (HTTP + WebSocket)
β”‚   β”œβ”€β”€ index.ts             # Entry point & startup routines
β”‚   β”œβ”€β”€ server.ts            # HTTP server factory
β”‚   β”œβ”€β”€ router.ts            # Lightweight HTTP router
β”‚   β”œβ”€β”€ websocket.ts         # WebSocket terminal I/O
β”‚   β”œβ”€β”€ db.ts                # SQLite database (better-sqlite3) with migrations
β”‚   β”œβ”€β”€ terminal.ts          # tmux + node-pty session management
β”‚   β”œβ”€β”€ auto-rename.ts       # LLM-powered session naming
β”‚   β”œβ”€β”€ agent-status.ts      # Agent working/waiting status monitor
β”‚   β”œβ”€β”€ mr-links.ts          # MR/PR URL extraction from terminal output
β”‚   β”œβ”€β”€ mr-status.ts         # MR/PR API status polling (GitLab, GitHub)
β”‚   β”œβ”€β”€ mr-merge.ts          # MR/PR merge via glab/gh CLIs
β”‚   β”œβ”€β”€ proxy.ts             # Reverse proxy for browser-pane HTTP targets
β”‚   β”œβ”€β”€ gitbutler.ts         # GitButler CLI integration
β”‚   β”œβ”€β”€ gitbutler-cache.ts   # DB-backed dashboard cache with background refresh
β”‚   β”œβ”€β”€ monitor-manager.ts   # Centralized session monitor lifecycle
β”‚   └── agent-session-tracker.ts  # Agent session ID generation & resume
β”œβ”€β”€ client/              # React + Vite frontend
β”‚   └── src/
β”‚       β”œβ”€β”€ App.tsx              # Main app shell
β”‚       β”œβ”€β”€ api.ts               # REST API client
β”‚       └── components/          # UI components
β”‚           β”œβ”€β”€ Sidebar.tsx          # Project & session sidebar
β”‚           β”œβ”€β”€ TerminalPane.tsx     # xterm.js terminal emulator
β”‚           β”œβ”€β”€ BrowserPane.tsx      # Side-by-side browser panel
β”‚           β”œβ”€β”€ GitButlerDashboard.tsx  # Branch visualization dashboard
β”‚           β”œβ”€β”€ MobileKeyboardBar.tsx   # Touch keyboard bar
β”‚           β”œβ”€β”€ EditSessionPopup.tsx    # Source URL & MR link editor
β”‚           β”œβ”€β”€ SettingsModal.tsx       # API token configuration
β”‚           └── ...                    # Popups, modals, shared components
β”œβ”€β”€ electron/            # Optional Electron desktop wrapper
β”‚   β”œβ”€β”€ main.ts              # Electron main process
β”‚   β”œβ”€β”€ view-manager.ts      # WebContentsView management
β”‚   β”œβ”€β”€ layout.ts            # Window layout & resizing
β”‚   β”œβ”€β”€ shortcuts.ts         # Electron keyboard shortcuts
β”‚   └── preload.ts           # Context bridge for renderer
└── package.json         # Workspace root

Tech stack: Node.js Β· TypeScript (native --experimental-strip-types) Β· React 18 Β· Vite Β· xterm.js Β· WebSocket (ws) Β· better-sqlite3 Β· node-pty Β· tmux Β· Electron (optional) Β· Vitest


Prerequisites

  • Node.js β‰₯ 22.6 (for native TypeScript stripping)
  • tmux installed and on PATH
  • claude CLI on PATH (for Claude Code sessions and auto-rename)
  • pi CLI on PATH (for Pi sessions, optional)
  • codex CLI on PATH (for Codex sessions, optional)
  • but (GitButler CLI) on PATH (for GitButler dashboard, optional)
  • glab / gh on PATH (for MR/PR merging from the dashboard, optional)

Getting Started

Install dependencies

npm install

This installs all three workspaces (shared, server, client) via npm workspaces.

Development mode

npm run dev

This runs concurrently:

  • The server on http://localhost:3001 (with --watch for auto-reload)
  • The Vite dev server on http://localhost:5173 (with HMR)

Open http://localhost:5173 in your browser.

Production build

# Build the client
npm run build

# Start the production server (serves the built client)
npm start

The production server runs on port 3001 by default. Override with the PORT environment variable:

PORT=8080 npm start

Electron (optional)

To run as a native desktop app:

# From the repo root β€” start the backend first
npm run dev:server

# In another terminal β€” build and launch Electron
cd electron
npm install
npm run dev

For standalone Electron (connecting to a running server):

cd electron
npm run start

Set DEVBOX_URL to point at a remote server if needed:

DEVBOX_URL=http://my-server:3001 npm run start

Usage

  1. Add a project β€” Click the + button in the sidebar. Enter a name, the absolute filesystem path, and optionally a browser URL.
  2. Create a session β€” Expand a project and click the + icon, or press Ctrl+Shift+N. Pick Terminal, Claude Code, Pi, or Codex. Optionally attach a source URL (Jira, Linear, etc.).
  3. Switch sessions β€” Click in the sidebar, use Ctrl+Shift+J / Ctrl+Shift+K, or swipe left/right on mobile.
  4. Browser pane β€” If a project has a browser URL configured, press Ctrl+Shift+B to open a side-by-side browser.
  5. MR links β€” When a git push prints a merge request URL, it appears as a status badge on the session. Configure GitLab/GitHub tokens in Settings to enable live status polling.
  6. GitButler dashboard β€” Press Ctrl+Shift+D for the current project or Ctrl+Shift+F for all projects. View branches, pull upstream changes, and merge MRs/PRs.
  7. Git commit & push β€” Press Ctrl+Shift+G to send /git-commit-and-push to an agent session.
  8. Revive sessions β€” Press Ctrl+Shift+A to open the archived sessions list for the current project. Use j/k to browse, Enter to revive. Orphaned sessions (from a crash) also show a revive button directly in the sidebar.
  9. Mobile β€” Install as a PWA from your browser. Use the floating keyboard bar for special keys, swipe to switch sessions, and long-press to rename.

License

Private β€” not yet published.

About

Session-aware developer workbench

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors