Skip to content

wonsss/ClaudeBar

Repository files navigation

ClaudeBar

한국어

A macOS menu bar app that monitors Claude Code sessions running in Ghostty in real time.

  • Menu bar: braille spinner + live processing/total count (e.g. ⠋ 2/19)
  • Dashboard window: Processing / Idle sections, per-session title · project · last-input time ("12m ago")
  • Click a card → jump to its Ghostty tab
  • Launch-at-login toggle

🧪 Beta (v0.1.1) · ⚠️ Ghostty only — iTerm2, Terminal.app, kitty, WezTerm, etc. are not supported (see "How it works").

ClaudeBar

Requirements

  • macOS 13 (Ventura) or later
  • Ghostty terminal
  • Claude Code sessions running in Ghostty tabs

Install

DMG (recommended)

Download the latest ClaudeBar-x.y.z.dmg from Releases and drag ClaudeBar.app into Applications.

It is signed & notarized, so it opens without a Gatekeeper warning. If it ever gets blocked, right-click → Open, or:

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

Build from source

git clone https://github.com/wonsss/ClaudeBar.git
cd ClaudeBar
./build.sh          # build + sign + install to /Applications

Permissions

On first run you'll get a "ClaudeBar wants to control Ghostty" automation prompt → Allow. If denied: System Settings > Privacy & Security > Automation > ClaudeBar → Ghostty. Reset if it gets stuck: tccutil reset AppleEvents io.github.wonsss.claudebar

Screen Recording permission is not needed. ClaudeBar only reads tab titles & working directories — never terminal contents/scrollback (Ghostty doesn't expose them) — and makes no network calls.

How it works

Data Source
Session list · title · state · tab location (for jump) Ghostty tabs (AppleScript). Title = Claude's generated summary
Processing vs idle Tab-title glyph — braille spinner ⠋⠙⠹… (U+2800–U+28FF) = processing, (U+2733) = idle
Last-input time ~/.claude/history.jsonl (last input per sessionId)
Live-session enrichment ~/.claude/sessions/<pid>.json + pgrep -x claude
  • Jump: focuses the tab by its windowID/tabIndex, then brings Ghostty forward via AppKit NSRunningApplication.activate (a reliable path for an accessory app to foreground another app).
  • Time matching: there is no stable key linking a session to a tab, so the last-input time is matched best-effort by keyword overlap between the tab title and the session's first prompt (omitted when no confident match).
  • AppleScript enumeration runs on a dedicated background thread with its own run loop, so the menu bar UI never blocks.

⚠️ Version dependency (important)

ClaudeBar relies on undocumented, internal behavior of Claude Code and Ghostty:

  • Claude Code: the file formats of ~/.claude/sessions/<pid>.json and ~/.claude/history.jsonl, and the status glyphs Claude writes into the tab title (braille spinner / ).
  • Ghostty: its AppleScript dictionary (window/tab/terminal, focus) and tab-group-… window IDs.

These are not public APIs, so an update to either app may change the format/glyphs and break ClaudeBar.

Verified against: Claude Code 2.1.x, Ghostty (latest as of 2026-06). If the list goes empty or jumping stops working after an upgrade, ClaudeBar may need an update — please open an issue.

Security

Item Status
Network None — zero networking code. All data stays in local memory
File writes None — no disk writes other than osascript stdin
Permissions Automation (→ Ghostty) only. No screen recording / accessibility / full-disk
Subprocesses /usr/bin/pgrep, /usr/bin/osascript — absolute paths, fixed args
AppleScript injection windowID validated against ^[A-Za-z0-9-]+$; tabIndex is a positive integer
Code signing Developer ID signed + notarized (Release DMG)

Note: prompt text from history.jsonl is read and shown in the dashboard (your own data, local only, never transmitted) — it may be visible during screen sharing/recording.

Limitations

  • Ghostty only — other terminals show an empty list.
  • Last-input time is best-effort; when several same-state sessions share a project, times may be attributed to a sibling session.

Project structure

File Role
Session.swift Session model
GhosttyScanner.swift Tab enumeration (title/state/cwd/windowID) + jump
SessionRegistry.swift · HistoryIndex.swift Read ~/.claude registry & history (time enrichment)
Matcher.swift Attach time by keyword-matching tabs ↔ history
AppleScriptRunner.swift Run NSAppleScript on a dedicated run-loop thread
SpinnerClock.swift · RelativeTime.swift Menu bar spinner · relative time
SessionStore.swift Polling + @Published state
DashboardView.swift Popover + dashboard window UI
LoginItem.swift · ClaudeBarApp.swift Login item · app entry point

Development

swift build                          # debug build
./build.sh                           # release build + sign + install
./notarize.sh --store-credentials    # one-time: store notarization credentials (TTY)
./create-dmg.sh                      # build a notarized DMG

Releases are cut manually:

./create-dmg.sh
gh release create vX.Y.Z ClaudeBar-X.Y.Z.dmg --title "ClaudeBar X.Y.Z" --prerelease -F CHANGELOG.md

License

MIT © 2026 Wonseok Jang

About

Ghostty 메뉴바에서 Claude Code 세션을 실시간 모니터링 (점자 스피너 · 마지막 입력 시각 · 탭 점프)

Topics

Resources

License

Stars

Watchers

Forks

Packages

 
 
 

Contributors