Documentation
The complete guide, from download to daily operations. Read the Getting Started part (about 10 minutes) and you'll have your first managed AI coding agent running on a remote server.
What is AgentMux#
AgentMux is a desktop application for operating AI coding agents — Claude Code, Codex, Gemini CLI, OpenCode, Aider, Cursor CLI — that execute on remote hosts and on this computer. Its core mechanism fits in one sentence:
It ships as a single binary: no server, no daemon, no account. All state is one SQLite file in the application data directory. Each remote host gets one multiplexed SSH connection — terminals, commands, and file transfers are channels on it, so ten terminals against one host is one authentication. Idle connections close after ten minutes.
Requirements#
The computer running AgentMux
| Platform | Requirement |
|---|---|
| macOS | macOS 11 (Big Sur) or later; universal binary for Intel and Apple Silicon |
| Windows | Windows 10 or later |
| Linux | GTK3 and WebKitGTK 4.1 at run time — libwebkit2gtk-4.1-0 on Debian/Ubuntu, webkit2gtk4.1 on Fedora |
| Tablet / phone | Any modern browser — the server runs elsewhere (see Tablet & Phone). Android also has a standalone app with the core embedded: Android 8.0+ · arm64 |
Managed hosts
- Remote Unix-like hosts (Linux / macOS): a POSIX shell,
tmux, and an SSH account. Missing tmux is fine — the install panel can install it. - Remote Windows hosts: just enable OpenSSH Server. There is no tmux there — sessions are hosted by AgentMux's own session daemon, deployed over SFTP on first use, with its protocol riding an SSH port forward, never a remote shell.
- Screen-only hosts: machines you want to watch rather than work on need nothing but an address with RDP or VNC answering — no SSH, and no credentials stored anywhere (see Host Operations → Screen-only hosts).
- This computer (Linux / macOS): just a local
tmux— no sshd, no credentials. - This computer (Windows): the same machine offers two hosts — the default WSL distribution (where tmux lives) and native Windows (PowerShell, Windows paths and toolchains, for MSVC builds, WPF, and running the .exe you just built). Native sessions persist through AgentMux's own session daemon, so closing the window doesn't stop native work either.
Optional: orchestrator and semantic search
Local orchestration and semantic memory search require Ollama plus one chat model and one embedding model. Without Ollama, everything else is fully functional.
Installation#
Each release
provides one build per platform, produced by GitHub Actions from the tagged commit, with a
.sha256 alongside. Builds are not yet code-signed or notarized, so the first launch
takes one extra confirmation per platform.
macOS
- Download
agentmux-macos-universal.zip, unzip, and dragAgentMux.appinto Applications. - Handle the unsigned-build prompt per your macOS version (table below).
- After that, it opens normally.
| macOS version | Procedure |
|---|---|
| 15 Sequoia or later | Open once and let it be blocked → System Settings → Privacy & Security → Security → Open Anyway |
| 14 Sonoma or earlier | Control-click the app → Open → Open |
| Any version | Run xattr -dr com.apple.quarantine /Applications/AgentMux.app, then open normally |
curl -L -O <url> avoids it altogether.
Windows
- Download and unzip
agentmux-windows-amd64.zip— it containsagentmux.exeand an install script. - Double-click to run; when SmartScreen appears, choose More info → Run anyway.
- For a proper install (to
%LOCALAPPDATA%\Programs\AgentMux, with desktop and Start menu shortcuts, no administrator rights), run from the unzipped folder:
powershell -ExecutionPolicy Bypass -File install-windows.ps1 The same script with -Uninstall reverses it, without touching the data in %APPDATA%\AgentMux.
Linux
- Install the runtime dependency first:
sudo apt install libwebkit2gtk-4.1-0on Debian/Ubuntu,sudo dnf install webkit2gtk4.1on Fedora. - Download and extract
agentmux-linux-amd64.tar.gz— binary, icon,.desktopentry, andinstall.sh. - Run
./install.sh, or execute the binary directly.
Verifying downloads
# every file ships with a .sha256:
shasum -a 256 -c agentmux-macos-universal.zip.sha256 # macOS
sha256sum -c agentmux-linux-amd64.tar.gz.sha256 # Linux Server build (headless)
The same application also ships as a fully static headless build:
agentmux-server-linux-amd64.tar.gz and agentmux-server-linux-arm64.tar.gz.
It links no GTK and no webview and needs no display — run it on any Linux server and it serves the
complete web application. The recommended way to deploy it is the one-line install script, which also
sets up a systemd service and self-updates — see The Headless Server.
Android
- Download
agentmux-android.apk(Android 8.0+ · arm64) and install it on the phone or tablet — you will need to allow installation from unknown sources. - On first launch a foreground service starts the embedded core and the WebView connects to
127.0.0.1. No server is involved. - When the repository has signing keys configured the APK is properly signed and upgrades in place; otherwise it carries a debug signature — installable all the same, but uninstall the old one before switching signatures.
Quick Start#
Four steps to your first managed agent. Everything here is also reachable through the Ctrl/⌘ K command palette — the fastest route to any action.
Step 1: Add a host
A remote host needs three things:
- Address and user — the same ones you'd use with
ssh user@host. - One of three auth methods: ssh-agent (recommended — nothing to fill in), a key file (passphrase supported), or a password.
- Jump hosts (optional) for environments behind a bastion.
This computer asks for nothing but a name — no sshd, no credentials. On Windows you'll see two local hosts: the WSL distribution and native Windows. Pick per workload — Unix toolchains go to WSL; MSVC/WPF go native.
Step 2: Add a project and workspace
A workspace is a working directory on the host (usually a repository root). Two ways to add one:
- The form: pick a host, enter a path.
- The file browser (faster): browse the host's files, find the directory, and "add as project" in place — its name, path, and host are already known.
Step 3: Add an agent and start it
An agent is a name plus the command that starts it — the same command you'd type in a terminal:
# typical start commands, adjust to taste
claude # Claude Code
codex # OpenAI Codex CLI
gemini # Gemini CLI
aider --model sonnet # Aider
opencode # OpenCode Hit Start and it's running inside tmux on the host. Agent API keys are configured on the host side (the agent's own config or environment) — AgentMux neither reads nor proxies them.
Step 4: Attach and work
Click the agent, or search its name via Ctrl/⌘ K. What you get is a real
terminal — colour, mouse, selection, search. Step in and type at any time, correct the
agent's course, hand control back — no restart needed. The side panel provides
Start / Stop / Restart / Attach, process state, and recent output.
The Terminal Wall#
The terminal area divides into up to nine panes (3×3), each holding its own session — on one host or several, each independently interactive:
- Add a pane:
Ctrl/⌘ \. With an open tab spare it splits instantly; otherwise a dialog offers hosts, workspace directories, running agents, and open tabs. - The layout adapts: panes divide the area in proportions, not pixels. A column too narrow to read is dropped, so a narrowed window wraps the 3×3 wall into a taller grid instead of nine slivers.
- Drag the seams to resize panes.
- Temporary zoom: double-click a pane's tab (or
Ctrl/⌘ ⇧ ↵) to fill the area; again to restore. The split underneath is untouched. - A pane is a view, not a session: closing one (
Ctrl/⌘ ⇧ \) hides the terminal while the tab and its shell stay attached. The pane count is restored on next start.
Keyboard Shortcuts#
| Shortcut | Action |
|---|---|
Ctrl/⌘ K | Command palette — the fastest route to attaching, opening shells, installing CLIs, changing theme |
Ctrl/⌘ B | Show or hide the tree |
Ctrl/⌘ \ | Add a pane — instantly with the next open tab, otherwise asking what to attach |
Ctrl/⌘ ⇧ \ | Close the pane, leaving the tab and its shell open |
Ctrl/⌘ ⇧ ↵ | Fill the area with the focused pane, and back again |
Ctrl/⌘ ⌥ ← → | Move between panes — zoomed, this reads them one at a time |
Broadcast & Receipts#
The Broadcast panel sends one instruction to any selection of agents — across projects and hosts. Unlike pasting into each terminal, every agent returns a delivery receipt telling you whether the instruction actually arrived.
- Target by project, by host, or tick agents individually.
- Per-agent delivery status; failed deliveries stand out and can be retried individually.
- Typical uses: pausing the whole fleet, issuing a new constraint ("all commit messages in English from now on"), polling progress across agents.
Host Operations#
The install panel: provisioning a new host
The install panel inspects the host first and offers only the agent CLIs and runtimes it can actually support, stating why others are unavailable. Installation runs inside tmux, so an interrupted connection cannot leave a partial package tree. tmux itself can be installed from here when missing.
One-click install covers the agent CLIs — Claude Code, Codex, Gemini CLI, Grok CLI, OpenCode, Aider, Cursor CLI — and runtimes including Node, Python, tmux, Docker and Ollama. Docker offers six methods (the official script first, then the distributions' own packages, then Docker Desktop through Homebrew), retrying against a mirror where the network needs one. Every engine install ends by starting the daemon and adding the user to the docker group, and says out loud that the group needs a fresh login.
Host telemetry
Per-host metrics are collected in a single command:
- CPU by mode and by core, memory, load
- Disk usage and throughput, network, file descriptors
- NVIDIA GPU utilisation where present
SFTP browser and editor
File access rides the same SSH connection. Writes are atomic and carry a modification check: if an agent working in the same directory changed the file, the save is refused rather than silently overwriting — look at what changed first, then decide.
Remote desktop (built-in RDP / VNC viewer)
Some work is a screen: an installer that insists on a window, a GUI test, a machine somebody has to look at. Right-click a host and pick Open desktop — the three usual ports, 3389 (RDP) and 5900 / 5901 (VNC), are dialled concurrently, and deliberately nothing beyond them: a tool that port-scans other people's machines on its own initiative is not a reasonable tool. On an SSH host the dial rides the connection that host already has, so a desktop listening on its own loopback needs nothing opened to the network and no second set of credentials.
- The viewer lives inside the application: the desktop opens as a tab in the terminal area, right next to your terminal panes. It is a real protocol client, not a picture of one — noVNC for VNC, IronRDP compiled to WebAssembly for RDP — loaded on demand, so people who never open a desktop never pay a byte for it. The remote resolution follows the pane as you resize it.
- Because the viewer is in the application, the capability exists on every client — the desktop app, a browser, a tablet, a phone — no longer depending on what happens to be installed locally.
- Login credentials are entered when the session opens, sent to the host over its existing channel, and kept nowhere.
- When Windows refuses a login you are told what it actually refused, not an NT status code: account locked out (and for how long), password expired, account disabled, not in the Remote Desktop Users group, logon-hours restrictions, a missing domain prefix — the common causes are translated, each with its remedy.
- The desktop app still offers a System client option: the answering port is forwarded to loopback on this computer and handed to whichever viewer it has — mstsc on Windows, Screen Sharing on macOS, Remmina or FreeRDP on Linux. The forward closes itself five minutes after the last client leaves, releasing the SSH lease; if no viewer is installed, it stays up and reports its address.
- Which desktop a host serves is remembered — only endpoints that actually answered, never a misdialled port — so the second opening asks nothing. That memory belongs to the host rather than to this installation, so it travels with a configuration export.
Screen-only hosts
Wanting to watch a machine and wanting to work on one are different needs. The Remote desktop host kind serves the first: a name, an address, and the operating system — which decides the protocol (RDP for Windows, VNC for macOS / Linux) and suggests the port, both editable. There is no credentials field at all: whatever the desktop asks for is entered when a session opens and kept nowhere.
- In the tree it is exactly a screen: no terminal, no agents, no workspaces, never a jump-host candidate, and no seat in the SSH connection pool — nothing that needs a shell will offer it as one.
- It is dialled directly on its desktop port, like any ordinary remote desktop client would; Test connection dials that port and reports the latency.
- Promoting it to a machine you can work on: its detail panel quietly probes port 22. If SSH answers, an Add as SSH host button opens the host dialog with the address pre-filled — a new, full host is created and the screen-only row stays as it was. If SSH does not answer and the system is Windows, the panel lays out the exact PowerShell command that enables OpenSSH Server, with one-click copy — paste it into the desktop pane you already have open, run it there, and hit refresh.
- With OpenSSH enabled, add the machine as a Remote Windows host and agents run natively — PowerShell, MSVC, WPF — kept alive by AgentMux's session daemon, so closing the window stops nothing. From then on the machine is both a screen and a place to work.
Make and model
The metrics panel now answers what a machine is, not only what it is doing: CPU model, DIMM specs, physical drives and graphics adapters. Those are static, so they ride a separate one-shot read cached for the session rather than the three-second ticker.
The Headless Server#
AgentMux's core can run without a window: a fully static headless build that links no GTK and no webview, and serves the complete web application from any Linux server — terminals, agents, broadcast, file browsing, remote desktop, the same feature set as the desktop build, not a reduced view. The desktop app, phones, tablets and any browser can connect to it and see one set of hosts and one set of running sessions.
The one-line install (recommended)
curl -fsSL https://raw.githubusercontent.com/tan-zhuo/AgentMux/main/scripts/install-server.sh | bash The script does everything on a Linux server (amd64 / arm64), entirely as the calling user — no root required:
- Downloads the server build for the current architecture, verifies the
.sha256, and installs to~/.local/bin— new file first, then an atomic rename, so a half-written binary can never exist. - Registers a systemd user service (
~/.config/systemd/user/agentmux.service, restarted on failure) and enables lingering — the service keeps running after you disconnect or log out. Machines without systemd fall back to nohup plus an@rebootcrontab. - Enables HTTPS by default (self-signed certificate), listening on
:8642. - Probes the server and only reports success once it actually answers; if it does not start, the relevant lines of the service log are printed for you, along with the most common cause (a taken port — pick another with
--addr). - On success it prints the three things a client needs: the address, the access token, and the certificate fingerprint.
Common options (after bash -s -- when piping):
| Option | Default | Effect |
|---|---|---|
--addr ADDR | :8642 | Listen address; 127.0.0.1:8642 restricts to this machine (for a reverse proxy) |
--no-tls | TLS on by default | Plain HTTP instead of self-signed HTTPS (trusted LANs only) |
--mirror URL | — | GitHub downloads through a mirror prefix (e.g. https://ghfast.top); same convention as the in-app update mirror |
--version vX.Y.Z | latest | Install a specific version |
--prefix DIR | ~/.local/bin | Where the binary goes |
--no-service | — | Install the binary only; register and start nothing |
Running it by hand
# server build (agentmux-server-linux-*): running it is serving; :8642, plain HTTP by default
./agentmux
# with flags: all interfaces, self-signed HTTPS
./agentmux --addr 0.0.0.0:8642 --tls
# the desktop binary enters the same mode
agentmux --serve --addr 0.0.0.0:8642 --tls | Flag | Environment variable | Meaning |
|---|---|---|
--addr | AGENTMUX_ADDR | Listen address, default :8642 |
--tls | AGENTMUX_TLS=1 | Self-signed HTTPS; the certificate is generated once and reused from the data directory |
--tls-cert / --tls-key | AGENTMUX_TLS_CERT / AGENTMUX_TLS_KEY | Bring your own PEM certificate and key (a CA-issued one, say) |
| — | AGENTMUX_TOKEN | Choose the access token yourself |
| — | AGENTMUX_DATA_DIR | Override the data directory |
The first start prints the access token (48 hex characters, persisted as serve-token in
the data directory, mode 0600) and, with TLS on, a certificate SHA-256 fingerprint — the line every
client pairs against.
Encryption and trust: a self-signed certificate, pinned by fingerprint
A self-signed certificate has no CA to vouch for it, so each device decides whom to believe: on first connection the client fetches the certificate, shows its SHA-256 fingerprint, and you compare it against the line in the server's log before confirming. From then on that device accepts exactly that certificate — no names, no expiry dates; a changed fingerprint is a refused connection. Switch the address to a proper CA certificate and the pin retires itself in favour of normal verification. Every value meant to be carried — token, address, fingerprint — comes with one-click copy: they are for clipboards, not for eyes.
./agentmux --addr 127.0.0.1:8642, then e.g.
caddy reverse-proxy --from mux.example.com --to 127.0.0.1:8642.
Or hand serve a real certificate directly with --tls-cert / --tls-key.
Limits: the server build is published for Linux only (amd64 / arm64). To serve from macOS or Windows,
use the desktop app's server mode, or build your own with
go build -tags headless.
Core Switching & Server Mode#
Behind every AgentMux window there is a core — the part that holds host configuration, SSH connections, keys and all state. By default the window looks at the core on this device, but the two decouple: the window can look at a core on another machine, and this device's core can be opened up for other devices to look at. Those two directions are two adjacent pages in Settings.
Pointing the window at a remote core (Settings → Connection)
- Pick Remote server and enter the address of a serve instance, e.g.
https://192.168.1.10:8642. - Against self-signed HTTPS a fingerprint card appears: compare it with the server log (or with the other machine's Server mode page) and confirm with “trust and connect”.
- Enter that machine's access token once, and the window switches over.
The window is then a screen onto that machine: host configuration, SSH keys, connections, all state live on the remote end, and this device remembers only the address and the fingerprint. Switch back to This device and you see the local data again — the two sides are independent and never synchronise.
- The recommended shape: one desktop or LAN server runs the core (the headless build, or server mode), and the laptop, phone and tablet all point at it — SSH keys and jump hosts are configured once, on that one machine, and every device sees the same hosts and the same running terminals.
- You can always get home: when the remote end is unreachable there is no blank window — an error page explains what failed, with a Retry button and a “back to this device” button.
- The Android app has the same Settings → Connection page: it defaults to the core embedded in the device, and can point at a remote instance instead.
Letting this computer be the server (Settings → Server mode)
The other direction: the desktop app itself can accept connections from other devices, with nothing extra installed:
- Settings → Server mode; confirm the listen address — the default
:8642listens on all interfaces,127.0.0.1:8642restricts to this machine. - “Encrypt (HTTPS, self-signed certificate)” is checked by default; press Enable.
- The page then lists the connection addresses, the access token, and the certificate fingerprint, each with one-click copy — enter the address in the phone app's Settings → Connection, paste the token, compare the fingerprint.
The window and the web are two faces of one core: what the phone shows is exactly the hosts and terminals on your desktop, live in both directions. The switch is remembered and restored on the next start.
Tablet & Phone#
Any modern browser opens the full application — an Android tablet, an iPad, a phone. Terminals, agents, the toolkit, file browsing and remote desktop all work; it is not a read-only view.
Getting a server to connect to
Stand one up as described in The Headless Server (one line on a Linux box), or flip on server mode in the desktop app. Either road hands you the same three things: an address, an access token, and a certificate fingerprint.
Opening it on a tablet
- Browse to
https://host:8642(with a self-signed certificate the browser asks once on its warning page; a plain-HTTP deployment ishttp://). - Enter the token once; the browser keeps it from then on.
- iPad: Safari's “Share → Add to Home Screen”. Android: Chrome's “Add to Home Screen”. It then runs as a standalone app with no address bar.
Closing the browser stops nothing — exactly like closing the desktop window, because the agents live in remote tmux.
The native Android app
Every release attaches agentmux-android.apk (Android 8.0+ · arm64). It goes one step beyond the
route above: it embeds the same core the server build ships, started on the device by a foreground
service, with the WebView joining it on 127.0.0.1. SSH runs from the phone or tablet itself and
configuration and keys stay on the device — no always-on machine is needed.
- The foreground service is deliberate: without it Android freezes the process at screen lock and cuts every SSH connection. That is why a persistent notification is shown.
- The agents live in remote tmux, so they are unaffected even if the system kills the app — reopening it reconnects.
- Remote mode: the app's Settings → Connection page can point it at a serve instance instead of the embedded core. Against self-signed HTTPS the app fetches the certificate and shows a fingerprint card — compare it with the server log and confirm; from then on this device accepts exactly that certificate.
- Known limit: against a self-signed, fingerprint-pinned server, the remote desktop viewer is unavailable (Android's WebView does not hand WebSocket certificate errors to the app to adjudicate). Terminals and everything else are unaffected; a real CA certificate lifts the limit.
A layout redone for thumbs
- Under 768px the side panels become overlay drawers — one at a time, closing when a tab is picked.
- The status bar's slot holds a bottom navigation bar: tree, command palette, detail panel and settings as labelled thumb-height buttons, with the safe-area inset respected.
- Dialogs and the command palette stop insisting on desktop margins where there is no room for any.
Orchestrator & Ollama#
The orchestrator is an operations assistant driven by a local model: give it an objective (say, "work out why agent-3 stopped progressing") and it inspects fleet state, retrieves prior context, and proceeds one tool call at a time. It is disabled until you enable it.
Prerequisites
- Install Ollama and keep it running.
- Pull one chat model and one embedding model, for example:
ollama pull qwen3 # chat model (example — pick for your hardware)
ollama pull nomic-embed-text # embedding model, used for semantic search The approval flow
- Every operation that modifies a host is held for your explicit approval. The approval card shows: the tool, its full arguments, the target host, and the model's stated justification.
- Destructive operations are confirmed on every host, regardless of its trust level.
- Tools are a fixed whitelist, each carrying a risk tier fixed at declaration. Execution passes a single gate combining tier × host trust level × the run's trigger.
- Remote output enters the model marked as data; instruction-shaped text raises a flag on the approval card and in the decision log (prompt-injection defence).
- Every step of every run is recorded — including proposals refused, rejected, or left unanswered.
Scheduled patrols
The orchestrator can patrol the fleet on a schedule and report stalled agents. Scheduled runs are refused every non-read tool unconditionally — the restriction is not configurable. Patrols can find problems; acting on them always waits for you.
Skills and memory
- Skills: reusable procedures — the conditions under which one applies, the steps, the tools, the constraints — matched automatically when those conditions recur. Skills proposed by the orchestrator enter a review queue and have no effect until approved.
- Memory: project facts, stated preferences, and agent activity are indexed for retrieval by wording or by meaning. Embeddings are computed locally; nothing leaves the machine. Credentials matching known patterns are redacted before storage.
Lifecycle Semantics#
Internalise these and you'll never have a "did I just lose my task?" moment:
| Action | What actually happens |
|---|---|
| Quitting AgentMux | Nothing stops. All agents keep running in tmux on their hosts. |
| Closing a pane | Hides the terminal view; the tab and its shell stay attached. |
| Deleting a workspace / agent record | Removes the local record only — the tmux session keeps running. |
| The agent process exits | Leaves a usable shell in the correct directory — the session isn't destroyed; investigate or restart in place. |
| Stop | Stops the agent process; session and shell remain. |
| Kill | The one control that destroys a running tmux session. It always confirms first, stating what is lost. |
| Network drop / lid close | Agents unaffected; the terminal reattaches itself to the same pane once the connection is back, scrollback intact. |
| Ten idle minutes | An SSH connection with nothing holding it closes; it's rebuilt automatically on next use. |
Agents that are waiting on a person
An agent asking a question, one that finished with results to review, and one sitting at its prompt with no task all read as “running” in the tree before. The poll now reads each pane and classifies it, raising a sticky mark on the transitions a human needs to see, and taking the mark down when someone actually looks — opens the terminal, answers, or dismisses it.
- The marks ride on the tree rows and bubble up to collapsed workspaces and projects, so a folded tree still shows where you are needed.
- They appear on the terminal tabs and on the detail panel as well.
Reconnecting after a drop
A terminal that lost its transport is not over: the tmux session on the far side is still running, the agent inside it is still working, and the only thing that broke was the pipe. So the pipe is rebuilt — same shell id, same scrollback, same pane — backing off from a second to fifteen and giving up after about five minutes, at which point the manual reattach button is still there.
- A session that ended on its own terms is left alone: an exit status is a decision, not a failure.
- Two keepalives, because they answer different questions. TCP keepalive stops the boxes in between from forgetting an idle flow; the SSH one proves the far end is still answering, and gives up on a ping after ten seconds.
- One-shot command terminals are exempt. Dialling back would mean running the command again, and re-running an install because the wifi blinked is a side effect nobody asked for.
Updates & Migration#
Update checks and one-click upgrades
The app checks the release feed shortly after launch and every six hours after. A newer version raises a one-line banner under the title bar: upgrade and restart, release notes, or later.
- Upgrading downloads the platform's asset with a live progress bar, verifies the published
sha256, swaps the running executable (the bundle on macOS; rename-aside on Windows, where a running program cannot be deleted), relaunches, and sweeps up the leftovers on the next start. - A failed swap rolls back to the build that was running.
- A dev build is never overwritten — it updates through git, and the settings dialog says so when asked to check.
Carrying an installation to another machine
Settings can write the whole configuration — hosts, folders, projects, workspaces and agent definitions, with the skill library and the preferences if you want them — into a single file, and open it on the other side.
- Encryption. The file is sealed with a passphrase rather than with this machine's master key, because that key lives in this computer's keychain and cannot travel: a copy of the database would be unreadable at the other end. Argon2id turns the passphrase into a key and AES-256-GCM seals the contents. The cost parameters have to travel in the clear to be usable at all, so they are authenticated rather than hidden — a header rewritten to something cheap stops the file opening instead of weakening it.
- SSH passwords and key passphrases travel only when asked for, exist in the clear for exactly as long as it takes to seal them, and are re-sealed under the new machine's own master key on arrival.
- An import never overwrites. A host at the same address, a project with the same name, a path on the same machine: each is left exactly as it is, and whatever pointed at it in the file is pointed at the copy that was already here. So importing the same file twice adds nothing, and trying an import costs nothing. What cannot be carried is said instead — a key file that is not on this machine, a jump host that did not travel, a session name already taken here.
- Two things deliberately stay behind. Terminal layout and agent runtime state describe this installation rather than the configuration, and whether the orchestrator may act is decided at each machine — a file arriving from somewhere else is not that decision.
Building from Source#
Go 1.25+ and Node 20+. The frontend builds first (it's embedded in the binary), then Go:
git clone git@github.com:tan-zhuo/AgentMux.git
cd AgentMux
cd frontend && npm install && npm run build && cd ..
go build -o agentmux .
./agentmux Linux needs the WebKitGTK headers and the gtk3 build tag:
sudo apt-get install -y build-essential pkg-config libgtk-3-dev libwebkit2gtk-4.1-dev
go build -tags gtk3 -o agentmux . Windows, for a double-clickable GUI binary with no console window:
go build -ldflags "-H windowsgui" -o agentmux.exe . More detail (testing, cutting a release) in docs/development.md.
Troubleshooting#
macOS says the app "is damaged" or won't open
That's the normal gate for unsigned builds, not corruption. Follow the table in
Installation, or fix it in one command:
xattr -dr com.apple.quarantine /Applications/AgentMux.app.
Linux fails to start / missing library
Almost always the WebKitGTK runtime. Debian/Ubuntu: sudo apt install libwebkit2gtk-4.1-0;
Fedora: sudo dnf install webkit2gtk4.1.
Windows: no window appears at all
GUI builds have no console for errors. Check startup-error.log in the data directory
(%APPDATA%\AgentMux) — the actual failure reason is written there.
"Host key mismatch" when connecting
The host's key differs from the one pinned on first connection. Establish why first: a reinstalled host or a re-assigned IP is normal — delete the host record and re-add it. If nothing should have changed, treat it as a possible man-in-the-middle and verify the fingerprint out of band.
Status bar reports the keychain is unavailable
The encryption master key normally lives in the OS keychain (Keychain / Credential Manager /
Secret Service). Where no keychain is available (common on minimal Linux desktops), AgentMux
falls back to a 0600 file and says so in the status bar. Nothing breaks; to restore
keychain storage on Linux, install and enable gnome-keyring or another Secret Service implementation.
The target host has no tmux
Open that host's install panel — tmux is on the list, and AgentMux installs it with the right package manager.
Orchestrator / semantic search unavailable
Check that Ollama is running (ollama list shows your models) and that both a chat
model and an embedding model are pulled. Without Ollama these two features stay disabled;
everything else is unaffected.
Where is my data?
All state is one SQLite file in the application data directory (%APPDATA%\AgentMux
on Windows). Back up that directory to back up everything; delete it for a full reset.
Credentials are stored AES-256-GCM-encrypted, with the key in the OS keychain.
The tablet cannot reach host:8642
- Check the scheme: the install script enables TLS by default, so the address is
https://; only a hand-started server without--tlsishttp://. A self-signed certificate asks once on the browser's warning page. - Check the listen address is not bound to
127.0.0.1— that is unreachable from the network (the default:8642listens on all interfaces). - Check the server's firewall allows 8642 (and the security group, on a cloud host).
- Check the tablet is on the same network, or on the same VPN.
Switched to a remote core and all I get is an error page
The error page is itself part of the design: a serve instance that is down, a VPN that is not connected,
a mistyped address all land on it, and it names what failed. Press Retry, or “back to this device” and
then check systemctl --user status agentmux on the server. Switching always has a way home —
you cannot be stranded in remote mode.
Lost the serve-mode access token
The token is kept as serve-token in the data directory, and printed in the log on first start.
To change it, delete that file and restart, or set AGENTMUX_TOKEN before starting.
The Android app will not install or upgrade
Allow installation from unknown sources first. A signature conflict means the installed build carries a debug signature (what the repository produces when no signing key is configured) — uninstall the old app and install the new one. The agents live in remote tmux and are unaffected.
Getting Help#
- File a GitHub issue — including platform, version, and
startup-error.log(if any) speeds things up considerably. - Orchestrator internals (the tool gate, trust levels, memory and skill layers) are documented in the orchestrator design doc.
- Author's blog: tanzhuo.xyz