hs.spotlight
ModuleQuery the macOS Spotlight metadata database.
hs.spotlight wraps NSMetadataQuery to let you search for files and other
metadata objects indexed by Spotlight. Queries use NSPredicate syntax with
kMDItem* attribute keys (see hs.spotlight.attribute for common shortcuts).
Quick start
// Find all PDFs in the home directory and log their paths
const q = hs.spotlight.create()
q.setQuery("kMDItemContentType == 'com.adobe.pdf'")
.setScopes([hs.spotlight.scope.home])
.setCallback((event) => {
if (event === 'didFinish') {
console.log('Found ' + q.count + ' PDFs')
q.results().forEach(item =>
console.log(item.valueForAttribute(hs.spotlight.attribute.path))
)
q.stop()
}
})
.start()
One-shot search convenience
const q = hs.spotlight.search(
"kMDItemDisplayName BEGINSWITH 'Invoice'",
(event) => {
if (event === 'didFinish') {
console.log('Found ' + q.count + ' invoices')
q.stop()
}
}
)
Grouping results by attribute
const q = hs.spotlight.create()
q.setQuery("kMDItemContentTypeTree == 'public.image'")
.setScopes([hs.spotlight.scope.home])
.setGroupingAttributes([hs.spotlight.attribute.kind])
.setCallback((event) => {
if (event === 'didFinish') {
q.groups().forEach(g =>
console.log(g.value() + ': ' + g.count + ' images')
)
q.stop()
}
})
.start()
Monitoring for live changes
// Keep the query running to receive live-update events
const q = hs.spotlight.create()
q.setQuery("kMDItemContentType == 'com.apple.application-bundle'")
.setScopes(['/Applications'])
.setCallback((event, update) => {
if (event === 'didFinish') {
console.log('Initial scan: ' + q.count + ' apps')
} else if (event === 'didUpdate') {
console.log('App list changed — now ' + q.count + ' apps')
if (update) console.log('Added: ' + update.added.length)
}
})
.start()
// Call q.stop() when you no longer want live updates
Types
This module provides the following types:
Properties
hs.spotlight.scope
[String: [String]]
Predefined search scope constants for use with `HSSpotlightQuery.setScopes()`.
| Key | Description |
|-----|-------------|
| `home` | The current user's home directory |
| `computer` | All locally mounted volumes |
| `network` | Network-mounted volumes |
| `applications` | Common locations for .app bundles |
| `icloud` | iCloud Documents |
| `icloudData` | iCloud Data (non-document ubiquitous files) |
hs.spotlight.attribute
{[key: string]: string}
Common Spotlight metadata attribute key shortcuts.
These are plain `kMDItem*` string values — using them is equivalent to typing
the raw key name, but they provide autocomplete and avoid typos.
| Key | Attribute | Description |
|-----|-----------|-------------|
| `path` | `kMDItemPath` | Absolute filesystem path |
| `displayName` | `kMDItemDisplayName` | User-visible display name |
| `fsName` | `kMDItemFSName` | Filename on disk |
| `contentType` | `kMDItemContentType` | UTI content type |
| `contentTypeTree` | `kMDItemContentTypeTree` | Full UTI conformance tree |
| `kind` | `kMDItemKind` | Finder "Kind" string |
| `fileSize` | `kMDItemFSSize` | File size in bytes |
| `creationDate` | `kMDItemFSCreationDate` | Filesystem creation date |
| `modifiedDate` | `kMDItemFSContentChangeDate` | Last content modification date |
| `lastUsedDate` | `kMDItemLastUsedDate` | Last time the item was opened |
| `useCount` | `kMDItemUseCount` | Number of times opened |
| `authors` | `kMDItemAuthors` | Document authors |
| `title` | `kMDItemTitle` | Document title |
| `comment` | `kMDItemComment` | User comment |
| `keywords` | `kMDItemKeywords` | Tags/keywords |
| `durationSeconds` | `kMDItemDurationSeconds` | Media duration in seconds |
| `pixelWidth` | `kMDItemPixelWidth` | Image/video width in pixels |
| `pixelHeight` | `kMDItemPixelHeight` | Image/video height in pixels |
| `whereFroms` | `kMDItemWhereFroms` | Download source URLs |
| `bundleIdentifier` | `kMDItemCFBundleIdentifier` | App bundle identifier |
Methods
hs.spotlight.create() -> HSSpotlightQuery
Creates and returns a new, unconfigured Spotlight query.
Configure it with `setQuery()`, `setScopes()`, and `setCallback()`, then call `start()`.
The query is automatically stopped and released when the module shuts down.
Declaration
hs.spotlight.create() -> HSSpotlightQuery
Returns
HSSpotlightQuery
A new `HSSpotlightQuery`
Example
const q = hs.spotlight.create()
q.setQuery("kMDItemKind == 'PDF Document'")
.setCallback((event) => { if (event === 'didFinish') q.stop() })
.start()
hs.spotlight.search(predicate, callback) -> HSSpotlightQuery
Convenience helper that creates, configures, and starts a query in one call.
Equivalent to `create().setQuery(predicate).setCallback(callback).start()`.
Call `q.stop()` from inside `callback` (when `event === 'didFinish'`) to end
the search once you have what you need.
Declaration
hs.spotlight.search(predicate, callback) -> HSSpotlightQuery
Parameters
| Name | Type | Description |
|---|---|---|
| predicate | string | An NSPredicate-format query string |
| callback | JSValue | A function called with `(event, update?)` lifecycle events |
Returns
HSSpotlightQuery
The `HSSpotlightQuery` object (use to stop the search early)
Example
const q = hs.spotlight.search(
"kMDItemDisplayName BEGINSWITH 'Report'",
(event) => {
if (event === 'didFinish') {
console.log('Found ' + q.count + ' reports')
q.stop()
}
}
)