One screen for all your Claude Code sessions, across all your machines.
Run Claude Code on your laptop, your desktop, your cloud box — and control all of them from a single browser tab. Hush gives you a spatial canvas where every session on every machine is visible at a glance.
- Multi-session orchestration — Run N Claude Code sessions in parallel. Status dots (green/amber/red) tell you where your attention is needed.
- Multi-machine mesh — Each machine runs a daemon. Daemons discover each other via gossip. Open one browser tab, see everything.
- Sessions survive disconnects — Close your laptop, Claude keeps working. Reconnect later, scrollback replays automatically.
- P2P upgrades — Build once, propagate to the whole mesh. No CI, no GitHub access needed on receiving machines.
Private network only. Hush is designed for use over Tailscale, a VPN, or a trusted LAN. Do not expose the daemon port to the public internet — there is no authentication on the daemon-to-daemon gossip channel.
- Rust (for building)
- Node.js 18+ (for building the UI)
- Claude Code CLI (
claudemust be on your PATH)
git clone https://github.com/hushctl/hush
cd hush
make installThis builds the daemon + UI and installs to ~/.local/bin/ and ~/.hush/ui/.
Add ~/.local/bin to your PATH if it isn't already:
# Add to ~/.zshrc or ~/.bashrc
export PATH="$HOME/.local/bin:$PATH"hushOn first run, Hush generates a TLS certificate authority and installs it into your OS trust store (macOS will prompt for your password once). After that, open https://localhost:9111 in your browser.
Click + project in the command bar, enter the path to a Git repo, then enter a branch name. A Claude Code session starts — click the dot on the grid to open a terminal pane.
Each machine runs its own hush daemon. The browser connects to all of them and merges everything into one grid. Daemons gossip peer lists, so adding one daemon URL is enough to discover the rest.
1. Install Tailscale on each machine (for encrypted networking)
# macOS
brew install tailscale && sudo tailscaled & && tailscale up2. Build and install Hush on each machine (or use P2P upgrades after the first)
make install3. Start the first machine
hush \
--bind 0.0.0.0 \
--advertise-url wss://$(tailscale ip -4):9111/ws \
--machine-name laptop \
--auto-upgrade4. Join additional machines
On the first machine, generate a short-lived join token:
hush invite
# prints: hush-join-XXXX-XXXX
# Token expires in 10 minutes.On each additional machine, join with the token. hush invite prints the exact --join URL to use — copy it and fill in your own flags:
hush \
--bind 0.0.0.0 \
--advertise-url wss://$(tailscale ip -4):9111/ws \
--machine-name studio \
--join wss://100.x.x.x:9111/peer \
--join-token hush-join-XXXX-XXXX \
--auto-upgradeThe joining machine POSTs to the CA machine's /join endpoint, receives a signed leaf cert, installs the mesh CA into its OS trust store (macOS will prompt for your password once), and starts. Within 30 seconds, every daemon knows about every other daemon.
--bind 0.0.0.0is required for multi-machine use so that remote browsers and peer daemons can reach this daemon over Tailscale. The default (127.0.0.1) is intentionally localhost-only for single-machine setups.
5. Open the browser
Navigate to any daemon's URL (e.g. https://100.x.x.x:9111). Click + daemon in the command bar to add a second daemon's URL — or just wait for gossip to auto-populate the rest.
hush [OPTIONS] [COMMAND]
Commands:
invite Generate a join token for enrolling a new machine into the mesh
upgrade Pull a newer binary from a peer (manual trigger)
trust Manage the local CA used for TLS certificates
Options:
-p, --port <PORT> Port to listen on [default: 9111]
--bind <ADDR> Bind address [default: 127.0.0.1]
Use 0.0.0.0 for multi-machine / Tailscale access
--state-file <PATH> State file [default: ~/.hush/state.json]
--machine-name <NAME> Label shown in the UI (default: hostname)
--advertise-url <URL> WebSocket URL peers should dial to reach this daemon
Required for peer discovery (e.g. wss://host:9111/ws)
--join <URL> Seed peer URL on startup (repeatable)
Use the /peer endpoint (e.g. wss://host:9111/peer)
`hush invite` prints the exact command to run
--join-token <TOKEN> Join token from `hush invite` on an existing mesh member
Used with --join to receive a signed cert from the CA machine
--auto-upgrade Automatically push this binary to older peers
--tls-dir <PATH> Directory for TLS CA and leaf cert (default: ~/.hush/)
-h, --help Print help
# Terminal 1
hush --port 9111 --machine-name laptop \
--advertise-url wss://localhost:9111/ws
# Generate a join token
hush invite
# → hush-join-XXXX-XXXX
# Terminal 2
hush --port 9112 --machine-name studio \
--state-file ~/.hush/state-studio.json \
--tls-dir ~/.hush/ \
--advertise-url wss://localhost:9112/ws \
--join wss://localhost:9111/peer \
--join-token hush-join-XXXX-XXXX
--tls-dir ~/.hush/points both daemons at the same CA so they trust each other's leaf certs without a separate trust-install step.
Add wss://localhost:9111/ws in the browser UI — studio appears automatically.
Create ~/Library/LaunchAgents/com.hush.daemon.plist:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN"
"http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>Label</key>
<string>com.hush.daemon</string>
<key>ProgramArguments</key>
<array>
<string>/Users/YOUR_USERNAME/.local/bin/hush</string>
<string>--bind</string>
<string>0.0.0.0</string>
<string>--advertise-url</string>
<string>wss://YOUR_TAILSCALE_IP:9111/ws</string>
<string>--machine-name</string>
<string>YOUR_MACHINE_NAME</string>
<string>--auto-upgrade</string>
</array>
<key>RunAtLoad</key>
<true/>
<key>KeepAlive</key>
<true/>
<key>StandardOutPath</key>
<string>/tmp/hush.log</string>
<key>StandardErrorPath</key>
<string>/tmp/hush.log</string>
</dict>
</plist>launchctl load ~/Library/LaunchAgents/com.hush.daemon.plistKeepAlive: true is required for P2P upgrades — after replacing its binary, hush exits and launchd restarts it with the new version.
Upgrades flow through the gossip mesh — no GitHub access required on any machine except the one that builds the new binary.
-
Build the new binary on one machine:
cd hush && make install
-
Restart that daemon with
--auto-upgrade. Within one gossip round (~30 seconds), it streams the new binary to each older peer over the existing TLS WebSocket. Each peer replaces its binary and restarts automatically.
Browser (any device)
└── WebSocket per daemon ──► hush (machine A) ◄── hush-hook shim
└──► hush (machine B) ◄── hush-hook shim
- Each
hushdaemon owns its pty sessions, project registry, and state file. - The browser namespaces IDs as
machineId:worktreeIdso projects from different machines never collide. - Daemons gossip peer lists every 30 seconds — adding one daemon seeds the whole mesh.
hush-hookis a shim invoked by Claude Code's hook system on lifecycle events (SessionStart,Stop,Notification, etc.). It writes structured JSON to a Unix socket so the daemon tracks status without parsing terminal output.- Pty sessions survive browser disconnects. Reconnect anytime; scrollback replays automatically.
- P2P upgrades stream the binary over the same TLS WebSocket used for pty data. Upgrade tarballs and worktree transfers are signed with the mesh CA key and verified on receipt.
- Each daemon has a leaf TLS cert signed by the mesh CA.
hush inviteissues a join token; the joining machine POSTs to/join, receives a signed cert, and joins the mesh. The CA private key never leaves the CA-origin machine.
# Start the daemon (debug build)
cd daemon && cargo run
# Start the UI dev server (hot reload)
cd ui && npm run devThe UI dev server runs on http://localhost:5173 and connects to the daemon's WebSocket at wss://localhost:9111/ws.
Optional: AI-powered command bar. The command bar uses regex parsing by default. To enable natural language intent classification (downloads a ~300MB model on first load):
VITE_ENABLE_AI_INTENT=true npm run devRun make hooks once after cloning to install the pre-commit build check.
MIT
