Skip to content
robgoughPublic

About

Resources

Stars

2 stars

Watchers

0 watching

Forks

Repository files navigation

Belfry

A native macOS + iPadOS front-end for tmux: a sidebar of hosts → sessions → windows you click to switch, with the selected session's live terminal filling the rest. Works against your local tmux server and remote machines over SSH — and shows live Claude Code status badges so you can see at a glance which session is working and which one is waiting on you.

Your sessions live in tmux, exactly as they always have. Belfry attaches; it never owns them. Quit the app, kill the network, switch devices — everything keeps running.

Belfry on macOS

Features

  • Host → session → window tree, driven by tmux control mode (tmux -C). On tmux ≥ 3.2 updates arrive by server push (refresh-client -B format subscriptions) — near-zero idle traffic and wakeups; older servers fall back to a light poll.
  • Instant switching. Every visited session keeps a warm, attached surface; changing sessions is a visibility toggle, not a re-attach.
  • Coding-agent status. Live Working / Waiting / Idle / Error states for Claude Code, Codex, OpenCode, pi and oh-my-pi, per window and in an Agents section listing every agent with its task, current tool, uncommitted +/− and time in state. Powered by optional status hooks you can install per-host from the UI (they stamp tmux pane options; removal is one click and only touches Belfry's tagged entries). On macOS the Dock badge counts agents waiting for your input.
  • Send files to Claude Code (macOS). Drag an image — or any file — onto the terminal, or use the paperclip toolbar button: the file's path is pasted into the prompt, and on SSH hosts the file is first uploaded over the existing connection so the remote Claude Code can read it.
  • Battery-conscious by design. Hidden surfaces absorb output without rendering, animations run in the render server, and the idle app measures ~0% CPU.
  • macOS: terminals render with libghostty (via a vendored Termini); your Ghostty colour theme is picked up automatically (Catppuccin Mocha fallback). The local tmux server is started under launchd, so even force-quitting Belfry can't take your sessions down.
  • iPadOS/iOS: terminals render with SwiftTerm over SwiftNIO SSH (no processes to spawn on iOS). Touch scrollback (swipe = tmux copy-mode wheel), a key bar with esc/ctrl/arrows, bundled Maple Mono NF for nerd-font glyphs, credentials in the Keychain, and a background grace period so quick app switches keep connections alive — longer absences reconnect and resync instantly on return.

Installing

Install with Homebrew:

brew tap robgough/belfry
brew install --cask belfry

(If you run Homebrew with HOMEBREW_REQUIRE_TAP_TRUST set, run brew trust robgough/belfry after tapping — it refuses untrusted third-party taps until then.)

Prefer a direct download? A notarized, universal Belfry.app (macOS 14+) is on the releases page — unzip and drag to Applications. Either way the app keeps itself current via Sparkle; changes per release are in CHANGELOG.md.

Building

macOS (14+)

Requires tmux (brew install tmux) and Xcode's toolchain.

swift build                     # debug binary
scripts/make_app.sh release     # assembles + ad-hoc signs Belfry.app
open Belfry.app

iPadOS / iOS (17+)

Requires xcodegen (brew install xcodegen).

xcodegen generate               # produces BelfryiOS.xcodeproj (gitignored)
open BelfryiOS.xcodeproj        # set your team under Signing, then run

Add hosts in-app: hostname, user, port, and either a password or an unencrypted ed25519 private key (paste the PEM; generate a dedicated one with ssh-keygen -t ed25519). Secrets are stored in the Keychain, never in the hosts file. The remote end needs sshd and tmux — and if you want your dev machines reachable from anywhere, Tailscale pairs beautifully with this.

Cutting a release — the notarized macOS zip (with the Sparkle appcast) or an iOS TestFlight build: see RELEASING.md.

Architecture, briefly

Each host gets two planes. The control plane is a tmux -C client attached to a hidden per-launch session — it feeds the sidebar and issues actions, and never sizes your real sessions. The data plane is one terminal surface per visited session running tmux attach. Both ride a per-platform transport behind a small seam: macOS forks PTYs (and drives the system ssh with connection sharing and a native askpass dialog); iOS speaks SSH in-process via SwiftNIO, running tmux as exec channels.

vendor/Termini is vendored (MIT) with local patches documented in LOCAL_PATCHES.md — most are on their way upstream.

License

MIT © Rob Gough — see LICENSE.

Bundled third parties: Termini (MIT), Ghostty/GhosttyKit (MIT), SwiftTerm (MIT), and Maple Mono NF (SIL OFL 1.1).

About

Resources

Stars

2 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages