A native macOS menu bar app for controlling LG webOS TVs.
| Menu bar (compact) | Menu bar (expanded) |
|---|---|
![]() Compact status view |
![]() Expanded controls |
| General settings | Automation settings | Diagnostics |
|---|---|---|
![]() Connection and input preferences |
![]() Wake/sleep and input rules |
![]() Logging and export tools |
- Wake-on-LAN: Wake your TV when your Mac wakes
- Auto Sleep: Turn off TV when Mac sleeps (skips if watching different input)
- Volume Control: Weighted slider with resistance at high volumes
- Input Switching: Quick switch between HDMI, DisplayPort, USB-C inputs
- Screen Control: Turn screen on/off without powering down TV
- PC Mode: Auto-detect and set PC mode for reduced input lag
- Media Keys: Capture volume keys to control TV volume
- Arylic Routing: Route volume controls to an Arylic device in Arylic-enabled builds
- Signed Updates: Sparkle 2 update checks backed by signed GitHub release appcasts
- Newer webOS Support: Prefer secure
wss://<tv>:3001and fall back tows://<tv>:3000 - Onboarding: First-run setup wizard
- macOS 15.0+
- LG webOS TV (2018 or newer recommended)
- TV and Mac on the same network
- Accessibility permission for keyboard media key capture
# Build the project
swift build
# Run tests
swift test
# Build and verify the non-menu bar UX validation app
./script/build_and_run.sh --verify
# Build a development DMG (ad-hoc signed)
./scripts/build-dmg.sh
# Build a local signed release without notarization
./scripts/build-dmg.sh --local-release
# Build a signed and notarized release
./scripts/build-dmg.sh --release
# Generate a signed Sparkle appcast after building a release DMG
./scripts/generate-appcast.sh
# Build a local/private app with Sparkle updater metadata removed
./scripts/build-dmg.sh --disable-updaterNotes:
./scripts/build-dmg.shproduces an ad-hoc signed development build../scripts/build-dmg.sh --local-releaserequires a localDeveloper ID Applicationcertificate../scripts/build-dmg.sh --releaserequires a localDeveloper ID Applicationcertificate plus App Store Connect notary credentials../scripts/generate-appcast.shrequires the Sparkle EdDSA private key fromSPARKLE_ED_PRIVATE_KEY,SPARKLE_PRIVATE_KEY_FILE, or the local Keychain account../scripts/build-dmg.sh --disable-updaterremovesSUFeedURL,SUPublicEDKey,SUEnableAutomaticChecks, andSUAutomaticallyUpdatefrom the staged app bundle.- The DMG layout uses
scripts/assets/dmg-background.pngand positions the app next to an Applications symlink for drag-and-drop installation. ./script/build_and_run.sh --screenshotwrites a UX validation screenshot toscreenshots/.
- Download the latest DMG from Releases
- Open the DMG and drag LGTVMenuBar to Applications
- Launch LGTVMenuBar
- Follow the onboarding wizard to connect your TV
- Grant Accessibility permission when prompted (for media key capture)
- Use Settings > General > Updates to check for signed GitHub releases
Official GitHub releases are Developer ID signed and notarized, so Gatekeeper should allow a normal first launch after you drag the app into Applications.
Official releases include Sparkle update metadata and can check the signed GitHub release appcast. Local/private builds made with ./scripts/build-dmg.sh --disable-updater remove that metadata so they do not self-update.
If you build the app locally with the default ./scripts/build-dmg.sh, the output is only ad-hoc signed for development. That build is not notarized, and macOS may treat it differently from the official release artifacts.
For local ad-hoc builds:
- Re-grant Accessibility permission after each rebuild.
- If Gatekeeper still blocks the app, open the bundle from Finder once with Open to confirm the local build.
On first launch, the onboarding wizard will guide you through:
- TV Discovery: Enter your TV's IP address and MAC address
- TV Pairing: Accept the pairing prompt on your TV
- Preferences: Configure wake/sleep behavior and preferred input
- Permissions: Grant necessary system permissions
- Swift 6.0 with strict concurrency
- SwiftUI for the menu bar popover UI
- WebSocket communication with LG webOS API, secure-first on newer TVs
- Sparkle 2 for signed app updates
- Keychain for secure pairing key storage
- Swift Testing for unit and integration coverage
Sources/LGTVMenuBar/
├── Models/ # Data models and enums
├── Protocols/ # Protocol definitions
├── Services/ # Business logic and API clients
└── Views/ # SwiftUI views
Tests/LGTVMenuBarTests/
├── Mocks/ # Mock implementations for testing
├── Services/ # Service integration tests
└── Unit/ # Unit tests
script/ # Local run and UX validation helpers
scripts/ # DMG packaging, notarization, and appcast scripts
MIT License - see LICENSE for details.




