Skip to content
whynbnbPublic

About

A lightweight macOS menu bar app with googly eyes that follow your cursor, blink on click, and offer quick utilities — open terminal at Finder path, prevent sleep, and more.

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Latest commit

 

History

79 Commits

Folders and files

Repository files navigation

👀 SwiftEyes

A lightweight macOS menu bar app that displays a pair of googly eyes that follow your mouse cursor, blink when you click, and provide quick utilities.

Inspired by Googly Eyes by Sindre Sorhus.

中文文档

Vibe coded with DeepSeek V4.1 Flash / OpenCode

macOS 15+ Apple Silicon

Normal1 Normal2 Normal3

Features

  • Eyes follow mouse — Each eye independently tracks the mouse cursor; when the cursor is between the eyes, they go cross-eyed 👀
  • Blink on click — Global left-click → left eye blinks, global right-click → right eye blinks; clicking the menu bar icon also blinks. Hold to keep closed, release to open
  • Left-click → Context menu — Left-click the menu bar icon for:
    • Current Finder path display (truncated with tooltip) & copy
    • Open terminal
    • Refresh position
    • Prevent Sleep (checkmark when enabled)
    • Launch at Login (checkmark when enabled)
    • Settings...
    • About (with version)
    • Restart — relaunch the app to reclaim memory
    • Quit
  • Right-click left eye → Open Terminal — Right-click the left eye area to launch your preferred terminal at the Finder's current window path. Built-in presets (Terminal, iTerm, Alacritty, Kitty, WezTerm, Ghostty) are launched correctly; a custom command with {path} / {app} placeholders can be set for full control and runs in a login shell
  • Right-click right eye → Prevent Sleep — Right-click the right eye area to toggle macOS sleep prevention (highlight turns red when active); auto-deactivates on screen lock or system sleep; persistence mode configurable in Settings (always maintain / don't maintain on sleep-lock / never maintain)
  • Configurable — Adjust eye size, pupil size, and eye gap via Settings
  • Launch at Login — Toggle from the menu or Settings (requires .app bundle)
  • Minimal resources — ~0% CPU when idle, only 20–40MB memory

Requirements

  • macOS 15.0 (Sequoia) or later
  • Apple Silicon Mac (M-series, arm64) — Intel Macs are not supported
  • Xcode 16+ (for .app bundle build)
  • Swift 6.0+ / SPM (for bare binary build)

Build & Run

Option 1: SPM (Quick Test, No App Bundle)

git clone https://github.com/WHYBBE/SwiftEyes.git
cd SwiftEyes
swift build -c release
.build/release/SwiftEyes

⚠️ SPM produces a bare binary without an app bundle. Launch-at-login and Finder path access via Apple Events will not work in this mode.

Option 2: Xcode (Full .app Bundle, Recommended)

cd SwiftEyes
open SwiftEyes.xcodeproj

Build & run from Xcode (⌘R). Or from the command line:

xcodebuild -project SwiftEyes.xcodeproj -scheme SwiftEyes -configuration Release -derivedDataPath .build/xcode build
open .build/xcode/Build/Products/Release/SwiftEyes.app

To install:

cp -r .build/xcode/Build/Products/Release/SwiftEyes.app /Applications/

Usage

Action Effect
Move mouse Pupils follow cursor direction
Left-click menu bar icon Context menu (and a blink)
Right-click left eye area Open terminal at Finder path
Right-click right eye area Toggle sleep prevention
Left-click anywhere Left eye blinks (hold to keep closed)
Right-click anywhere Right eye blinks (hold to keep closed)
Context menu
↳ Path / Copy Path Show (truncated, tooltip for full) & copy Finder's front window path
↳ Open Terminal Open terminal at Finder path
↳ Refresh Position Recalculate eye centers
↳ Prevent Sleep Toggle sleep prevention (checkmark when enabled; auto-deactivates on lock/sleep)
↳ Launch at Login Toggle launch at login (checkmark when enabled)
↳ Settings... Open settings window
↳ About Show about window with repo link (menu shows version)
↳ Restart Relaunch the app, releasing all memory
↳ Quit Quit app

Visual Indicators

State Left Eye Right Eye
Default Black pupil, white highlight Black pupil, white highlight
Sleep prevention OFF — Black pupil + white highlight
Sleep prevention ON — Black pupil + red highlight
Blinking Closed line Closed line

The left eye is a one-shot action (open terminal), so it has no persistent active state. The right eye's highlight turns red while sleep prevention is active.

Screenshots

Left blink Right blink Prevent Sleep
Left blink Right blink Prevent sleep
Menu Settings
Menu Settings

Settings

Setting Default Range
Eye size 11 6–11 (capped to the menu bar height)
Pupil size 5 2–10
Eye gap 6 0–20
Terminal app Terminal / iTerm / Alacritty / Kitty / WezTerm / Ghostty / Custom Preset or any .app
Custom command (empty) Shell command using {path} / {app} (Custom mode)
Language System System / 中文 / English
Launch at login Off On/Off
Sleep prevention persistence Don't maintain on sleep/lock, maintain on restart Always maintain / Don't maintain on sleep/lock / Never maintain

Each slider has a reset button (↺) to restore its default value. The custom command runs in a login shell, so tools installed via Homebrew are on PATH.

Architecture

Sources/SwiftEyes/
├── SwiftEyesApp.swift              # AppKit @main entry + AppDelegate (no SwiftUI)
├── Info.plist                      # Bundle metadata (LSUIElement, etc.)
├── SwiftEyes.entitlements          # Apple Events entitlement
├── Assets.xcassets/               # App icon & asset catalog
├── StatusBar/
│   └── StatusBarController.swift   # NSStatusItem + GooglyEyesNSView + context menu
├── Views/
│   ├── GooglyEyesView.swift        # NSView-based eye drawing (Core Graphics)
│   ├── SettingsView.swift          # AppKit settings form (Auto Layout)
│   ├── SettingsWindowController.swift  # Settings window management
│   └── AboutWindowController.swift     # About window with repo link
└── Services/
    ├── EyesConfig.swift            # Eye parameters + sleep persist mode
    ├── EyesState.swift             # Blink & active state (event monitors)
    ├── MouseTracker.swift          # Global mouse tracking (throttled)
    ├── TerminalLauncher.swift      # Finder path (osascript) + terminal launch
    ├── SleepPreventer.swift        # IOKit IOPMAssertion (system + display sleep)
    ├── WindowActivationManager.swift  # Reference-counted NSApp activation policy
    ├── L10n.swift                  # Localization (Chinese / English)
    └── Log.swift                   # os.Logger

Key Design Decisions

  • Pure AppKit — A plain NSApplicationDelegate entry point; the status item, windows and the settings form are all AppKit (NSStackView + Auto Layout). No SwiftUI dependency.
  • NSView + Core Graphics — Direct drawing via NSView.draw() with needsDisplay, no diffing or hosting layer overhead
  • Throttled mouse tracking — Global NSEvent monitor at ~12fps with offset deduplication; onOffsetChanged triggers a redraw only when the pupil position actually changes
  • No Combine in the hot path — MouseTracker and EyesState use plain properties + callbacks instead of @Published/ObservableObject
  • Blink handling — Global monitors cover other apps; the menu bar icon click is handled explicitly (global monitors ignore our own events). Blink/active changes repaint immediately so the status item updates even while a menu is tracking
  • Eye size cap — The eye radius is clamped to half the status bar height so it never clips
  • Coalesced layout updates — scheduleUpdateEyeCenters() batches same-runloop coordinate recalculations when dragging settings sliders
  • IOKit dual assertion — PreventUserIdleSystemSleep + PreventUserIdleDisplaySleep held while active; auto-released on screen lock or system sleep; desired state persisted with a configurable persistence mode; always-maintain mode re-arms assertions on wake/unlock
  • Async Finder path — The front Finder window path is fetched off the main thread via osascript and cached (2s TTL); the first Automation prompt never blocks the UI
  • Terminal launch — Known terminals are launched via their bundle binaries (so a new window opens even when the app is already running); a user command template with {path} / {app} can override this and runs in a login shell
  • Dirty-rect partial redraw — Mouse moves invalidate the union of the previous and current pupil rects, not the whole view; full redraw is reserved for blink/config changes
  • hypot for distance — Uses hypot(dx, dy) instead of sqrt(dx*dx + dy*dy)
  • Static CGColor constants — Eye colors pre-converted to CGColor once, avoiding per-frame bridging
  • WindowActivationManager — Reference-counted pushRegular/popRegular so opening both Settings and About won't prematurely flip back to .accessory; keeps the app out of the Dock while letting windows come to the front
  • L10n dictionary — In-memory translation table keyed by language code, no .strings files; language persisted via UserDefaults and defaulting to System

License

MIT

About

A lightweight macOS menu bar app with googly eyes that follow your cursor, blink on click, and offer quick utilities — open terminal at Finder path, prevent sleep, and more.

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages