A macOS menu bar teleprompter app designed to live near the notch. Click the menu bar icon to reveal a floating panel with smooth auto-scrolling text.
- Floating panel anchored below the menu bar / notch
- 60fps smooth auto-scroll with adjustable speed
- 5 color themes
- Mirror mode (for teleprompter glass setups)
- Edit mode — type or paste your script directly in the app
- Drag and drop
.txtfile import - Keyboard shortcuts for hands-free control
- Persistent settings — speed, font size, theme, and script survive restarts
- No Dock icon — lives entirely in the menu bar
Coming soon
- macOS 13.0 (Ventura) or later
- Xcode 15+ (for building from source)
- XcodeGen (only needed if regenerating the
.xcodeproj)
-
Clone the repo:
git clone https://github.com/raajpatkar/telenotch.git cd telenotch -
Open the project in Xcode:
open Telenotch.xcodeproj
-
Select the Telenotch scheme, then press Cmd+R to build and run.
The app will appear in your menu bar. There is no Dock icon — this is intentional (LSUIElement=YES).
xcodebuild -project Telenotch.xcodeproj \
-scheme Telenotch \
build \
CODE_SIGNING_REQUIRED=NO \
CODE_SIGN_IDENTITY=""If you edit project.yml (the XcodeGen spec), regenerate the .xcodeproj with:
xcodegen generateInstall XcodeGen via Homebrew if you don't have it:
brew install xcodegen- Click the text icon in the menu bar to open the panel.
- Click Edit to enter your script, then click Done when ready.
- Press Space or click Play to start scrolling.
- Drag and drop a
.txtfile onto the panel to load a script. - Click the icon again (or press Esc) to close the panel.
| Key | Action |
|---|---|
Space |
Play / Pause |
↑ |
Increase speed |
↓ |
Decrease speed |
R |
Reset scroll to top |
Esc |
Close panel |
Shortcuts are active whenever the panel is visible. They are disabled while in Edit mode so normal text input works.
| File | Role |
|---|---|
main.swift |
NSApplication entry point |
AppDelegate.swift |
Status item, panel lifecycle, keyboard event monitor |
TelenotchPanel.swift |
NSPanel subclass — borderless, floating, always-on-top |
PrompterState.swift |
ObservableObject — all app state, 60fps timer, UserDefaults persistence |
Theme.swift |
enum Theme — 5 color themes |
TeleprompterView.swift |
Root SwiftUI view hosted in the panel |
ControlBar.swift |
Top control strip — buttons and sliders |
ScrollingTextView.swift |
Manual-offset scroll view with gradient fades and mirror support |
Info.plist |
Bundle config — LSUIElement=YES suppresses Dock icon |
project.yml |
XcodeGen spec |
AppDelegate-first — no SwiftUI @main. main.swift boots NSApplication and sets AppDelegate as delegate.
PrompterState is the single source of truth. It owns the 60fps Timer, all @Published properties, and UserDefaults persistence. It is injected into all SwiftUI views as .environmentObject.
Scrolling is manual — no ScrollView. A Text view inside a .clipped() container uses .offset(y: -scrollOffset). A PreferenceKey (TextHeightKey) bubbles content height up from a GeometryReader so the max scroll offset can be computed correctly.
Keyboard shortcuts use NSEvent.addLocalMonitorForEvents(matching: .keyDown). The monitor is installed on panel show and removed on panel hide to avoid leaks.
MIT