Should a console application be chosen on xcode to develop macos daemons?

I have a few questions regarding daemons. Indeed, even the macos developer center has limited information resources.

I want to develop an application daemon that runs after system boot without login.

a) a Daemon; Is it a simple console application combined with a plist? Because there are almost no tutorials on daemon development related to xcode. If there is a code sample reference, can you share it here?

b) Can daemons be downloaded from the app store? Because there must be a software that I can offer to everyone through the app store. Is the installation automatic like other app store apps? If anyone has experience and can share it, I would be very grateful.

c) I am working on an api related to mirroring the screen to android phone. Do you think a daemon has full access to wifi/ble and screen capture APIs?

I would be very happy to hear your suggestions.

Answered by DTS Engineer in 707894022

Indeed, even the macos developer center has limited information resources.

There are some useful docs but, sadly, they’re all in the documentation archive. Specifically:

The latter covers the concept of execution contexts in great detail, and that really matters to your project.

Can daemons be downloaded from the app store?

No. Specifically, this requirement:

I want to develop [a program] that runs after system boot without login.

is not feasible in a Mac App Store app.

a Daemon; Is it a simple console application combined with a plist?

As always, it depends.

To start, “console application” doesn’t accurately describe a daemon. If someone says “console application” to me, I think of something that runs in Terminal but which is interactive. Think vi.

A better term is command-line tool, which encompasses application-y stuff (vi), traditional shell stuff (cat), and daemons and agents.

Xcode has a macOS > Command Line Tool template that may be the best starting point for you. I say may because it depends on whether your daemon ends up needing entitlements. If it does, it’s better to start with the macOS > App template, as discussed in Signing a Daemon with a Restricted Entitlement.

I am working on an api related to mirroring the screen to android phone. Do you think a daemon has full access to wifi/ble and screen capture APIs?

Definitely not. TN2083 describes the layered execution contexts of macOS. A daemon exists in the global context and it can only access daemon-safe things. Of the list you mentioned:

  • Only Wi-Fi is truly daemon safe [1].

  • On the screen capture front, such code must be running in a GUI login session.

  • For Bluetooth LE, the Core Bluetooth API was historically daemon safe but the recent introduction of System Preferences > Security & Privacy > Privacy > Bluetooth has muddied the waters considerably. As things currently stand, my advice is that you do your Bluetooth work in a GUI login session.

So, how can you make this work? Screen sharing products are usually based on two cooperating executables:

  • A launchd daemon, which is the product’s global presence. It coordinates shared state, including the networking.

  • A launchd agent, which is the daemon’s agent (hey hey) in each GUI login session. Configure that agent [2] to run in both the pre-login context (LoginWindow) and GUI per-user context (Aqua). It then connects to the daemon via IPC (typically XPC) to coordinate its work.

Keep in mind there may be 0 or more instances of your launchd agent, running in an arbitrary combination of pre-login and per-user contexts. That’s why you need the daemon, to act as a central hub for all that work.

Share and Enjoy

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

[1] I presume you’re using Wi-Fi to mean “networking in general”. If you’re actually trying to work with low-level Wi-Fi APIs — and on macOS that means Core WLAN — the story gets more complex.

[2] Via the LimitLoadToSessionType property in the launchd property list; see the launchd.plist man page for details.

Accepted Answer

Indeed, even the macos developer center has limited information resources.

There are some useful docs but, sadly, they’re all in the documentation archive. Specifically:

The latter covers the concept of execution contexts in great detail, and that really matters to your project.

Can daemons be downloaded from the app store?

No. Specifically, this requirement:

I want to develop [a program] that runs after system boot without login.

is not feasible in a Mac App Store app.

a Daemon; Is it a simple console application combined with a plist?

As always, it depends.

To start, “console application” doesn’t accurately describe a daemon. If someone says “console application” to me, I think of something that runs in Terminal but which is interactive. Think vi.

A better term is command-line tool, which encompasses application-y stuff (vi), traditional shell stuff (cat), and daemons and agents.

Xcode has a macOS > Command Line Tool template that may be the best starting point for you. I say may because it depends on whether your daemon ends up needing entitlements. If it does, it’s better to start with the macOS > App template, as discussed in Signing a Daemon with a Restricted Entitlement.

I am working on an api related to mirroring the screen to android phone. Do you think a daemon has full access to wifi/ble and screen capture APIs?

Definitely not. TN2083 describes the layered execution contexts of macOS. A daemon exists in the global context and it can only access daemon-safe things. Of the list you mentioned:

  • Only Wi-Fi is truly daemon safe [1].

  • On the screen capture front, such code must be running in a GUI login session.

  • For Bluetooth LE, the Core Bluetooth API was historically daemon safe but the recent introduction of System Preferences > Security & Privacy > Privacy > Bluetooth has muddied the waters considerably. As things currently stand, my advice is that you do your Bluetooth work in a GUI login session.

So, how can you make this work? Screen sharing products are usually based on two cooperating executables:

  • A launchd daemon, which is the product’s global presence. It coordinates shared state, including the networking.

  • A launchd agent, which is the daemon’s agent (hey hey) in each GUI login session. Configure that agent [2] to run in both the pre-login context (LoginWindow) and GUI per-user context (Aqua). It then connects to the daemon via IPC (typically XPC) to coordinate its work.

Keep in mind there may be 0 or more instances of your launchd agent, running in an arbitrary combination of pre-login and per-user contexts. That’s why you need the daemon, to act as a central hub for all that work.

Share and Enjoy

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

[1] I presume you’re using Wi-Fi to mean “networking in general”. If you’re actually trying to work with low-level Wi-Fi APIs — and on macOS that means Core WLAN — the story gets more complex.

[2] Via the LimitLoadToSessionType property in the launchd property list; see the launchd.plist man page for details.

Well, what class does an application with an icon like battery, sound, bluetooth and such in the upper right corner of the screen fall into?

Such programs are called UI elements. A UI element has the same runtime model as a standard app but has the LSUIElement property property set and thus doesn’t show up in the Dock, display a menu bar, and so on.

A UI element is different from a background-only application (using the LSBackgroundOnly property) in that the latter shows no UI at all while the former can display limited amounts of UI.

Specifically, a UI element will often display a status item using NSStatusBar.

In most case you package a UI element within an app that has a UI for the user to control it. If you want the UI element to run at login, the container app enables that using SMLoginItemSetEnabled (thus making the UI element also a Service Management login item).

However, there are other ways to do this. For example, if your product already has a launchd agent, it can act as a UI element.


As to whether this is appropriate for you, it very much depends on your specific requirements. Earlier you wrote:

I want to develop an application daemon that runs after system boot without login.

which suggests that a UI element will not be sufficient because you want to provide your screen sharing service at the login window. A UI element only makes sense during a GUI user login session.

Which brings us back to the idea of a group of processes coöperating to create your final product. You could, for example, have:

  • A daemon that provides central coordination

  • A launchd agent that acts as the daemon’s agent in each GUI session

  • Another launchd agent that acts as a UI element in each GUI user login session

Or you could combine the two, having the agent behave differently depending on whether it’s in a pre-login or user GUI login session.

Or, if you don’t care about running pre-login, you might be able to get away with a UI element that provides the entire screen sharing with a container app to configure it.

Share and Enjoy

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

Should a console application be chosen on xcode to develop macos daemons?
 
 
Q