API Docs

A configurable Spotlight search query that can be started, stopped, and queried for results.

Create instances via hs.spotlight.create() or the convenience helper hs.spotlight.search(). Configure the query with chainable setter methods, register a callback, then call start().

Results accumulate during the initial gathering phase ("didStart""inProgress""didFinish") and continue to update during the live-monitoring phase ("didUpdate"). Stop explicitly with stop() when you no longer need live updates.

  • Example:
const q = hs.spotlight.create()
q.setQuery("kMDItemContentType == 'com.apple.application-bundle'")
 .setScopes([hs.spotlight.scope.computer])
 .setCallback((event) => {
     if (event === 'didFinish') {
         console.log('Found ' + q.count + ' applications')
         q.results().forEach(item =>
             console.log(item.valueForAttribute(hs.spotlight.attribute.displayName))
         )
         q.stop()
     }
 })
 .start()

Properties

identifier

string
A unique identifier for this query object (UUID string).

count

number
The number of results gathered so far.

isRunning

boolean
Whether the query is currently running (gathering or monitoring for live updates).

isGathering

boolean
Whether the query is in the initial gathering phase. `true` from `"didStart"` until `"didFinish"`; `false` thereafter while live-monitoring.

Methods

setQuery(predicate) -> HSSpotlightQuery

Sets the NSPredicate query string for this search. The string must be a valid `NSPredicate` format expression using `kMDItem*` attribute keys and MDQuery operators (`==`, `!=`, `<`, `>`, `BEGINSWITH`, `CONTAINS`, etc.). If the query is already running when this is called, it is stopped and restarted automatically.
setQuery(predicate) -> HSSpotlightQuery
Name Type Description
predicate string An NSPredicate-format query string
HSSpotlightQuery
this query, for chaining
// Find PDFs larger than 1 MB
q.setQuery("kMDItemContentType == 'com.adobe.pdf' AND kMDItemFSSize > 1048576")

// Find items whose display name begins with "Report"
q.setQuery("kMDItemDisplayName BEGINSWITH 'Report'")

// Find images taken in 2024
q.setQuery("kMDItemContentTypeTree == 'public.image' AND kMDItemContentCreationDate >= $time.iso('2024-01-01')")

setScopes(scopes) -> HSSpotlightQuery

Sets the search scopes that restrict where Spotlight looks. Pass an array of predefined scope strings from `hs.spotlight.scope`, absolute directory paths, or a mix of both. Paths beginning with `~` are expanded to the user's home directory. When not set, the query defaults to `hs.spotlight.scope.computer`.
setScopes(scopes) -> HSSpotlightQuery
Name Type Description
scopes JSValue An array of scope-constant strings or absolute directory paths
HSSpotlightQuery
this query, for chaining
// Home directory only
q.setScopes([hs.spotlight.scope.home])

// Specific folder
q.setScopes(['/Users/alice/Documents'])

// Mix of predefined scope and a folder
q.setScopes([hs.spotlight.scope.home, '/Volumes/ExternalDrive/Projects'])

setSortDescriptors(descriptors) -> HSSpotlightQuery

Sets sort descriptors that control the order of results.
setSortDescriptors(descriptors) -> HSSpotlightQuery
Name Type Description
descriptors JSValue An array of sort descriptor objects
HSSpotlightQuery
this query, for chaining
q.setSortDescriptors([
    { attribute: hs.spotlight.attribute.fsName, ascending: true },
    { attribute: hs.spotlight.attribute.fileSize, ascending: false }
])

setGroupingAttributes(attrs) -> HSSpotlightQuery

Sets the attributes by which results will be grouped. When grouping attributes are set, use `groups()` to retrieve results organised into `HSSpotlightGroup` objects. Specifying multiple attributes creates nested subgroups accessible via `group.subgroups()`.
setGroupingAttributes(attrs) -> HSSpotlightQuery
Name Type Description
attrs JSValue An array of attribute name strings
HSSpotlightQuery
this query, for chaining
// Group image results by content type
q.setQuery("kMDItemContentTypeTree == 'public.image'")
 .setGroupingAttributes([hs.spotlight.attribute.contentType])
 .setCallback((event) => {
     if (event === 'didFinish') {
         q.groups().forEach(g =>
             console.log(g.value() + ': ' + g.count + ' images')
         )
     }
 })
 .start()

setValueListAttributes(attrs) -> HSSpotlightQuery

Sets the attributes for which aggregate value-list summaries are computed. After the query finishes, `valueLists()` returns aggregate data for each specified attribute: distinct values and the number of results carrying each value.
setValueListAttributes(attrs) -> HSSpotlightQuery
Name Type Description
attrs JSValue An array of attribute name strings
HSSpotlightQuery
this query, for chaining
q.setValueListAttributes([hs.spotlight.attribute.kind])
 .setCallback((event) => {
     if (event === 'didFinish') {
         q.valueLists().forEach(vl => {
             console.log('=== ' + vl.attribute + ' ===')
             vl.values.forEach(v =>
                 console.log('  ' + v.value + ': ' + v.count + ' items')
             )
         })
     }
 })
 .start()

setCallback(fn) -> HSSpotlightQuery

Registers a callback that receives query lifecycle events. of `HSSpotlightItem` objects describing what changed in this update cycle
setCallback(fn) -> HSSpotlightQuery
Name Type Description
fn JSValue A JavaScript function `(event, update?) => void`
HSSpotlightQuery
this query, for chaining
q.setCallback((event, update) => {
    if (event === 'didFinish') {
        console.log('Initial gather complete — ' + q.count + ' results')
    } else if (event === 'didUpdate') {
        const added = update ? update.added.length : 0
        console.log(added + ' items added in this update')
    }
})

start() -> HSSpotlightQuery

Starts the query. The query must have a predicate set (via `setQuery()`) before calling `start()`. Calling `start()` on an already-running query is a no-op.
start() -> HSSpotlightQuery
HSSpotlightQuery
this query, for chaining
q.setQuery("kMDItemKind == 'Application'").setCallback(handler).start()

stop() -> HSSpotlightQuery

Stops the query while preserving accumulated results. After stopping, `results()`, `count`, `groups()`, and `valueLists()` continue to return the last gathered data. Call `start()` again to resume.
stop() -> HSSpotlightQuery
HSSpotlightQuery
this query, for chaining
q.stop()
console.log('Final result count: ' + q.count)

results() -> HSSpotlightItem[]

Returns the current results as an array of `HSSpotlightItem` objects. The result set is briefly frozen during access to ensure consistency. Safe to call from within a query callback.
results() -> HSSpotlightItem[]
HSSpotlightItem[]
An array of `HSSpotlightItem` objects (may be empty if the query has not run)
const items = q.results()
items.forEach(item =>
    console.log(item.valueForAttribute(hs.spotlight.attribute.path))
)

groups() -> HSSpotlightGroup[]

Returns grouped results when grouping attributes have been configured. Returns an empty array if `setGroupingAttributes()` was not called.
groups() -> HSSpotlightGroup[]
HSSpotlightGroup[]
An array of `HSSpotlightGroup` objects
q.groups().forEach(group =>
    console.log(group.attribute + ' = ' + group.value() + ' (' + group.count + ' items)')
)

valueLists() -> [[String: Any]]

Returns aggregate value-list summaries for attributes set via `setValueListAttributes()`. Returns an empty array if `setValueListAttributes()` was not called.
valueLists() -> [[String: Any]]
[[String: Any]]
An array of summary objects
q.valueLists().forEach(vl =>
    vl.values.forEach(v =>
        console.log(vl.attribute + ': ' + v.value + ' (' + v.count + ')')
    )
)