Hangar keeps every local server — your web app, API, worker, docs site — in one window. Register a command once, then start, stop, and watch its logs without juggling terminal tabs. When a server is done, Hangar shuts down the whole process tree, so nothing is left squatting on port 3000.
- One home for every server. Register a name, working directory, shell command, and optional environment variables. Start and stop each one with a click.
- Live logs. stdout and stderr stream straight into the app, per server — no terminal tabs to hunt through.
- Clean shutdown. Stopping a server signals the entire process tree (
SIGTERM, thenSIGKILLafter a short grace period). No orphanednode/vite/pythonprocesses holding your ports. - URL auto-detect. Hangar watches log output for
http://localhost:PORTand gives you a one-click button to open it in your browser. - Your real shell. Commands run through a login shell (
zsh -ilc), sonvm,pyenv,asdf, and yourPATHresolve exactly like they do in Terminal. - Menu bar access. See and toggle every server from the menu bar without opening the main window.
- Status at a glance. Stopped, Starting, Running, or Crashed (with exit code) — shown with a color-coded dot.
- Liquid Glass UI. Light, dark, or system appearance, with six pastel background tints.
- Automatic updates. Hangar checks for new releases with Sparkle and installs them in place — no hunting for DMGs.
- Download the latest
Hangar-x.y.z.dmgfrom the Releases page. - Open the DMG and drag Hangar into Applications.
- Launch it. The app is signed with a Developer ID and notarized by Apple, so it opens with no Gatekeeper warnings.
Requires macOS 14 (Sonoma) or later.
After the first launch Hangar keeps itself up to date with Sparkle: it checks for new versions automatically (with your permission) and you can trigger a check anytime from Hangar ▸ Check for Updates… or Settings ▸ About.
Hangar uses XcodeGen to generate its Xcode project from project.yml.
brew install xcodegen # one-time, if you don't have it
xcodegen generate # regenerates Hangar.xcodeproj
open Hangar.xcodeproj # build & run with ⌘RTo produce a signed, notarized DMG (requires a Developer ID Application certificate and a notarytool keychain profile):
./scripts/release.sh # full build → sign → notarize → DMG → appcast
./scripts/release.sh --skip-notarize # signed only, no notarizationThe script also writes dist/appcast.xml, the Sparkle update feed. To ship a release:
- Bump
CFBundleShortVersionStringandCFBundleVersioninproject.yml— Sparkle detects updates by the integerCFBundleVersion, so it must increase every release. - Run
xcodegen generateso the project picks up the new version. - Run
./scripts/release.sh— it builds, signs, notarizes, and producesHangar-x.y.z.dmgplusappcast.xmlindist/. - Create a GitHub release tagged
vx.y.zand upload both files as assets — the script prints the exactgh release createcommand.
Signing the appcast needs the Sparkle EdDSA private key in your login keychain (created once with Sparkle's generate_keys); its public half is pinned as SUPublicEDKey in project.yml.
Hangar is a native SwiftUI app whose only external dependency is Sparkle, which powers in-app updates. Each registered server gets a ServerRunner that launches the command as a child process, pipes its output into a log buffer, and tracks its lifecycle. There is no daemon and no background service — when you quit Hangar, every server it started is terminated with it.
MIT © Himanshu Kumar