agtmux-term

March 27, 2026 · View on GitHub

macOS tmux cockpit for AI-agent sessions with a terminal-first embedded Ghostty terminal and a tmux/agent sidebar overlay in the same window.

App Icon

Features

  • Terminal-first main panel — the main terminal starts as a plain shell and stays in the same app window as the sidebar
  • Sidebar overlay — live tmux session list grouped by session/window/pane, with optional agent metadata when the local metadata lane is enabled
  • Retarget current terminal — clicking a session or pane reuses the main terminal in place instead of jumping to a separate Ghostty window
  • Native Ghostty runtime — terminal rendering, input, and IME behavior come from GhosttyKit/libghostty rather than a custom terminal implementation
  • Opt-in local metadata — the bundled agtmux daemon can enrich the sidebar with agent state, health, and conversation titles when enabled
  • SSH targets — connect to remote hosts (SSH/Mosh) and manage their sessions from one window
  • Claude hooks — register/unregister/verify Claude Code hooks directly from the Settings sheet
  • Optional auto-launch — can create a configured tmux session automatically when no local sessions are running
  • Daemon bundled — XPC service can manage the agtmux daemon lifecycle when the local metadata lane is enabled

Install

brew tap g960059/tap
brew install --cask agtmux-term

The daemon (agtmux) is bundled inside the app — no separate install needed. Power users who want the CLI standalone:

brew install agtmux

DMG

Download the latest AgtmuxTerm-vx.y.z.dmg from Releases, open it, and drag AgtmuxTerm.app to Applications.

Note: While Apple Developer signing is still pending, release CI falls back to an unsigned, non-notarized DMG. On first launch, right-click → Open, or run:

xattr -dr com.apple.quarantine /Applications/AgtmuxTerm.app

Once signing secrets are configured, the same workflow returns to the fully notarized path.

Requirements

  • macOS 14 (Sonoma) or later
  • tmux available in PATH (for local sessions)

Current Runtime Default

Normal app launches currently default to the tmux-inventory fast path while the local metadata hot path is being rewritten for performance. That means the main terminal and sidebar session inventory work without starting the bundled agtmux daemon.

If you explicitly want the current local metadata lane during this rewrite, launch with:

AGTMUX_ENABLE_LOCAL_METADATA=1 open -na /Applications/AgtmuxTerm.app

Build from Source

# 1. Clone the repo
git clone https://github.com/g960059/agtmux-term
cd agtmux-term

# 2. Prepare GhosttyKit.xcframework
brew install zig
./scripts/dev/prepare-ghosttykit.sh

# 3. Generate Xcode project
brew install xcodegen
xcodegen generate --spec project.yml

# 4. Install repo-managed git hooks
./scripts/install-git-hooks.sh

# 5. Build agtmux daemon (optional — app falls back to PATH)
cd ../agtmux && cargo build --release
export AGTMUX_BIN=$PWD/target/release/agtmux
cd ../agtmux-term

# 6. Open in Xcode or build via command line
open AgtmuxTerm.xcodeproj
# or: xcodebuild build -scheme AgtmuxTerm -destination "platform=macOS" AGTMUX_BIN=$AGTMUX_BIN

Setup

Claude Code Hooks

For live agent state updates, agtmux hooks into Claude Code's event system when the local metadata lane is enabled:

  1. Open agtmux-term
  2. Go to Settings (gear icon at sidebar bottom)
  3. Click Register under "Claude Hooks"

Or from the CLI:

agtmux setup-hooks

SSH Targets

Add remote hosts to monitor their tmux sessions over SSH/Mosh:

  1. Settings → SSH Targets → Add Target
  2. Enter hostname, username (optional), display name, and transport

Auto-launch Session

Settings → Session → configure the session name to create on startup. Leave empty to keep the default plain-shell startup.

Daemon Resolution

The agtmux binary is resolved in this order:

  1. AGTMUX_BIN env var (explicit override)
  2. AgtmuxTerm.app/Contents/Resources/Tools/agtmux (bundled)
  3. PATH and known directories (~/.cargo/bin, /opt/homebrew/bin, etc.)

Architecture

agtmux-term (Swift macOS tmux cockpit)
├── Sidebar / inventory / diagnostics
├── Main embedded terminal + sidebar overlay
├── Session retarget / restore state
├── AgtmuxDaemonService.xpc        ← XPC service managing daemon lifecycle
├── agtmux daemon (UDS RPC, opt-in) ← Agent state estimation engine
├── tmux (PTY / SSH target truth)  ← Session multiplexer and source of session existence
└── GhosttyKit / libghostty        ← Terminal runtime engine inside the app

The mainline product is a terminal-first embedded Ghostty cockpit with a supplementary tmux/agent sidebar, not separate Ghostty app windows or generic workspace state.

Documentation and Workflow

Durable docs live in:

  • docs/product/ for product intent
  • docs/decisions/ for ADRs
  • docs/runbooks/ for operating procedures
  • docs/research/ for dated, non-authoritative research notes

Active multi-step work lives in docs/changes/<issue-id>-slug/ and is removed from the default branch after merge. Read order for contributors and agents is:

  1. README.md
  2. docs/README.md
  3. docs/product/
  4. docs/decisions/
  5. docs/runbooks/
  6. the active GitHub Issue / PR
  7. the active change pack under docs/changes/, if the work uses one

Normal GitHub flow is:

Discussion -> Issue -> docs/changes/<issue-id>-slug/ -> branch -> PR -> merge -> retire change pack

Release / CI

WorkflowTriggerWhat it does
ci.ymlpush / PRBuild + unit tests
docs-validate.ymlpush / PR / merge queueValidate docs layout, ADR naming, research naming, and change-pack completeness
release.ymlv* tagBuild universal binary → sign/notarize when secrets exist, otherwise fall back to unsigned DMG → GitHub Release; update Homebrew only for signed releases

To release a new version:

git tag v0.2.0
git push origin v0.2.0

The workflow builds a universal (arm64 + x86_64) app with the agtmux daemon bundled. When Apple signing secrets are present it signs, notarizes, creates a DMG, publishes a GitHub Release, and updates the Homebrew tap cask. When those Apple secrets are absent it still publishes a GitHub Release with an unsigned, non-notarized DMG and skips the Homebrew tap update.

prepare-ghosttykit.sh rebuilds from pinned upstream Ghostty v1.3.1 when needed and applies the repo's aggregate Ghostty patch (scripts/patches/ghostty-agtmux.patch) before producing the checked-in GhosttyKit.xcframework. That patch carries the custom OSC bridge, the current embedded-scroll renderer optimizations, and the renderer-owned cadence hooks that the embedded main-terminal path relies on.

Required GitHub secrets:

SecretDescription
APPLE_DEVELOPER_CERTIFICATE_P12Base64-encoded Developer ID .p12 for signed/notarized releases
APPLE_DEVELOPER_CERTIFICATE_PASSWORDPassword for the .p12
APPLE_TEAM_ID10-character Apple Team ID
APPLE_IDApple ID email for notarytool
APPLE_APP_SPECIFIC_PASSWORDApp-specific password for notarytool
HOMEBREW_TAP_TOKENGitHub PAT with write access to g960059/homebrew-tap for signed releases
  • agtmux — Rust daemon that tracks AI agent state via Claude Code hooks, JSONL parsing, and tmux polling
  • Ghostty — Terminal emulator providing libghostty (GPU rendering core)

License

TBD