A macOS menubar port of omarchy-timber
(the QuickShell bar widget): a timber icon in the menubar plus a popover for
managed Git worktrees. Requires the timber CLI and an Xcode toolchain.
- Popover lists existing worktrees as
name@reporows (plus thetimber lsStatus and Todo badges — the[<upstream>]suffix is omitted, and Todo hides when the worktree has no checklist items), with a fuzzy filter field (type worktree@repo).@narrows by repo, e.g.f@scribble. - Typing a qualified
name@repothat does not exist yet offers a+row to create it (timber create --no-herdr), then opens it in Zed. - Row click or Return opens the worktree in Zed (
zed <path>, respecting the CLI new/existing window setting). - Selected rows show Zed / Herdr / delete buttons. Herdr runs
timber herdr space --new(or creates with--herdr) and posts a notification instead of opening Zed. - Delete is two-phase: first click arms (red), second click runs
timber remove. Any list change or selection move disarms. +header button opens atimber repo add <url> [--name]form.- Action failures post a macOS notification.
- Keyboard: Up/Down move, Return activates, Esc closes form / clears filter, Ctrl+U clears.
- Right-click (or Ctrl-click) the menubar icon for an Open at Login toggle and Quit; left-click toggles the popover.
Worktree names and locations come from timber list --json, including custom checkout locations and worktrees created directly with Git for registered repositories.
The app opens the returned path rather than inferring a path from the worktree name.
If the CLI listing fails, the app retains its cached list.
Repository names for creation come from timber repo list -q.
The repository form has URL + Name only, since timber repo add has no --alias flag.
Sources/Timber/TimberApp.swift— AppKit status item (left-click popover, right-click Quit menu), popover UI, action state.Sources/Timber/main.swift— plain AppKit entry point (no SwiftUI App scene, so no stray windows).Sources/Timber/TimberCommand.swift—timber/zedprocesses, enumeration, notifications.Sources/Timber/Resources/— Zed/Herdr action icons, rasterized from upstreamzed.svg/herdr.svg(originals kept inArtwork/; the Herdr glyph was stripped of its light-mode background and whitened so both render as monochrome template images).Sources/TimberModel/TimberModel.swift— pure filter/argv logic ported fromTimberModel.js, UI-independent.Assets/AppIcon.icon/— Icon Composer source for the app icon;mise run buildcompiles it toAssets.carviaactool, andCFBundleIconNameinpackaging/Info.plistpoints at it.Tests/TimberModelTests/— unit tests for the model.Tests/TimberTests/— CLI enumeration and refresh integration tests.
Your xcode-select may point at the Command Line Tools; the mise tasks
pin DEVELOPER_DIR to Xcode explicitly (or run
sudo xcode-select -s /Applications/Xcode.app once).
mise run # builds dist/Timber.app and opens it (recommended)
mise test # swift test (model and CLI integration suites)
mise lint # SwiftLint (strict) + SwiftFormat check
mise format # format Sources and Tests in placemise run ships a real .app bundle (with LSUIElement, so no Dock
icon). That also matters for notifications: UNUserNotificationCenter
traps in a raw binary, so the app posts native notifications only from
the bundle and falls back to osascript display notification otherwise
(e.g. swift run Timber).
Release zips carry a universal (arm64 + x86_64) build with an
ad-hoc signature (no notarization). On first launch Gatekeeper will
refuse a plain double-click; instead right-click (or Ctrl-click)
Timber.app → Open → Open, or clear quarantine once:
xattr -d com.apple.quarantine Timber.app # path to your copy