Every background process, recurring cron-style job, and system service in macOS is initialized and supervised by launchd, the master system bootstrap daemon (PID 1). Unlike legacy Unix init scripts or systemd, launchd manages background workloads via XML-formatted property list (.plist) files categorized into LaunchDaemons and LaunchAgents. When software uninstallation leaves orphaned daemons or misbehaving background jobs restart in tight crash loops, the modern launchctl command-line utility provides administrative control to audit and manage services.
Architectural Overview of macOS launchd Domains
Workloads in launchd are strictly separated by execution domain and privilege boundaries:
- System LaunchDaemons (
/Library/LaunchDaemons): Execute with root privileges at system startup before user login. - Global LaunchAgents (
/Library/LaunchAgents): Execute per-user within the user GUI session context for all accounts on the Mac. - User LaunchAgents (
~/Library/LaunchAgents): User-specific startup items belonging strictly to the logged-in user. - Domain Targets: Modern macOS utilizes domain specifiers such as
gui/<uid>andsystemrather than legacy load/unload syntax.
Auditing Active Services with launchctl list and print
To inspect currently registered background workloads:
# List all running user agents in the current user session
launchctl list
# Inspect detailed telemetry for a specific service domain
launchctl print gui/$(id -u)/com.apple.Safari.History
In the launchctl list output, examine the three columns:
- PID: Process ID if currently running (or
-if idle/sleeping). - Status: Exit code of the last run. A non-zero number (such as
1or negative values like-9) indicates repeated crashing. - Label: Unique reverse-DNS identifier for the service.
Enabling and Disabling Services Using Modern Subcommands
Apple deprecated launchctl load and unload in favor of granular bootstrap and bootout commands:
# Unload (stop) a user agent from the current user session
launchctl bootout gui/$(id -u)/com.example.maliciousagent
# Permanently disable a service from starting automatically
launchctl disable gui/$(id -u)/com.example.maliciousagent
# Load a newly created service plist into the user session
launchctl bootstrap gui/$(id -u) ~/Library/LaunchAgents/com.digitash.backup.plist
Managing Elevated System Daemons
Modifying system-level daemons requires executing launchctl with superuser privileges targeting the system domain:
# Inspect system-wide daemon status
sudo launchctl print system/com.example.daemon
# Stop and unload an orphaned system daemon
sudo launchctl bootout system /Library/LaunchDaemons/com.example.daemon.plist
Using modern launchctl commands ensures clean service termination without leaving orphaned socket bindings or memory leaks.