Skip to content

Building from Source

Build AgentMux from source on Windows, macOS, or Linux. AgentMux is a Rust desktop app with a SolidJS frontend, hosted in a bundled Chromium runtime via CEF (cef-rs).

ToolVersionPurpose
Node.js24 LTS (>=24.11.0)Frontend build (Vite + SolidJS)
Rust1.77+Backend, host, and launcher
TaskLatestBuild orchestration
CMake3.20+Required by cef-dll-sys (CEF C wrapper)
Ninja1.10+Required by cef-dll-sys
Terminal window
xcode-select --install
brew install cmake ninja
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
  1. Install Rust from rustup.rs.
  2. Install Visual Studio Build Tools — select “Desktop development with C++” (provides CMake and Ninja).
  3. Verify Ninja is on PATH. The Visual Studio install ships Ninja inside Common7/IDE/CommonExtensions/Microsoft/CMake/Ninja/; copy or symlink ninja.exe to a PATH entry. From Git Bash (note: the * must be unquoted so the shell expands it):
    Terminal window
    cp /c/Program\ Files/Microsoft\ Visual\ Studio/*/Community/Common7/IDE/CommonExtensions/Microsoft/CMake/Ninja/ninja.exe /c/Systems/bin/
    Or substitute the actual edition (Community, Professional, Enterprise) and year (2022, etc.) so no glob is needed.
Terminal window
sudo apt install cmake ninja-build build-essential curl wget file libssl-dev git zip \
libwayland-dev libxkbcommon-dev libgtk-3-dev \
libglib2.0-dev libpango1.0-dev libcairo2-dev \
libgdk-pixbuf2.0-dev libatk1.0-dev
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
Terminal window
# macOS
brew install go-task/tap/go-task
# Linux
sudo snap install task --classic
# Windows
winget install Task.Task
Terminal window
git clone https://github.com/agentmuxai/agentmux.git
cd agentmux
npm install
Terminal window
task dev

This launches the four-process app with Vite hot reload. The frontend rebuilds on save (SolidJS HMR via Vite); changes to the Rust crates require a rebuild and restart.

ChangedAction
Frontend (TypeScript / SolidJS)Auto-reloads via Vite HMR
Rust sidecar (crates/srv/)task build:backend, then restart task dev
Rust host (crates/cef/)task build:host, then restart task dev
Launcher (crates/launcher/)task package (portable / installed builds). Note: task dev now runs through the launcher on all platforms as of v0.41.0 — launcher changes are exercised by task dev, not just package builds.
CommandDescription
task devDevelopment mode (CEF host + Vite hot reload)
task build:hostBuild the CEF host binary
task bundleBundle CEF runtime DLLs
task build:backendBuild agentmux-srv
task build:frontendBuild frontend only
task packagePackage a local Windows portable (a folder plus a .7z) — ephemeral labeled build, see below
task package -- --fresh…with a throwaway data dir (clean-slate session) instead of the branch’s persistent one
task package:linuxLocal Linux AppImage to ~/Desktop (package:linux:deb, :rpm and :tarball make the other formats)
task package:macosLocal signed macOS .app + .dmg to ~/Desktop (notarized when a notarytool profile is set up)
task package:msixWindows MSIX built from a portable (-- -Sign for a self-signed test package)
task package:installerWindows .exe installer (Inno Setup) built from a portable
task cleanClean build artifacts

Run task --list to see every task. Each package task runs only on its own platform. package, package:macos and the package:linux tasks each have a package:release twin that bakes the stable channel and refuses to run unless HEAD is a merged release commit; published release artifacts are built by the release pipeline.

task package is for local builds. It does not bump the version and does not touch git — the committed version moves only through task release (changesets). Each local build instead carries an ephemeral, traceable label:

agentmux-<version>+g<sha>[.dirty].<stamp>-x64-portable

Everything after + is semver build metadata — ignored for version precedence, so a local label can never collide with or reorder a release version. The <sha> ties the build back to its source commit, .dirty marks a build made from uncommitted changes, and <stamp> (a UTC build timestamp) makes every build’s folder unique — so a running instance can never lock the next build’s output folder. The data dir is keyed on a per-build channel local-<branch>-<hash>-<build-id> baked at compile time, so each build is its own isolated instance (its own data dir, cef-cache, and single-instance pipe) — two rebuilds of one branch do not share a data dir or session. Agents and auth are account-wide (under ~/.agentmux/shared/), so a fresh per-build data dir still shows every agent and stays logged in; only pane layout and memories start fresh. (--fresh is now a no-op, since every build is already isolated.) Full rationale: SPEC_LOCAL_BUILD_VERSIONING_2026_05_28.md.

There is no task test. CI runs these, and so can you:

Terminal window
npx vitest run # frontend and script tests (npm test starts vitest in watch mode)
npx tsc --noEmit -p tsconfig.citypecheck.json # TypeScript type check
cargo test --workspace -- --test-threads=1 # Rust tests, all crates
agentmux/
├── crates/launcher/ # Launcher — spawns the host and the sidecar, owns OS-level facts
├── crates/cef/ # CEF host — embeds Chromium, owns the OS window
├── crates/srv/ # Sidecar — RPC engine, SQLite persistence, sagas
├── crates/common/ # Shared library (path resolution, runtime mode, IPC types)
├── crates/mcp/ # agentmux-mcp — the MCP server agents use for MuxAPI
├── crates/bashwrap/ # Streaming bash wrapper and CLI hook helper
├── crates/remote/ # Helper installed on SSH hosts (durable sessions, files)
├── crates/procstats/ # Per-process CPU and memory for Tower
├── frontend/ # SolidJS + TypeScript (Vite)
├── docs/ # Architecture docs; specs in docs/specs/
└── Taskfile.yml # Build task definitions
launcher ◀── named pipe ──▶ host (CEF)
│
├── JS bridge ──▶ renderer (SolidJS)
│
├── websocket ──▶ sidecar (agentmux-srv)
│ │
│ └── ssh ──▶ agentmux-remote on an SSH host
│
▼
OS window, browser panes

See Architecture overview for the full topology and what each edge carries.

Open Chromium DevTools from the hamburger menu (≡) in the top tab bar → Dev Tools, or use the keyboard shortcut. DevTools is no longer a widget-bar entry (moved to the hamburger menu — see Pane types). Reload the renderer with Ctrl+R / Cmd+R.

The host log lives in <data-dir>/logs/ (per channel/version). The sidecar logs directly to the shared ~/.agentmux/logs/, alongside pointer files that resolve to the running host’s per-channel log. Use the muxlog shell helper from any AgentMux terminal — it handles both:

Terminal window
muxlog host # tail the current host log
muxlog srv # tail the sidecar log
muxlog host '\[fe\]' # filter the host log to frontend lines
muxlog host cat # full file contents

See Multi-instance & dev mode for the per-instance path layout and pointer-file resolution.

If cargo build fails with “CMake was unable to find a build program corresponding to Ninja”, verify ninja --version works on PATH. On Windows, see the install steps above.

Run task build:backend and verify the binary lands in target/release/ (or the platform-equivalent location). The launcher auto-spawns the sidecar by absolute path.

Check the Vite dev port (task dev prints it on startup) is not already in use. Clear and reinstall if needed:

Terminal window
rm -rf node_modules package-lock.json
npm install
task dev

dist/schema/ is wiped by task clean but automatically recreated by the copy:schema dependency in dev, start, and package tasks.