Created
October 26, 2025 09:35
-
-
Save cvcore/fd8a573cf3fc510c5eb12368b2915124 to your computer and use it in GitHub Desktop.
Keep mac awake with native Caffeinate
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #!/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