
Have you ever been mid-presentation, watching a long build compile, or waiting for a large file to download β only for your Mac to decide it's nap time? macOS ships a built-in tool for exactly this: caffeinate. But running it from the terminal every time is clunky.
So I built NoSleep β a tiny macOS menu bar utility that wraps caffeinate in a one-click toggle. No Dock icon. No main window. Just a cup icon in your menu bar.
Features
- One-click toggle β start/stop caffeinate from the menu bar
- Duration presets β 15 min, 30 min, 1 hr, 2 hr, 4 hr, 8 hr, 10 hr, or Indefinite
-
Live countdown β shows remaining time while active (e.g.
2h 34m) - Start at Login β optional LaunchAgent so it auto-starts on boot
-
Prevents display + idle sleep β uses
caffeinate -d -i
The Stack
- Swift 6.0 with strict concurrency
-
SwiftUI +
MenuBarExtra(macOS 13+) - Swift Package Manager β no Xcode project file required
- Minimum target: macOS 14 (Sonoma)
App Entry Point: MenuBarExtra
The entire app lives in the menu bar, which SwiftUI makes surprisingly clean with MenuBarExtra:
@main
struct NoSleepApp: App {
@StateObject private var caffeinateManager = CaffeinateManager()
@StateObject private var loginManager = LoginItemManager()
var body: some Scene {
MenuBarExtra {
MenuBarView(manager: caffeinateManager, loginManager: loginManager)
} label: {
Image(systemName: caffeinateManager.isActive
? "cup.and.saucer.fill"
: "cup.and.saucer")
}
}
}
That's the whole entry point. MenuBarExtra handles all the menu bar plumbing β no NSStatusItem, no AppKit boilerplate. The icon toggles between a filled and outlined cup based on whether caffeinate is running.
Setting LSUIElement: true in Info.plist hides the Dock icon and removes the main window entirely.
Core Logic: CaffeinateManager
The heart of the app is CaffeinateManager β an @MainActor ObservableObject that manages the caffeinate child process and a countdown timer.
Spawning the Process
func start() {
stop()
let proc = Process()
proc.executableURL = URL(fileURLWithPath: "/usr/bin/caffeinate")
var args = ["-d", "-i"]
if selectedDuration != .indefinite {
args += ["-t", "\(selectedDuration.rawValue)"]
remainingSeconds = selectedDuration.rawValue
}
proc.arguments = args
proc.terminationHandler = { [weak self] _ in
Task { @MainActor [weak self] in
self?.handleTermination()
}
}
try? proc.run()
process = proc
isActive = true
if selectedDuration != .indefinite {
timer = Timer.scheduledTimer(withTimeInterval: 1, repeats: true) { [weak self] _ in
Task { @MainActor [weak self] in
self?.tick()
}
}
}
}
A few things worth noting:
-d -i flags β -d prevents the display from sleeping, -i prevents idle sleep. Together they cover the common use cases.
-t <seconds> β when a duration is selected, caffeinate self-terminates after that many seconds. The app also runs a Timer in parallel to track remaining time for the UI.
terminationHandler β if caffeinate exits on its own (duration expired, or the system killed it), this handler fires and cleans up app state. The Task { @MainActor in ... } pattern bridges from the background callback thread into the main actor, which Swift 6 strict concurrency requires.
Duration Options
Durations are a typed enum with raw values in seconds:
enum SleepDuration: Int, CaseIterable, Identifiable, Sendable {
case fifteenMin = 900
case thirtyMin = 1800
case oneHour = 3600
case twoHours = 7200
case fourHours = 14400
case eightHours = 28800
case tenHours = 36000
case indefinite = 0
}
The selected duration is persisted in UserDefaults so the preference survives app restarts.
Login Item: LaunchAgent Plist
Rather than using SMAppService (which requires a sandboxed app), NoSleep writes a LaunchAgent plist directly to ~/Library/LaunchAgents/:
<?xml version="1.0" encoding="UTF-8"?>
<plist version="1.0">
<dict>
<key>Label</key>
<string>com.nosleep.app</string>
<key>ProgramArguments</key>
<array>
<string>/Users/you/Applications/NoSleep.app/Contents/MacOS/NoSleep</string>
</array>
<key>RunAtLoad</key>
<true/>
</dict>
</plist>
This approach works without sandboxing and gives full control over the plist.
Build & Install
The project uses Swift Package Manager β no .xcodeproj needed.
# Build (compiles, bundles, ad-hoc code signs)
./build.sh
# Run
open NoSleep.app
# Install to ~/Applications (optional)
./install.sh
Requirements: Swift 6.0+, Xcode Command Line Tools, macOS 14+.
Source Code
NoSleep is open source under the GPLv3.
GitHub: github.com/sergio-farfan/nosleep
Contributions, issues, and stars are all welcome. If you run into any macOS quirks with caffeinate or MenuBarExtra, feel free to open an issue.
Built with Swift 6 and SwiftUI on macOS Sonoma.
United States
NORTH AMERICA
Related News

Open Harness: The Multi-Panel AI Powerhouse Revolutionizing Developer Workflows
10h ago
Firefox Announces Built-In VPN and Other New Features - and Introduces Its New Mascot
9h ago
50% of Consumers Prefer Brands That Avoid GenAI Content
9h ago
Officer Leaks Location of French Aircraft Carrier With Strava Run
9h ago
CBS News Shutters Radio Service After Nearly a Century
9h ago
