← Back to all projects

LEARN MACOS MONITORING APIS

Modern productivity and developer tools often rely on understanding user context. They passively observe activity to provide insights, automate workflows, or capture valuable information. Building these tools requires a deep dive into macOS frameworks that are often poorly documented and guarded by strict privacy permissions.

Learn macOS Monitoring APIs: From Zero to Activity Tracking Master

Goal: Deeply understand the macOS APIs that allow applications like RescueTime and Pieces to monitor system activity, from the current application and window title to keyboard events and clipboard content.


Why Learn macOS Monitoring?

Modern productivity and developer tools often rely on understanding user context. They passively observe activity to provide insights, automate workflows, or capture valuable information. Building these tools requires a deep dive into macOS frameworks that are often poorly documented and guarded by strict privacy permissions.

After completing these projects, you will:

  • Know how to identify the active application and its windows.
  • Use the Accessibility API to read UI elements from other apps.
  • Monitor global keyboard and mouse events securely.
  • Capture clipboard content.
  • Understand the powerful (and sensitive) nature of system-wide monitoring and the importance of user privacy.

Core Concept Analysis

macOS provides several distinct APIs for observing system state. Each is designed for a specific purpose and requires explicit user consent.

โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
โ”‚                                 Your Application                               โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
                                        โ”‚
     โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ผโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
     โ”‚                                  โ”‚                                  โ”‚
     โ–ผ                                  โ–ผ                                  โ–ผ
โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”      โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”      โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
โ”‚ NSWorkspace        โ”‚      โ”‚ Accessibility API (AX)   โ”‚      โ”‚ CoreGraphics Event Tapsโ”‚
โ”‚                    โ”‚      โ”‚                          โ”‚      โ”‚                        โ”‚
โ”‚ โ€ข Get active app   โ”‚      โ”‚ โ€ข Read window titles     โ”‚      โ”‚ โ€ข Global key/mouse     โ”‚
โ”‚ โ€ข List running appsโ”‚      โ”‚ โ€ข Get UI element values  โ”‚      โ”‚   listeners (e.g. Cmd+C) โ”‚
โ”‚                    โ”‚      โ”‚ โ€ข Get browser URLs       โ”‚      โ”‚                        โ”‚
โ”‚ Permission: None   โ”‚      โ”‚                          โ”‚      โ”‚ Permission:            โ”‚
โ”‚ (App Sandbox)      โ”‚      โ”‚ Permission: Accessibilityโ”‚      โ”‚ Input Monitoring       โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜      โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜      โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
             โ”‚                        โ”‚                                  โ”‚
             โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”                  โ”‚
                             โ”‚                        โ”‚                  โ”‚
                             โ–ผ                        โ–ผ                  โ–ผ
              โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”  โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”  โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
              โ”‚ NSPasteboard           โ”‚  โ”‚ FSEvents / FileProviderโ”‚  โ”‚ EndpointSecurity   โ”‚
              โ”‚                        โ”‚  โ”‚                        โ”‚  โ”‚                    โ”‚
              โ”‚ โ€ข Read clipboard       โ”‚  โ”‚ โ€ข Watch for file       โ”‚  โ”‚ โ€ข System-wide      โ”‚
              โ”‚   content              โ”‚  โ”‚   changes              โ”‚  โ”‚   process/file/net โ”‚
              โ”‚ โ€ข Get change count     โ”‚  โ”‚                        โ”‚  โ”‚   events           โ”‚
              โ”‚                        โ”‚  โ”‚ Permission:            โ”‚  โ”‚                    โ”‚
              โ”‚ Permission: None       โ”‚  โ”‚ Full Disk Access (often) โ”‚  โ”‚ Permission: Specialโ”‚
              โ”‚                        โ”‚  โ”‚                        โ”‚  โ”‚ Entitlement (Apple)โ”‚
              โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜  โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜  โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜


Project List

These projects are designed to be built in order, as each one introduces a new core concept and often a new user permission youโ€™ll need to handle. The primary language is Swift, the modern standard for macOS development.


Project 1: Active App Menu Bar Ticker

  • File: LEARN_MACOS_MONITORING_APIS.md
  • Main Programming Language: Swift
  • Alternative Programming Languages: Objective-C
  • Coolness Level: Level 2: Practical but Forgettable
  • Business Potential: 1. The โ€œResume Goldโ€
  • Difficulty: Level 1: Beginner
  • Knowledge Area: macOS App Development / AppKit
  • Software or Tool: Xcode
  • Main Book: โ€œBeginning iPhone Development with Swiftโ€ by David Mark, Jack Nutting (provides a good foundation for Swift and Appleโ€™s development paradigm, though itโ€™s iOS-focused)

What youโ€™ll build: A simple macOS application that lives in the menu bar. Its icon will change to the icon of the currently active application, and the tooltip will show the active applicationโ€™s name.

Why it teaches monitoring: This is the โ€œhello worldโ€ of activity monitoring. It introduces NSWorkspace, the simplest and safest API for getting system-state information, and teaches the basics of building a background macOS utility.

Core challenges youโ€™ll face:

  • Creating a menu bar app โ†’ maps to using NSStatusItem
  • Getting the active application โ†’ maps to using NSWorkspace.shared.frontmostApplication
  • Setting up a timer โ†’ maps to using Timer to poll for changes periodically
  • Handling application icons โ†’ maps to working with NSRunningApplication and NSImage

Key Concepts:

Difficulty: Beginner Time estimate: Weekend Prerequisites: Basic Swift knowledge, Xcode installed.

Real world outcome: A new icon appears in your macOS menu bar. As you switch between applications (e.g., from Finder to Chrome), the icon in the menu bar updates in real-time to match the active app.

Implementation Hints: In your AppDelegate or main app controller:

  1. Create an NSStatusItem in the system status bar.
  2. Set up a Timer to fire every 1 or 2 seconds.
  3. In the timerโ€™s action method, get the frontmostApplication from NSWorkspace.shared.
  4. This NSRunningApplication object has properties like localizedName and icon.
  5. Update the NSStatusItemโ€™s button with the new icon and its toolTip with the name.

Learning milestones:

  1. A menu bar item appears.
  2. The name of the active app can be printed to the console.
  3. The menu bar icon updates when the active app changes.
  4. The app is sandboxed and runs correctly.

Project 2: Window Title Logger

  • File: LEARN_MACOS_MONITORING_APIS.md
  • Main Programming Language: Swift
  • Alternative Programming Languages: Objective-C
  • Coolness Level: Level 3: Genuinely Clever
  • Business Potential: 2. The โ€œMicro-SaaS / Pro Toolโ€
  • Difficulty: Level 3: Advanced
  • Knowledge Area: Accessibility API / Inter-App Communication
  • Software or Tool: Xcode
  • Main Book: N/A (relies on documentation and articles)

What youโ€™ll build: A background utility that logs the window title of the active application every time it changes. For example, it will log the subject of an email, the name of a document in Word, or the title of a webpage.

Why it teaches monitoring: This is the core technique used by apps like RescueTime. It forces you to learn the Accessibility API, a powerful but complex framework that lets your app inspect and control other applications. It also introduces the critical concept of requesting user permissions.

Core challenges youโ€™ll face:

  • Requesting Accessibility permissions โ†’ maps to prompting the user and checking status
  • Getting the frontmost window of another app โ†’ maps to using AXUIElement to reference another appโ€™s UI
  • Reading the title attribute โ†’ maps to querying accessibility attributes of a UI element
  • Handling permissions denial gracefully โ†’ maps to guiding the user to System Settings

Resources for key challenges:

Key Concepts:

  • Accessibility (AX) API: The framework for inspecting and controlling other apps.
  • AXUIElement: An accessibility object representing a UI element in another process.
  • Info.plist Privacy Strings: The NSPrivacyAccessedAPICategoryAccessibility key is required to explain why you need the permission.

Difficulty: Advanced Time estimate: 1-2 weeks Prerequisites: Project 1, understanding of Swift optionals and error handling.

Real world outcome: Youโ€™ll have a text file (activity_log.txt) that contains a timestamped list of every window youโ€™ve focused on, providing a raw data source for your computer activity.

Implementation Hints:

  1. First, you must check for and request accessibility permissions using AXIsProcessTrustedWithOptions. This will show a system prompt to the user.
  2. Get the pid (process identifier) of the frontmostApplication.
  3. Create an AXUIElement representing that application using AXUIElementCreateApplication(pid).
  4. From the application element, get the value of the kAXFocusedWindowAttribute.
  5. This gives you another AXUIElement for the window. From this, get the value of kAXTitleAttribute.
  6. This process is โ€œfailableโ€ at every step, so use robust error checking.
  7. Combine this with the timer from Project 1 to poll for the title.

Learning milestones:

  1. Your app correctly prompts for Accessibility permissions.
  2. You can get the window title of your own app.
  3. You can get the window title of another app (e.g., TextEdit).
  4. The app logs titles as you switch between different windows and applications.

Project 3: Global Copy & Paste Logger

  • File: LEARN_MACOS_MONITORING_APIS.md
  • Main Programming Language: Swift
  • Alternative Programming Languages: Objective-C, Python (with pyobjc)
  • Coolness Level: Level 4: Hardcore Tech Flex
  • Business Potential: 3. The โ€œService & Supportโ€ Model
  • Difficulty: Level 3: Advanced
  • Knowledge Area: Event Taps / Pasteboard API
  • Software or Tool: Xcode
  • Main Book: N/A

What youโ€™ll build: A background tool that detects every time the user copies text (Cmd+C) and logs that text to a file. This mimics a core feature of Pieces.app.

Why it teaches monitoring: This teaches two distinct but related concepts:

  1. How to listen for global keyboard events using CoreGraphics Event Taps.
  2. How to read data from the systemโ€™s shared clipboard (NSPasteboard).

Core challenges youโ€™ll face:

  • Creating a CGEventTap โ†’ maps to a low-level C API for intercepting system-wide events
  • Requesting Input Monitoring permissions โ†’ maps to another critical privacy permission
  • Interpreting keyboard flags โ†’ maps to detecting if the Command key is held down
  • Reading from NSPasteboard โ†’ maps to checking for text content and reading it

Resources for key challenges:

Key Concepts:

  • CGEventTapCreate: The C function to create an event listener.
  • Input Monitoring Permission: Required for event taps. Your Info.plist needs NSPrivacyAccessedAPICategoryInputMonitoring.
  • NSPasteboard: The class for interacting with the clipboard.

Difficulty: Advanced Time estimate: 1-2 weeks Prerequisites: Project 1, some comfort with C-style APIs in Swift.

Real world outcome: A log file (clipboard_history.txt) containing every piece of text youโ€™ve copied. A powerful (and dangerous!) tool that makes the privacy implications of this work very clear.

Implementation Hints:

Part 1: The Event Tap

  1. Set up a CGEventTap for the keyDown event. This requires a C-style callback function.
  2. In the callback, check the eventโ€™s keyboard flags to see if the command flag is set.
  3. Check if the keycode is for the โ€˜cโ€™ key.
  4. If Cmd+C is detected, post a Notification using NotificationCenter.

Part 2: The Pasteboard Listener

  1. In another part of your app, subscribe to the notification from Part 1.
  2. When the notification is received, access NSPasteboard.general.
  3. Check if the pasteboard contains strings (canReadObjects(forClasses: [NSString.self])).
  4. If so, read the string content using string(forType: .string).
  5. Log the content.

This two-part approach decouples the low-level event tap from the higher-level pasteboard logic.

Learning milestones:

  1. Your app prompts for Input Monitoring permissions.
  2. A log message appears in the console every time any key is pressed.
  3. The log is filtered to only show when Cmd+C is pressed.
  4. The copied text is successfully read from the pasteboard and saved.

Project 4: Downloads Folder Watcher

  • File: LEARN_MACOS_MONITORING_APIS.md
  • Main Programming Language: Swift
  • Alternative Programming Languages: C
  • Coolness Level: Level 2: Practical but Forgettable
  • Business Potential: 2. The โ€œMicro-SaaS / Pro Toolโ€
  • Difficulty: Level 2: Intermediate
  • Knowledge Area: File System APIs
  • Software or Tool: Xcode
  • Main Book: โ€œAdvanced Programming in the UNIX Environmentโ€ by Stevens & Rago (for general filesystem concepts).

What youโ€™ll build: A utility that monitors the ~/Downloads directory and sends a user notification whenever a new file appears.

Why it teaches monitoring: It teaches you how to monitor file system activity efficiently, without manually polling folder contents. This is fundamental for any app that needs to react to file changes (e.g., Dropbox, Hazel, image optimizers).

Core challenges youโ€™ll face:

  • Using the FSEvents API โ†’ maps to another C-based API for file system notifications
  • Setting up a stream โ†’ maps to defining the path and latency for monitoring
  • Parsing event flags โ†’ maps to determining if an event is a file creation, modification, etc.
  • Handling App Sandbox โ†’ maps to understanding which directories your app can access

Key Concepts:

  • FSEvents API: The low-level C API for getting file system notifications.
  • FSEventStreamCreate: The core function to start monitoring a path.
  • User Notifications: The UserNotifications framework for displaying alerts to the user.

Difficulty: Intermediate Time estimate: 1 week Prerequisites: Project 1.

Real world outcome: When a file finishes downloading in your browser, a notification immediately appears on your screen: โ€œNew file detected: downloaded-image.pngโ€.

Implementation Hints:

  1. Create an FSEventStream that watches the path to ~/Downloads.
  2. Youโ€™ll provide a callback function that the system will execute when events occur.
  3. The callback receives the path(s) that changed and flags indicating the type of change.
  4. In your callback, iterate through the events. If you see an ItemCreated flag, youโ€™ve found a new file.
  5. To show a notification, you first need to request permission using UNUserNotificationCenter.current().requestAuthorization.
  6. Then, construct and submit a UNNotificationRequest.

Learning milestones:

  1. An FSEventStream is successfully created and started.
  2. The callback fires when you manually create a file in the Downloads folder.
  3. Your app can distinguish between file creation and modification events.
  4. A user notification is displayed for new files.

Project 5: The Ultimate Challenge - Endpoint Security Process Monitor

  • File: LEARN_MACOS_MONITORING_APIS.md
  • Main Programming Language: Swift/C
  • Alternative Programming Languages: N/A (requires tight OS integration)
  • Coolness Level: Level 5: Pure Magic (Super Cool)
  • Business Potential: 4. The โ€œOpen Coreโ€ Infrastructure
  • Difficulty: Level 5: Master
  • Knowledge Area: System Internals / Security
  • Software or Tool: Xcode, Apple Developer Account
  • Main Book: โ€œmacOS Internalsโ€ (online resources are more current)

What youโ€™ll build: A command-line tool that logs every time a new process starts running on your system, anywhere. It will show the process name and its PID.

Why it teaches monitoring: This is the deepest level of monitoring possible on modern macOS without writing a kernel extension. It introduces the Endpoint Security framework, the official tool for antivirus and EDR (Endpoint Detection and Response) software.

Core challenges youโ€™ll face:

  • Requesting a special entitlement โ†’ maps to you must apply to Apple for permission to use this framework
  • Creating an Endpoint Security client โ†’ maps to subscribing to system-wide event streams like process execution
  • Handling C structs and pointers extensively โ†’ maps to these are low-level C APIs with no Swift overlays
  • Building a System Extension โ†’ maps to the modern way to deploy background daemons that use this framework

Resources for key challenges:

Key Concepts:

  • Endpoint Security: The framework for system-wide security monitoring.
  • System Extension: The modern replacement for kernel extensions.
  • Entitlements: Special permissions granted by Apple that are baked into your appโ€™s signature.

Difficulty: Master Time estimate: 1 month+ Prerequisites: Strong C and Swift skills, understanding of system architecture, and a paid Apple Developer account.

Real world outcome: When you run your tool, youโ€™ll see a real-time stream of every process starting on your Mac, from the tiny background daemons to the applications you launch.

$ sudo ./process_monitor
EXEC: /bin/ls (PID: 50123)
EXEC: /usr/bin/grep (PID: 50124)
EXEC: /Applications/Calculator.app/Contents/MacOS/Calculator (PID: 50126)
...

Implementation Hints:

  1. This is a huge undertaking. The first step is to apply for the Endpoint Security entitlement from Apple.
  2. Once granted, youโ€™ll create a new โ€œSystem Extensionโ€ target in Xcode.
  3. The core of your code will be creating an es_client_t and subscribing to events, specifically ES_EVENT_TYPE_NOTIFY_EXEC.
  4. Your event handler will receive an es_message_t containing information about the process. Youโ€™ll need to parse this C struct to get the executable path and PID.
  5. Because this is a privileged operation, your tool will need to be installed and run with root permissions.

Learning milestones:

  1. Your entitlement request is approved by Apple.
  2. You can build and install a simple System Extension.
  3. Your client successfully subscribes to the event stream.
  4. You can correctly parse an es_message_t and log process execution events.

Summary

Project Main Language Difficulty Core API
1. Active App Menu Bar Ticker Swift Beginner NSWorkspace
2. Window Title Logger Swift Advanced Accessibility
3. Global Copy & Paste Logger Swift Advanced CGEventTap, NSPasteboard
4. Downloads Folder Watcher Swift Intermediate FSEvents
5. Endpoint Security Monitor Swift/C Master EndpointSecurity