Skip to content

Instantly share code, notes, and snippets.

@cvcore
Created October 26, 2025 09:35
Show Gist options
  • Select an option

  • Save cvcore/fd8a573cf3fc510c5eb12368b2915124 to your computer and use it in GitHub Desktop.

Select an option

Save cvcore/fd8a573cf3fc510c5eb12368b2915124 to your computer and use it in GitHub Desktop.
Keep mac awake with native Caffeinate
#!/usr/bin/swift
// This script adds an icon in the macOS menu bar that controls the active status of caffeinate.
import AppKit
// The AppDelegate class manages the application's lifecycle and UI.
class AppDelegate: NSObject, NSApplicationDelegate {
// UI Elements
private var statusItem: NSStatusItem!
private var menu: NSMenu!
private var toggleMenuItem: NSMenuItem!
// State Management for the caffeinate process
private var caffeinateProcess: Process?
// This method is called once the app has finished launching.
func applicationDidFinishLaunching(_ aNotification: Notification) {
// 1. Create the status bar item.
statusItem = NSStatusBar.system.statusItem(withLength: NSStatusItem.squareLength)
// 2. Create the dropdown menu.
menu = NSMenu()
// 3. Create the menu item that will toggle caffeinate.
// We give it a target (self) and an action (the function to call when clicked).
toggleMenuItem = NSMenuItem(
title: "Deactivate Caffeinate", // Initial state is active
action: #selector(toggleCaffeinate),
keyEquivalent: ""
)
menu.addItem(toggleMenuItem)
// Add a separator for visual clarity.
menu.addItem(NSMenuItem.separator())
// Add the standard "Quit" option.
menu.addItem(
withTitle: "Quit",
action: #selector(NSApplication.terminate(_:)),
keyEquivalent: "q"
)
// Assign the menu to our status bar item.
statusItem.menu = menu
// 4. Start caffeinate by default on launch.
startCaffeinate()
// 5. Set the initial UI state.
updateUI()
}
// This is the function called by our toggle menu item.
@objc func toggleCaffeinate() {
if caffeinateProcess == nil {
// If the process isn't running, start it.
startCaffeinate()
} else {
// If the process is running, stop it.
stopCaffeinate()
}
// After any state change, update the icon and menu text.
updateUI()
}
// Starts the /usr/bin/caffeinate command.
private func startCaffeinate() {
// Ensure we don't start a second process by mistake.
guard caffeinateProcess == nil else { return }
caffeinateProcess = Process()
caffeinateProcess?.executableURL = URL(fileURLWithPath: "/usr/bin/caffeinate")
// The "-d" argument prevents the display from sleeping.
// You could use "-i" to prevent system idle sleep.
caffeinateProcess?.arguments = ["-d"]
do {
try caffeinateProcess?.run()
} catch {
print("Error starting caffeinate: \(error)")
caffeinateProcess = nil // Reset if it fails
}
}
// Stops the running caffeinate process.
private func stopCaffeinate() {
caffeinateProcess?.terminate() // Sends a standard termination signal.
caffeinateProcess = nil // Set to nil to reflect its stopped state.
}
// Updates the status bar icon and menu item text based on the current state.
private func updateUI() {
if caffeinateProcess != nil {
// Caffeinate is RUNNING
statusItem.button?.title = "⚡️"
toggleMenuItem.title = "Deactivate Caffeinate"
} else {
// Caffeinate is STOPPED
statusItem.button?.title = "💤"
toggleMenuItem.title = "Activate Caffeinate"
}
}
// This function is called just before the application quits.
func applicationWillTerminate(_ aNotification: Notification) {
// CRITICAL: Ensure we kill the caffeinate process when the app exits.
// This prevents leaving a "zombie" process running in the background.
print("Quitting and cleaning up caffeinate process...")
stopCaffeinate()
}
}
// --- Application Boilerplate ---
// This code sets up and runs the application.
let app = NSApplication.shared
let delegate = AppDelegate()
app.delegate = delegate
app.run()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment