Sweepfor Mac

Mac maintenance

Launch Agents vs Launch Daemons on Mac: What's the Difference?

Launch agents and launch daemons on Mac both run background tasks but in very different ways. Here's what they do, where they live, and how to manage them.

10 min read

That update checker that ran when your Mac woke up. The Dropbox process you don’t remember starting. The thing Adobe installed that’s running right now even though no Adobe app is open. All of these come from the same machinery: macOS’s launchd system, configured through launch agents and launch daemons. They’re how persistent background work happens on your Mac, and they’re also where most of the slow startup, spinning fan noise, and unexplained network traffic comes from.

The two terms get used interchangeably online, but they’re meaningfully different. One runs as you when you’re logged in. The other runs as root, all the time, regardless of who’s at the keyboard. Both can be benign, both can be hostile, and both are managed by the same tool: launchctl.

What launchd Actually Is

launchd is the master process on macOS — process ID 1, the first thing the kernel starts after booting. Everything else either descends from launchd or is started by it on demand. Apple replaced the older Unix init system with launchd back in OS X 10.4 because they wanted something smarter: not just “run these things at startup,” but “run these things when needed and shut them down when not.”

It accomplishes that by reading plist files — XML configuration files that describe a job. A plist tells launchd: here’s the program to run, here’s when to run it (at boot, on a schedule, when a file changes, when a network port is accessed), here’s whether to keep it running or restart it if it crashes.

Each of those plist files is either a launch agent or a launch daemon. The difference is where it lives and what context it runs in.

Launch Agents: User-Level Background Jobs

Launch agents run in the context of a logged-in user. They start when that user logs in and die when the user logs out. They have access to the user’s GUI session, can display windows, and can read the user’s home folder.

They live in three locations:

  • ~/Library/LaunchAgents — agents installed by individual users, only run when that user logs in
  • /Library/LaunchAgents — agents installed system-wide, run when any user logs in
  • /System/Library/LaunchAgents — Apple’s own agents, protected by SIP

Examples of common launch agents: Dropbox’s sync daemon, Spotify’s helper, Slack’s notification handler, Adobe’s Creative Cloud monitor, the Google Software Update agent.

A typical user-installed launch agent plist at ~/Library/LaunchAgents/com.example.updater.plist might look like:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
    <key>Label</key>
    <string>com.example.updater</string>
    <key>ProgramArguments</key>
    <array>
        <string>/Applications/Example.app/Contents/Helpers/Updater</string>
    </array>
    <key>RunAtLoad</key>
    <true/>
    <key>KeepAlive</key>
    <true/>
</dict>
</plist>

That tells launchd: when I (the user) log in, start the Updater binary, and if it dies, restart it.

Launch Daemons: System-Level Background Jobs

Launch daemons run in the context of the system itself, usually as root. They start at boot, before any user logs in, and keep running regardless of who’s logged in or whether anyone’s logged in at all. They have no GUI access and shouldn’t try to draw to the screen.

They live in two locations:

  • /Library/LaunchDaemons — daemons installed system-wide
  • /System/Library/LaunchDaemons — Apple’s own daemons, protected by SIP

Examples: the SSH daemon, the Bluetooth audio service, kernel extensions cached at boot, third-party VPN clients, virus scanners, hardware drivers like Logitech’s keyboard daemon.

The plist format is identical to a launch agent, just with different placement.

Skip the manual huntSweep audits launch agents, daemons, and helpers in one screen. Download Sweep free →

The Critical Differences

Side by side, the practical differences:

AspectLaunch AgentLaunch Daemon
Runs asThe logged-in userroot (usually)
StartsAt loginAt boot
StopsAt logoutAt shutdown
GUI accessYesNo
Common location (user)~/Library/LaunchAgentsN/A
Common location (system)/Library/LaunchAgents/Library/LaunchDaemons
Apple’s own/System/Library/LaunchAgents/System/Library/LaunchDaemons
Typical useSync clients, helpers, GUI accessoryHardware drivers, network services, system maintenance

When a third-party installer wants to run something only when you’re using your Mac, it should install a launch agent. When it needs to run regardless (a VPN that connects on boot, a printer driver, a kernel extension’s helper), it installs a launch daemon. Some apps install both: a daemon for the privileged work and an agent for the user-facing piece that talks to it.

Listing Everything Currently Loaded

The launchctl command is how you interact with launchd. To see everything currently loaded for your user session:

launchctl list

You’ll get a long list with three columns: PID (or - if not currently running), exit status of last run, and label. The label is what identifies the job, usually formatted as a reverse-DNS string like com.dropbox.DropboxMacUpdate.agent.

To see the actual plist for a job:

launchctl print gui/$(id -u)/com.dropbox.DropboxMacUpdate.agent

(For agents, the domain is gui/<uid>; for daemons, it’s system.)

To list system-level daemons:

sudo launchctl print system | head -50

That dumps a huge amount of information — every daemon, when it last ran, what triggers it has registered, current state.

Tip: Compare the count from ls ~/Library/LaunchAgents | wc -l with the count for /Library/LaunchAgents and /Library/LaunchDaemons. On a heavily-used Mac, all three add up to 50–100+ entries.

Why They Slow Down Your Mac

Here’s where this matters in practice. Every launch agent that has RunAtLoad set to true runs at login. Every launch daemon with RunAtLoad runs at boot. If you have 30 of them, your machine is doing 30 things in parallel before you ever get to use it.

It gets worse with KeepAlive set. That tells launchd to restart the program if it ever exits. If a poorly-written updater crashes 20 times an hour, launchd restarts it 20 times an hour, each time consuming CPU and possibly network.

Common culprits:

  • Adobe — installs multiple daemons and agents for Creative Cloud, even if you only use one Adobe app
  • Microsoft Office — license check daemons, AutoUpdate, Teams helpers, Office Click-to-Run
  • VPN clients — often install daemons that run regardless of whether you’re connected
  • Unused apps — uninstall the app, but the launch agent stays behind, periodically trying to start a binary that no longer exists

That last category is especially insidious. You drag-and-drop an app to the Trash. The agent in /Library/LaunchAgents is still there. Every login, launchd tries to start the binary. The binary doesn’t exist. The agent fails. launchd logs the failure. Nothing visible happens — but it’s wasted work, every login, forever.

Inspecting a Plist Before Trusting It

Open any plist file with plutil to see it in human-readable form:

plutil -p ~/Library/LaunchAgents/com.example.updater.plist

The fields to scan for:

  • Label — the job’s identifier
  • ProgramArguments — what’s actually being run
  • RunAtLoad — does it auto-start?
  • KeepAlive — does it auto-restart?
  • StartInterval or StartCalendarInterval — does it run on a schedule?
  • WatchPaths — does it run when a file/folder changes?

If ProgramArguments points to a binary that no longer exists, that agent is dead weight and can be removed.

Power users use SweepSweep handles all the cleanup that articles like this describe. Get Sweep free →

Removing an Agent or Daemon Cleanly

Three steps to fully remove a launch agent or daemon:

  1. Unload it from launchd so the current process stops:

    For an agent:

    launchctl bootout gui/$(id -u) ~/Library/LaunchAgents/com.example.updater.plist
    

    For a daemon:

    sudo launchctl bootout system /Library/LaunchDaemons/com.example.helper.plist
    
  2. Delete the plist file:

    rm ~/Library/LaunchAgents/com.example.updater.plist
    

    (Or sudo rm for /Library/LaunchDaemons paths.)

  3. Find and delete the binary it pointed to, if you don’t want it on your system at all.

bootout is the modern replacement for the older unload command. The latter still works on most macOS versions but is deprecated.

What Should Run, What Shouldn’t

Apple’s own agents and daemons in /System/Library/ should never be touched — System Integrity Protection prevents you from modifying them anyway. They’re load-bearing.

Third-party items in /Library/LaunchAgents, /Library/LaunchDaemons, and ~/Library/LaunchAgents are fair game to audit. The honest reality on most Macs: 30–60% of what’s loaded there is from apps you no longer use, or from helpers you don’t actually need running.

The minimum-effort audit:

  1. List everything in those three directories
  2. For each, check if the corresponding app is still installed and used
  3. For each remaining item, decide if you actually need it running automatically (vs. just when you launch the app)
  4. Remove the rest

This is one of the highest-leverage cleanup tasks on a Mac that’s been in service for more than a couple of years.

When You Have to Be Careful

Some launch daemons are load-bearing for things you do care about: the VPN that connects when you wake your laptop, the keyboard driver that makes your custom keys work, the cloud backup tool that runs every hour. Don’t randomly delete daemons without knowing what they do.

The Label field is your best clue. Search the bundle ID online (com.bombich.ccc is Carbon Copy Cloner; com.docker.helper is Docker Desktop; com.expressvpn.helper is ExpressVPN). If you don’t recognize what installed it and you can’t find anything online, leave it alone until you can investigate further.

Knowing the difference between agents and daemons — where they live, who they run as, what launchctl can tell you — is the foundation of making your Mac actually do what you want at startup, instead of what every app you’ve ever installed thinks you want.

← Back to all guides