←→ Underneath: Background Apps · All Mac guides

How to disable launch agents on a Mac safely

Deleting a .plist from LaunchAgents is the advice you see most often. It is also the worst way: the job keeps running until you restart, and you cannot undo it. Here is the safe, reversible way.

Short answer: find the job's label, then run

launchctl bootout gui/$(id -u)/com.example.label
launchctl disable gui/$(id -u)/com.example.label

The first command stops it now. The second keeps it off after restarts. launchctl enable undoes it.

Before you start: do not touch anything in /System/Library or any label that starts with com.apple.. Those belong to macOS. Leave VPN, backup, security and driver tools alone unless you are removing the tool.

Step 1: Find the job

Launch agents and daemons live in three folders you may change:

List what is loaded now, without Apple's own jobs:

launchctl list | grep -v com.apple

The columns are process ID (- if not running), last exit status, and label. You need the label.

Step 2: Check what it does

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

If the program path points to an app you deleted, the job is a leftover and safe to remove. If it is an updater, disabling it means the app will not update by itself.

Step 3: Back it up

mkdir -p ~/LaunchAgents-backup
cp ~/Library/LaunchAgents/com.example.label.plist ~/LaunchAgents-backup/

Step 4: Stop it now

For an agent (in either LaunchAgents folder):

launchctl bootout gui/$(id -u)/com.example.label

For a daemon in /Library/LaunchDaemons:

sudo launchctl bootout system/com.example.label

This unloads the job and ends its process. It does not survive a restart if the job has RunAtLoad.

Step 5: Keep it off

Pick one.

Option A: launchctl disable (recommended)

launchctl disable gui/$(id -u)/com.example.label

For a daemon: sudo launchctl disable system/com.example.label.

macOS stores the label in its own disabled list, so the job stays off even if the app writes its plist again. Check the list with:

launchctl print-disabled gui/$(id -u)

Option B: move the plist away

mkdir -p ~/Library/LaunchAgents/Disabled
mv ~/Library/LaunchAgents/com.example.label.plist ~/Library/LaunchAgents/Disabled/

launchd only reads files directly in the LaunchAgents folder, not in subfolders, so the job will not load at next login. The file is still there if you need it. If the app recreates the plist, the job comes back; Option A avoids that.

Option C: System Settings

Many jobs also appear in System Settings › General › Login Items & Extensions › Allow in the Background. Turning the switch off there works too, but one switch may cover several jobs from the same developer. See what “Allow in the Background” means.

Step 6: Check it worked

launchctl list | grep com.example.label

No output means it is not loaded. Restart, then run it again to be sure.

Undo

If you used Option A:

launchctl enable gui/$(id -u)/com.example.label
launchctl bootstrap gui/$(id -u) ~/Library/LaunchAgents/com.example.label.plist

If you used Option B, move the file back and run the same bootstrap line. For daemons use sudo and system instead of gui/$(id -u).

Old commands you will see online

launchctl unload -w file.plist and launchctl load -w file.plist still work, but Apple calls them legacy. bootout, bootstrap, disable and enable are the current ones and give clearer errors.

FAQ

Is it safe to delete files in LaunchAgents?

It is safer to disable than to delete. Deleting a plist does not stop a job that is already loaded, and you lose the file if you need it back. Use launchctl bootout and launchctl disable, or move the file to a backup folder.

Should I use launchctl unload -w?

It still works, but Apple marks load and unload as legacy. On current macOS use launchctl bootout to stop a job and launchctl disable to keep it off.

Can I disable Apple launch agents in /System/Library?

Do not. They are part of macOS, System Integrity Protection guards the files, and disabling them can break features such as iCloud, Spotlight or updates.

How do I undo launchctl disable?

Run launchctl enable gui/$(id -u)/<label>, then launchctl bootstrap gui/$(id -u) with the plist path, or log out and back in.

The app put its launch agent back. What now?

Use launchctl disable. It disables the label, so it stays off even if the app writes the plist again. Also turn off the app's own “Launch at login” setting.