HSSpotlightQuery
TypeA 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
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.
Declaration
setQuery(predicate) -> HSSpotlightQuery
Parameters
| Name | Type | Description |
|---|---|---|
| predicate | string | An NSPredicate-format query string |
Returns
HSSpotlightQuery
this query, for chaining
Example
// 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`.
Declaration
setScopes(scopes) -> HSSpotlightQuery
Parameters
| Name | Type | Description |
|---|---|---|
| scopes | JSValue | An array of scope-constant strings or absolute directory paths |
Returns
HSSpotlightQuery
this query, for chaining
Example
// 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.
Declaration
setSortDescriptors(descriptors) -> HSSpotlightQuery
Parameters
| Name | Type | Description |
|---|---|---|
| descriptors | JSValue | An array of sort descriptor objects |
Returns
HSSpotlightQuery
this query, for chaining
Example
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()`.
Declaration
setGroupingAttributes(attrs) -> HSSpotlightQuery
Parameters
| Name | Type | Description |
|---|---|---|
| attrs | JSValue | An array of attribute name strings |
Returns
HSSpotlightQuery
this query, for chaining
Example
// 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.
Declaration
setValueListAttributes(attrs) -> HSSpotlightQuery
Parameters
| Name | Type | Description |
|---|---|---|
| attrs | JSValue | An array of attribute name strings |
Returns
HSSpotlightQuery
this query, for chaining
Example
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
Declaration
setCallback(fn) -> HSSpotlightQuery
Parameters
| Name | Type | Description |
|---|---|---|
| fn | JSValue | A JavaScript function `(event, update?) => void` |
Returns
HSSpotlightQuery
this query, for chaining
Example
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.
Declaration
start() -> HSSpotlightQuery
Returns
HSSpotlightQuery
this query, for chaining
Example
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.
Declaration
stop() -> HSSpotlightQuery
Returns
HSSpotlightQuery
this query, for chaining
Example
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.
Declaration
results() -> HSSpotlightItem[]
Returns
HSSpotlightItem[]
An array of `HSSpotlightItem` objects (may be empty if the query has not run)
Example
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.
Declaration
groups() -> HSSpotlightGroup[]
Returns
HSSpotlightGroup[]
An array of `HSSpotlightGroup` objects
Example
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.
Declaration
valueLists() -> [[String: Any]]
Returns
[[String: Any]]
An array of summary objects
Example
q.valueLists().forEach(vl =>
vl.values.forEach(v =>
console.log(vl.attribute + ': ' + v.value + ' (' + v.count + ')')
)
)