Thanks for being a part of WWDC25!

How did we do? We’d love to know your thoughts on this year’s conference. Take the survey here

How can I bundle resources along with my launch agent?

I have an app which contains a bundled launch agent that I register using SMAppService.agent(plistName:). I’ve packaged the launch agent executable in the typical Mac app bundle structure so I can embed a framework in it. So, the launch agent lives in Contents/SharedSupport/MyLaunchAgent.app/Contents/MacOS/MyLaunchAgent.

However, I suspect this approach might be falling afoul of the scheduler, since the taskinfo tool reports my launch agent has a requested & effective role of TASK_DEFAULT_APPLICATION (PRIO_DARWIN_ROLE_UI), rather than the TASK_UNSPECIFIED (PRIO_DARWIN_ROLE_DEFAULT) value I see with system daemons.

I tried setting the LSUIElement Info.plist key of my launch agent to YES, but this seems to have had no effect.

What’s the recommended approach here?

Answered by DTS Engineer in 841858022
I'm not really sure what the difference between a Login Item and a Launch Agent would be.

There are some key differences:

  • launchd agents can publish named XPC endpoints.

  • launchd agents can use the launchd run-on-demand lifecycle. Login items launch at login and that’s that.

  • One important upshot of the previous point is that the system is able to relaunch a launchd agent that crashes.

There are good reasons to package a launchd agent in an app-like wrapper. The most important is that it’s the only way for your agent to use restricted entitlements, that is, entitlements that must be authorised by a provisioning profile. See Signing a daemon with a restricted entitlement, which discusses this in terms of daemons but the same basic logic applies to agents.

Having said that, this packaging isn’t necessary if you use SMAppService to install your agent. In that case the agent is embedded within your app [1], so it can access resources in one of two ways:

  • It can navigate up the file system hierarchy to access resources from the app’s bundle.

  • It can call a framework, which can have its own resources.

Share and Enjoy

Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"

[1] Technically this isn’t required, but it’s the standard approach.

I don't think "SharedSupport" is the appropriate place. The legacy documentation says that this location is for "additional non-critical resources that do not impact the ability of the application to run".

Unfortunately, I think the legacy migration documentation is wrong because it explicitly says to use the "Resources" folder for executable code. Don't do that.

Here is the current documentation.

None of that is really what you're asking about, but I think it leads up to it. Typically, launch agents are single-file executables. I'm not familiar with the taskinfo tool or its output. But what it says makes sense. A Launch Agent would run with a user space UI role. That's how Launch Agents work. That's not the same as a Launch Daemon that runs as root and does not require a login session.

When I look at how most other apps handle these things, what you're describing sounds more like a Login Item. A login item would live in "Contents/Library/LoginItems". Of all the apps I have installed that contain items in "Contents/Library", virtually all that contain bundled apps have them as Login Items. So I recommend you treat this thing as a Login Item.

(Note that I mean a newer Service Management Login Item, not the really old school Login Items meant for end users).

It's only recently that Apple added the ability to bundle Launch Agents and Daemons inside an app bundle. In a modern app, I'm not really sure what the difference between a Login Item and a Launch Agent would be. They seem to perform very similar roles. I guess a Launch Agent would be able to use some of the plist config file tricks that a Login Item would probably have to code manually. I can tell you that I have a couple of apps in development that will contain some background functionality and I plan to use Login Items rather than Launch Agents.

Accepted Answer
I'm not really sure what the difference between a Login Item and a Launch Agent would be.

There are some key differences:

  • launchd agents can publish named XPC endpoints.

  • launchd agents can use the launchd run-on-demand lifecycle. Login items launch at login and that’s that.

  • One important upshot of the previous point is that the system is able to relaunch a launchd agent that crashes.

There are good reasons to package a launchd agent in an app-like wrapper. The most important is that it’s the only way for your agent to use restricted entitlements, that is, entitlements that must be authorised by a provisioning profile. See Signing a daemon with a restricted entitlement, which discusses this in terms of daemons but the same basic logic applies to agents.

Having said that, this packaging isn’t necessary if you use SMAppService to install your agent. In that case the agent is embedded within your app [1], so it can access resources in one of two ways:

  • It can navigate up the file system hierarchy to access resources from the app’s bundle.

  • It can call a framework, which can have its own resources.

Share and Enjoy

Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"

[1] Technically this isn’t required, but it’s the standard approach.

launchd agents can publish named XPC endpoints.

I know enough about that to stay away from it.

the system is able to relaunch a launchd agent that crashes.

That might be useful.

However, there is one important distinction. Can a Launch Agent be used in the Mac App Store?

Login Items are explicitly allowed in the "retired" Mac App Store documentation.

The current App Review guidelines only mention user consent. Is there a modern replacement for the old "Submitting o the Mac App Store" documentation?

Can a Launch Agent be used in the Mac App Store?

Yes, assuming you target macOS 13 or later, which is when SMAppService rolled out.

Share and Enjoy

Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"

Thanks!

It can call a framework, which can have its own resources

This is a good point, I suppose I don’t really need the bundle structure to package resources. I think it makes my build phases in Xcode a little cleaner, though, so I’ll stick with it.

Thanks!

A Launch Agent would run with a user space UI role. That's how Launch Agents work. That's not the same as a Launch Daemon that runs as root and does not require a login session.

Ah, you’re right! I feel a bit silly for not testing the null hypothesis earlier, but indeed even if I don’t embed my launch agent in an app bundle I still see the same output from taskinfo.

How can I bundle resources along with my launch agent?
 
 
Q