#!/bin/sh # agentmux — modern terminal workspace control plane over tmux # Install: curl -fsSL https://amux.coder.company/install.sh | sh # Repo: https://github.com/coder-company/agentmux set -e REPO="coder-company/agentmux" BIN="agentmux" INSTALL_DIR="${INSTALL_DIR:-/usr/local/bin}" # ── colors ────────────────────────────────────────────────────────── if [ -t 1 ] && command -v tput >/dev/null 2>&1 && [ "$(tput colors 2>/dev/null || echo 0)" -ge 8 ]; then BOLD=$(tput bold) DIM=$(tput setaf 8) PURPLE=$(tput setaf 5) CYAN=$(tput setaf 6) GREEN=$(tput setaf 2) RED=$(tput setaf 1) YELLOW=$(tput setaf 3) RESET=$(tput sgr0) else BOLD="" DIM="" PURPLE="" CYAN="" GREEN="" RED="" YELLOW="" RESET="" fi # ── output helpers ────────────────────────────────────────────────── banner() { echo "" echo "${PURPLE}${BOLD} ⣿ agentmux${RESET}" echo "${DIM} terminal workspace control plane${RESET}" echo "" } info() { printf " ${CYAN}→${RESET} %s\n" "$1"; } success() { printf " ${GREEN}✓${RESET} %s\n" "$1"; } warn() { printf " ${YELLOW}!${RESET} %s\n" "$1"; } fail() { printf " ${RED}✗${RESET} %s\n" "$1" >&2; exit 1; } step() { STEP_N=$((${STEP_N:-0} + 1)) printf "\n ${BOLD}[%d/4]${RESET} %s\n" "$STEP_N" "$1" } # ── detection ─────────────────────────────────────────────────────── detect_os() { case "$(uname -s)" in Linux*) echo "linux" ;; Darwin*) echo "darwin" ;; *) fail "Unsupported OS: $(uname -s). agentmux supports Linux and macOS." ;; esac } detect_arch() { case "$(uname -m)" in x86_64|amd64) echo "amd64" ;; aarch64|arm64) echo "arm64" ;; *) fail "Unsupported architecture: $(uname -m). agentmux supports amd64 and arm64." ;; esac } has_cmd() { command -v "$1" >/dev/null 2>&1; } check_tmux() { if has_cmd tmux; then success "tmux $(tmux -V 2>/dev/null | head -1 | sed 's/tmux //')" else warn "tmux not found — install it before running agentmux" echo "" echo " ${DIM}macOS: brew install tmux${RESET}" echo " ${DIM}Debian: sudo apt install tmux${RESET}" echo " ${DIM}Arch: sudo pacman -S tmux${RESET}" echo " ${DIM}Fedora: sudo dnf install tmux${RESET}" echo "" fi } # ── download helpers ──────────────────────────────────────────────── fetch() { if has_cmd curl; then curl -fsSL "$1" elif has_cmd wget; then wget -qO- "$1" else fail "curl or wget required" fi } download() { if has_cmd curl; then curl -fsSL -o "$2" "$1" elif has_cmd wget; then wget -qO "$2" "$1" fi } # ── install methods ───────────────────────────────────────────────── install_release() { OS="$1" ARCH="$2" step "Fetching latest release" TAG=$(fetch "https://api.github.com/repos/${REPO}/releases/latest" \ | grep '"tag_name"' | head -1 | sed 's/.*"tag_name": *"//;s/".*//') if [ -z "$TAG" ]; then return 1 fi VERSION="${TAG#v}" ARCHIVE="${BIN}_${VERSION}_${OS}_${ARCH}.tar.gz" URL="https://github.com/${REPO}/releases/download/${TAG}/${ARCHIVE}" info "Release: ${BOLD}${TAG}${RESET} (${OS}/${ARCH})" step "Downloading" TMPDIR=$(mktemp -d) trap 'rm -rf "$TMPDIR"' EXIT download "$URL" "${TMPDIR}/${ARCHIVE}" success "Downloaded ${ARCHIVE}" step "Installing" tar -xzf "${TMPDIR}/${ARCHIVE}" -C "${TMPDIR}" do_install "${TMPDIR}/${BIN}" return 0 } install_source() { if ! has_cmd go; then fail "No release found and Go is not installed. Cannot build from source." fi if ! has_cmd git; then fail "git is required to build from source." fi step "Building from source" info "No prebuilt release — compiling with Go" TMPDIR=$(mktemp -d) trap 'rm -rf "$TMPDIR"' EXIT git clone --depth 1 "https://github.com/${REPO}.git" "${TMPDIR}/agentmux" 2>/dev/null (cd "${TMPDIR}/agentmux" && go build -ldflags "-s -w" -o "${BIN}" ./cmd/agentmux) success "Built from source" step "Installing" do_install "${TMPDIR}/agentmux/${BIN}" } do_install() { SRC="$1" if [ -w "${INSTALL_DIR}" ]; then mv "$SRC" "${INSTALL_DIR}/${BIN}" chmod +x "${INSTALL_DIR}/${BIN}" ln -sf "${BIN}" "${INSTALL_DIR}/atmux" else info "Need sudo to write to ${INSTALL_DIR}" sudo mv "$SRC" "${INSTALL_DIR}/${BIN}" sudo chmod +x "${INSTALL_DIR}/${BIN}" sudo ln -sf "${BIN}" "${INSTALL_DIR}/atmux" fi success "Installed ${INSTALL_DIR}/${BIN}" success "Symlink ${INSTALL_DIR}/atmux → ${BIN}" } # ── summary ───────────────────────────────────────────────────────── print_summary() { echo "" echo " ${GREEN}${BOLD}Installation complete.${RESET}" echo "" echo " ${BOLD}Quick start${RESET}" echo " ${DIM}────────────────────────────────────────${RESET}" echo " ${CYAN}agentmux${RESET} Launch the TUI" echo " ${CYAN}atmux${RESET} Same thing, shorter" echo " ${CYAN}agentmux list${RESET} List tmux sessions" echo " ${CYAN}agentmux new${RESET} ${DIM}myproj${RESET} Create a session" echo " ${CYAN}agentmux attach${RESET} ${DIM}foo${RESET} Attach to session" echo " ${CYAN}agentmux init${RESET} Generate config file" echo "" echo " ${BOLD}Config${RESET}" echo " ${DIM}────────────────────────────────────────${RESET}" echo " ${DIM}~/.config/agentmux/config.toml${RESET}" echo "" echo " ${BOLD}Keybindings (TUI)${RESET}" echo " ${DIM}────────────────────────────────────────${RESET}" echo " ${CYAN}j/k${RESET} navigate ${CYAN}enter${RESET} attach" echo " ${CYAN}n${RESET} new ${CYAN}x${RESET} kill" echo " ${CYAN}r${RESET} rename ${CYAN}/${RESET} search" echo " ${CYAN}p${RESET} projects ${CYAN}?${RESET} help" echo "" echo " ${DIM}Docs: https://github.com/${REPO}${RESET}" echo "" } # ── main ──────────────────────────────────────────────────────────── main() { banner step "Detecting system" OS=$(detect_os) ARCH=$(detect_arch) info "Platform: ${BOLD}${OS}/${ARCH}${RESET}" info "Target: ${INSTALL_DIR}" check_tmux if ! has_cmd tar; then fail "tar is required" fi if install_release "$OS" "$ARCH" 2>/dev/null; then print_summary else install_source print_summary fi } main "$@"