← Blog

How to Inspect Launch Agents on macOS

July 1, 2026

How to Inspect Launch Agents on macOS

If your Mac starts behaving oddly right after login - a browser opens by itself, a background process keeps respawning, or network traffic appears when nothing obvious is running - launch agents are one of the first places to look. Knowing how to inspect launch agents gives you a practical way to check what is set to run automatically in your user session, and whether it belongs there.

Launch agents are part of macOS's startup plumbing. They are usually small property list files, called .plist files, that tell launchd to start an app, script, or helper process under specific conditions. Plenty of legitimate software uses them. Password managers, cloud sync tools, update checkers, menu bar apps, and developer tooling all rely on them. That makes them useful, but it also makes them attractive for persistence. If something wants to survive a reboot and quietly come back every time you log in, this is a familiar place to hide.

What launch agents actually do

A launch agent runs in the context of a logged-in user, not as a system-wide daemon. That distinction matters. If the suspicious behavior only appears after you sign in, a launch agent is more likely than a launch daemon. Agents commonly handle user-facing or session-aware tasks, like launching a helper app, checking for updates, or keeping a menu bar process alive.

The file itself is usually readable XML and contains a few fields worth understanding. Label is the job name. Program or ProgramArguments points to what gets executed. RunAtLoad tells it to start when the agent is loaded, often at login. KeepAlive can make the process restart if it exits. Once you understand those four ideas, most launch agent reviews become much less mysterious.

How to inspect launch agents in the right locations

On a typical Mac, the main folders to check are ~/Library/LaunchAgents, /Library/LaunchAgents, and sometimes app-specific support paths that drop related files nearby. The first path affects only the current user. The second applies more broadly and is usually used by installed software for all users.

Start with the user-level folder because it is both common and easier for unwanted software to write to if something already gained access to your account. In Terminal, list the files with:

```bash ls -la ~/Library/LaunchAgents ```

Then check the system-wide folder:

```bash ls -la /Library/LaunchAgents ```

File names often tell part of the story. Legitimate vendors usually use reverse-domain naming like com.vendor.product.plist. That is not proof of legitimacy, but it is a useful clue. Names that imitate Apple services, use random strings, or point to scripts buried in odd directories deserve a closer look.

To inspect the contents of a specific plist, use:

```bash plutil -p ~/Library/LaunchAgents/com.example.agent.plist ```

That command prints the structure in a readable format. You can also use cat for raw XML, but plutil is cleaner and faster when you are reviewing several files.

What to look for inside a launch agent

The most important question is simple: what does this thing launch?

Look at Program and ProgramArguments first. If the agent points to a well-known app in /Applications or a signed helper under a vendor's app bundle, that is usually less concerning. If it points to a shell script in /tmp, a hidden file in your home directory, or an executable with a vague name like update, service, helper, or install living in a strange path, slow down and inspect further.

RunAtLoad is common and not suspicious by itself. KeepAlive is also common for apps that need to stay running. The problem is the combination of stealthy naming, unusual file paths, and persistence behavior that does not match software you knowingly installed.

It also helps to compare the plist's modification time with your own memory. If a launch agent appeared yesterday and that lines up with installing a VPN client, that is one thing. If it appeared after clicking a sketchy download or opening a fake browser update, that is another.

Check what is currently loaded

A plist sitting on disk is one clue. A loaded job is stronger evidence. On modern macOS, you can query launchd with:

```bash launchctl print gui/$(id -u) ```

This shows jobs in the current user's graphical session. The output is long, so you may want to search it for a label you saw in a plist:

```bash launchctl print gui/$(id -u) | grep -i example ```

You can also ask launchctl for a specific service if you know the label. That helps confirm whether the agent is active, failing repeatedly, or tied to a particular executable path.

There is a trade-off here. launchctl gives useful truth about what launchd knows, but the output is not especially friendly. It is built for operators, not for calm, plain-English inspection. That is why pairing raw system data with context matters. A tiny security guard for your computer should not just tell you a label exists. It should help you decide whether it is normal, noisy, broken, or risky.

Verify the executable, not just the plist

A launch agent is only the wrapper. The real question is the binary or script it starts.

Once you identify the target path, inspect that file directly. Use ls -la to confirm where it lives and who owns it. If it is an app bundle helper, code signing is worth checking:

```bash codesign -dv --verbose=4 /path/to/executable ```

If Gatekeeper data is available, you can also inspect it with:

```bash spctl --assess --verbose /path/to/executable ```

These checks are not magic lie detectors. Plenty of legitimate internal tools are unsigned, and some malware uses valid signatures. But signatures, paths, ownership, and file age together paint a clearer picture than any single signal on its own.

If the executable is a script, open it and read it. Shell scripts often reveal intent quickly. A few lines that launch a known app helper are ordinary. A script that downloads code, hides files, or phones home with curl is a very different story.

Use context to separate normal from suspicious

This is where people either save time or waste an afternoon. Not every background item is a threat. Developers often install tooling that creates agents. Design apps, update frameworks, menu bar utilities, password managers, and sync clients all do this routinely.

The fastest way to triage is to ask four questions. Did you install something that would reasonably need to run at login? Does the label match a vendor you recognize? Does the target path live where legitimate software usually lives? Does its behavior line up with what the software claims to do?

When the answer is no across the board, suspicion rises fast. A random launch agent in your user folder pointing to a hidden shell script with RunAtLoad enabled is not something to shrug off.

This is also where visibility tools help. A monitor like avai can inspect startup persistence alongside other system surfaces, then correlate what it finds with network activity, browser changes, and threat intelligence. That matters because persistence rarely tells the whole story by itself. A weird agent plus a suspicious outbound connection is much more useful than either clue alone.

What to do if you find a suspicious launch agent

Do not delete files blindly if you are still unsure what they belong to. Some software breaks messily when you remove only part of its startup machinery. First, preserve evidence. Note the plist path, label, executable path, timestamps, and any related process names.

If you want to stop it from loading for testing, unload or boot it out carefully, depending on your macOS version and context. Then observe whether the behavior stops. After that, move the plist to a safe quarantine location rather than immediately erasing it, and inspect the target executable as well. If you leave the payload in place, a different mechanism may recreate the agent.

Also check neighboring persistence points. Launch daemons, login items, cron jobs, browser extensions, and configuration profiles can all work together. Attackers and aggressive adware rarely rely on a single hiding spot if they can avoid it.

Common mistakes when inspecting launch agents

The first mistake is assuming Apple-looking names are safe. Malware authors know what blends in. The second is trusting signatures too much. Signing adds confidence, not certainty. The third is focusing only on what exists on disk and ignoring what is actively loaded and what it connects to.

Another common miss is forgetting the user context. A launch agent under one account may never affect another. On shared Macs or test machines, that can lead to false reassurance if you inspect the wrong home directory.

The best inspections are boring in a good way. You identify the file, read the plist, verify the target, check whether it is loaded, and compare it against expected software on that machine. No guesswork, no panic.

If you are trying to figure out how to inspect launch agents, the goal is not to memorize every launchctl quirk. It is to get to a plain-English answer you can trust: what starts at login, why it starts, and whether it deserves to stay. That kind of clarity is what turns startup persistence from a black box into something you can actually manage.

A clean machine is not one with zero launch agents. It is one where every automatic process has a reason to exist, and none of them surprise you.

How to Inspect Launch Agents on macOS — avai