Apple recommends a new API for programmatically setting and removing Login Items in Mac OS 10.5, Leopard and later.  This replaces the old LoginItemsAE which never worked reliably  due to its dependence of SystemEvents.

The header is on your hard drive:


It's undocumented, not very nice to use (Carbon-style C API) and also there is a bug (see below).

To make it nicer to use, I wrote this Cocoa wrapper, and Doxygen documentation.


Visit this project's GitHub Repository to download, fetch, or clone this code.


Updated 20090818:  Bogus items in Login Items (which, I believe, are items for which the path has disappeared) are now ignored instead of causing an error to be returned and, later, a crash.

Updated 20090819:  I believe I fixed conceptual memory-management errors.  In some places, I was releasing the elements in the 'snapshot' array, in addition to releasing the array itself (which is correct), and compensating by retaining (but not always).  I'm still not sure that it's all correct, but it's better than it was.

Updated 20090819: Generated documentation using Doxygen instead of HeaderDoc.  Curses on Apple for apparently trying to breathe a last gasp of life into HeaderDoc by recommending HeaderDoc in their Xcode news feed back during January 2008.  Doxygen is way better.

Updated 20090925: Removed dependency on NSError+SSYAdds.h/.m, replaced with NSError+LowLevel.h/.m which is smaller.

Here's the text of the bug:

Apple Bug Reporter.  Problem ID 5901742

30-Apr-2008 01:48 PM Jerry Krinock: 

* SUMMARY The 'hidden' attribute for Login Items in the LSSharedList API has a disconnect with the reality. In more detail, when reading a Login Item, the 'hidden' attribute is read as 0, even if it is in fact '1', unless the 'hidden' attribute has been set by the LSSharedList API. In that case, it doesn't really set, but when you read it back with the API, it says that it is set, even though in fact it is not.

* STEPS TO REPRODUCE Build and run the attached project. Follow the prompts shown in the the console.

* EXPECTED RESULTS In all tests, the values read and written using the LSSharedList API and shown in the log should agree with what is shown in the System Preferences application.

* ACTUAL RESULTS In Test #1, items which have the "Hide" box checked in System Preferences read from the API hidden=0. In Test #5, although the API set Safari to "Hide" and the API read it back as hidden=1, if you look in System Preferences you see that the "Hide" box is not checked.