diff --git a/Hammerspoon 2/Modules/hs.window/HSWindow.swift b/Hammerspoon 2/Modules/hs.window/HSWindow.swift index 4f60f1464..fa361ac18 100644 --- a/Hammerspoon 2/Modules/hs.window/HSWindow.swift +++ b/Hammerspoon 2/Modules/hs.window/HSWindow.swift @@ -9,10 +9,45 @@ import Foundation import JavaScriptCore import AppKit import AXSwift +import ScreenCaptureKit // Expose some private API, per https://github.com/saagarjha/Ensemble/blob/27f3fd77c261660c1f469a246858d23d06aa8c1f/macOS/SPI.swift#L21 let _AXUIElementGetWindow = unsafe unsafeBitCast(dlsym(dlopen(nil, RTLD_LAZY), "_AXUIElementGetWindow"), to: (@convention(c) (AXUIElement, UnsafeMutablePointer) -> AXError)?.self) +/// Captures the current on-screen contents of the window with the given ID. +/// +/// Shared by `HSWindow.snapshot()` and `HSWindowModule.snapshotForID()`. +func captureWindowSnapshot(windowID: CGWindowID, keepTransparency: Bool) -> JSPromise? { + return JSEngine.shared.createPromise { holder in + Task.detached { + do { + let content = try await SCShareableContent.current + guard let scWindow = content.windows.first(where: { $0.windowID == windowID }) else { + await holder.rejectWithMessage("hs.window.snapshot: could not locate window \(windowID)") + return + } + + let filter = SCContentFilter(desktopIndependentWindow: scWindow) + let config = SCStreamConfiguration() + config.width = Int(filter.contentRect.width * Double(filter.pointPixelScale)) + config.height = Int(filter.contentRect.height * Double(filter.pointPixelScale)) + config.showsCursor = false + if !keepTransparency { + config.backgroundColor = CGColor.black + } + + let cgImage = try await SCScreenshotManager.captureImage( + contentFilter: filter, + configuration: config + ) + await holder.resolveWith(HSImage(image: NSImage(cgImage: cgImage, size: filter.contentRect.size))) + } catch { + await holder.rejectWithMessage("hs.window.snapshot: \(error.localizedDescription)") + } + } + } +} + /// Object representing a window. You should not instantiate these directly, but rather, use the methods in hs.window to create them for you. /// Note that this type uses private macOS APIs @objc protocol HSWindowAPI: HSTypeAPI, JSExport { @@ -192,6 +227,21 @@ let _AXUIElementGetWindow = unsafe unsafeBitCast(dlsym(dlopen(nil, RTLD_LAZY), " /// ``` @objc func centerOnScreen() + // MARK: - Screenshot + + /// Capture the current on-screen contents of this window as an image. + /// + /// Requires **Screen Recording** permission. + /// + /// - Parameter keepTransparency?: Whether to preserve the window's alpha channel. If `false` (the default), transparent regions are filled with an opaque black background. + /// - Returns: {Promise} Resolves with the captured image, or rejects if the capture fails (e.g. permission denied, or the window could no longer be located). + /// - Example: + /// ```js + /// const win = hs.window.focusedWindow() + /// win.snapshot().then(img => img.saveToFile("/tmp/window.png")) + /// ``` + @objc func snapshot(_ keepTransparency: Bool) -> JSPromise? + // MARK: - Advanced /// Get the underlying AXElement @@ -468,6 +518,19 @@ let _AXUIElementGetWindow = unsafe unsafeBitCast(dlsym(dlopen(nil, RTLD_LAZY), " position = HSPoint(x: Double(centerX), y: Double(centerY)) } + // MARK: - Screenshot + + @objc func snapshot(_ keepTransparency: Bool = false) -> JSPromise? { + guard id > 0, let windowID = CGWindowID(exactly: id) else { + return JSEngine.shared.createPromise { holder in + Task.detached { + await holder.rejectWithMessage("hs.window.snapshot: window has no valid ID") + } + } + } + return captureWindowSnapshot(windowID: windowID, keepTransparency: keepTransparency) + } + // MARK: - Advanced @objc func axElement() -> HSAXElement { diff --git a/Hammerspoon 2/Modules/hs.window/HSWindowModule.swift b/Hammerspoon 2/Modules/hs.window/HSWindowModule.swift index 0a572951c..44e0fd4ba 100644 --- a/Hammerspoon 2/Modules/hs.window/HSWindowModule.swift +++ b/Hammerspoon 2/Modules/hs.window/HSWindowModule.swift @@ -77,6 +77,20 @@ import AXSwift /// ``` @objc func orderedWindows() -> [HSWindow] + /// Capture the current on-screen contents of the window with the given ID. + /// + /// Requires **Screen Recording** permission. + /// + /// - Parameters: + /// - id: The window's underlying ID (see the `id` property on `hs.window` objects). + /// - keepTransparency?: Whether to preserve the window's alpha channel. If `false` (the default), transparent regions are filled with an opaque black background. + /// - Returns: {Promise} Resolves with the captured image, or rejects if no window with that ID can be found, or the capture fails. + /// - Example: + /// ```js + /// hs.window.snapshotForID(12345).then(img => img.saveToFile("/tmp/window.png")) + /// ``` + @objc func snapshotForID(_ id: Int, _ keepTransparency: Bool) -> JSPromise? + // MARK: - Swift-retained storage for JS-defined enhancements // These are set by hs.window.js. They must be real, pre-declared properties (not // dynamically-added JS properties) or JavaScriptCore silently drops them the first time @@ -319,4 +333,15 @@ import AXSwift return windows } + + @objc func snapshotForID(_ id: Int, _ keepTransparency: Bool = false) -> JSPromise? { + guard id > 0, let windowID = CGWindowID(exactly: id) else { + return JSEngine.shared.createPromise { holder in + Task.detached { + await holder.rejectWithMessage("hs.window.snapshotForID: invalid window ID \(id)") + } + } + } + return captureWindowSnapshot(windowID: windowID, keepTransparency: keepTransparency) + } } diff --git a/docs/api.json b/docs/api.json index 928913ee3..a79f500a9 100644 --- a/docs/api.json +++ b/docs/api.json @@ -24951,6 +24951,44 @@ "filePath": "Hammerspoon 2/Modules/hs.window/HSWindowModule.swift", "lineNumber": 78 }, + { + "name": "snapshotForID", + "signature": "func snapshotForID(_ id: Int, _ keepTransparency: Bool) -> JSPromise?", + "isStatic": false, + "rawDocumentation": "Capture the current on-screen contents of the window with the given ID.\n\nRequires **Screen Recording** permission.\n\n- Parameters:\n - id: The window's underlying ID (see the `id` property on `hs.window` objects).\n - keepTransparency?: Whether to preserve the window's alpha channel. If `false` (the default), transparent regions are filled with an opaque black background.\n- Returns: {Promise} Resolves with the captured image, or rejects if no window with that ID can be found, or the capture fails.\n- Example:\n```js\nhs.window.snapshotForID(12345).then(img => img.saveToFile(\"/tmp/window.png\"))\n```", + "description": "Capture the current on-screen contents of the window with the given ID.\nRequires **Screen Recording** permission.", + "params": [ + { + "name": "id", + "type": "number", + "description": "The window's underlying ID (see the `id` property on `hs.window` objects).", + "optional": false, + "tsType": null + }, + { + "name": "keepTransparency", + "type": "boolean", + "description": "Whether to preserve the window's alpha channel. If `false` (the default), transparent regions are filled with an opaque black background.", + "optional": true, + "tsType": null + } + ], + "returns": { + "type": "JSPromise", + "description": "Resolves with the captured image, or rejects if no window with that ID can be found, or the capture fails.", + "promiseType": "HSImage" + }, + "notes": [], + "examples": [ + { + "lang": "js", + "code": "hs.window.snapshotForID(12345).then(img => img.saveToFile(\"/tmp/window.png\"))" + } + ], + "source": "swift", + "filePath": "Hammerspoon 2/Modules/hs.window/HSWindowModule.swift", + "lineNumber": 92 + }, { "name": "findByTitle", "rawDocumentation": "Find windows by title\nParameter title: The window title to search for. All windows with titles that include this string, will be matched\nReturns: {HSWindow[]} An array of HSWindow objects with matching titles", @@ -25083,7 +25121,7 @@ ], "source": "swift", "filePath": "Hammerspoon 2/Modules/hs.window/HSWindow.swift", - "lineNumber": 139 + "lineNumber": 174 }, { "name": "minimize", @@ -25105,7 +25143,7 @@ ], "source": "swift", "filePath": "Hammerspoon 2/Modules/hs.window/HSWindow.swift", - "lineNumber": 148 + "lineNumber": 183 }, { "name": "unminimize", @@ -25127,7 +25165,7 @@ ], "source": "swift", "filePath": "Hammerspoon 2/Modules/hs.window/HSWindow.swift", - "lineNumber": 157 + "lineNumber": 192 }, { "name": "raise", @@ -25149,7 +25187,7 @@ ], "source": "swift", "filePath": "Hammerspoon 2/Modules/hs.window/HSWindow.swift", - "lineNumber": 166 + "lineNumber": 201 }, { "name": "toggleFullscreen", @@ -25171,7 +25209,7 @@ ], "source": "swift", "filePath": "Hammerspoon 2/Modules/hs.window/HSWindow.swift", - "lineNumber": 175 + "lineNumber": 210 }, { "name": "close", @@ -25193,7 +25231,7 @@ ], "source": "swift", "filePath": "Hammerspoon 2/Modules/hs.window/HSWindow.swift", - "lineNumber": 184 + "lineNumber": 219 }, { "name": "centerOnScreen", @@ -25212,7 +25250,38 @@ ], "source": "swift", "filePath": "Hammerspoon 2/Modules/hs.window/HSWindow.swift", - "lineNumber": 193 + "lineNumber": 228 + }, + { + "name": "snapshot", + "signature": "func snapshot(_ keepTransparency: Bool) -> JSPromise?", + "isStatic": false, + "rawDocumentation": "Capture the current on-screen contents of this window as an image.\n\nRequires **Screen Recording** permission.\n\n- Parameter keepTransparency?: Whether to preserve the window's alpha channel. If `false` (the default), transparent regions are filled with an opaque black background.\n- Returns: {Promise} Resolves with the captured image, or rejects if the capture fails (e.g. permission denied, or the window could no longer be located).\n- Example:\n```js\nconst win = hs.window.focusedWindow()\nwin.snapshot().then(img => img.saveToFile(\"/tmp/window.png\"))\n```", + "description": "Capture the current on-screen contents of this window as an image.\nRequires **Screen Recording** permission.", + "params": [ + { + "name": "keepTransparency", + "type": "boolean", + "description": "Whether to preserve the window's alpha channel. If `false` (the default), transparent regions are filled with an opaque black background.", + "optional": true, + "tsType": null + } + ], + "returns": { + "type": "JSPromise", + "description": "Resolves with the captured image, or rejects if the capture fails (e.g. permission denied, or the window could no longer be located).", + "promiseType": "HSImage" + }, + "notes": [], + "examples": [ + { + "lang": "js", + "code": "const win = hs.window.focusedWindow()\nwin.snapshot().then(img => img.saveToFile(\"/tmp/window.png\"))" + } + ], + "source": "swift", + "filePath": "Hammerspoon 2/Modules/hs.window/HSWindow.swift", + "lineNumber": 243 }, { "name": "axElement", @@ -25234,7 +25303,7 @@ ], "source": "swift", "filePath": "Hammerspoon 2/Modules/hs.window/HSWindow.swift", - "lineNumber": 204 + "lineNumber": 254 } ], "properties": [ @@ -25253,7 +25322,7 @@ ], "source": "swift", "filePath": "Hammerspoon 2/Modules/hs.window/HSWindow.swift", - "lineNumber": 27 + "lineNumber": 62 }, { "name": "application", @@ -25270,7 +25339,7 @@ ], "source": "swift", "filePath": "Hammerspoon 2/Modules/hs.window/HSWindow.swift", - "lineNumber": 35 + "lineNumber": 70 }, { "name": "pid", @@ -25287,7 +25356,7 @@ ], "source": "swift", "filePath": "Hammerspoon 2/Modules/hs.window/HSWindow.swift", - "lineNumber": 43 + "lineNumber": 78 }, { "name": "id", @@ -25304,7 +25373,7 @@ ], "source": "swift", "filePath": "Hammerspoon 2/Modules/hs.window/HSWindow.swift", - "lineNumber": 52 + "lineNumber": 87 }, { "name": "isMinimized", @@ -25321,7 +25390,7 @@ ], "source": "swift", "filePath": "Hammerspoon 2/Modules/hs.window/HSWindow.swift", - "lineNumber": 62 + "lineNumber": 97 }, { "name": "isVisible", @@ -25338,7 +25407,7 @@ ], "source": "swift", "filePath": "Hammerspoon 2/Modules/hs.window/HSWindow.swift", - "lineNumber": 70 + "lineNumber": 105 }, { "name": "isFocused", @@ -25355,7 +25424,7 @@ ], "source": "swift", "filePath": "Hammerspoon 2/Modules/hs.window/HSWindow.swift", - "lineNumber": 78 + "lineNumber": 113 }, { "name": "isFullscreen", @@ -25372,7 +25441,7 @@ ], "source": "swift", "filePath": "Hammerspoon 2/Modules/hs.window/HSWindow.swift", - "lineNumber": 86 + "lineNumber": 121 }, { "name": "isStandard", @@ -25389,7 +25458,7 @@ ], "source": "swift", "filePath": "Hammerspoon 2/Modules/hs.window/HSWindow.swift", - "lineNumber": 94 + "lineNumber": 129 }, { "name": "position", @@ -25406,7 +25475,7 @@ ], "source": "swift", "filePath": "Hammerspoon 2/Modules/hs.window/HSWindow.swift", - "lineNumber": 104 + "lineNumber": 139 }, { "name": "size", @@ -25423,7 +25492,7 @@ ], "source": "swift", "filePath": "Hammerspoon 2/Modules/hs.window/HSWindow.swift", - "lineNumber": 112 + "lineNumber": 147 }, { "name": "frame", @@ -25440,7 +25509,7 @@ ], "source": "swift", "filePath": "Hammerspoon 2/Modules/hs.window/HSWindow.swift", - "lineNumber": 120 + "lineNumber": 155 }, { "name": "screen", @@ -25457,7 +25526,7 @@ ], "source": "swift", "filePath": "Hammerspoon 2/Modules/hs.window/HSWindow.swift", - "lineNumber": 128 + "lineNumber": 163 } ] } @@ -27544,5 +27613,5 @@ "types": [] } ], - "generatedAt": "2026-09-09T14:10:40.769Z" + "generatedAt": "2026-09-09T15:56:16.638Z" } \ No newline at end of file diff --git a/docs/hammerspoon.d.ts b/docs/hammerspoon.d.ts index 3b967b413..5cf161ea5 100644 --- a/docs/hammerspoon.d.ts +++ b/docs/hammerspoon.d.ts @@ -9604,6 +9604,15 @@ declare namespace hs.window { */ function orderedWindows(): HSWindow[]; + /** + * Capture the current on-screen contents of the window with the given ID. +Requires **Screen Recording** permission. + * @param id The window's underlying ID (see the `id` property on `hs.window` objects). + * @param keepTransparency Whether to preserve the window's alpha channel. If `false` (the default), transparent regions are filled with an opaque black background. + * @returns Resolves with the captured image, or rejects if no window with that ID can be found, or the capture fails. + */ + function snapshotForID(id: number, keepTransparency?: boolean): Promise; + /** * Find windows by title Parameter title: The window title to search for. All windows with titles that include this string, will be matched @@ -9690,6 +9699,14 @@ declare class HSWindow { */ centerOnScreen(): void; + /** + * Capture the current on-screen contents of this window as an image. +Requires **Screen Recording** permission. + * @param keepTransparency Whether to preserve the window's alpha channel. If `false` (the default), transparent regions are filled with an opaque black background. + * @returns Resolves with the captured image, or rejects if the capture fails (e.g. permission denied, or the window could no longer be located). + */ + snapshot(keepTransparency?: boolean): Promise; + /** * Get the underlying AXElement * @returns The accessibility element for this window diff --git a/docs/js/html/HSWindow.html b/docs/js/html/HSWindow.html index 6aaf2e69b..521f0da87 100644 --- a/docs/js/html/HSWindow.html +++ b/docs/js/html/HSWindow.html @@ -76,7 +76,7 @@

title

string
The window's title
@@ -84,7 +84,7 @@

application

HSApplication
The application that owns this window
@@ -92,7 +92,7 @@

pid

number
The process ID of the application that owns this window
@@ -101,7 +101,7 @@

id

The window's underlying ID. A value of 0 or -1 likely means no window ID could be determined.
@@ -117,7 +117,7 @@

isVisible

boolean
Whether the window is visible (not minimized or hidden)
@@ -141,7 +141,7 @@

isStandard

boolean
Whether the window is standard (has a titlebar)
@@ -149,7 +149,7 @@

position

HSPoint
The window's position on screen {x: Int, y: Int}
@@ -157,7 +157,7 @@

size

HSSize
The window's size {w: Int, h: Int}
@@ -165,7 +165,7 @@

frame

HSRect
The window's frame {x: Int, y: Int, w: Int, h: Int}
@@ -173,7 +173,7 @@

screen

HSScreen
The screen that contains the largest portion of this window.
@@ -199,7 +199,7 @@

wins[0].focus() +
+

+snapshot(keepTransparency) -> Promise<HSImage> +

+ +
Capture the current on-screen contents of this window as an image. +Requires **Screen Recording** permission.
+ + +
snapshot(keepTransparency) -> Promise<HSImage>
+ + + + + + + + + + + + + + + + + +
NameTypeDescription
keepTransparencybooleanWhether to preserve the window's alpha channel. If `false` (the default), transparent regions are filled with an opaque black background.
+ + +
Promise<HSImage>
+
Resolves with the captured image, or rejects if the capture fails (e.g. permission denied, or the window could no longer be located).
+ + + +
const win = hs.window.focusedWindow()
+win.snapshot().then(img => img.saveToFile("/tmp/window.png"))
+ +
diff --git a/docs/js/html/hs.window.html b/docs/js/html/hs.window.html index 6af92c447..649d3b439 100644 --- a/docs/js/html/hs.window.html +++ b/docs/js/html/hs.window.html @@ -282,6 +282,50 @@

hs.window.orderedWindows() -> HSWindow[]

Hammerspoon 2/Modules/hs.window/HSWindowModule.swift:78 +
+

hs.window.snapshotForID(id, keepTransparency) -> Promise<HSImage>

+ +
Capture the current on-screen contents of the window with the given ID. +Requires **Screen Recording** permission.
+ + +
hs.window.snapshotForID(id, keepTransparency) -> Promise<HSImage>
+ + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
idnumberThe window's underlying ID (see the `id` property on `hs.window` objects).
keepTransparencybooleanWhether to preserve the window's alpha channel. If `false` (the default), transparent regions are filled with an opaque black background.
+ + +
Promise<HSImage>
+
Resolves with the captured image, or rejects if no window with that ID can be found, or the capture fails.
+ + + +
hs.window.snapshotForID(12345).then(img => img.saveToFile("/tmp/window.png"))
+ + +

hs.window.findByTitle(title) -> HSWindow[]

diff --git a/docs/js/html/script.js b/docs/js/html/script.js index e3aba1fee..c94a3620f 100644 --- a/docs/js/html/script.js +++ b/docs/js/html/script.js @@ -421,7 +421,7 @@ const navigationData = { } ] }; -const searchIndex = [{"fullName":"hs.canvas","description":"A complete guide to hs.canvas: the element/property reference, the action pipeline, and worked examples combining shapes, text, images, gradients, and mouse interaction.","url":"canvas-guide.html","kind":"guide"},{"fullName":"Spoons","description":"How to install, use, and write Spoons - packaged, reusable pieces of Hammerspoon 2 configuration.","url":"spoons-guide.html","kind":"guide"},{"fullName":"Migrating from Hammerspoon 1","description":"A guide for Hammerspoon 1 users on what changed, what moved, and what was removed in Hammerspoon 2.","url":"migration-guide.html","kind":"guide"},{"fullName":"Getting Started","description":"A guide to your first Hammerspoon 2 config: hotkeys, object lifecycle, watchers, and hs.ui.","url":"getting-started.html","kind":"guide"},{"fullName":"console","description":"These functions are provided to maintain convenience with the console.log() function present in many JavaScript instances.","url":"console.html","kind":"module"},{"fullName":"console.log(message)","description":"Log a message to the Hammerspoon Log Window","url":"console.html#log","kind":"method"},{"fullName":"console.error(message)","description":"Log an error to the Hammerspoon Log Window","url":"console.html#error","kind":"method"},{"fullName":"console.warn(message)","description":"Log a warning to the Hammerspoon Log WIndow","url":"console.html#warn","kind":"method"},{"fullName":"console.info(message)","description":"Log an informational message to the Hammerspoon Log Window","url":"console.html#info","kind":"method"},{"fullName":"console.debug(message)","description":"Log a debug message to the Hammerspoon Log Window","url":"console.html#debug","kind":"method"},{"fullName":"hs","description":"","url":"hs.html","kind":"module"},{"fullName":"hs.spoons","description":"A namespace holding every Spoon loaded so far via loadSpoon(), keyed by name - e.g. a Spoon loaded with hs.loadSpoon(\"MySpoon\") is also reachable as hs.spoons.MySpoon. Empty until at least one Spoon has been loaded.","url":"hs.html#spoons","kind":"property"},{"fullName":"hs.reload()","description":"Destroy the current JavaScript runtime and start a new one, loading all configuration from disk again","url":"hs.html#reload","kind":"method"},{"fullName":"hs.collectGarbage()","description":"Force garbage collection of JavaScript objects that no longer have any references","url":"hs.html#collectGarbage","kind":"method"},{"fullName":"hs.openConsole()","description":"Open the Hammerspoon Console window","url":"hs.html#openConsole","kind":"method"},{"fullName":"hs.closeConsole()","description":"Close the Hammerspoon Console window","url":"hs.html#closeConsole","kind":"method"},{"fullName":"hs.clearConsole()","description":"Clear the Hammerspoon Console log","url":"hs.html#clearConsole","kind":"method"},{"fullName":"hs.loadSpoon(name)","description":"Load a Spoon - a packaged, reusable piece of configuration - by name, from the Spoons directory inside your config directory. A Spoon must contain a well-formed spoon.json (with non-empty name, author, version, and description fields) and an init.js, or loading fails with an exception. init.js is loaded through the same require() used for the rest of your config, so it can itself require() further files from within the Spoon's own directory using relative paths. On success, the Spoon's module.exports is also stored on hs.spoons under its name, so other code can reach an already-loaded Spoon without needing to call loadSpoon() again. init.js must set module.exports to an object (or a function, since functions are objects too) - loading fails with an exception otherwise. Its author, description, and version properties are then set from spoon.json, overwriting any of the same name the Spoon's own init.js set, so that information is always present and always reflects what's on disk. If the resulting object has an init() method, it's called automatically (with this bound to the object) before loadSpoon() returns - matching Hammerspoon 1's behavior. An exception thrown from init() fails the load: nothing is stored on hs.spoons, and loadSpoon() throws. Unlike init.js itself (which require() only ever evaluates once), init() runs again on every loadSpoon() call for the same Spoon, since the same cached object is returned each time - write it to be safe to call more than once, or do one-time setup at init.js's top level instead.","url":"hs.html#loadSpoon","kind":"method"},{"fullName":"hs.appinfo","description":"Module for accessing information about the Hammerspoon application itself","url":"hs.appinfo.html","kind":"module"},{"fullName":"hs.appinfo.appName","description":"The application's internal name (e.g., \"Hammerspoon 2\")","url":"hs.appinfo.html#appName","kind":"property"},{"fullName":"hs.appinfo.displayName","description":"The application's display name shown to users","url":"hs.appinfo.html#displayName","kind":"property"},{"fullName":"hs.appinfo.version","description":"The application's version string (e.g., \"2.0.0\")","url":"hs.appinfo.html#version","kind":"property"},{"fullName":"hs.appinfo.build","description":"The application's build number","url":"hs.appinfo.html#build","kind":"property"},{"fullName":"hs.appinfo.minimumOSVersion","description":"The minimum macOS version required to run this application","url":"hs.appinfo.html#minimumOSVersion","kind":"property"},{"fullName":"hs.appinfo.copyrightNotice","description":"The copyright notice for this application","url":"hs.appinfo.html#copyrightNotice","kind":"property"},{"fullName":"hs.appinfo.bundleIdentifier","description":"The application's bundle identifier (e.g., \"com.hammerspoon.Hammerspoon-2\")","url":"hs.appinfo.html#bundleIdentifier","kind":"property"},{"fullName":"hs.appinfo.bundlePath","description":"The filesystem path to the application bundle","url":"hs.appinfo.html#bundlePath","kind":"property"},{"fullName":"hs.appinfo.resourcePath","description":"The filesystem path to the application's resource directory","url":"hs.appinfo.html#resourcePath","kind":"property"},{"fullName":"hs.appinfo.configPath","description":"The filesystem path to the main Hammerspoon 2 configuration file","url":"hs.appinfo.html#configPath","kind":"property"},{"fullName":"hs.appinfo.configDir","description":"The filesystem path to the directory Hammerspoon 2 loaded its config from","url":"hs.appinfo.html#configDir","kind":"property"},{"fullName":"hs.appinfo.machineName","description":"The user-assigned name of this Mac, as shown in System Settings > Sharing","url":"hs.appinfo.html#machineName","kind":"property"},{"fullName":"hs.appinfo.pid","description":"Hammerspoon 2's Process Identifier (PID)","url":"hs.appinfo.html#pid","kind":"property"},{"fullName":"hs.appinfo.arguments","description":"The command-line arguments Hammerspoon 2 was launched with","url":"hs.appinfo.html#arguments","kind":"property"},{"fullName":"hs.appinfo.environment","description":"The environment variables Hammerspoon 2 was launched with","url":"hs.appinfo.html#environment","kind":"property"},{"fullName":"hs.appinfo.osVersion","description":"The version of macOS Hammerspoon 2 is currently running on (e.g., \"Version 26.5.2 (Build 25F84)\")","url":"hs.appinfo.html#osVersion","kind":"property"},{"fullName":"hs.appinfo.osVersionParts","description":"The version of macOS Hammerspoon 2 is currently running on, broken into its numeric components Keys: major, minor, patch.","url":"hs.appinfo.html#osVersionParts","kind":"property"},{"fullName":"hs.appinfo.cpuCount","description":"The number of logical CPU cores available on this Mac","url":"hs.appinfo.html#cpuCount","kind":"property"},{"fullName":"hs.appinfo.ramAmount","description":"The amount of physical RAM installed on this Mac, in gigabytes","url":"hs.appinfo.html#ramAmount","kind":"property"},{"fullName":"hs.application","description":"Module for interacting with applications","url":"hs.application.html","kind":"module"},{"fullName":"hs.application.runningApplications()","description":"Fetch all running applications","url":"hs.application.html#runningApplications","kind":"method"},{"fullName":"hs.application.matchingName(name)","description":"Fetch the first running application that matches a name","url":"hs.application.html#matchingName","kind":"method"},{"fullName":"hs.application.matchingBundleID(bundleID)","description":"Fetch the first running application that matches a Bundle ID","url":"hs.application.html#matchingBundleID","kind":"method"},{"fullName":"hs.application.fromPID(pid)","description":"Fetch the running application that matches a POSIX PID","url":"hs.application.html#fromPID","kind":"method"},{"fullName":"hs.application.frontmost()","description":"Fetch the currently focused application","url":"hs.application.html#frontmost","kind":"method"},{"fullName":"hs.application.menuBarOwner()","description":"Fetch the application which currently owns the menu bar","url":"hs.application.html#menuBarOwner","kind":"method"},{"fullName":"hs.application.pathForBundleID(bundleID)","description":"Fetch the filesystem path for an application","url":"hs.application.html#pathForBundleID","kind":"method"},{"fullName":"hs.application.pathsForBundleID(bundleID)","description":"Fetch filesystem paths for an application","url":"hs.application.html#pathsForBundleID","kind":"method"},{"fullName":"hs.application.pathForFileType(fileType)","description":"Fetch filesystem path for an application able to open a given file type","url":"hs.application.html#pathForFileType","kind":"method"},{"fullName":"hs.application.pathsForFileType(fileType)","description":"Fetch filesystem paths for applications able to open a given file type","url":"hs.application.html#pathsForFileType","kind":"method"},{"fullName":"hs.application.launchOrFocus(bundleID)","description":"Launch an application, or give it focus if it's already running","url":"hs.application.html#launchOrFocus","kind":"method"},{"fullName":"hs.application.addWatcher(listener)","description":"Create a watcher for application events","url":"hs.application.html#addWatcher","kind":"method"},{"fullName":"hs.application.removeWatcher(listener)","description":"Remove a watcher for application events","url":"hs.application.html#removeWatcher","kind":"method"},{"fullName":"hs.audiodevice","description":"Module for discovering and controlling audio devices.","url":"hs.audiodevice.html","kind":"module"},{"fullName":"hs.audiodevice.all()","description":"All audio devices attached to the system.","url":"hs.audiodevice.html#all","kind":"method"},{"fullName":"hs.audiodevice.allOutputDevices()","description":"All audio devices that have at least one output stream.","url":"hs.audiodevice.html#allOutputDevices","kind":"method"},{"fullName":"hs.audiodevice.allInputDevices()","description":"All audio devices that have at least one input stream.","url":"hs.audiodevice.html#allInputDevices","kind":"method"},{"fullName":"hs.audiodevice.defaultOutputDevice()","description":"The current system default output device.","url":"hs.audiodevice.html#defaultOutputDevice","kind":"method"},{"fullName":"hs.audiodevice.defaultInputDevice()","description":"The current system default input device.","url":"hs.audiodevice.html#defaultInputDevice","kind":"method"},{"fullName":"hs.audiodevice.defaultEffectDevice()","description":"The current system alert sound device.","url":"hs.audiodevice.html#defaultEffectDevice","kind":"method"},{"fullName":"hs.audiodevice.findDeviceByName(name)","description":"Find the first audio device whose name matches the given string.","url":"hs.audiodevice.html#findDeviceByName","kind":"method"},{"fullName":"hs.audiodevice.findDeviceByUID(uid)","description":"Find the audio device with the given unique identifier.","url":"hs.audiodevice.html#findDeviceByUID","kind":"method"},{"fullName":"hs.audiodevice.addWatcher(listener)","description":"Register a listener for all system-level audio configuration events.","url":"hs.audiodevice.html#addWatcher","kind":"method"},{"fullName":"hs.audiodevice.removeWatcher(listener)","description":"Remove a previously registered system-level listener.","url":"hs.audiodevice.html#removeWatcher","kind":"method"},{"fullName":"hs.ax","description":"# Accessibility API Module","url":"hs.ax.html","kind":"module"},{"fullName":"hs.ax.notificationTypes","description":"A dictionary containing all of the notification types that can be used with hs.ax.addWatcher()","url":"hs.ax.html#notificationTypes","kind":"property"},{"fullName":"hs.ax.systemWideElement()","description":"Get the system-wide accessibility element","url":"hs.ax.html#systemWideElement","kind":"method"},{"fullName":"hs.ax.applicationElement(element)","description":"Get the accessibility element for an application","url":"hs.ax.html#applicationElement","kind":"method"},{"fullName":"hs.ax.windowElement(window)","description":"Get the accessibility element for a window","url":"hs.ax.html#windowElement","kind":"method"},{"fullName":"hs.ax.elementAtPoint(point)","description":"Get the accessibility element at the specific screen position","url":"hs.ax.html#elementAtPoint","kind":"method"},{"fullName":"hs.ax.addWatcher(application, notification, listener)","description":"Add a watcher for application AX events","url":"hs.ax.html#addWatcher","kind":"method"},{"fullName":"hs.ax.removeWatcher(application, notification, listener)","description":"Remove a watcher for application AX events","url":"hs.ax.html#removeWatcher","kind":"method"},{"fullName":"hs.ax.focusedElement()","description":"Fetch the focused UI element","url":"hs.ax.html#focusedElement","kind":"method"},{"fullName":"hs.ax.findByRole(role, parent)","description":"Find AX elements matching a given role","url":"hs.ax.html#findByRole","kind":"method"},{"fullName":"hs.ax.findByTitle(title, parent)","description":"Find AX elements whose title contains a given string","url":"hs.ax.html#findByTitle","kind":"method"},{"fullName":"hs.ax.printHierarchy(element, maxDepth)","description":"Print the accessibility hierarchy of an element to the Console","url":"hs.ax.html#printHierarchy","kind":"method"},{"fullName":"hs.bonjour","description":"Discover and publish Bonjour (mDNS / Zeroconf) network services.","url":"hs.bonjour.html","kind":"module"},{"fullName":"hs.bonjour.serviceTypes","description":"A frozen object mapping short service-type names to their mDNS strings. Populated by the JavaScript enhancement layer.","url":"hs.bonjour.html#serviceTypes","kind":"property"},{"fullName":"hs.bonjour.createSearch()","description":"Creates a new Bonjour search for discovering services or domains. Call one of the find… methods on the returned search to start discovering. Remove it with removeSearch() when finished.","url":"hs.bonjour.html#createSearch","kind":"method"},{"fullName":"hs.bonjour.removeSearch(search)","description":"Stops and removes a previously created search.","url":"hs.bonjour.html#removeSearch","kind":"method"},{"fullName":"hs.bonjour.advertise(name, type, port, domain, callback)","description":"Starts advertising a local service on the network. If domain is omitted or not a string, it defaults to \"local.\". If the 4th argument is a function, it is used as the callback and domain defaults to \"local.\".","url":"hs.bonjour.html#advertise","kind":"method"},{"fullName":"hs.bonjour.stopAdvertising(name, type)","description":"Stops advertising a service previously started with advertise().","url":"hs.bonjour.html#stopAdvertising","kind":"method"},{"fullName":"hs.bonjour.networkServices(timeout)","description":"Returns a Promise that resolves to an array of service-type strings currently advertised on the local network. Internally searches for _services._dns-sd._udp. services, collects results for up to timeout seconds (or until the browser signals no more results), then resolves.","url":"hs.bonjour.html#networkServices","kind":"method"},{"fullName":"hs.camera","description":"Module for discovering and interacting with camera devices.","url":"hs.camera.html","kind":"module"},{"fullName":"hs.camera.all()","description":"All video camera devices currently connected to the system.","url":"hs.camera.html#all","kind":"method"},{"fullName":"hs.camera.findByName(name)","description":"Find the first camera whose name matches the given string.","url":"hs.camera.html#findByName","kind":"method"},{"fullName":"hs.camera.findByUID(uid)","description":"Find the camera with the given unique identifier.","url":"hs.camera.html#findByUID","kind":"method"},{"fullName":"hs.camera.addWatcher(listener)","description":"Register a listener for camera device connect/disconnect events.","url":"hs.camera.html#addWatcher","kind":"method"},{"fullName":"hs.camera.removeWatcher(listener)","description":"Remove a previously registered module-level event listener.","url":"hs.camera.html#removeWatcher","kind":"method"},{"fullName":"hs.canvas","description":"# hs.canvas","url":"hs.canvas.html","kind":"module"},{"fullName":"hs.canvas.windowLevels","description":"Named window levels, exposed as raw numeric values (not opaque strings) so scripts can do arithmetic on them, matching v1 behavior.","url":"hs.canvas.html#windowLevels","kind":"property"},{"fullName":"hs.canvas.windowBehaviors","description":"Named window Spaces/Exposé collection behaviors, exposed as raw numeric bit values.","url":"hs.canvas.html#windowBehaviors","kind":"property"},{"fullName":"hs.canvas.compositeTypes","description":"Named compositing/blend rules usable as an element's compositeRule attribute.","url":"hs.canvas.html#compositeTypes","kind":"property"},{"fullName":"hs.canvas.create(rect)","description":"Create a new canvas Named create() rather than v1's new() -- new cannot be used as a JavaScriptCore-exported method name (it collides with the JS new operator keyword at the bridging layer), and this codebase's conventions additionally forbid method names starting with new/alloc/copy (an ARC/ObjC hazard).","url":"hs.canvas.html#create","kind":"method"},{"fullName":"hs.chooser","description":"# hs.chooser","url":"hs.chooser.html","kind":"module"},{"fullName":"hs.chooser.create()","description":"Create a new chooser.","url":"hs.chooser.html#create","kind":"method"},{"fullName":"hs.docs","description":"# hs.docs","url":"hs.docs.html","kind":"module"},{"fullName":"hs.docs.show(moduleName, showTS)","description":"Open the Hammerspoon 2 API documentation in a new window","url":"hs.docs.html#show","kind":"method"},{"fullName":"hs.docs.get(identifier)","description":"Return documentation for a module, method, or property","url":"hs.docs.html#get","kind":"method"},{"fullName":"hs.docs.jsDocsPath()","description":"Return the filesystem path to the bundled JS documentation directory","url":"hs.docs.html#jsDocsPath","kind":"method"},{"fullName":"hs.docs.tsDocsPath()","description":"Return the filesystem path to the bundled TypeScript documentation directory","url":"hs.docs.html#tsDocsPath","kind":"method"},{"fullName":"hs.docs.apiJSON()","description":"Return the contents of the bundled api.json file","url":"hs.docs.html#apiJSON","kind":"method"},{"fullName":"hs.eventtap","description":"Monitor and synthesise macOS input events: keyboard, mouse, and scroll wheel.","url":"hs.eventtap.html","kind":"module"},{"fullName":"hs.eventtap.eventTypes","description":"A dictionary mapping event type names to their numeric values. Pass values from this dictionary to addWatcher() to specify which events to monitor.","url":"hs.eventtap.html#eventTypes","kind":"property"},{"fullName":"hs.eventtap.modifierFlags","description":"A dictionary mapping modifier key names to their bitmask values for use with rawFlags. Includes generic names (cmd, shift, alt, ctrl) and side-specific names (leftCmd, rightCmd, leftShift, rightShift, leftAlt, rightAlt, leftCtrl, rightCtrl) for distinguishing physical keys.","url":"hs.eventtap.html#modifierFlags","kind":"property"},{"fullName":"hs.eventtap.consume","description":"Return this from an event tap callback to suppress the event (prevent other apps from receiving it).","url":"hs.eventtap.html#consume","kind":"property"},{"fullName":"hs.eventtap.emit","description":"Return this from an event tap callback to allow the event to pass through to other applications.","url":"hs.eventtap.html#emit","kind":"property"},{"fullName":"hs.eventtap.addWatcher(types, callback, listenOnly)","description":"Create an event tap that calls a function for matching events. Call .start() to activate it. The callback receives an HSEventTapEvent. For modify taps (listenOnly omitted or false), return hs.eventtap.consume (false) to suppress the event or hs.eventtap.emit (true) to pass it through. For listen-only taps the callback's return value is ignored — events are always delivered to other applications. Requires Accessibility permission.","url":"hs.eventtap.html#addWatcher","kind":"method"},{"fullName":"hs.eventtap.removeWatcher(tap)","description":"Stop and remove a previously created watcher","url":"hs.eventtap.html#removeWatcher","kind":"method"},{"fullName":"hs.eventtap.makeKeyEvent(key, isDown)","description":"Create a keyboard event","url":"hs.eventtap.html#makeKeyEvent","kind":"method"},{"fullName":"hs.eventtap.makeKeyEventWithCode(keyCode, isDown)","description":"Create a keyboard event using a raw key code","url":"hs.eventtap.html#makeKeyEventWithCode","kind":"method"},{"fullName":"hs.eventtap.makeMouseEvent(type, x, y, button)","description":"Create a mouse event at the given position. Coordinates are in Hammerspoon screen coordinates (top-left origin of the primary display, y increases downward), matching the values returned by hs.screen.","url":"hs.eventtap.html#makeMouseEvent","kind":"method"},{"fullName":"hs.eventtap.makeScrollWheelEvent(deltaX, deltaY, x, y)","description":"Create a scroll wheel event at the given position. Coordinates are in Hammerspoon screen coordinates (top-left origin, y increases downward).","url":"hs.eventtap.html#makeScrollWheelEvent","kind":"method"},{"fullName":"hs.eventtap.keyStroke(mods, key)","description":"Send a key down and key up event with optional modifier keys. A 5 ms pause is inserted between the key-down and key-up events to improve compatibility with applications that miss very fast synthetic keystrokes.","url":"hs.eventtap.html#keyStroke","kind":"method"},{"fullName":"hs.eventtap.keyStrokes(text)","description":"Type a string of characters as individual key events. A 5 ms pause is inserted between each key-down and key-up event. This blocks the calling thread (the main thread) for the duration of typing — for long strings, prefer keyStrokesAsync() to avoid stalling the rest of Hammerspoon while typing.","url":"hs.eventtap.html#keyStrokes","kind":"method"},{"fullName":"hs.eventtap.keyStrokesAsync(text)","description":"Type a string of characters as individual key events, without blocking the main thread. Behaves like keyStrokes(), but the key events are posted from a background task, so JavaScript execution and the rest of Hammerspoon continue running while typing proceeds.","url":"hs.eventtap.html#keyStrokesAsync","kind":"method"},{"fullName":"hs.eventtap.leftClick(x, y)","description":"Post a left mouse button click at the given position. Coordinates are in Hammerspoon screen coordinates (top-left origin, y increases downward).","url":"hs.eventtap.html#leftClick","kind":"method"},{"fullName":"hs.eventtap.rightClick(x, y)","description":"Post a right mouse button click at the given position. Coordinates are in Hammerspoon screen coordinates (top-left origin, y increases downward).","url":"hs.eventtap.html#rightClick","kind":"method"},{"fullName":"hs.eventtap.doubleLeftClick(x, y)","description":"Post a left mouse button double-click at the given position. Coordinates are in Hammerspoon screen coordinates (top-left origin, y increases downward).","url":"hs.eventtap.html#doubleLeftClick","kind":"method"},{"fullName":"hs.eventtap.middleClick(x, y)","description":"Post a middle mouse button click at the given position. Coordinates are in Hammerspoon screen coordinates (top-left origin, y increases downward).","url":"hs.eventtap.html#middleClick","kind":"method"},{"fullName":"hs.eventtap.scrollWheel(deltaX, deltaY, x, y)","description":"Post a scroll wheel event at the given position. Coordinates are in Hammerspoon screen coordinates (top-left origin, y increases downward).","url":"hs.eventtap.html#scrollWheel","kind":"method"},{"fullName":"hs.eventtap.currentModifiers()","description":"Returns the currently held modifier keys","url":"hs.eventtap.html#currentModifiers","kind":"method"},{"fullName":"hs.eventtap.checkMouseButtons()","description":"Returns the currently pressed mouse buttons","url":"hs.eventtap.html#checkMouseButtons","kind":"method"},{"fullName":"hs.eventtap.mouseLocation()","description":"Returns the current mouse cursor position in Hammerspoon screen coordinates (top-left origin of primary display, y increases downward, matching hs.screen).","url":"hs.eventtap.html#mouseLocation","kind":"method"},{"fullName":"hs.eventtap.doubleClickInterval()","description":"Returns the system double-click interval in seconds","url":"hs.eventtap.html#doubleClickInterval","kind":"method"},{"fullName":"hs.eventtap.keyRepeatDelay()","description":"Returns the system key repeat delay in seconds","url":"hs.eventtap.html#keyRepeatDelay","kind":"method"},{"fullName":"hs.eventtap.keyRepeatInterval()","description":"Returns the system key repeat interval in seconds","url":"hs.eventtap.html#keyRepeatInterval","kind":"method"},{"fullName":"hs.eventtap.bindHotkey(mods, key, callbackPressed, callbackReleased)","description":"Bind a keyboard shortcut using an event tap. Unlike hs.hotkey.bind(), this supports the fn modifier and left/right modifier key distinction (e.g. leftCmd, rightAlt). The hotkey is active immediately and consumes (suppresses) the key events. It's important to note that this a much heavier-weight tool than hs.hotkey - every single key you press will be examined by Hammerspoon to see if it matches one of the EventTap hotkeys (where hs.hotkey relies on macOS to efficiently deliver only matching keypresses). Please consider this when choosing to use hs.eventtap for hotkeys. Requires Accessibility permission. ctrl, fn) and side-specific names (leftCmd, rightCmd, leftAlt, rightAlt, leftCtrl, rightCtrl, leftShift, rightShift).","url":"hs.eventtap.html#bindHotkey","kind":"method"},{"fullName":"hs.eventtap.removeHotkey(hotkey)","description":"Remove a previously bound hotkey and stop it from firing","url":"hs.eventtap.html#removeHotkey","kind":"method"},{"fullName":"hs.fs","description":"Module for filesystem operations.","url":"hs.fs.html","kind":"module"},{"fullName":"hs.fs.read(path, offset, length)","description":"Read part or all of a file as a UTF-8 string.","url":"hs.fs.html#read","kind":"method"},{"fullName":"hs.fs.readLines(path, callback)","description":"Read a file line-by-line, invoking a callback for each line. Lines are delivered with newline characters stripped. Both \\n and \\r\\n line endings are handled.","url":"hs.fs.html#readLines","kind":"method"},{"fullName":"hs.fs.write(path, content, inPlace)","description":"Write a UTF-8 string to a file, creating it or overwriting any existing content. Intermediate directories are not created automatically; use mkdir first if needed.","url":"hs.fs.html#write","kind":"method"},{"fullName":"hs.fs.append(path, content)","description":"Append a UTF-8 string to a file, creating it if it does not exist.","url":"hs.fs.html#append","kind":"method"},{"fullName":"hs.fs.exists(path)","description":"Determine if a filesystem object exists at the given path Unlike isFile and isDirectory, this follows symlinks.","url":"hs.fs.html#exists","kind":"method"},{"fullName":"hs.fs.isFile(path)","description":"Determine if a file exists at the given path This does not follow symlinks; a symlink pointing at a file returns false.","url":"hs.fs.html#isFile","kind":"method"},{"fullName":"hs.fs.isDirectory(path)","description":"Determine if a directory exists at the given path This does not follow symlinks; a symlink pointing at a directory returns false.","url":"hs.fs.html#isDirectory","kind":"method"},{"fullName":"hs.fs.isSymlink(path)","description":"Determine if a symlink exists at the given path","url":"hs.fs.html#isSymlink","kind":"method"},{"fullName":"hs.fs.isReadable(path)","description":"Determine if a given filesystem path is readable","url":"hs.fs.html#isReadable","kind":"method"},{"fullName":"hs.fs.isWritable(path)","description":"Determine if a given filesystem path is writable","url":"hs.fs.html#isWritable","kind":"method"},{"fullName":"hs.fs.copy(source, destination)","description":"Copy a file or directory to a new location. The destination must not already exist. If source is a directory, its entire contents are copied recursively.","url":"hs.fs.html#copy","kind":"method"},{"fullName":"hs.fs.move(source, destination)","description":"Move (rename) a file or directory. The destination must not already exist.","url":"hs.fs.html#move","kind":"method"},{"fullName":"hs.fs.deletePath(path)","description":"Delete a file or directory at the given path. Directories are removed recursively. To remove only an empty directory, use rmdir instead.","url":"hs.fs.html#deletePath","kind":"method"},{"fullName":"hs.fs.list(path)","description":"List the immediate contents of a directory. Returns bare filenames (not full paths), sorted alphabetically. The . and .. entries are never included.","url":"hs.fs.html#list","kind":"method"},{"fullName":"hs.fs.listRecursive(path)","description":"Recursively list all entries under a directory. Returns paths relative to path, sorted alphabetically.","url":"hs.fs.html#listRecursive","kind":"method"},{"fullName":"hs.fs.mkdir(path)","description":"Create a directory, including all necessary intermediate directories. Succeeds silently if the directory already exists.","url":"hs.fs.html#mkdir","kind":"method"},{"fullName":"hs.fs.rmdir(path)","description":"Remove an empty directory. Fails if the directory is not empty. Use deletePath to remove a non-empty directory recursively.","url":"hs.fs.html#rmdir","kind":"method"},{"fullName":"hs.fs.currentDir()","description":"Returns the current working directory of the process.","url":"hs.fs.html#currentDir","kind":"method"},{"fullName":"hs.fs.chdir(path)","description":"Change the current working directory of the process.","url":"hs.fs.html#chdir","kind":"method"},{"fullName":"hs.fs.pathToAbsolute(path)","description":"Resolve a path to its absolute, canonical form. Expands ~, resolves . and .., and follows all symbolic links. Returns null if any component of the path does not exist.","url":"hs.fs.html#pathToAbsolute","kind":"method"},{"fullName":"hs.fs.displayName(path)","description":"Return the localised display name for a file or directory as shown by Finder. For example, /Library appears as \"Library\" in Finder even though its on-disk name is the same.","url":"hs.fs.html#displayName","kind":"method"},{"fullName":"hs.fs.temporaryDirectory()","description":"Returns the temporary directory for the current user.","url":"hs.fs.html#temporaryDirectory","kind":"method"},{"fullName":"hs.fs.homeDirectory()","description":"Returns the home directory for the current user.","url":"hs.fs.html#homeDirectory","kind":"method"},{"fullName":"hs.fs.urlFromPath(path)","description":"Returns a file:// URL string for the given path.","url":"hs.fs.html#urlFromPath","kind":"method"},{"fullName":"hs.fs.attributes(path)","description":"Get metadata attributes for a file or directory. Does not follow symbolic links. Use isSymlink to detect links before calling this if needed.","url":"hs.fs.html#attributes","kind":"method"},{"fullName":"hs.fs.touch(path)","description":"Update the modification timestamp of a file to the current time. Creates the file if it does not exist (equivalent to the POSIX touch command).","url":"hs.fs.html#touch","kind":"method"},{"fullName":"hs.fs.link(source, destination)","description":"Create a hard link at destination pointing at source. Both paths must be on the same filesystem volume.","url":"hs.fs.html#link","kind":"method"},{"fullName":"hs.fs.symlink(source, destination)","description":"Create a symbolic link at destination pointing at source. Unlike hard links, symlinks may cross filesystem boundaries and may point to paths that do not yet exist.","url":"hs.fs.html#symlink","kind":"method"},{"fullName":"hs.fs.readlink(path)","description":"Read the target of a symbolic link without resolving it.","url":"hs.fs.html#readlink","kind":"method"},{"fullName":"hs.fs.tags(path)","description":"Get the Finder tags assigned to a file or directory.","url":"hs.fs.html#tags","kind":"method"},{"fullName":"hs.fs.fileUTI(path)","description":"Replace all Finder tags on a file or directory. This function is only available on macOS Tahoe (26) or later.","url":"hs.fs.html#fileUTI","kind":"method"},{"fullName":"hs.fs.pathToBookmark(path)","description":"Encode a file path as a persistent bookmark that survives file moves and renames. The returned string is base64-encoded bookmark data that can be stored and later resolved with pathFromBookmark.","url":"hs.fs.html#pathToBookmark","kind":"method"},{"fullName":"hs.fs.pathFromBookmark(data)","description":"Resolve a base64-encoded bookmark back to a file path.","url":"hs.fs.html#pathFromBookmark","kind":"method"},{"fullName":"hs.fs.volumes(showHidden)","description":"Return information about all currently mounted filesystem volumes.","url":"hs.fs.html#volumes","kind":"method"},{"fullName":"hs.fs.ejectVolume(path)","description":"Unmount and eject the volume at the given path.","url":"hs.fs.html#ejectVolume","kind":"method"},{"fullName":"hs.fs.addVolumeWatcher()","description":"Create a new volume event watcher. Call setCallback() and start() on the returned object to begin receiving volume mount/unmount/rename events.","url":"hs.fs.html#addVolumeWatcher","kind":"method"},{"fullName":"hs.fs.removeVolumeWatcher(watcher)","description":"Stop and destroy a volume watcher previously created with addVolumeWatcher.","url":"hs.fs.html#removeVolumeWatcher","kind":"method"},{"fullName":"hs.fs.createPathWatcher(path)","description":"Create a watcher for filesystem events at a given path. Events are batched and delivered with a latency of approximately one second. Call setCallback() and start() on the returned object to begin receiving events.","url":"hs.fs.html#createPathWatcher","kind":"method"},{"fullName":"hs.fs.xattrGet(path, attribute, options, position)","description":"Get the value of an extended attribute for a file or directory. Attribute values are returned as ISO Latin-1 encoded strings so that arbitrary byte sequences are represented without loss. ASCII text attribute values appear readable as-is.","url":"hs.fs.html#xattrGet","kind":"method"},{"fullName":"hs.fs.xattrList(path, options)","description":"List all extended attributes defined for a file or directory.","url":"hs.fs.html#xattrList","kind":"method"},{"fullName":"hs.fs.xattrSet(path, attribute, value, options, position)","description":"Set the value of an extended attribute for a file or directory. The value is written as ISO Latin-1 bytes, providing a lossless round-trip with xattrGet. Plain ASCII strings work directly without any encoding.","url":"hs.fs.html#xattrSet","kind":"method"},{"fullName":"hs.fs.xattrRemove(path, attribute, options)","description":"Remove an extended attribute from a file or directory.","url":"hs.fs.html#xattrRemove","kind":"method"},{"fullName":"hs.hash","description":"Module for hashing and encoding operations","url":"hs.hash.html","kind":"module"},{"fullName":"hs.hash.base64Encode(data)","description":"Encode a string to base64","url":"hs.hash.html#base64Encode","kind":"method"},{"fullName":"hs.hash.base64Decode(data)","description":"Decode a base64 string","url":"hs.hash.html#base64Decode","kind":"method"},{"fullName":"hs.hash.md5(data)","description":"Generate MD5 hash of a string","url":"hs.hash.html#md5","kind":"method"},{"fullName":"hs.hash.sha1(data)","description":"Generate SHA1 hash of a string","url":"hs.hash.html#sha1","kind":"method"},{"fullName":"hs.hash.sha256(data)","description":"Generate SHA256 hash of a string","url":"hs.hash.html#sha256","kind":"method"},{"fullName":"hs.hash.sha512(data)","description":"Generate SHA512 hash of a string","url":"hs.hash.html#sha512","kind":"method"},{"fullName":"hs.hash.hmacMD5(key, data)","description":"Generate HMAC-MD5 of a string with a key","url":"hs.hash.html#hmacMD5","kind":"method"},{"fullName":"hs.hash.hmacSHA1(key, data)","description":"Generate HMAC-SHA1 of a string with a key","url":"hs.hash.html#hmacSHA1","kind":"method"},{"fullName":"hs.hash.hmacSHA256(key, data)","description":"Generate HMAC-SHA256 of a string with a key","url":"hs.hash.html#hmacSHA256","kind":"method"},{"fullName":"hs.hash.hmacSHA512(key, data)","description":"Generate HMAC-SHA512 of a string with a key","url":"hs.hash.html#hmacSHA512","kind":"method"},{"fullName":"hs.hotkey","description":"Module for creating and managing system-wide hotkeys","url":"hs.hotkey.html","kind":"module"},{"fullName":"hs.hotkey.alertDuration","description":"Duration in seconds for the on-screen toast shown when a hotkey with a message set fires. Default is 1.","url":"hs.hotkey.html#alertDuration","kind":"property"},{"fullName":"hs.hotkey.bind(mods, key, callbackPressed, callbackReleased, callbackRepeat)","description":"Bind a hotkey cmd / command / ⌘, shift / ⇧, alt / option / ⌥, ctrl / control / ⌃.","url":"hs.hotkey.html#bind","kind":"method"},{"fullName":"hs.hotkey.getKeyCodeMap()","description":"Get the system-wide mapping of key names to key codes","url":"hs.hotkey.html#getKeyCodeMap","kind":"method"},{"fullName":"hs.hotkey.getModifierMap()","description":"Get the mapping of modifier names to modifier flags","url":"hs.hotkey.html#getModifierMap","kind":"method"},{"fullName":"hs.hotkey.create(mods, key, callbackPressed, callbackReleased, callbackRepeat)","description":"Create a hotkey without enabling it cmd / command / ⌘, shift / ⇧, alt / option / ⌥, ctrl / control / ⌃.","url":"hs.hotkey.html#create","kind":"method"},{"fullName":"hs.hotkey.getHotkeys()","description":"Get a list of all currently-enabled hotkeys","url":"hs.hotkey.html#getHotkeys","kind":"method"},{"fullName":"hs.hotkey.systemAssigned(mods, key)","description":"Check whether macOS itself has already claimed a key combination (e.g. for Spotlight, screenshots, etc.)","url":"hs.hotkey.html#systemAssigned","kind":"method"},{"fullName":"hs.hotkey.assignable(mods, key)","description":"Check whether a key combination is available to be bound (i.e. not already claimed by macOS)","url":"hs.hotkey.html#assignable","kind":"method"},{"fullName":"hs.hotkey.deleteAll(mods, key)","description":"Disable and remove every hotkey currently bound to a key combination","url":"hs.hotkey.html#deleteAll","kind":"method"},{"fullName":"hs.hotkey.disableAll(mods, key)","description":"Disable every hotkey currently bound to a key combination, without removing them","url":"hs.hotkey.html#disableAll","kind":"method"},{"fullName":"hs.hotkey.bindSpec(spec)","description":"Bind a hotkey from a single options object. Like hs.hotkey.bind()/create(), but also accepts a message and a repeat callback. message is available on any hotkey (not just ones created via bindSpec()) by setting .message directly on the returned object; see hs.hotkey's message property for exactly when it is shown.","url":"hs.hotkey.html#bindSpec","kind":"method"},{"fullName":"hs.hotkey.createModal(mods, key)","description":"Create a new modal hotkey group, optionally entered via a trigger key combination","url":"hs.hotkey.html#createModal","kind":"method"},{"fullName":"hs.hotkey.showHotkeys(mods, key)","description":"Create and enable a hotkey that, while held down, displays a list of all currently enabled hotkeys (and their messages, if any) as an on-screen toast.","url":"hs.hotkey.html#showHotkeys","kind":"method"},{"fullName":"hs.http","description":"HTTP client module for making network requests from JavaScript.","url":"hs.http.html","kind":"module"},{"fullName":"hs.http.get(url, headers)","description":"Perform an HTTP GET request.","url":"hs.http.html#get","kind":"method"},{"fullName":"hs.http.post(url, body, headers)","description":"Perform an HTTP POST request.","url":"hs.http.html#post","kind":"method"},{"fullName":"hs.http.put(url, body, headers)","description":"Perform an HTTP PUT request.","url":"hs.http.html#put","kind":"method"},{"fullName":"hs.http.doRequest(url, method, body, headers)","description":"Perform an HTTP request with any method (GET, POST, PUT, DELETE, PATCH, etc.). Use this for methods not covered by the convenience helpers, such as DELETE or PATCH.","url":"hs.http.html#doRequest","kind":"method"},{"fullName":"hs.http.encodeForQuery(string)","description":"URL-encode a string for use as a query parameter value. Encodes characters that are illegal in a URL query string (including ?, =, +, &, #) using percent-encoding.","url":"hs.http.html#encodeForQuery","kind":"method"},{"fullName":"hs.http.urlParts(url)","description":"Parse a URL into its component parts. Returns an object containing only the fields present in the URL. The queryItems field is an array of {name, value} objects from the query string.","url":"hs.http.html#urlParts","kind":"method"},{"fullName":"hs.http.convertHtmlEntities(string)","description":"Convert HTML entities in a string to their UTF-8 character equivalents. Handles named entities (e.g. &, <, ©), decimal numeric references (&), and hexadecimal numeric references (&).","url":"hs.http.html#convertHtmlEntities","kind":"method"},{"fullName":"hs.http.openWebSocket(url)","description":"Open a WebSocket connection to the given URL. The connection begins immediately. Use the returned object's chainable setter methods to register event callbacks. The connection is automatically closed when hs.reload() is called or the engine shuts down.","url":"hs.http.html#openWebSocket","kind":"method"},{"fullName":"hs.httpserver","description":"Module for creating and managing HTTP servers.","url":"hs.httpserver.html","kind":"module"},{"fullName":"hs.httpserver.create()","description":"Create a new HTTP server instance. The server is not running until you call start() on the returned object.","url":"hs.httpserver.html#create","kind":"method"},{"fullName":"hs.ipc","description":"Module for enabling CLI access to Hammerspoon 2 via the hs2 command-line tool.","url":"hs.ipc.html","kind":"module"},{"fullName":"hs.ipc.isListening","description":"Whether the IPC server is currently accepting connections.","url":"hs.ipc.html#isListening","kind":"property"},{"fullName":"hs.ipc.start()","description":"Start the IPC server. The server listens on a named XPC Mach service (net.tenshu.Hammerspoon-2.ipc). In release builds, only processes signed with the same Team ID can connect. Calling start() when already running logs a warning and does nothing.","url":"hs.ipc.html#start","kind":"method"},{"fullName":"hs.ipc.stop()","description":"Stop the IPC server and disconnect all connected clients.","url":"hs.ipc.html#stop","kind":"method"},{"fullName":"hs.ipc.installBinary(directory)","description":"Install the hs2 command-line tool to the given directory as a symlink. Creates a symlink in the target directory that points to the hs2 binary inside the Hammerspoon 2 app bundle. Using a symlink means the CLI automatically reflects any app update without reinstalling. Any existing hs2 file at that path is replaced. The directory must be on your $PATH for hs2 to work without a full path. Permissions: /usr/local/bin is typically user-writable on Intel Macs with Homebrew. On Apple Silicon, prefer /opt/homebrew/bin. On a stock Mac (no Homebrew), both directories require root — if this method returns false, run the logged command in a terminal with sudo.","url":"hs.ipc.html#installBinary","kind":"method"},{"fullName":"hs.ipc.uninstallBinary(directory)","description":"Remove the hs2 command-line tool from the given directory.","url":"hs.ipc.html#uninstallBinary","kind":"method"},{"fullName":"hs.ipc.isBinaryInstalled(directory)","description":"Check whether the hs2 command-line tool exists at the given directory.","url":"hs.ipc.html#isBinaryInstalled","kind":"method"},{"fullName":"hs.keyboard","description":"Module for querying and controlling CapsLock state, and for enumerating attached keyboards and controlling their LEDs individually.","url":"hs.keyboard.html","kind":"module"},{"fullName":"hs.keyboard.capsLockState()","description":"Checks the system-wide state of CapsLock. This reflects a single, global lock state shared by every attached keyboard — macOS has no public API to query the functional (character-affecting) CapsLock state independently per keyboard. For a genuinely per-keyboard signal, see keyboardCapsLockState(), which reads each keyboard's own CapsLock LED.","url":"hs.keyboard.html#capsLockState","kind":"method"},{"fullName":"hs.keyboard.setCapsLockState(state)","description":"Sets the system-wide state of CapsLock.","url":"hs.keyboard.html#setCapsLockState","kind":"method"},{"fullName":"hs.keyboard.toggleCapsLockState()","description":"Toggles the system-wide state of CapsLock.","url":"hs.keyboard.html#toggleCapsLockState","kind":"method"},{"fullName":"hs.keyboard.setLED(name, state)","description":"Sets a keyboard LED on every attached keyboard that has one.","url":"hs.keyboard.html#setLED","kind":"method"},{"fullName":"hs.keyboard.attachedKeyboards()","description":"Returns all currently attached keyboard HID devices. Each object has keyboardID (number — pass to keyboardCapsLockState()/setKeyboardLED()), productName (string), vendorName (string), productID (number), and vendorID (number). serialNumber (string) and locationID (number) are included when available.","url":"hs.keyboard.html#attachedKeyboards","kind":"method"},{"fullName":"hs.keyboard.keyboardCapsLockState(keyboardID)","description":"Checks a specific keyboard's own CapsLock LED state. Unlike capsLockState(), this queries the individual keyboard identified by keyboardID (from attachedKeyboards()), reflecting how modern macOS tracks CapsLock independently per physical keyboard.","url":"hs.keyboard.html#keyboardCapsLockState","kind":"method"},{"fullName":"hs.keyboard.setKeyboardLED(keyboardID, name, state)","description":"Sets a specific keyboard's LED, leaving all other attached keyboards untouched.","url":"hs.keyboard.html#setKeyboardLED","kind":"method"},{"fullName":"hs.keycodes","description":"Access information about the current keyboard layout and input sources, and respond to changes.","url":"hs.keycodes.html","kind":"module"},{"fullName":"hs.keycodes.map","description":"A bidirectional mapping between key names and their macOS virtual key codes. Entries exist for both directions: look up a name to get its integer keycode, or look up a keycode (as a string) to get the key name. The map is rebuilt automatically whenever the keyboard input source changes.","url":"hs.keycodes.html#map","kind":"property"},{"fullName":"hs.keycodes.currentLayout()","description":"Returns the localized name of the current keyboard layout. Uses the base keyboard layout, which is the underlying layout even when an input method (such as a CJK input method) is also active.","url":"hs.keycodes.html#currentLayout","kind":"method"},{"fullName":"hs.keycodes.currentMethod()","description":"Returns the localized name of the active input method, or null if none is active. Input methods are distinct from keyboard layouts. They provide complex character composition such as CJK input. Returns null when using a plain keyboard layout with no input method overlay.","url":"hs.keycodes.html#currentMethod","kind":"method"},{"fullName":"hs.keycodes.currentSourceID()","description":"Returns the reverse-DNS identifier of the currently selected keyboard input source.","url":"hs.keycodes.html#currentSourceID","kind":"method"},{"fullName":"hs.keycodes.layouts()","description":"Returns the localized names of all currently enabled keyboard layouts.","url":"hs.keycodes.html#layouts","kind":"method"},{"fullName":"hs.keycodes.methods()","description":"Returns the localized names of all currently enabled input methods.","url":"hs.keycodes.html#methods","kind":"method"},{"fullName":"hs.keycodes.setLayout(layoutName)","description":"Switches the active keyboard layout to the one with the given localized name. Use layouts() to enumerate valid names.","url":"hs.keycodes.html#setLayout","kind":"method"},{"fullName":"hs.keycodes.setMethod(methodName)","description":"Switches the active input method to the one with the given localized name. Use methods() to enumerate valid names.","url":"hs.keycodes.html#setMethod","kind":"method"},{"fullName":"hs.keycodes.setSourceID(sourceID)","description":"Switches the active input source to the one with the given reverse-DNS identifier. Use currentSourceID() to see the current value.","url":"hs.keycodes.html#setSourceID","kind":"method"},{"fullName":"hs.keycodes.addWatcher(listener)","description":"Registers a listener that fires whenever the keyboard input source changes. The listener is called with no arguments. Read currentLayout(), currentSourceID(), or map inside the callback to inspect the new state. The OS subscription starts lazily on the first listener and is released automatically when the last listener is removed via removeWatcher.","url":"hs.keycodes.html#addWatcher","kind":"method"},{"fullName":"hs.keycodes.removeWatcher(listener)","description":"Removes a previously registered input source change listener.","url":"hs.keycodes.html#removeWatcher","kind":"method"},{"fullName":"hs.locale","description":"Retrieve information about the user's Language & Region settings, and respond to changes.","url":"hs.locale.html","kind":"module"},{"fullName":"hs.locale.availableLocales()","description":"Returns the identifiers for all locales available on the system.","url":"hs.locale.html#availableLocales","kind":"method"},{"fullName":"hs.locale.current()","description":"Returns the user's currently selected locale identifier.","url":"hs.locale.html#current","kind":"method"},{"fullName":"hs.locale.preferredLanguages()","description":"Returns the user's preferred languages, in priority order.","url":"hs.locale.html#preferredLanguages","kind":"method"},{"fullName":"hs.locale.details(identifier)","description":"Returns detailed information about the current or a specified locale. user's currently selected locale is used.","url":"hs.locale.html#details","kind":"method"},{"fullName":"hs.locale.localizedName(localeCode, baseLocaleCode)","description":"Returns the localized display name for a locale identifier. of the strings returned by availableLocales(). currently selected locale is used. Must be one of the strings returned by availableLocales().","url":"hs.locale.html#localizedName","kind":"method"},{"fullName":"hs.locale.addWatcher(listener)","description":"Registers a listener that fires whenever any of the user's locale settings change. The listener is called with no arguments. Read current() or details() inside the callback to inspect the new state. The OS subscription starts lazily on the first listener and is released automatically when the last listener is removed via removeWatcher.","url":"hs.locale.html#addWatcher","kind":"method"},{"fullName":"hs.locale.removeWatcher(listener)","description":"Removes a previously registered locale change listener.","url":"hs.locale.html#removeWatcher","kind":"method"},{"fullName":"hs.location","description":"Determine the Mac's location via macOS Location Services.","url":"hs.location.html","kind":"module"},{"fullName":"hs.location.lookupAddress(address)","description":"Geocodes an address string into an array of placemarkTables. Returns a Promise that resolves with an array of placemarkTable objects (sorted by relevance) or rejects with an error message.","url":"hs.location.html#lookupAddress","kind":"method"},{"fullName":"hs.location.lookupLocation(locationTable)","description":"Reverse-geocodes a locationTable into an array of placemarkTables. Returns a Promise that resolves with matching placemarks or rejects with an error.","url":"hs.location.html#lookupLocation","kind":"method"},{"fullName":"hs.location.servicesEnabled()","description":"Returns true if Location Services are enabled system-wide.","url":"hs.location.html#servicesEnabled","kind":"method"},{"fullName":"hs.location.authorizationStatus()","description":"Returns the app's current Location Services authorization status as a string.","url":"hs.location.html#authorizationStatus","kind":"method"},{"fullName":"hs.location.get()","description":"Returns the most recently cached location as a locationTable, or null. Activates Location Services if not already running. The cache is updated periodically while any watcher is running.","url":"hs.location.html#get","kind":"method"},{"fullName":"hs.location.distance(from, to)","description":"Calculates the straight-line distance in metres between two locationTables. Does not require Location Services.","url":"hs.location.html#distance","kind":"method"},{"fullName":"hs.location.sunrise(latitude, longitude, date)","description":"Returns the time of sunrise for the given coordinates and date, or null if the sun does not rise on that date (polar night).","url":"hs.location.html#sunrise","kind":"method"},{"fullName":"hs.location.sunset(latitude, longitude, date)","description":"Returns the time of sunset for the given coordinates and date, or null if the sun does not set on that date (midnight sun).","url":"hs.location.html#sunset","kind":"method"},{"fullName":"hs.location.addWatcher()","description":"Creates a new location watcher object. Call .start() on it to begin receiving updates. The watcher is automatically stopped when the module shuts down.","url":"hs.location.html#addWatcher","kind":"method"},{"fullName":"hs.location.removeWatcher(watcher)","description":"Removes a previously created watcher and stops it if running.","url":"hs.location.html#removeWatcher","kind":"method"},{"fullName":"hs.menubar","description":"Module for creating and managing macOS system menu bar items.","url":"hs.menubar.html","kind":"module"},{"fullName":"hs.menubar.create(hidden)","description":"Create a new menu bar item","url":"hs.menubar.html#create","kind":"method"},{"fullName":"hs.midi","description":"A module for enumerating, watching, and communicating with MIDI devices. IMPORTANT NOTE: This module has not had very much real-world testing yet. Please report positive or negative feedback via GitHub Issues.","url":"hs.midi.html","kind":"module"},{"fullName":"hs.midi.commandTypes","description":"A table mapping each MIDI command type name to a stable numeric identifier.","url":"hs.midi.html#commandTypes","kind":"property"},{"fullName":"hs.midi.devices()","description":"Returns the names of all currently connected (online) physical MIDI devices.","url":"hs.midi.html#devices","kind":"method"},{"fullName":"hs.midi.virtualSources()","description":"Returns the names of all available virtual MIDI sources — endpoints published by other apps/drivers (e.g. the IAC Driver, virtual instruments) rather than belonging to a physical device.","url":"hs.midi.html#virtualSources","kind":"method"},{"fullName":"hs.midi.deviceCallback(fn)","description":"Sets or removes a callback fired whenever the set of connected MIDI devices or virtual sources changes. The callback receives two arguments: the current result of devices() and the current result of virtualSources().","url":"hs.midi.html#deviceCallback","kind":"method"},{"fullName":"hs.midi.deviceNamed(deviceName)","description":"Creates an hs.midi object for a physical device. new/alloc/copy-prefixed method names, which have special meaning under Objective-C's ARC ownership conventions.","url":"hs.midi.html#deviceNamed","kind":"method"},{"fullName":"hs.midi.virtualSourceNamed(virtualSourceName)","description":"Creates an hs.midi object for an existing virtual source (receive-only — a \"source\" endpoint can only be read from). the same ARC-related reason as deviceNamed().","url":"hs.midi.html#virtualSourceNamed","kind":"method"},{"fullName":"hs.mouse","description":"Control and inspect the mouse pointer and attached mouse devices.","url":"hs.mouse.html","kind":"module"},{"fullName":"hs.mouse.absolutePosition()","description":"Returns the current mouse pointer position in Hammerspoon screen coordinates. Hammerspoon coordinates have (0, 0) at the top-left of the primary display, with y increasing downward.","url":"hs.mouse.html#absolutePosition","kind":"method"},{"fullName":"hs.mouse.setAbsolutePosition(x, y)","description":"Moves the mouse pointer to the specified absolute position in Hammerspoon screen coordinates.","url":"hs.mouse.html#setAbsolutePosition","kind":"method"},{"fullName":"hs.mouse.getRelativePosition()","description":"Returns the mouse pointer position relative to the screen it is currently on. The returned coordinates have (0, 0) at the top-left corner of the screen that the cursor is on.","url":"hs.mouse.html#getRelativePosition","kind":"method"},{"fullName":"hs.mouse.setRelativePosition(x, y)","description":"Moves the mouse pointer to a position relative to the screen it is currently on.","url":"hs.mouse.html#setRelativePosition","kind":"method"},{"fullName":"hs.mouse.getCurrentScreen()","description":"Returns the screen that the mouse pointer is currently on.","url":"hs.mouse.html#getCurrentScreen","kind":"method"},{"fullName":"hs.mouse.count(includeInternal)","description":"Returns the number of mouse devices currently attached to the system.","url":"hs.mouse.html#count","kind":"method"},{"fullName":"hs.mouse.names(includeInternal)","description":"Returns the product names of all mouse devices currently attached to the system.","url":"hs.mouse.html#names","kind":"method"},{"fullName":"hs.mouse.trackingSpeed()","description":"Returns the current mouse tracking speed (acceleration level). Values range from -1.0 (system default, acceleration disabled) to 3.0 (maximum acceleration). Returns -1.0 if the value cannot be read.","url":"hs.mouse.html#trackingSpeed","kind":"method"},{"fullName":"hs.mouse.setTrackingSpeed(speed)","description":"Sets the mouse tracking speed (acceleration level). The change takes effect immediately for the current login session and is also persisted to preferences so it survives a restart. Values outside the valid range or non-finite values are rejected with a warning and no change is made.","url":"hs.mouse.html#setTrackingSpeed","kind":"method"},{"fullName":"hs.mouse.scrollDirection()","description":"Returns the current scroll wheel direction setting.","url":"hs.mouse.html#scrollDirection","kind":"method"},{"fullName":"hs.mouse.currentCursorType()","description":"Returns the name of the cursor type currently set by this application. has the keyboard focus, the visible system cursor may differ.","url":"hs.mouse.html#currentCursorType","kind":"method"},{"fullName":"hs.network","description":"Module for inspecting network interfaces, resolving hostnames, and reading system configuration","url":"hs.network.html","kind":"module"},{"fullName":"hs.network.reachabilityFlags","description":"A dictionary of named flag constants for use with HSNetworkReachability.status(). Compare individual bits against these constants to determine which network conditions apply. The numeric values match the deprecated SCNetworkReachabilityFlags for backward compatibility. Keys: transientConnection, reachable, connectionRequired, connectionOnTraffic, interventionRequired, connectionOnDemand, isLocalAddress, isDirect.","url":"hs.network.html#reachabilityFlags","kind":"property"},{"fullName":"hs.network.interfaces()","description":"Returns all network interfaces present on this system. Each object contains name (string), isLoopback (boolean), isUp (boolean), and isRunning (boolean). A displayName string is included when the system provides a human-readable label for the interface (e.g. \"Wi-Fi\" or \"Ethernet\").","url":"hs.network.html#interfaces","kind":"method"},{"fullName":"hs.network.primaryInterface()","description":"Returns the name of the primary network interface, i.e. the one currently providing the default route.","url":"hs.network.html#primaryInterface","kind":"method"},{"fullName":"hs.network.addresses()","description":"Returns all IP addresses assigned to this host. Each object contains interface (the BSD name of the interface), address (the address string), and family (\"ipv4\" or \"ipv6\").","url":"hs.network.html#addresses","kind":"method"},{"fullName":"hs.network.hostnames()","description":"Returns all hostnames known for this Mac.","url":"hs.network.html#hostnames","kind":"method"},{"fullName":"hs.network.resolve(hostname, family)","description":"Asynchronously resolves a hostname to its IP addresses using the system DNS resolver. Uses CFHost, which respects the system's network configuration including VPN routes and proxy settings.","url":"hs.network.html#resolve","kind":"method"},{"fullName":"hs.network.reachabilityForAddress(address)","description":"Creates a reachability monitor for a specific IP address. Returns null if address is not a valid IPv4 or IPv6 address literal. Under the hood this monitors general system connectivity (the same as reachabilityInternet()), because NWPathMonitor does not support per-address targeting.","url":"hs.network.html#reachabilityForAddress","kind":"method"},{"fullName":"hs.network.reachabilityForAddressPair(localAddress, remoteAddress)","description":"Creates a reachability monitor for a source/destination IP address pair. Returns null if either address is not a valid IPv4 or IPv6 address literal. Under the hood this monitors general system connectivity (the same as reachabilityInternet()), because NWPathMonitor does not support per-address targeting.","url":"hs.network.html#reachabilityForAddressPair","kind":"method"},{"fullName":"hs.network.reachabilityForHostName(hostName)","description":"Creates a reachability monitor for a given hostname. Returns null if hostName is empty. Under the hood this monitors general system connectivity (the same as reachabilityInternet()), because NWPathMonitor does not support per-hostname targeting.","url":"hs.network.html#reachabilityForHostName","kind":"method"},{"fullName":"hs.network.reachabilityInternet()","description":"Creates a reachability monitor for general internet connectivity. This is the most common factory method. Use it when you want to know whether the device currently has a working internet connection.","url":"hs.network.html#reachabilityInternet","kind":"method"},{"fullName":"hs.network.reachabilityLinkLocal()","description":"Creates a reachability monitor for link-local connectivity. Link-local addresses cover the 169.254.x.x (IPv4) and fe80::/10 (IPv6) ranges used for direct device-to-device communication without a router. Under the hood this monitors general system connectivity (the same as reachabilityInternet()), because NWPathMonitor does not distinguish link-local reachability.","url":"hs.network.html#reachabilityLinkLocal","kind":"method"},{"fullName":"hs.network.configurationStore(pattern)","description":"Returns the contents of the macOS System Configuration dynamic store as a dictionary. The store holds live network configuration for the running system — interface addresses, routing, DNS servers, proxy settings, VPN state, and more. Keys follow a hierarchical path convention (e.g. \"State:/Network/Global/IPv4\"). Omit or pass null to return all keys (equivalent to \".*\").","url":"hs.network.html#configurationStore","kind":"method"},{"fullName":"hs.network.configurationLocations()","description":"Returns a mapping of all configured network location UUIDs to their display names. Use this to discover available locations before calling configurationSetLocation().","url":"hs.network.html#configurationLocations","kind":"method"},{"fullName":"hs.network.configurationSetLocation(location)","description":"Switches the active network location to the one with the given name or UUID. Pass the location's display name (e.g. \"Home\") or its UUID from configurationLocations(). The change is applied immediately. Returns false if the location was not found or the preferences could not be committed (e.g. insufficient privileges).","url":"hs.network.html#configurationSetLocation","kind":"method"},{"fullName":"hs.network.configurationWatcher()","description":"Creates a watcher that fires a callback when System Configuration dynamic store keys change. Call setKeys() to specify which keys (or patterns) to watch, setCallback() to register the handler, then start() to begin monitoring. The module automatically stops and destroys all watchers on hs.reload().","url":"hs.network.html#configurationWatcher","kind":"method"},{"fullName":"hs.network.ping(server, options)","description":"Sends ICMP Echo Requests to server and reports results via a callback. DNS resolution and the first ping begin immediately. The returned object can be used to pause, resume, or cancel the ping, and to read statistics. timeout (seconds per packet, default 2.0), family (\"any\" | \"ipv4\" | \"ipv6\", default \"any\"), and callback (function).","url":"hs.network.html#ping","kind":"method"},{"fullName":"hs.notify","description":"Module for creating and displaying macOS system notifications.","url":"hs.notify.html","kind":"module"},{"fullName":"hs.notify.show(title, body, callback)","description":"Display a notification immediately.","url":"hs.notify.html#show","kind":"method"},{"fullName":"hs.notify.create(options)","description":"Create a richly configured notification without sending it yet.","url":"hs.notify.html#create","kind":"method"},{"fullName":"hs.notify.removeAllDelivered()","description":"Remove all delivered Hammerspoon notifications from Notification Center.","url":"hs.notify.html#removeAllDelivered","kind":"method"},{"fullName":"hs.notify.removeAllPending()","description":"Cancel all pending (not yet delivered) Hammerspoon notifications.","url":"hs.notify.html#removeAllPending","kind":"method"},{"fullName":"hs.ocr","description":"Recognize text in images using Apple's Vision framework.","url":"hs.ocr.html","kind":"module"},{"fullName":"hs.ocr.recognizeText(path, options)","description":"Recognize text in the image at the given file path. Returns a Promise that resolves with an HSOCRResult containing all recognized text and per-region observations. The image must exist on disk; URLs and data buffers are not supported. Recognition is performed on a background thread; the main thread is not blocked during the operation. \"accurate\" uses a larger neural network for better results; \"fast\" trades accuracy for speed. Observations whose confidence is below this threshold are excluded from result.observations (and therefore from result.text). Hints Vision toward specific languages. Use supportedLanguages() to enumerate the available codes for the current device. When true, Vision selects recognition languages automatically. Overrides languages when set.","url":"hs.ocr.html#recognizeText","kind":"method"},{"fullName":"hs.ocr.supportedLanguages()","description":"Returns the BCP-47 language codes supported by the Vision text recognizer on this device. The set of languages varies between macOS versions and hardware. Call this at runtime to discover which codes are valid for the languages option passed to recognizeText().","url":"hs.ocr.html#supportedLanguages","kind":"method"},{"fullName":"hs.osascript","description":"Run AppleScript and OSA JavaScript from Hammerspoon scripts.","url":"hs.osascript.html","kind":"module"},{"fullName":"hs.osascript.applescript(source)","description":"Run an AppleScript source string.","url":"hs.osascript.html#applescript","kind":"method"},{"fullName":"hs.osascript.javascript(source)","description":"Run an OSA JavaScript source string. OSA JavaScript is Apple's Open Scripting Architecture dialect of JavaScript, distinct from the JavaScriptCore engine that runs Hammerspoon scripts themselves.","url":"hs.osascript.html#javascript","kind":"method"},{"fullName":"hs.osascript.applescriptFromFile(path)","description":"Read a file from disk and execute its contents as AppleScript. The file is read in the main process before being sent to the XPC helper. If the file cannot be read the promise resolves immediately with { success: false, result: null, raw: \"Failed to read file: \" }.","url":"hs.osascript.html#applescriptFromFile","kind":"method"},{"fullName":"hs.osascript.javascriptFromFile(path)","description":"Read a file from disk and execute its contents as OSA JavaScript. The file is read in the main process before being sent to the XPC helper. If the file cannot be read the promise resolves immediately with { success: false, result: null, raw: \"Failed to read file: \" }.","url":"hs.osascript.html#javascriptFromFile","kind":"method"},{"fullName":"hs.osascript._execute(source, language)","description":"Low-level execution entry point used by the higher-level helpers. Prefer applescript() or javascript() over calling this directly.","url":"hs.osascript.html#_execute","kind":"method"},{"fullName":"hs.osascript.applescriptSync(source)","description":"Run an AppleScript source string synchronously. Blocks the JS thread until the script completes.","url":"hs.osascript.html#applescriptSync","kind":"method"},{"fullName":"hs.osascript.javascriptSync(source)","description":"Run an OSA JavaScript source string synchronously. Blocks the JS thread until the script completes.","url":"hs.osascript.html#javascriptSync","kind":"method"},{"fullName":"hs.osascript.applescriptSyncFromFile(path)","description":"Read a file from disk and execute its contents as AppleScript synchronously.","url":"hs.osascript.html#applescriptSyncFromFile","kind":"method"},{"fullName":"hs.osascript.javascriptSyncFromFile(path)","description":"Read a file from disk and execute its contents as OSA JavaScript synchronously.","url":"hs.osascript.html#javascriptSyncFromFile","kind":"method"},{"fullName":"hs.osascript._executeSync(source, language)","description":"Low-level synchronous execution entry point. Prefer applescriptSync() or javascriptSync() over calling this directly.","url":"hs.osascript.html#_executeSync","kind":"method"},{"fullName":"hs.pasteboard","description":"Module for interacting with the macOS pasteboard (clipboard)","url":"hs.pasteboard.html","kind":"module"},{"fullName":"hs.pasteboard.changeCount","description":"The pasteboard change count. Increments each time any application writes to the pasteboard. Comparing a saved value to the current value is the standard way to detect external changes.","url":"hs.pasteboard.html#changeCount","kind":"property"},{"fullName":"hs.pasteboard.watcherInterval","description":"The polling interval for the pasteboard watcher, in seconds. Defaults to 0.5. Changes take effect the next time a watcher is started (i.e. after removing and re-adding).","url":"hs.pasteboard.html#watcherInterval","kind":"property"},{"fullName":"hs.pasteboard.readString()","description":"Read plain text from the pasteboard","url":"hs.pasteboard.html#readString","kind":"method"},{"fullName":"hs.pasteboard.readHTML()","description":"Read HTML from the pasteboard","url":"hs.pasteboard.html#readHTML","kind":"method"},{"fullName":"hs.pasteboard.readRTF()","description":"Read RTF from the pasteboard","url":"hs.pasteboard.html#readRTF","kind":"method"},{"fullName":"hs.pasteboard.readURL()","description":"Read a URL from the pasteboard","url":"hs.pasteboard.html#readURL","kind":"method"},{"fullName":"hs.pasteboard.readImage()","description":"Read an image from the pasteboard","url":"hs.pasteboard.html#readImage","kind":"method"},{"fullName":"hs.pasteboard.readData(uti)","description":"Read raw data for a specific UTI type, returned as a base64-encoded string. Use this for types not covered by the convenience read methods.","url":"hs.pasteboard.html#readData","kind":"method"},{"fullName":"hs.pasteboard.writeString(str)","description":"Write plain text to the pasteboard, replacing all current contents","url":"hs.pasteboard.html#writeString","kind":"method"},{"fullName":"hs.pasteboard.writeHTML(html)","description":"Write HTML to the pasteboard, replacing all current contents","url":"hs.pasteboard.html#writeHTML","kind":"method"},{"fullName":"hs.pasteboard.writeRTF(rtf)","description":"Write RTF to the pasteboard, replacing all current contents","url":"hs.pasteboard.html#writeRTF","kind":"method"},{"fullName":"hs.pasteboard.writeURL(url)","description":"Write a URL to the pasteboard, replacing all current contents","url":"hs.pasteboard.html#writeURL","kind":"method"},{"fullName":"hs.pasteboard.writeImage(image)","description":"Write an image to the pasteboard, replacing all current contents","url":"hs.pasteboard.html#writeImage","kind":"method"},{"fullName":"hs.pasteboard.writeData(base64, uti)","description":"Write raw base64-encoded data for a specific UTI type, replacing all current contents. Use this for types not covered by the convenience write methods.","url":"hs.pasteboard.html#writeData","kind":"method"},{"fullName":"hs.pasteboard.writeObjects(representations)","description":"Write multiple type representations to the pasteboard atomically, replacing all current contents. Keys must be UTI type strings; values must be strings. This is how you provide both a plain-text fallback and a richer representation (such as HTML) in a single clipboard operation.","url":"hs.pasteboard.html#writeObjects","kind":"method"},{"fullName":"hs.pasteboard.types()","description":"Get all UTI type strings currently on the pasteboard, across all items","url":"hs.pasteboard.html#types","kind":"method"},{"fullName":"hs.pasteboard.hasType(uti)","description":"Check whether a specific UTI type is currently available on the pasteboard","url":"hs.pasteboard.html#hasType","kind":"method"},{"fullName":"hs.pasteboard.clear()","description":"Clear all contents from the pasteboard","url":"hs.pasteboard.html#clear","kind":"method"},{"fullName":"hs.pasteboard.addWatcher(listener)","description":"Add a watcher that is called whenever the pasteboard contents change. Multiple watchers may be registered; they are each called independently. Because macOS provides no pasteboard change notification API, this is implemented by polling changeCount at the interval specified by watcherInterval.","url":"hs.pasteboard.html#addWatcher","kind":"method"},{"fullName":"hs.pasteboard.removeWatcher(listener)","description":"Remove a previously registered pasteboard watcher","url":"hs.pasteboard.html#removeWatcher","kind":"method"},{"fullName":"hs.permissions","description":"Module for checking and requesting system permissions","url":"hs.permissions.html","kind":"module"},{"fullName":"hs.permissions.checkAccessibility()","description":"Check if the app has Accessibility permission","url":"hs.permissions.html#checkAccessibility","kind":"method"},{"fullName":"hs.permissions.requestAccessibility()","description":"Request Accessibility permission (shows system dialog if not granted)","url":"hs.permissions.html#requestAccessibility","kind":"method"},{"fullName":"hs.permissions.checkScreenRecording()","description":"Check if the app has Screen Recording permission","url":"hs.permissions.html#checkScreenRecording","kind":"method"},{"fullName":"hs.permissions.requestScreenRecording()","description":"Request Screen Recording permission","url":"hs.permissions.html#requestScreenRecording","kind":"method"},{"fullName":"hs.permissions.checkCamera()","description":"Check if the app has Camera permission","url":"hs.permissions.html#checkCamera","kind":"method"},{"fullName":"hs.permissions.requestCamera()","description":"Request Camera permission (shows system dialog if not granted)","url":"hs.permissions.html#requestCamera","kind":"method"},{"fullName":"hs.permissions.checkMicrophone()","description":"Check if the app has Microphone permission","url":"hs.permissions.html#checkMicrophone","kind":"method"},{"fullName":"hs.permissions.requestMicrophone()","description":"Request Microphone permission (shows system dialog if not granted)","url":"hs.permissions.html#requestMicrophone","kind":"method"},{"fullName":"hs.permissions.checkNotifications()","description":"Check if the app has permission to display notifications. The result is cached from the last request or check; the cache is refreshed asynchronously, so the very first call in a session may return false before the cached value is populated. Use requestNotifications() on first launch to ensure the result is accurate.","url":"hs.permissions.html#checkNotifications","kind":"method"},{"fullName":"hs.permissions.requestNotifications()","description":"Request notification permission (shows the system dialog if the user has not yet decided). It is safe to call this on every launch — the dialog only appears once; subsequent calls resolve immediately with the previously granted or denied state.","url":"hs.permissions.html#requestNotifications","kind":"method"},{"fullName":"hs.permissions.checkLocation()","description":"Check if the app has Location permission.","url":"hs.permissions.html#checkLocation","kind":"method"},{"fullName":"hs.permissions.requestLocation()","description":"Request Location permission (shows the system dialog if the user has not yet decided).","url":"hs.permissions.html#requestLocation","kind":"method"},{"fullName":"hs.permissions.checkInputMonitoring()","description":"Check if the app has Input Monitoring permission. Input Monitoring is required for hs.keyboard to query and control CapsLock state and LEDs on a per-keyboard basis.","url":"hs.permissions.html#checkInputMonitoring","kind":"method"},{"fullName":"hs.permissions.requestInputMonitoring()","description":"Request Input Monitoring permission (shows the system dialog if the user has not yet decided).","url":"hs.permissions.html#requestInputMonitoring","kind":"method"},{"fullName":"hs.plist","description":"Module for reading and writing macOS property list (plist) files.","url":"hs.plist.html","kind":"module"},{"fullName":"hs.plist.fromFile(path)","description":"Read a plist file and return its contents as a JavaScript value. Supports both XML and binary plist formats. Returns a JavaScript object for dictionary-rooted plists, an array for array-rooted plists, or a string or number for scalar-rooted plists.","url":"hs.plist.html#fromFile","kind":"method"},{"fullName":"hs.plist.fromString(plistString)","description":"Read a plist from an XML string and return its contents as a JavaScript value.","url":"hs.plist.html#fromString","kind":"method"},{"fullName":"hs.plist.toFile(path, data, binary)","description":"Write a JavaScript object to a plist file on disk. Keys must be strings. Values may be strings, numbers, booleans, arrays, or nested objects. JavaScript null values are not plist-compatible and will cause the write to fail.","url":"hs.plist.html#toFile","kind":"method"},{"fullName":"hs.plist.toString(data, binary)","description":"Serialize a JavaScript object to a plist string. With binary set to false (default), returns an XML plist string suitable for storing in text files or passing to readString. With binary set to true, returns a base64-encoded binary plist string.","url":"hs.plist.html#toString","kind":"method"},{"fullName":"hs.power","description":"Monitor and control system power: prevent sleep, read battery state, respond to power events, and lock or sleep the machine.","url":"hs.power.html","kind":"module"},{"fullName":"hs.power.percentage","description":"The current battery charge percentage (0–100), or -1 if no battery is present.","url":"hs.power.html#percentage","kind":"property"},{"fullName":"hs.power.isCharging","description":"Whether the battery is currently charging. Returns false when no battery is present.","url":"hs.power.html#isCharging","kind":"property"},{"fullName":"hs.power.powerSource","description":"The current power source. Returns \"ac\" when plugged in, \"battery\" when on battery power, \"ups\" when powered by a UPS, or \"unknown\" if the source cannot be determined.","url":"hs.power.html#powerSource","kind":"property"},{"fullName":"hs.power.isLowPowerMode","description":"Whether Low Power Mode is currently active.","url":"hs.power.html#isLowPowerMode","kind":"property"},{"fullName":"hs.power.thermalState","description":"The current thermal state of the system. Returns one of: \"nominal\", \"fair\", \"serious\", \"critical\".","url":"hs.power.html#thermalState","kind":"property"},{"fullName":"hs.power.preventSleep(type)","description":"Prevents the specified type of system sleep. Creates an IOKit power assertion that stops macOS from allowing the specified type of sleep. Call allowSleep with the same type to release the assertion. idle sleep), \"systemIdle\" (prevent system idle sleep), \"system\" (prevent all system sleep, including from power button or lid close).","url":"hs.power.html#preventSleep","kind":"method"},{"fullName":"hs.power.allowSleep(type)","description":"Releases a previously created sleep prevention assertion.","url":"hs.power.html#allowSleep","kind":"method"},{"fullName":"hs.power.isSleepPrevented(type)","description":"Returns whether Hammerspoon is currently preventing the specified type of sleep.","url":"hs.power.html#isSleepPrevented","kind":"method"},{"fullName":"hs.power.declareActivity()","description":"Simulates user activity, briefly resetting the display idle timer. Equivalent to moving the mouse — does not create a persistent assertion.","url":"hs.power.html#declareActivity","kind":"method"},{"fullName":"hs.power.currentAssertions()","description":"Returns the active power management assertions from all processes on the system.","url":"hs.power.html#currentAssertions","kind":"method"},{"fullName":"hs.power.systemSleep()","description":"Puts the system to sleep immediately. Requires the Automation permission for System Events.","url":"hs.power.html#systemSleep","kind":"method"},{"fullName":"hs.power.lockScreen()","description":"Locks the screen immediately.","url":"hs.power.html#lockScreen","kind":"method"},{"fullName":"hs.power.startScreensaver()","description":"Starts the screensaver immediately.","url":"hs.power.html#startScreensaver","kind":"method"},{"fullName":"hs.power.batteryInfo()","description":"Returns a snapshot of all available battery information, or null if no battery is present.","url":"hs.power.html#batteryInfo","kind":"method"},{"fullName":"hs.power.addEventWatcher(listener)","description":"Registers a listener that fires when system power events occur. \"screensDidSleep\", \"screensDidWake\", \"screensDidLock\", \"screensDidUnlock\", \"screensaverDidStart\", \"screensaverDidStop\", \"screensaverWillStop\", \"systemWillSleep\", \"systemDidWake\", \"systemWillPowerOff\", \"sessionDidBecomeActive\", \"sessionDidResignActive\". The OS notification subscription starts lazily on the first listener and is released automatically when the last listener is removed.","url":"hs.power.html#addEventWatcher","kind":"method"},{"fullName":"hs.power.removeEventWatcher(listener)","description":"Removes a previously registered power event listener.","url":"hs.power.html#removeEventWatcher","kind":"method"},{"fullName":"hs.power.addBatteryWatcher(listener)","description":"Registers a listener that fires whenever battery state changes. The listener receives no arguments; call batteryInfo() or read individual properties inside the callback to determine what changed. The OS notification subscription starts lazily on the first listener and is released automatically when the last listener is removed.","url":"hs.power.html#addBatteryWatcher","kind":"method"},{"fullName":"hs.power.removeBatteryWatcher(listener)","description":"Removes a previously registered battery change listener.","url":"hs.power.html#removeBatteryWatcher","kind":"method"},{"fullName":"hs.screen","description":"Inspect and control the displays attached to the system.","url":"hs.screen.html","kind":"module"},{"fullName":"hs.screen.all()","description":"All connected screens.","url":"hs.screen.html#all","kind":"method"},{"fullName":"hs.screen.main()","description":"The screen that currently contains the focused window, or the screen with the keyboard focus if no window is focused.","url":"hs.screen.html#main","kind":"method"},{"fullName":"hs.screen.primary()","description":"The primary display — the one that contains the global menu bar.","url":"hs.screen.html#primary","kind":"method"},{"fullName":"hs.screen.addWatcher(listener)","description":"Registers a listener that fires whenever the display configuration changes — monitors connected/disconnected, resolution or arrangement changed, or the menu bar moved to a different display. The listener receives no arguments; call all()/main()/primary() inside the callback to inspect the new configuration. The OS notification subscription starts lazily on the first listener and is released automatically when the last listener is removed.","url":"hs.screen.html#addWatcher","kind":"method"},{"fullName":"hs.screen.removeWatcher(listener)","description":"Removes a previously registered display-configuration listener.","url":"hs.screen.html#removeWatcher","kind":"method"},{"fullName":"hs.serial","description":"Communicate with devices connected to serial ports (RS-232, USB-serial adapters, etc).","url":"hs.serial.html","kind":"module"},{"fullName":"hs.serial.availablePortNames()","description":"Returns the names of all currently connected serial ports.","url":"hs.serial.html#availablePortNames","kind":"method"},{"fullName":"hs.serial.availablePortPaths()","description":"Returns the device paths of all currently connected serial ports.","url":"hs.serial.html#availablePortPaths","kind":"method"},{"fullName":"hs.serial.availablePortDetails()","description":"Returns IOKit registry details for all currently connected serial ports.","url":"hs.serial.html#availablePortDetails","kind":"method"},{"fullName":"hs.serial.createPortNamed(name)","description":"Creates a serial port object for a port discovered via availablePortNames().","url":"hs.serial.html#createPortNamed","kind":"method"},{"fullName":"hs.serial.createPortAtPath(path)","description":"Creates a serial port object for an arbitrary device path. Unlike createPortNamed(), the path does not need to correspond to a port currently discoverable via IOKit — it is only validated when you call open().","url":"hs.serial.html#createPortAtPath","kind":"method"},{"fullName":"hs.serial.addWatcher(listener)","description":"Register a listener for serial port connection and disconnection events. The listener is called with two arguments: the event type string (\"added\" or \"removed\") and a port-info object with name and path fields.","url":"hs.serial.html#addWatcher","kind":"method"},{"fullName":"hs.serial.removeWatcher(listener)","description":"Remove a previously registered serial port event listener.","url":"hs.serial.html#removeWatcher","kind":"method"},{"fullName":"hs.sharing","description":"Share data with other people and apps via macOS sharing services (Mail, Messages, AirDrop, and more).","url":"hs.sharing.html","kind":"module"},{"fullName":"hs.sharing.builtinServices","description":"A table of shortcut names for the sharing services that are still functional on modern macOS, mapped to the raw service identifiers createShare() expects. | Key | Service | |-----|---------| | mail | Compose an email in Mail | | message | Compose a message in Messages | | airdrop | Send via AirDrop | | safariReadingList | Add to Safari's Reading List | | photos | Add to the Photos library | | desktopPicture | Use as the desktop picture |","url":"hs.sharing.html#builtinServices","kind":"property"},{"fullName":"hs.sharing.createShare(name)","description":"Creates a sharing service for the given name.","url":"hs.sharing.html#createShare","kind":"method"},{"fullName":"hs.sharing.servicesFor(items)","description":"Finds every sharing service — built-in and third-party (e.g. Notes, Reminders, installed apps' Share Extensions) — that can handle the given items.","url":"hs.sharing.html#servicesFor","kind":"method"},{"fullName":"hs.shortcuts","description":"Run and interact with macOS Shortcuts from JavaScript.","url":"hs.shortcuts.html","kind":"module"},{"fullName":"hs.shortcuts.list()","description":"Returns an array of all available shortcuts. | Key | Type | Description | |-----|------|-------------| | name | string | The display name of the shortcut | | id | string | A UUID uniquely identifying the shortcut | | acceptsInput | boolean | Whether the shortcut expects input when run | | actionCount | number | How many actions the shortcut contains |","url":"hs.shortcuts.html#list","kind":"method"},{"fullName":"hs.shortcuts.run(name)","description":"Runs a Shortcuts shortcut by name and returns any output. Executes the shortcut in the background via the shortcuts CLI tool. If the shortcut produces output (via a \"Stop and Output\" action), the Promise resolves with that string. If the shortcut produces no output, the Promise resolves with null. The Promise rejects if the shortcut cannot be found or exits with a non-zero status.","url":"hs.shortcuts.html#run","kind":"method"},{"fullName":"hs.shortcuts.open(name)","description":"Opens a shortcut in the Shortcuts app for viewing or editing. Uses the shortcuts://open-shortcut URL scheme to bring Shortcuts to the foreground and navigate directly to the named shortcut.","url":"hs.shortcuts.html#open","kind":"method"},{"fullName":"hs.sound","description":"Play audio from files on disk or from the system's built-in sound library.","url":"hs.sound.html","kind":"module"},{"fullName":"hs.sound.fromFile(path)","description":"Loads an audio file from the given path and returns a sound object. Returns null if the file cannot be loaded.","url":"hs.sound.html#fromFile","kind":"method"},{"fullName":"hs.sound.named(name)","description":"Creates a sound object for a built-in system sound by name. Returns null if no sound with that name can be found. Use hs.sound.systemSounds() to discover available names.","url":"hs.sound.html#named","kind":"method"},{"fullName":"hs.sound.systemSounds()","description":"Returns a sorted array of all available system sound names. These names can be passed directly to hs.sound.named(). Scans /System/Library/Sounds, /Library/Sounds, and ~/Library/Sounds.","url":"hs.sound.html#systemSounds","kind":"method"},{"fullName":"hs.spotlight","description":"Query the macOS Spotlight metadata database.","url":"hs.spotlight.html","kind":"module"},{"fullName":"hs.spotlight.scope","description":"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) |","url":"hs.spotlight.html#scope","kind":"property"},{"fullName":"hs.spotlight.attribute","description":"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 |","url":"hs.spotlight.html#attribute","kind":"property"},{"fullName":"hs.spotlight.create()","description":"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.","url":"hs.spotlight.html#create","kind":"method"},{"fullName":"hs.spotlight.search(predicate, callback)","description":"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.","url":"hs.spotlight.html#search","kind":"method"},{"fullName":"hs.streamdeck","description":"Direct hardware control of Elgato Stream Deck devices — buttons, encoders, and the LCD touch strip on the Stream Deck Plus.","url":"hs.streamdeck.html","kind":"module"},{"fullName":"hs.streamdeck.all()","description":"All Stream Deck devices currently connected to the system.","url":"hs.streamdeck.html#all","kind":"method"},{"fullName":"hs.streamdeck.findBySerialNumber(serialNumber)","description":"Find the connected device with the given serial number.","url":"hs.streamdeck.html#findBySerialNumber","kind":"method"},{"fullName":"hs.streamdeck.addWatcher(listener)","description":"Register a listener for Stream Deck connect/disconnect events.","url":"hs.streamdeck.html#addWatcher","kind":"method"},{"fullName":"hs.streamdeck.removeWatcher(listener)","description":"Remove a previously registered connect/disconnect listener.","url":"hs.streamdeck.html#removeWatcher","kind":"method"},{"fullName":"hs.task","description":"Module for running external processes","url":"hs.task.html","kind":"module"},{"fullName":"hs.task.sequence","description":"Run multiple tasks in sequence. Swift-retained storage for the JS implementation.","url":"hs.task.html#sequence","kind":"property"},{"fullName":"hs.task.TaskBuilder","description":"TaskBuilder class. Swift-retained storage for the JS implementation.","url":"hs.task.html#TaskBuilder","kind":"property"},{"fullName":"hs.task.create(launchPath, arguments, completionCallback, environment, streamingCallback)","description":"Create a new task","url":"hs.task.html#create","kind":"method"},{"fullName":"hs.task.runAsync(launchPath, args, options, legacyStreamCallback)","description":"Create and run a task asynchronously","url":"hs.task.html#runAsync","kind":"method"},{"fullName":"hs.task.shell(command, options)","description":"Run a shell command asynchronously","url":"hs.task.html#shell","kind":"method"},{"fullName":"hs.task.parallel(tasks)","description":"Run multiple tasks in parallel","url":"hs.task.html#parallel","kind":"method"},{"fullName":"hs.task.builder(launchPath)","description":"Create a task builder for fluent API","url":"hs.task.html#builder","kind":"method"},{"fullName":"hs.timer","description":"Module for creating and managing timers","url":"hs.timer.html","kind":"module"},{"fullName":"hs.timer.create(interval, callback, continueOnError)","description":"Create a new timer","url":"hs.timer.html#create","kind":"method"},{"fullName":"hs.timer.doAfter(seconds, callback)","description":"Create and start a one-shot timer","url":"hs.timer.html#doAfter","kind":"method"},{"fullName":"hs.timer.doEvery(interval, callback)","description":"Create and start a repeating timer","url":"hs.timer.html#doEvery","kind":"method"},{"fullName":"hs.timer.doAt(time, repeatInterval, callback, continueOnError)","description":"Create and start a timer that fires at a specific time","url":"hs.timer.html#doAt","kind":"method"},{"fullName":"hs.timer.usleep(microseconds)","description":"Block execution for a specified number of microseconds (strongly discouraged)","url":"hs.timer.html#usleep","kind":"method"},{"fullName":"hs.timer.secondsSinceEpoch()","description":"Get the current time as seconds since the UNIX epoch with sub-second precision","url":"hs.timer.html#secondsSinceEpoch","kind":"method"},{"fullName":"hs.timer.absoluteTime()","description":"Get the number of nanoseconds since the system was booted (excluding sleep time)","url":"hs.timer.html#absoluteTime","kind":"method"},{"fullName":"hs.timer.localTime()","description":"Get the number of seconds since local midnight","url":"hs.timer.html#localTime","kind":"method"},{"fullName":"hs.timer.minutes(n)","description":"Converts minutes to seconds","url":"hs.timer.html#minutes","kind":"method"},{"fullName":"hs.timer.hours(n)","description":"Converts hours to seconds","url":"hs.timer.html#hours","kind":"method"},{"fullName":"hs.timer.days(n)","description":"Converts days to seconds","url":"hs.timer.html#days","kind":"method"},{"fullName":"hs.timer.weeks(n)","description":"Converts weeks to seconds","url":"hs.timer.html#weeks","kind":"method"},{"fullName":"hs.timer.doUntil(predicateFn, actionFn, checkInterval)","description":"Repeat a function/lambda until a given predicate function/lambda returns true","url":"hs.timer.html#doUntil","kind":"method"},{"fullName":"hs.timer.doWhile(predicateFn, actionFn, checkInterval)","description":"Repeat a function/lambda while a given predicate function/lambda returns true","url":"hs.timer.html#doWhile","kind":"method"},{"fullName":"hs.timer.waitUntil(predicateFn, actionFn, checkInterval)","description":"Wait to call a function/lambda until a given predicate function/lambda returns true","url":"hs.timer.html#waitUntil","kind":"method"},{"fullName":"hs.timer.waitWhile(predicateFn, actionFn, checkInterval)","description":"Wait to call a function/lambda until a given predicate function/lambda returns false","url":"hs.timer.html#waitWhile","kind":"method"},{"fullName":"hs.translation","description":"Translate text between languages using the macOS on-device Translation framework.","url":"hs.translation.html","kind":"module"},{"fullName":"hs.translation.supportedLanguages()","description":"All language codes supported by the on-device translation engine. Resolves to an array of BCP-47 identifiers (e.g. [\"ar\", \"de\", \"en\", \"es\", \"fr\"]). This covers every language the framework knows about, regardless of whether the packs are installed locally. Use status() to distinguish installed pairs from merely supported ones.","url":"hs.translation.html#supportedLanguages","kind":"method"},{"fullName":"hs.translation.status(sourceLanguage, targetLanguage)","description":"Check the installation status of a language pair.","url":"hs.translation.html#status","kind":"method"},{"fullName":"hs.translation.session(sourceLanguage, targetLanguage)","description":"Create a translation session for a language pair. Returns an HSTranslationSession, or null if the system is running macOS older than 26.0.","url":"hs.translation.html#session","kind":"method"},{"fullName":"hs.ui","description":"# hs.ui","url":"hs.ui.html","kind":"module"},{"fullName":"hs.ui.window(dict)","description":"Create a custom UI window Creates a borderless window that can contain custom UI elements built using a declarative, SwiftUI-like syntax with shapes, text, and layout containers.","url":"hs.ui.html#window","kind":"method"},{"fullName":"hs.ui.alert(message)","description":"Create a temporary on-screen alert Displays a temporary notification that automatically dismisses after the specified duration. Similar to the old hs.alert module but with more features.","url":"hs.ui.html#alert","kind":"method"},{"fullName":"hs.ui.dialog(message)","description":"Create a modal dialog with buttons Shows a blocking dialog with customizable message, informative text, and buttons. Use the callback to handle button presses.","url":"hs.ui.html#dialog","kind":"method"},{"fullName":"hs.ui.textPrompt(message)","description":"Create a text input prompt Shows a modal dialog with a text input field. The callback receives the button index and the entered text.","url":"hs.ui.html#textPrompt","kind":"method"},{"fullName":"hs.ui.string(initialValue)","description":"Create a reactive string for binding text element content to a dynamic value An HSString is a reactive value container. When passed to .text(), the canvas automatically re-renders whenever .set() is called from JavaScript.","url":"hs.ui.html#string","kind":"method"},{"fullName":"hs.ui.filePicker()","description":"Create a file or directory picker Shows a standard macOS file picker dialog. Can be configured to select files, directories, or both, with support for file type filtering and multiple selection.","url":"hs.ui.html#filePicker","kind":"method"},{"fullName":"hs.ui.webview()","description":"Create a web browser element for embedding in hs.ui.window (macOS 26+) Returns a UIWebView element that you configure and then embed in any hs.ui.window via .webview(element). The element fills the available space inside the window layout. Keep a reference to call navigation methods after the window is shown.","url":"hs.ui.html#webview","kind":"method"},{"fullName":"hs.urlevent","description":"Handle URL events received by Hammerspoon 2.","url":"hs.urlevent.html","kind":"module"},{"fullName":"hs.urlevent.httpCallback","description":"Callback invoked when Hammerspoon 2 receives an http:// or https:// URL. Fires only when Hammerspoon 2 is the system default handler for http/https. Assign null to remove the callback.","url":"hs.urlevent.html#httpCallback","kind":"property"},{"fullName":"hs.urlevent.mailtoCallback","description":"Callback invoked when Hammerspoon 2 receives a mailto: URL. Fires only when Hammerspoon 2 is the system default handler for mailto. Assign null to remove the callback.","url":"hs.urlevent.html#mailtoCallback","kind":"property"},{"fullName":"hs.urlevent.bind(eventName, callback)","description":"Register or remove a callback for a named hammerspoon2:// URL event. The URL format is hammerspoon2://eventName?key=value. The host component (eventName) selects the callback to invoke.","url":"hs.urlevent.html#bind","kind":"method"},{"fullName":"hs.urlevent.openURL(urlString)","description":"Open a URL using the system default application for its scheme.","url":"hs.urlevent.html#openURL","kind":"method"},{"fullName":"hs.urlevent.openURLWithBundle(urlString, bundleID)","description":"Open a URL with a specific application identified by bundle ID.","url":"hs.urlevent.html#openURLWithBundle","kind":"method"},{"fullName":"hs.urlevent.getDefaultHandler(scheme)","description":"Returns the bundle identifier of the default application for a URL scheme.","url":"hs.urlevent.html#getDefaultHandler","kind":"method"},{"fullName":"hs.urlevent.getAllHandlersForScheme(scheme)","description":"Returns all bundle identifiers capable of handling a URL scheme.","url":"hs.urlevent.html#getAllHandlersForScheme","kind":"method"},{"fullName":"hs.urlevent.setDefaultHandler(scheme, bundleID)","description":"Set the default application for a URL scheme. macOS may display a confirmation dialog for sensitive schemes such as http and https. For custom schemes (hammerspoon2) no dialog is shown.","url":"hs.urlevent.html#setDefaultHandler","kind":"method"},{"fullName":"hs.usb","description":"Module for monitoring USB device connections and disconnections","url":"hs.usb.html","kind":"module"},{"fullName":"hs.usb.attachedDevices()","description":"Returns all currently attached USB devices.","url":"hs.usb.html#attachedDevices","kind":"method"},{"fullName":"hs.usb.addWatcher(listener)","description":"Register a listener for USB device connection and disconnection events. The listener is called with two arguments: the event type string (\"added\" or \"removed\") and a device-info object with the same fields as attachedDevices().","url":"hs.usb.html#addWatcher","kind":"method"},{"fullName":"hs.usb.removeWatcher(listener)","description":"Remove a previously registered USB event listener.","url":"hs.usb.html#removeWatcher","kind":"method"},{"fullName":"hs.userdefaults","description":"Module for storing small amounts of data that persists across Hammerspoon restarts.","url":"hs.userdefaults.html","kind":"module"},{"fullName":"hs.userdefaults.set(key, value)","description":"Store a value under the given key. The value persists across Hammerspoon restarts. Values must be storable as a property list: strings, numbers, booleans, Dates, arrays, or objects (which may themselves nest any of those types). is rejected with a logged error and nothing is stored. JavaScript functions have no property-list representation; if passed directly, or nested inside an array or object, they are silently stored as an empty object.","url":"hs.userdefaults.html#set","kind":"method"},{"fullName":"hs.userdefaults.get(key)","description":"Retrieve a previously stored value.","url":"hs.userdefaults.html#get","kind":"method"},{"fullName":"hs.userdefaults.clear(key)","description":"Delete a previously stored value.","url":"hs.userdefaults.html#clear","kind":"method"},{"fullName":"hs.userdefaults.getKeys()","description":"Get the names of all currently stored settings.","url":"hs.userdefaults.html#getKeys","kind":"method"},{"fullName":"hs.userdefaults.addWatcher(key, listener)","description":"Watch a key for changes.","url":"hs.userdefaults.html#addWatcher","kind":"method"},{"fullName":"hs.userdefaults.removeWatcher(key, listener)","description":"Remove a previously registered watcher.","url":"hs.userdefaults.html#removeWatcher","kind":"method"},{"fullName":"hs.wifi","description":"Control and query Wi-Fi interfaces, scan for networks, and watch for Wi-Fi events.","url":"hs.wifi.html","kind":"module"},{"fullName":"hs.wifi.watcherEventTypes","description":"The Wi-Fi event types that can be passed to HSWifiWatcher.events.","url":"hs.wifi.html#watcherEventTypes","kind":"property"},{"fullName":"hs.wifi.interfaces()","description":"Returns the names of all Wi-Fi interfaces attached to the system (e.g. [\"en0\"]).","url":"hs.wifi.html#interfaces","kind":"method"},{"fullName":"hs.wifi.interfaceDetails(interface)","description":"Returns detailed information about a Wi-Fi interface.","url":"hs.wifi.html#interfaceDetails","kind":"method"},{"fullName":"hs.wifi.currentNetwork(interface)","description":"Returns the SSID of the network currently joined on an interface.","url":"hs.wifi.html#currentNetwork","kind":"method"},{"fullName":"hs.wifi.setPower(state, interface)","description":"Turns a Wi-Fi interface on or off.","url":"hs.wifi.html#setPower","kind":"method"},{"fullName":"hs.wifi.disassociate(interface)","description":"Disconnects an interface from its current network.","url":"hs.wifi.html#disassociate","kind":"method"},{"fullName":"hs.wifi.associate(ssid, passphrase, interface)","description":"Scans for a network by SSID and joins it. Enterprise networks are not supported. This can take several seconds; it runs off the main thread so it does not block the app.","url":"hs.wifi.html#associate","kind":"method"},{"fullName":"hs.wifi.scanNetworks(interface)","description":"Scans for visible Wi-Fi networks. This can take a few seconds; it runs off the main thread so it does not block the app.","url":"hs.wifi.html#scanNetworks","kind":"method"},{"fullName":"hs.wifi.addWatcher()","description":"Creates a new Wi-Fi event watcher. Call .setCallback() and .start() to activate it. The watcher is stopped automatically when the module shuts down.","url":"hs.wifi.html#addWatcher","kind":"method"},{"fullName":"hs.window","description":"Module for interacting with windows","url":"hs.window.html","kind":"module"},{"fullName":"hs.window.focusedWindow()","description":"Get the currently focused window","url":"hs.window.html#focusedWindow","kind":"method"},{"fullName":"hs.window.allWindows()","description":"Get all windows from all applications","url":"hs.window.html#allWindows","kind":"method"},{"fullName":"hs.window.visibleWindows()","description":"Get all visible (not minimized) windows","url":"hs.window.html#visibleWindows","kind":"method"},{"fullName":"hs.window.windowsForApp(app)","description":"Get windows for a specific application","url":"hs.window.html#windowsForApp","kind":"method"},{"fullName":"hs.window.windowsOnScreen(screenIndex)","description":"Get all windows on a specific screen","url":"hs.window.html#windowsOnScreen","kind":"method"},{"fullName":"hs.window.windowAtPoint(point)","description":"Get the window at a specific screen position","url":"hs.window.html#windowAtPoint","kind":"method"},{"fullName":"hs.window.orderedWindows()","description":"Get ordered windows (front to back)","url":"hs.window.html#orderedWindows","kind":"method"},{"fullName":"hs.window.findByTitle(title)","description":"Find windows by title Parameter title: The window title to search for. All windows with titles that include this string, will be matched","url":"hs.window.html#findByTitle","kind":"method"},{"fullName":"hs.window.currentWindows()","description":"Get all windows for the current application","url":"hs.window.html#currentWindows","kind":"method"},{"fullName":"hs.window.moveToLeftHalf(win)","description":"Move a window to left half of screen Parameter win: An HSWindow object","url":"hs.window.html#moveToLeftHalf","kind":"method"},{"fullName":"hs.window.moveToRightHalf(win)","description":"Move a window to right half of screen Parameter win: An HSWindow object","url":"hs.window.html#moveToRightHalf","kind":"method"},{"fullName":"hs.window.maximize(win)","description":"Maximize a window Parameter win: An HSWindow object","url":"hs.window.html#maximize","kind":"method"},{"fullName":"HSApplication","description":"Object representing an application. You should not instantiate this directly in JavaScript, but rather, use the methods from hs.application which will return appropriate HSApplication objects.","url":"HSApplication.html","kind":"type"},{"fullName":"HSApplication.pid","description":"POSIX Process Identifier","url":"HSApplication.html#pid","kind":"property"},{"fullName":"HSApplication.bundleID","description":"Bundle Identifier (e.g. com.apple.Safari)","url":"HSApplication.html#bundleID","kind":"property"},{"fullName":"HSApplication.title","description":"The application's title","url":"HSApplication.html#title","kind":"property"},{"fullName":"HSApplication.bundlePath","description":"Location of the application on disk","url":"HSApplication.html#bundlePath","kind":"property"},{"fullName":"HSApplication.isHidden","description":"Is the application hidden","url":"HSApplication.html#isHidden","kind":"property"},{"fullName":"HSApplication.isActive","description":"Is the application focused","url":"HSApplication.html#isActive","kind":"property"},{"fullName":"HSApplication.mainWindow","description":"The main window of this application, or nil if there is no main window","url":"HSApplication.html#mainWindow","kind":"property"},{"fullName":"HSApplication.focusedWindow","description":"The focused window of this application, or nil if there is no focused window","url":"HSApplication.html#focusedWindow","kind":"property"},{"fullName":"HSApplication.allWindows","description":"All windows of this application","url":"HSApplication.html#allWindows","kind":"property"},{"fullName":"HSApplication.visibleWindows","description":"All visible (ie non-hidden) windows of this application","url":"HSApplication.html#visibleWindows","kind":"property"},{"fullName":"HSApplication.isRunning","description":"Whether the application process is still running","url":"HSApplication.html#isRunning","kind":"property"},{"fullName":"HSApplication.kind","description":"The kind of application: \"standard\" (regular dock app), \"accessory\" (no dock), or \"background\" (agent)","url":"HSApplication.html#kind","kind":"property"},{"fullName":"HSApplication.kill()","description":"Terminate the application","url":"HSApplication.html#kill","kind":"method"},{"fullName":"HSApplication.kill9()","description":"Force-terminate the application","url":"HSApplication.html#kill9","kind":"method"},{"fullName":"HSApplication.axElement()","description":"The application's HSAXElement object, for use with the hs.ax APIs","url":"HSApplication.html#axElement","kind":"method"},{"fullName":"HSApplication.activate(allWindows)","description":"Bring this application to the foreground","url":"HSApplication.html#activate","kind":"method"},{"fullName":"HSApplication.hide()","description":"Hide this application and all its windows","url":"HSApplication.html#hide","kind":"method"},{"fullName":"HSApplication.unhide()","description":"Unhide this application","url":"HSApplication.html#unhide","kind":"method"},{"fullName":"HSApplication.getMenuItems()","description":"Get the full menu structure of this application","url":"HSApplication.html#getMenuItems","kind":"method"},{"fullName":"HSApplication.findMenuItemByName(name)","description":"Find a menu item by searching all menus for a matching title (case-insensitive)","url":"HSApplication.html#findMenuItemByName","kind":"method"},{"fullName":"HSApplication.findMenuItemByPath(path)","description":"Find a menu item by following a hierarchical path of titles","url":"HSApplication.html#findMenuItemByPath","kind":"method"},{"fullName":"HSApplication.selectMenuItemByName(name)","description":"Click a menu item found by searching all menus for a matching title (case-insensitive)","url":"HSApplication.html#selectMenuItemByName","kind":"method"},{"fullName":"HSApplication.selectMenuItemByPath(path)","description":"Click a menu item found by following a hierarchical path of titles","url":"HSApplication.html#selectMenuItemByPath","kind":"method"},{"fullName":"HSApplication.findWindow(pattern)","description":"Find windows whose title contains the given string (case-insensitive)","url":"HSApplication.html#findWindow","kind":"method"},{"fullName":"HSApplication.getWindow(title)","description":"Get the first window with exactly the given title","url":"HSApplication.html#getWindow","kind":"method"},{"fullName":"HSAudioDevice","description":"An audio device attached to the system. Obtain instances via `hs.audiodevice module methods — do not instantiate directly. ## Getting and setting volume `javascript const dev = hs.audiodevice.defaultOutputDevice(); if (dev) { console.log(dev.volume); // 0.0 – 1.0, or null dev.volume = 0.5; } ` ## Watching for changes `javascript const dev = hs.audiodevice.defaultOutputDevice(); if (dev) { var fn = function(event) { console.log(\"Device event:\", event); }; dev.addWatcher(fn); // later… dev.removeWatcher(fn); } ``","url":"HSAudioDevice.html","kind":"type"},{"fullName":"HSAudioDevice.id","description":"The CoreAudio object ID of this device.","url":"HSAudioDevice.html#id","kind":"property"},{"fullName":"HSAudioDevice.name","description":"The human-readable name of this device (e.g. \"Built-in Output\").","url":"HSAudioDevice.html#name","kind":"property"},{"fullName":"HSAudioDevice.uid","description":"The persistent unique identifier for this device.","url":"HSAudioDevice.html#uid","kind":"property"},{"fullName":"HSAudioDevice.isOutput","description":"Whether this device has output streams (can play audio).","url":"HSAudioDevice.html#isOutput","kind":"property"},{"fullName":"HSAudioDevice.isInput","description":"Whether this device has input streams (can record audio).","url":"HSAudioDevice.html#isInput","kind":"property"},{"fullName":"HSAudioDevice.transportType","description":"The transport mechanism: \"built-in\", \"usb\", \"bluetooth\", \"bluetooth-le\", \"hdmi\", \"display-port\", \"firewire\", \"airplay\", \"avb\", \"thunderbolt\", \"virtual\", \"aggregate\", \"pci\", or \"unknown\".","url":"HSAudioDevice.html#transportType","kind":"property"},{"fullName":"HSAudioDevice.outputChannels","description":"Number of output channels, or 0 if the device has no output.","url":"HSAudioDevice.html#outputChannels","kind":"property"},{"fullName":"HSAudioDevice.inputChannels","description":"Number of input channels, or 0 if the device has no input.","url":"HSAudioDevice.html#inputChannels","kind":"property"},{"fullName":"HSAudioDevice.volume","description":"Output volume scalar in the range 0.0–1.0, or null if the device has no controllable output volume. Setting null is a no-op.","url":"HSAudioDevice.html#volume","kind":"property"},{"fullName":"HSAudioDevice.muted","description":"Whether output is muted. Always false if the device has no mutable output.","url":"HSAudioDevice.html#muted","kind":"property"},{"fullName":"HSAudioDevice.balance","description":"Output stereo balance in the range 0.0 (full left)–1.0 (full right), or null if balance control is not available.","url":"HSAudioDevice.html#balance","kind":"property"},{"fullName":"HSAudioDevice.inputVolume","description":"Input (microphone) volume scalar in the range 0.0–1.0, or null if the device has no controllable input volume.","url":"HSAudioDevice.html#inputVolume","kind":"property"},{"fullName":"HSAudioDevice.inputMuted","description":"Whether input is muted. Always false if the device has no mutable input.","url":"HSAudioDevice.html#inputMuted","kind":"property"},{"fullName":"HSAudioDevice.sampleRate","description":"The current nominal sample rate in Hz (e.g. 44100), or null if unknown.","url":"HSAudioDevice.html#sampleRate","kind":"property"},{"fullName":"HSAudioDevice.availableSampleRates","description":"All sample rates (in Hz) that this device supports. For devices that support a range, both the minimum and maximum are included.","url":"HSAudioDevice.html#availableSampleRates","kind":"property"},{"fullName":"HSAudioDevice.currentOutputDataSource()","description":"The current output data source as { id, name }, or null if unavailable.","url":"HSAudioDevice.html#currentOutputDataSource","kind":"method"},{"fullName":"HSAudioDevice.currentInputDataSource()","description":"The current input data source as { id, name }, or null if unavailable.","url":"HSAudioDevice.html#currentInputDataSource","kind":"method"},{"fullName":"HSAudioDevice.outputDataSources()","description":"All available output data sources as an array of { id, name } objects.","url":"HSAudioDevice.html#outputDataSources","kind":"method"},{"fullName":"HSAudioDevice.inputDataSources()","description":"All available input data sources as an array of { id, name } objects.","url":"HSAudioDevice.html#inputDataSources","kind":"method"},{"fullName":"HSAudioDevice.setCurrentOutputDataSource(sourceID)","description":"Select an output data source by its numeric ID.","url":"HSAudioDevice.html#setCurrentOutputDataSource","kind":"method"},{"fullName":"HSAudioDevice.setCurrentInputDataSource(sourceID)","description":"Select an input data source by its numeric ID.","url":"HSAudioDevice.html#setCurrentInputDataSource","kind":"method"},{"fullName":"HSAudioDevice.setDefaultOutputDevice()","description":"Make this device the system default output device.","url":"HSAudioDevice.html#setDefaultOutputDevice","kind":"method"},{"fullName":"HSAudioDevice.setDefaultInputDevice()","description":"Make this device the system default input device.","url":"HSAudioDevice.html#setDefaultInputDevice","kind":"method"},{"fullName":"HSAudioDevice.setDefaultEffectDevice()","description":"Make this device the system alert sound (effect) device.","url":"HSAudioDevice.html#setDefaultEffectDevice","kind":"method"},{"fullName":"HSAudioDevice.addWatcher(listener)","description":"Register a listener for a per-device property-change event.","url":"HSAudioDevice.html#addWatcher","kind":"method"},{"fullName":"HSAudioDevice.removeWatcher(listener)","description":"Remove a previously registered per-device listener.","url":"HSAudioDevice.html#removeWatcher","kind":"method"},{"fullName":"HSAXElement","description":"Object representing an Accessibility element. You should not instantiate this directly, but rather, use the hs.ax methods to create these as required.","url":"HSAXElement.html","kind":"type"},{"fullName":"HSAXElement.role","description":"The element's role (e.g., \"AXWindow\", \"AXButton\")","url":"HSAXElement.html#role","kind":"property"},{"fullName":"HSAXElement.subrole","description":"The element's subrole","url":"HSAXElement.html#subrole","kind":"property"},{"fullName":"HSAXElement.title","description":"The element's title","url":"HSAXElement.html#title","kind":"property"},{"fullName":"HSAXElement.value","description":"The element's value","url":"HSAXElement.html#value","kind":"property"},{"fullName":"HSAXElement.elementDescription","description":"The element's description","url":"HSAXElement.html#elementDescription","kind":"property"},{"fullName":"HSAXElement.isEnabled","description":"Whether the element is enabled","url":"HSAXElement.html#isEnabled","kind":"property"},{"fullName":"HSAXElement.isFocused","description":"Whether the element is focused","url":"HSAXElement.html#isFocused","kind":"property"},{"fullName":"HSAXElement.position","description":"The element's position on screen","url":"HSAXElement.html#position","kind":"property"},{"fullName":"HSAXElement.size","description":"The element's size","url":"HSAXElement.html#size","kind":"property"},{"fullName":"HSAXElement.frame","description":"The element's frame (position and size combined)","url":"HSAXElement.html#frame","kind":"property"},{"fullName":"HSAXElement.parent","description":"The element's parent","url":"HSAXElement.html#parent","kind":"property"},{"fullName":"HSAXElement.pid","description":"Get the process ID of the application that owns this element","url":"HSAXElement.html#pid","kind":"property"},{"fullName":"HSAXElement.children()","description":"The element's children","url":"HSAXElement.html#children","kind":"method"},{"fullName":"HSAXElement.childAtIndex(index)","description":"Get a specific child by index","url":"HSAXElement.html#childAtIndex","kind":"method"},{"fullName":"HSAXElement.attributeNames()","description":"Get all available attribute names","url":"HSAXElement.html#attributeNames","kind":"method"},{"fullName":"HSAXElement.attributeValue(attribute)","description":"Get the value of a specific attribute","url":"HSAXElement.html#attributeValue","kind":"method"},{"fullName":"HSAXElement.setAttributeValue(attribute, value)","description":"Set the value of a specific attribute","url":"HSAXElement.html#setAttributeValue","kind":"method"},{"fullName":"HSAXElement.isAttributeSettable(attribute)","description":"Check if an attribute is settable","url":"HSAXElement.html#isAttributeSettable","kind":"method"},{"fullName":"HSAXElement.actionNames()","description":"Get all available action names","url":"HSAXElement.html#actionNames","kind":"method"},{"fullName":"HSAXElement.performAction(action)","description":"Perform a specific action","url":"HSAXElement.html#performAction","kind":"method"},{"fullName":"HSBonjourSearch","description":"Discovers Bonjour services and domains advertised on the local network. Create via hs.bonjour.newSearch(), then call one of the find… methods. Each search type uses its own underlying NetServiceBrowser, so service and domain searches can run concurrently. Restarting any single search type stops only that browser before beginning the new one. ## Service search callback events | Event | Data | Description | |-------|------|-------------| | \"serviceFound\" | HSBonjourService | A matching service appeared | | \"serviceRemoved\" | HSBonjourService | A previously found service disappeared | | \"error\" | error string | The search failed | ## Domain search callback events | Event | Data | Description | |-------|------|-------------| | \"domainFound\" | domain string | A domain was discovered | | \"domainRemoved\" | domain string | A domain disappeared | | \"error\" | error string | The search failed |","url":"HSBonjourSearch.html","kind":"type"},{"fullName":"HSBonjourSearch.identifier","description":"A unique identifier for this search object.","url":"HSBonjourSearch.html#identifier","kind":"property"},{"fullName":"HSBonjourSearch.includesPeerToPeer","description":"Whether to search over peer-to-peer Bluetooth/Wi-Fi in addition to standard network interfaces. Defaults to false.","url":"HSBonjourSearch.html#includesPeerToPeer","kind":"property"},{"fullName":"HSBonjourSearch.findServices(type, domain, callback)","description":"Searches for services of the given type in the given domain. If a service search is already active it is stopped before starting the new one. Domain searches are unaffected. The callback receives (event, service, moreComing) — see the type documentation for the complete event table.","url":"HSBonjourSearch.html#findServices","kind":"method"},{"fullName":"HSBonjourSearch.findBrowsableDomains(callback)","description":"Searches for domains visible to this machine (browsable domains). If a browsable-domain search is already active it is stopped before starting the new one. Service and registration-domain searches are unaffected. The callback receives (event, domain, moreComing).","url":"HSBonjourSearch.html#findBrowsableDomains","kind":"method"},{"fullName":"HSBonjourSearch.findRegistrationDomains(callback)","description":"Searches for domains on which this machine can register services. If a registration-domain search is already active it is stopped before starting the new one. Service and browsable-domain searches are unaffected. The callback receives (event, domain, moreComing).","url":"HSBonjourSearch.html#findRegistrationDomains","kind":"method"},{"fullName":"HSBonjourSearch.stop()","description":"Stops all active searches. Safe to call when no search is active.","url":"HSBonjourSearch.html#stop","kind":"method"},{"fullName":"HSBonjourService","description":"A discovered Bonjour service record. Call resolve() to look up its hostname, port, and addresses. Instances are delivered by an HSBonjourSearch callback. Call resolve() to discover their hostname, port, and addresses, and optionally monitor() to watch for TXT record changes. ## Callback events | Method | Event | Extra data | |--------|-------|------------| | resolve() | \"resolved\" | _(none)_ | | resolve() | \"stopped\" | _(none)_ | | resolve() | \"error\" | error message string | | monitor() | \"txtRecord\" | updated TXT record dict |","url":"HSBonjourService.html","kind":"type"},{"fullName":"HSBonjourService.identifier","description":"A unique identifier assigned to this service object.","url":"HSBonjourService.html#identifier","kind":"property"},{"fullName":"HSBonjourService.name","description":"The service name (e.g. \"My Web Server\").","url":"HSBonjourService.html#name","kind":"property"},{"fullName":"HSBonjourService.type","description":"The service type string (e.g. \"_http._tcp.\").","url":"HSBonjourService.html#type","kind":"property"},{"fullName":"HSBonjourService.domain","description":"The mDNS domain (almost always \"local.\").","url":"HSBonjourService.html#domain","kind":"property"},{"fullName":"HSBonjourService.hostname","description":"The resolved hostname, or null before resolve() completes.","url":"HSBonjourService.html#hostname","kind":"property"},{"fullName":"HSBonjourService.port","description":"The service port. -1 until resolve() completes.","url":"HSBonjourService.html#port","kind":"property"},{"fullName":"HSBonjourService.addresses","description":"IP address strings (IPv4 and/or IPv6) populated after resolve() completes.","url":"HSBonjourService.html#addresses","kind":"property"},{"fullName":"HSBonjourService.txtRecord","description":"The TXT record as a {key: value} object, or null if none is available. Populated after resolve() completes or when updated via monitor().","url":"HSBonjourService.html#txtRecord","kind":"property"},{"fullName":"HSBonjourService.includesPeerToPeer","description":"Whether peer-to-peer Bluetooth/Wi-Fi is included in resolution.","url":"HSBonjourService.html#includesPeerToPeer","kind":"property"},{"fullName":"HSBonjourService.resolve(timeout, callback)","description":"Resolves the hostname, port, addresses, and TXT record of this service.","url":"HSBonjourService.html#resolve","kind":"method"},{"fullName":"HSBonjourService.monitor(callback)","description":"Starts monitoring the TXT record for changes. The callback fires whenever the TXT record is updated. Call stopMonitoring() to unsubscribe.","url":"HSBonjourService.html#monitor","kind":"method"},{"fullName":"HSBonjourService.stop()","description":"Stops any active resolution.","url":"HSBonjourService.html#stop","kind":"method"},{"fullName":"HSBonjourService.stopMonitoring()","description":"Stops TXT record monitoring started by monitor().","url":"HSBonjourService.html#stopMonitoring","kind":"method"},{"fullName":"HSCamera","description":"A camera device attached to the system. Obtain instances via the `hs.camera module — do not instantiate directly. ## Reading camera properties `javascript const cam = hs.camera.all()[0] console.log(cam.name + \" uid=\" + cam.uid + \" inUse=\" + cam.isInUse) ` ## Watching for in-use state changes `javascript const cam = hs.camera.all()[0] const fn = (isInUse) => { console.log(cam.name + \" is now \" + (isInUse ? \"in use\" : \"not in use\")) } cam.addWatcher(fn) // later… cam.removeWatcher(fn) ` ## Capturing a still image `javascript const cam = hs.camera.all()[0] cam.captureImage() .then(img => img.saveToFile(\"/tmp/shot.png\")) .catch(err => console.error(\"Capture failed: \" + err)) ``","url":"HSCamera.html","kind":"type"},{"fullName":"HSCamera.typeName","description":"The type name for JavaScript introspection. Always \"HSCamera\".","url":"HSCamera.html#typeName","kind":"property"},{"fullName":"HSCamera.uid","description":"The persistent unique identifier for this camera.","url":"HSCamera.html#uid","kind":"property"},{"fullName":"HSCamera.name","description":"The human-readable name of this camera (e.g. \"FaceTime HD Camera\").","url":"HSCamera.html#name","kind":"property"},{"fullName":"HSCamera.isInUse","description":"Whether this camera is currently being used by any application. Queries the underlying CoreMediaIO device state each time it is read.","url":"HSCamera.html#isInUse","kind":"property"},{"fullName":"HSCamera.addWatcher(listener)","description":"Register a listener that fires whenever this camera's in-use state changes. The listener receives one argument: a boolean that is true when the camera starts being used and false when it is released.","url":"HSCamera.html#addWatcher","kind":"method"},{"fullName":"HSCamera.removeWatcher(listener)","description":"Remove a previously registered per-camera in-use listener.","url":"HSCamera.html#removeWatcher","kind":"method"},{"fullName":"HSCamera.captureImage()","description":"Capture a still image from this camera. Camera permission must be granted via hs.permissions.requestCamera() before calling this method. The returned HSImage can be saved, displayed in a UI element, or passed to other image-processing APIs.","url":"HSCamera.html#captureImage","kind":"method"},{"fullName":"HSCanvas","description":"# HSCanvas A single canvas window: an absolutely-positioned, low-level drawing surface mirroring v1 Hammerspoon's hs.canvas. Elements are plain JS objects (matching v1's Lua tables) added with appendElements() and mutated in place with setElementAttribute()/elementAttribute(). Supports the same fill/stroke/ strokeAndFill/clip/build/skip action pipeline as v1, including the build+clip+reversePath technique used to punch holes in shapes (see hs.canvas.windowLevels/hs.canvas.windowBehaviors for the window-level/Spaces controls needed alongside this for overlay-style canvases). ## Example ``javascript const c = hs.canvas.create({x: 100, y: 100, w: 200, h: 200}) c.appendElements([ { type: \"rectangle\", action: \"fill\", fillColor: { red: 0.2, green: 0.5, blue: 0.9, alpha: 1 } } ]) c.show() ``","url":"HSCanvas.html","kind":"type"},{"fullName":"HSCanvas.show()","description":"Show the canvas window","url":"HSCanvas.html#show","kind":"method"},{"fullName":"HSCanvas.hide()","description":"Hide the canvas window (keeps it in memory; elements and window config are preserved)","url":"HSCanvas.html#hide","kind":"method"},{"fullName":"HSCanvas.destroy()","description":"Destroy the canvas window and release its resources Named destroy() rather than v1's delete() -- delete cannot be used as a JavaScriptCore-exported method name in this codebase's bridging layer.","url":"HSCanvas.html#destroy","kind":"method"},{"fullName":"HSCanvas.isShowing()","description":"Whether the canvas window is currently ordered onto the screen","url":"HSCanvas.html#isShowing","kind":"method"},{"fullName":"HSCanvas.isVisible()","description":"Whether the canvas is showing AND at least partially visible (not fully occluded or off-screen)","url":"HSCanvas.html#isVisible","kind":"method"},{"fullName":"HSCanvas.isOccluded()","description":"Whether the canvas is hidden behind other windows, or off-screen entirely","url":"HSCanvas.html#isOccluded","kind":"method"},{"fullName":"HSCanvas.frame()","description":"The canvas window's current position and size","url":"HSCanvas.html#frame","kind":"method"},{"fullName":"HSCanvas.setFrame(rect)","description":"Move and/or resize the canvas window","url":"HSCanvas.html#setFrame","kind":"method"},{"fullName":"HSCanvas.topLeft()","description":"The canvas window's current top-left corner the point at the window's highest y (its screen-visual top), not y = 0.","url":"HSCanvas.html#topLeft","kind":"method"},{"fullName":"HSCanvas.setTopLeft(point)","description":"Move the canvas window without changing its size","url":"HSCanvas.html#setTopLeft","kind":"method"},{"fullName":"HSCanvas.size()","description":"The canvas window's current size","url":"HSCanvas.html#size","kind":"method"},{"fullName":"HSCanvas.setSize(dimensions)","description":"Resize the canvas window without moving its top-left corner","url":"HSCanvas.html#setSize","kind":"method"},{"fullName":"HSCanvas.level(name)","description":"Set the window level by name","url":"HSCanvas.html#level","kind":"method"},{"fullName":"HSCanvas.levelValue(value)","description":"Set the window level to a raw numeric value Split out from level(_:) (rather than accepting a string-or-number union) because JSExport parameters must have a single concrete type -- see hs.canvas.windowLevels, which exposes raw numeric values (not opaque name strings) so scripts can do arithmetic on them, matching v1 behavior.","url":"HSCanvas.html#levelValue","kind":"method"},{"fullName":"HSCanvas.behavior(name)","description":"Set the window's Spaces/Exposé collection behavior to a single named behavior","url":"HSCanvas.html#behavior","kind":"method"},{"fullName":"HSCanvas.behaviorList(names)","description":"Set the window's Spaces/Exposé collection behavior to a combination of named behaviors","url":"HSCanvas.html#behaviorList","kind":"method"},{"fullName":"HSCanvas.behaviorValue(value)","description":"Set the window's Spaces/Exposé collection behavior to a raw bitmask","url":"HSCanvas.html#behaviorValue","kind":"method"},{"fullName":"HSCanvas.clickActivating(flag)","description":"Set whether clicking the canvas activates the Hammerspoon app","url":"HSCanvas.html#clickActivating","kind":"method"},{"fullName":"HSCanvas.ignoreMouseEvents(flag)","description":"Set whether the canvas window ignores all mouse events, passing clicks through to whatever is behind it This is a capability beyond v1's hs.canvas API surface (not a literal v1 method name) -- v1 has no direct equivalent for full click pass-through.","url":"HSCanvas.html#ignoreMouseEvents","kind":"method"},{"fullName":"HSCanvas.appendElements(elements)","description":"Append one or more elements to the end of the canvas Element frame/center/coordinates values are y-down (y = 0 at the top of the canvas) -- a different sense from the canvas window's own x/y position, which is unflipped AppKit screen coordinates. See hs.canvas's module-level docs for the full explanation.","url":"HSCanvas.html#appendElements","kind":"method"},{"fullName":"HSCanvas.insertElement(element, index)","description":"Insert an element at a specific index","url":"HSCanvas.html#insertElement","kind":"method"},{"fullName":"HSCanvas.assignElement(element, index)","description":"Replace the element at an index, or append if the index equals the current element count","url":"HSCanvas.html#assignElement","kind":"method"},{"fullName":"HSCanvas.removeElement(index)","description":"Remove the element at a specific index","url":"HSCanvas.html#removeElement","kind":"method"},{"fullName":"HSCanvas.removeLastElement()","description":"Remove the last element","url":"HSCanvas.html#removeLastElement","kind":"method"},{"fullName":"HSCanvas.replaceElements(elements)","description":"Replace all elements on the canvas","url":"HSCanvas.html#replaceElements","kind":"method"},{"fullName":"HSCanvas.elementCount()","description":"The number of elements on the canvas","url":"HSCanvas.html#elementCount","kind":"method"},{"fullName":"HSCanvas.canvasElements()","description":"All elements currently on the canvas","url":"HSCanvas.html#canvasElements","kind":"method"},{"fullName":"HSCanvas.elementKeys(index)","description":"The attribute keys present on an element","url":"HSCanvas.html#elementKeys","kind":"method"},{"fullName":"HSCanvas.elementAttribute(index, key)","description":"Get a single attribute value from an element Returns Any? (mirroring hs.userdefaults.get()) rather than a concrete Swift type because an element attribute's value is genuinely heterogeneous -- a string, number, boolean, nested object, or array, matching v1's dynamically-typed Lua table values.","url":"HSCanvas.html#elementAttribute","kind":"method"},{"fullName":"HSCanvas.setElementAttribute(index, key, value)","description":"Set a single attribute value on an element","url":"HSCanvas.html#setElementAttribute","kind":"method"},{"fullName":"HSCanvas.removeElementAttribute(index, key)","description":"Remove a single attribute from an element","url":"HSCanvas.html#removeElementAttribute","kind":"method"},{"fullName":"HSCanvas.elementBounds(index)","description":"The smallest rectangle enclosing an element's rendered shape","url":"HSCanvas.html#elementBounds","kind":"method"},{"fullName":"HSCanvas.minimumTextSize(index, text)","description":"The smallest size that can fully render a string of text, using a text element's font attributes (textFont/textSize/textWeight/textDesign/textItalic) Mirrors v1's hs.canvas:minimumTextSize(). Multi-line strings (separated by \\n) are measured correctly -- the height covers every line and the width is the longest line's width, not a fixed single-line size.","url":"HSCanvas.html#minimumTextSize","kind":"method"},{"fullName":"HSCanvas.mouseCallback(callback)","description":"Set the callback fired for tracked mouse events Fires for elements with trackMouseDown/trackMouseUp/trackMouseEnterExit/ trackMouseMove set to true in their element dictionary, and for whole-canvas regions enabled via canvasMouseEvents() (delivered with id \"_canvas\").","url":"HSCanvas.html#mouseCallback","kind":"method"},{"fullName":"HSCanvas.canvasMouseEvents(down, up, enterExit, move)","description":"Enable whole-canvas mouse tracking for regions not covered by any individually tracked element. Delivered through mouseCallback() with id \"_canvas\".","url":"HSCanvas.html#canvasMouseEvents","kind":"method"},{"fullName":"HSCanvas.rotateElement(index, angle)","description":"Rotate an element about its own bounding-box center","url":"HSCanvas.html#rotateElement","kind":"method"},{"fullName":"HSCanvas.rotateElementAroundPoint(index, angle, point)","description":"Rotate an element about a specific point","url":"HSCanvas.html#rotateElementAroundPoint","kind":"method"},{"fullName":"HSCanvas.setElementTransformation(index, matrix)","description":"Apply a raw 2D affine transformation matrix to a single element","url":"HSCanvas.html#setElementTransformation","kind":"method"},{"fullName":"HSCanvas.setTransformation(matrix)","description":"Apply a raw 2D affine transformation matrix to the whole canvas","url":"HSCanvas.html#setTransformation","kind":"method"},{"fullName":"HSCanvas.clearTransformation()","description":"Remove the whole-canvas transformation set by setTransformation()","url":"HSCanvas.html#clearTransformation","kind":"method"},{"fullName":"HSCanvas.imageFromCanvas()","description":"Render the canvas's current contents to an image","url":"HSCanvas.html#imageFromCanvas","kind":"method"},{"fullName":"HSCanvas.duplicate()","description":"Create an independent copy of this canvas, with the same frame, elements, and window configuration Named duplicate() rather than v1's copy() -- this codebase's conventions forbid method names starting with copy (an ARC/ObjC hazard), the same rule that renamed new() to create().","url":"HSCanvas.html#duplicate","kind":"method"},{"fullName":"HSCanvas.setAccessibilitySubrole(subrole)","description":"Set the accessibility subrole reported for this canvas's window","url":"HSCanvas.html#setAccessibilitySubrole","kind":"method"},{"fullName":"HSCanvas.draggingCallback(callback)","description":"Set a callback fired when files or text are dropped onto the canvas","url":"HSCanvas.html#draggingCallback","kind":"method"},{"fullName":"HSChooser","description":"A keyboard-driven floating chooser panel. Create via hs.chooser.create(). Configure choices, set callbacks, then call .show(). ## Choice format Each choice is a plain object with required text and optional subText, image, valid, and contextMenu fields. All other fields are passed through to the onSelect callback unchanged. The contextMenu array defines per-row right-click menu entries. Each entry is either ``javascript { text: \"Open Safari\", subText: \"com.apple.Safari\", image: HSImage.fromAppBundle(\"com.apple.Safari\"), valid: true, myData: 42, contextMenu: [ { title: \"Open\", action: () => hs.urlevent.openURL(\"https://apple.com\") }, { type: \"divider\" }, { title: \"Copy bundle ID\", action: () => hs.pasteboard.writeString(\"com.apple.Safari\") } ] } `` ## Keyboard shortcuts","url":"HSChooser.html","kind":"type"},{"fullName":"HSChooser.typeName","description":"Read-only type identifier.","url":"HSChooser.html#typeName","kind":"property"},{"fullName":"HSChooser.identifier","description":"Stable UUID string for this chooser instance.","url":"HSChooser.html#identifier","kind":"property"},{"fullName":"HSChooser.query","description":"The current text in the search field. Setting this from JS updates the display but does not invoke the onQueryChange callback.","url":"HSChooser.html#query","kind":"property"},{"fullName":"HSChooser.placeholder","description":"Placeholder text shown in the empty search field (default: \"Search...\").","url":"HSChooser.html#placeholder","kind":"property"},{"fullName":"HSChooser.searchSubText","description":"Whether searches match against subText in addition to text (default: false). Only applies when a static choices array is provided.","url":"HSChooser.html#searchSubText","kind":"property"},{"fullName":"HSChooser.enableDefaultForQuery","description":"When true and the query is non-empty but there are no matching choices, onSelect is called with { text: } instead of null (default: false).","url":"HSChooser.html#enableDefaultForQuery","kind":"property"},{"fullName":"HSChooser.selectedRow","description":"The zero-based index of the currently highlighted row (-1 when empty).","url":"HSChooser.html#selectedRow","kind":"property"},{"fullName":"HSChooser.width","description":"Width of the chooser as a fraction of the screen width (default: 0.5 = 50 %).","url":"HSChooser.html#width","kind":"property"},{"fullName":"HSChooser.visibleRows","description":"Maximum number of rows visible at once without scrolling (default: 10).","url":"HSChooser.html#visibleRows","kind":"property"},{"fullName":"HSChooser.isVisible","description":"true if the chooser panel is currently on screen.","url":"HSChooser.html#isVisible","kind":"property"},{"fullName":"HSChooser.onSelect","description":"Called when the user confirms a selection, or null to remove the handler. The argument is the chosen row object (the original dict you passed to setChoices, with text, subText, image, valid, and any custom fields intact). The argument is null when dismissed (Escape).","url":"HSChooser.html#onSelect","kind":"property"},{"fullName":"HSChooser.onQueryChange","description":"Called on every keystroke with the new query string, or null to remove the handler. Use this to debounce expensive searches or trigger async data fetching.","url":"HSChooser.html#onQueryChange","kind":"property"},{"fullName":"HSChooser.onShow","description":"Called after the panel becomes visible, or null to remove the handler.","url":"HSChooser.html#onShow","kind":"property"},{"fullName":"HSChooser.onHide","description":"Called after the panel is hidden (for any reason: selection, Escape, or hide()), or null to remove the handler.","url":"HSChooser.html#onHide","kind":"property"},{"fullName":"HSChooser.onInvalid","description":"Called when the user activates a row whose valid field is false, or null to remove the handler. The chooser stays open; the argument is the row dict (same shape as onSelect). If unset, activating an invalid row is silently ignored.","url":"HSChooser.html#onInvalid","kind":"property"},{"fullName":"HSChooser.setChoices(choices)","description":"on show. The function is responsible for filtering; the chooser displays all items it returns.","url":"HSChooser.html#setChoices","kind":"method"},{"fullName":"HSChooser.refreshChoices()","description":"Re-apply filtering (static choices) or re-invoke the choices function (dynamic). Call after updating an external data source in an async onQueryChange handler.","url":"HSChooser.html#refreshChoices","kind":"method"},{"fullName":"HSChooser.show()","description":"Show the chooser.","url":"HSChooser.html#show","kind":"method"},{"fullName":"HSChooser.hide()","description":"Hide the chooser without making a selection. Restores focus to the previously active window.","url":"HSChooser.html#hide","kind":"method"},{"fullName":"HSChooser.select(row)","description":"Programmatically confirm a selection. Omit row to confirm the currently highlighted row. Fires onSelect (or onInvalid for rows with valid: false) and hides the chooser.","url":"HSChooser.html#select","kind":"method"},{"fullName":"HSChooser.selectedRowContents(row)","description":"Returns the dict for the highlighted row, or for a specific row by index. Returns null if the index is out of range or no choices are set.","url":"HSChooser.html#selectedRowContents","kind":"method"},{"fullName":"HSEventTap","description":"An event tap watcher that intercepts input events from the system. Obtain instances via hs.eventtap.addWatcher() — do not instantiate directly. ## Monitoring keyboard events ``js const tap = hs.eventtap.addWatcher([hs.eventtap.eventTypes.keyDown], (event) => { console.log(\"Key pressed: \" + event.keyCode) }) ``","url":"HSEventTap.html","kind":"type"},{"fullName":"HSEventTap.identifier","description":"A unique identifier for this tap","url":"HSEventTap.html#identifier","kind":"property"},{"fullName":"HSEventTap.listenOnly","description":"Whether this tap was created as listen-only (events are observed but never modified or suppressed)","url":"HSEventTap.html#listenOnly","kind":"property"},{"fullName":"HSEventTap.start()","description":"Start receiving events. Requires Accessibility permission.","url":"HSEventTap.html#start","kind":"method"},{"fullName":"HSEventTap.stop()","description":"Stop receiving events","url":"HSEventTap.html#stop","kind":"method"},{"fullName":"HSEventTap.setCallback(callback)","description":"Replace the callback function","url":"HSEventTap.html#setCallback","kind":"method"},{"fullName":"HSEventTap.isEnabled()","description":"Whether this tap is currently active","url":"HSEventTap.html#isEnabled","kind":"method"},{"fullName":"HSEventTap.isCreated()","description":"Whether this tap has been registered with macOS","url":"HSEventTap.html#isCreated","kind":"method"},{"fullName":"HSEventTapEvent","description":"An input event captured or constructed by hs.eventtap. Objects of this type are passed to event tap callbacks and can also be created directly via the factory methods on hs.eventtap. Properties can be inspected and modified before the event is passed through or posted back to the system.","url":"HSEventTapEvent.html","kind":"type"},{"fullName":"HSEventTapEvent.typeName","description":"Type name for introspection","url":"HSEventTapEvent.html#typeName","kind":"property"},{"fullName":"HSEventTapEvent.type","description":"The numeric event type, matching a value in hs.eventtap.eventTypes","url":"HSEventTapEvent.html#type","kind":"property"},{"fullName":"HSEventTapEvent.keyCode","description":"The virtual key code for keyboard events (get/set)","url":"HSEventTapEvent.html#keyCode","kind":"property"},{"fullName":"HSEventTapEvent.rawFlags","description":"The raw modifier flags bitmask (get/set). Use values from hs.eventtap.modifierFlags.","url":"HSEventTapEvent.html#rawFlags","kind":"property"},{"fullName":"HSEventTapEvent.flags","description":"An array of active modifier key names (e.g. [\"cmd\", \"shift\"]). When a device-specific modifier is detected, both the generic and side-specific names are included — e.g. pressing the left Command key yields [\"cmd\", \"leftCmd\"].","url":"HSEventTapEvent.html#flags","kind":"property"},{"fullName":"HSEventTapEvent.location","description":"The event's screen position as {x, y} in Hammerspoon screen coordinates (top-left origin of primary display, y increases downward, matching hs.screen).","url":"HSEventTapEvent.html#location","kind":"property"},{"fullName":"HSEventTapEvent.buttonNumber","description":"The mouse button number for mouse events (0=left, 1=right, 2=middle)","url":"HSEventTapEvent.html#buttonNumber","kind":"property"},{"fullName":"HSEventTapEvent.scrollingDeltaX","description":"The horizontal scroll delta for scroll wheel events","url":"HSEventTapEvent.html#scrollingDeltaX","kind":"property"},{"fullName":"HSEventTapEvent.scrollingDeltaY","description":"The vertical scroll delta for scroll wheel events","url":"HSEventTapEvent.html#scrollingDeltaY","kind":"property"},{"fullName":"HSEventTapEvent.characters","description":"The Unicode characters produced by this keyboard event, or null for non-keyboard events","url":"HSEventTapEvent.html#characters","kind":"property"},{"fullName":"HSEventTapEvent.duplicate()","description":"Create an independent copy of this event","url":"HSEventTapEvent.html#duplicate","kind":"method"},{"fullName":"HSEventTapEvent.post(app)","description":"Post this event to the HID event stream, optionally targeting a specific application. When app is omitted or null, the event is posted to the global HID stream and delivered by the OS as if a real input device generated it. When an application is provided, the event is delivered directly to that process by PID.","url":"HSEventTapEvent.html#post","kind":"method"},{"fullName":"HSEventTapHotkey","description":"A keyboard shortcut binding backed by an event tap. Supports fn modifier and left/right modifier key distinction. Obtain instances via hs.eventtap.bindHotkey() — do not instantiate directly.","url":"HSEventTapHotkey.html","kind":"type"},{"fullName":"HSEventTapHotkey.callbackPressed","description":"The callback function to be called when the hotkey is pressed, or null to remove it","url":"HSEventTapHotkey.html#callbackPressed","kind":"property"},{"fullName":"HSEventTapHotkey.callbackReleased","description":"The callback function to be called when the hotkey is released, or null to remove it","url":"HSEventTapHotkey.html#callbackReleased","kind":"property"},{"fullName":"HSEventTapHotkey.enable()","description":"Enable the hotkey","url":"HSEventTapHotkey.html#enable","kind":"method"},{"fullName":"HSEventTapHotkey.disable()","description":"Disable the hotkey","url":"HSEventTapHotkey.html#disable","kind":"method"},{"fullName":"HSEventTapHotkey.isEnabled()","description":"Check if the hotkey is currently enabled","url":"HSEventTapHotkey.html#isEnabled","kind":"method"},{"fullName":"HSPathWatcher","description":"Watches a filesystem path for changes and invokes a callback when they occur. Created via hs.fs.createPathWatcher(path). Set a callback with setCallback(), then call start() to begin receiving events. | Flag | Meaning | |------|---------| | \"itemCreated\" | Item was created | | \"itemRemoved\" | Item was removed | | \"itemRenamed\" | Item was renamed or moved | | \"itemModified\" | File data was modified | | \"itemInodeMetaMod\" | Inode metadata changed (permissions, timestamps, etc.) | | \"itemFinderInfoMod\" | Finder info changed | | \"itemChangeOwner\" | Ownership or group changed | | \"itemXattrMod\" | Extended attributes changed | | \"itemIsFile\" | The item is a file | | \"itemIsDir\" | The item is a directory | | \"itemIsSymlink\" | The item is a symbolic link | | \"itemIsHardlink\" | The item is a hard link | | \"itemIsLastHardlink\" | This is the last hard link to the inode | | \"itemCloned\" | Item was cloned | | \"ownEvent\" | Event was generated by this process | | \"mustScanSubDirs\" | Subtree must be rescanned (events may have been dropped) | | \"userDropped\" | Events were dropped at the user-space level | | \"kernelDropped\" | Events were dropped at the kernel level | | \"rootChanged\" | The watched root path itself changed | | \"mount\" | A volume was mounted under the watched path | | \"unmount\" | A volume was unmounted from under the watched path |","url":"HSPathWatcher.html","kind":"type"},{"fullName":"HSPathWatcher.identifier","description":"The unique identifier assigned to this watcher.","url":"HSPathWatcher.html#identifier","kind":"property"},{"fullName":"HSPathWatcher.start()","description":"Starts monitoring the watched path for filesystem changes.","url":"HSPathWatcher.html#start","kind":"method"},{"fullName":"HSPathWatcher.stop()","description":"Stops monitoring the watched path.","url":"HSPathWatcher.html#stop","kind":"method"},{"fullName":"HSPathWatcher.setCallback(fn)","description":"Sets the callback invoked when filesystem changes are detected.","url":"HSPathWatcher.html#setCallback","kind":"method"},{"fullName":"HSPathWatcher.destroy()","description":"Stops the watcher and releases all resources. Called automatically during shutdown.","url":"HSPathWatcher.html#destroy","kind":"method"},{"fullName":"HSVolumeWatcher","description":"A volume event watcher that monitors filesystem mount/unmount/rename events. Create via hs.fs.addVolumeWatcher(). Set a callback with setCallback(), then call start() to begin receiving events. | Event | Info keys | |-------|-----------| | \"didMount\" | path: string | | \"didUnmount\" | path: string | | \"willUnmount\" | path: string | | \"didRename\" | path: string, name: string, oldPath?: string, oldName?: string |","url":"HSVolumeWatcher.html","kind":"type"},{"fullName":"HSVolumeWatcher.identifier","description":"The unique identifier assigned to this watcher.","url":"HSVolumeWatcher.html#identifier","kind":"property"},{"fullName":"HSVolumeWatcher.start()","description":"Starts monitoring volume events.","url":"HSVolumeWatcher.html#start","kind":"method"},{"fullName":"HSVolumeWatcher.stop()","description":"Stops monitoring volume events.","url":"HSVolumeWatcher.html#stop","kind":"method"},{"fullName":"HSVolumeWatcher.setCallback(fn)","description":"Sets the callback function invoked when volume events occur.","url":"HSVolumeWatcher.html#setCallback","kind":"method"},{"fullName":"HSVolumeWatcher.destroy()","description":"Stops the watcher and releases all resources. Called automatically during shutdown.","url":"HSVolumeWatcher.html#destroy","kind":"method"},{"fullName":"HSHotkey","description":"Object representing a system-wide hotkey. You should not create these objects directly, but rather, use the methods in hs.hotkey to instantiate these.","url":"HSHotkey.html","kind":"type"},{"fullName":"HSHotkey.mods","description":"The modifier keys this hotkey was bound with, as originally passed to bind()/create()","url":"HSHotkey.html#mods","kind":"property"},{"fullName":"HSHotkey.key","description":"The key this hotkey was bound with, as originally passed to bind()/create()","url":"HSHotkey.html#key","kind":"property"},{"fullName":"HSHotkey.message","description":"An optional description of what this hotkey does, or null if none was set. When set, it is shown as an on-screen toast via hs.ui.alert() (duration controlled by hs.hotkey.alertDuration) just before the hotkey's callback runs: before the pressed callback if one exists, otherwise before the released callback if one exists.","url":"HSHotkey.html#message","kind":"property"},{"fullName":"HSHotkey.callbackRepeat","description":"The callback function to be called repeatedly while the hotkey is held down, or null to remove it. Repeats at the system keyboard-repeat delay/interval, matching how held-down keys repeat elsewhere in macOS.","url":"HSHotkey.html#callbackRepeat","kind":"property"},{"fullName":"HSHotkey.callbackPressed","description":"The callback function to be called when the hotkey is pressed, or null to remove it","url":"HSHotkey.html#callbackPressed","kind":"property"},{"fullName":"HSHotkey.callbackReleased","description":"The callback function to be called when the hotkey is released, or null to remove it","url":"HSHotkey.html#callbackReleased","kind":"property"},{"fullName":"HSHotkey.enable()","description":"Enable the hotkey","url":"HSHotkey.html#enable","kind":"method"},{"fullName":"HSHotkey.disable()","description":"Disable the hotkey","url":"HSHotkey.html#disable","kind":"method"},{"fullName":"HSHotkey.isEnabled()","description":"Check if the hotkey is currently enabled","url":"HSHotkey.html#isEnabled","kind":"method"},{"fullName":"HSHotkey.destroy()","description":"Disable and permanently remove this hotkey, releasing all associated resources","url":"HSHotkey.html#destroy","kind":"method"},{"fullName":"HSHotkeyModal","description":"A modal hotkey group returned by hs.hotkey.createModal(). Hotkeys bound to the modal via bind() are only enabled while the modal is active (i.e. between enter() and exit()).","url":"HSHotkeyModal.html","kind":"type"},{"fullName":"HSHotkeyModal.isActive","description":"Whether the modal is currently active","url":"HSHotkeyModal.html#isActive","kind":"property"},{"fullName":"HSHotkeyModal.enterFn","description":"Callback invoked when the modal is entered","url":"HSHotkeyModal.html#enterFn","kind":"property"},{"fullName":"HSHotkeyModal.exitFn","description":"Callback invoked when the modal is exited","url":"HSHotkeyModal.html#exitFn","kind":"property"},{"fullName":"HSHotkeyModal.bind(mods, key, callbackPressed, callbackReleased)","description":"Bind a hotkey to this modal. The hotkey is only enabled while the modal is active.","url":"HSHotkeyModal.html#bind","kind":"method"},{"fullName":"HSHotkeyModal.enter()","description":"Enter the modal: its trigger (if any) is disabled and its bound hotkeys are enabled.","url":"HSHotkeyModal.html#enter","kind":"method"},{"fullName":"HSHotkeyModal.exit()","description":"Exit the modal: its bound hotkeys are disabled and its trigger (if any) is re-enabled.","url":"HSHotkeyModal.html#exit","kind":"method"},{"fullName":"HSHotkeyModal.destroy()","description":"Destroy the modal, along with its trigger and all hotkeys bound to it.","url":"HSHotkeyModal.html#destroy","kind":"method"},{"fullName":"HSWebSocket","description":"A WebSocket client connection created by hs.http.openWebSocket(). The connection opens immediately when returned. Use the chainable setter methods to register event callbacks, then call send() to transmit messages. Do not instantiate HSWebSocket directly — use hs.http.openWebSocket().","url":"HSWebSocket.html","kind":"type"},{"fullName":"HSWebSocket.identifier","description":"A unique identifier for this connection (UUID string).","url":"HSWebSocket.html#identifier","kind":"property"},{"fullName":"HSWebSocket.readyState","description":"The current connection state.","url":"HSWebSocket.html#readyState","kind":"property"},{"fullName":"HSWebSocket.setOpenCallback(callback)","description":"Set the callback invoked when the connection is established.","url":"HSWebSocket.html#setOpenCallback","kind":"method"},{"fullName":"HSWebSocket.setMessageCallback(callback)","description":"Set the callback invoked when a text message is received from the server.","url":"HSWebSocket.html#setMessageCallback","kind":"method"},{"fullName":"HSWebSocket.setCloseCallback(callback)","description":"Set the callback invoked when the connection is closed by the remote end.","url":"HSWebSocket.html#setCloseCallback","kind":"method"},{"fullName":"HSWebSocket.setErrorCallback(callback)","description":"Set the callback invoked when a connection or protocol error occurs.","url":"HSWebSocket.html#setErrorCallback","kind":"method"},{"fullName":"HSWebSocket.send(message)","description":"Send a text message to the server. The connection must be open (readyState === 1).","url":"HSWebSocket.html#send","kind":"method"},{"fullName":"HSWebSocket.close()","description":"Close the WebSocket connection with a normal closure code (1000). If a close callback is registered, it is invoked synchronously.","url":"HSWebSocket.html#close","kind":"method"},{"fullName":"HSWebSocket.destroy()","description":"Destroy this WebSocket, releasing all resources without invoking callbacks. Called automatically by hs.http.shutdown(). After destroy(), do not use this object.","url":"HSWebSocket.html#destroy","kind":"method"},{"fullName":"HSHTTPServer","description":"An HTTP server instance created by hs.httpserver.create(). Configure with chainable setter methods, then call start() to begin accepting connections. The server supports synchronous and async (Promise-returning) request callbacks, optional static file serving, HTTP Basic authentication, Bonjour advertisement, and TLS via PKCS#12. Do not instantiate HSHTTPServer directly — use hs.httpserver.create().","url":"HSHTTPServer.html","kind":"type"},{"fullName":"HSHTTPServer.identifier","description":"A unique identifier for this server instance (UUID string).","url":"HSHTTPServer.html#identifier","kind":"property"},{"fullName":"HSHTTPServer.setPort(port)","description":"Set the TCP port to listen on. Must be called before start(). Pass 0 to let the OS assign an available port (use getPort() after start() to discover it).","url":"HSHTTPServer.html#setPort","kind":"method"},{"fullName":"HSHTTPServer.setInterface(iface)","description":"Set the network interface to listen on. Pass null to listen on all interfaces (the default). Pass \"localhost\" or \"loopback\" to restrict to the loopback interface only.","url":"HSHTTPServer.html#setInterface","kind":"method"},{"fullName":"HSHTTPServer.setPassword(password)","description":"Set a password required for Basic authentication. When set, every request must supply an Authorization: Basic header with any username and the configured password. Pass null to disable authentication.","url":"HSHTTPServer.html#setPassword","kind":"method"},{"fullName":"HSHTTPServer.setMaxBodySize(size)","description":"Set the maximum allowed incoming request body size in bytes. Requests with a body exceeding this limit receive a 413 response. Defaults to 10 MB.","url":"HSHTTPServer.html#setMaxBodySize","kind":"method"},{"fullName":"HSHTTPServer.setName(name)","description":"Set the Bonjour service name advertised on the local network. Only used when Bonjour is enabled via setBonjour(true).","url":"HSHTTPServer.html#setName","kind":"method"},{"fullName":"HSHTTPServer.setBonjour(enable)","description":"Enable or disable Bonjour advertisement of this server on the local network.","url":"HSHTTPServer.html#setBonjour","kind":"method"},{"fullName":"HSHTTPServer.setCallback(callback)","description":"Set the request handler callback. If the callback returns null or undefined, the server falls through to static file serving (if a document root is set), or responds with 404.","url":"HSHTTPServer.html#setCallback","kind":"method"},{"fullName":"HSHTTPServer.setDocumentRoot(path)","description":"Set the filesystem path to serve static files from. When a document root is set, requests not handled by the callback are served as static files from this directory. Pass null to disable static file serving.","url":"HSHTTPServer.html#setDocumentRoot","kind":"method"},{"fullName":"HSHTTPServer.setDirectoryIndex(files)","description":"Set the list of index filenames checked when a directory is requested. Defaults to [\"index.html\", \"index.htm\"]. Files are checked in order.","url":"HSHTTPServer.html#setDirectoryIndex","kind":"method"},{"fullName":"HSHTTPServer.setAllowDirectoryListing(allow)","description":"Enable or disable directory listing for requests that map to a directory with no index file. When disabled (the default), directory requests without an index file return 403.","url":"HSHTTPServer.html#setAllowDirectoryListing","kind":"method"},{"fullName":"HSHTTPServer.setTLSFromPKCS12(path, password)","description":"Configure TLS using a PKCS#12 (.p12) identity file. When TLS is configured, the server accepts HTTPS connections. The .p12 file must contain both the certificate and the private key.","url":"HSHTTPServer.html#setTLSFromPKCS12","kind":"method"},{"fullName":"HSHTTPServer.start()","description":"Start the server and begin accepting connections. The server must be configured before calling start(). To restart the server with new settings, call stop() followed by start().","url":"HSHTTPServer.html#start","kind":"method"},{"fullName":"HSHTTPServer.stop()","description":"Stop the server and close all connections.","url":"HSHTTPServer.html#stop","kind":"method"},{"fullName":"HSHTTPServer.destroy()","description":"Destroy this server, releasing all resources. After calling destroy(), the server object should not be used.","url":"HSHTTPServer.html#destroy","kind":"method"},{"fullName":"HSHTTPServer.getPort()","description":"Get the TCP port the server is currently listening on. Returns 0 if the server is not running.","url":"HSHTTPServer.html#getPort","kind":"method"},{"fullName":"HSHTTPServer.getName()","description":"Get the configured Bonjour service name.","url":"HSHTTPServer.html#getName","kind":"method"},{"fullName":"HSHTTPServer.getInterface()","description":"Get the configured network interface, or null if listening on all interfaces.","url":"HSHTTPServer.html#getInterface","kind":"method"},{"fullName":"HSHTTPServer.setWebSocketCallback(path, callback)","description":"Register a WebSocket handler for a URL path. When a client connects and performs a WebSocket upgrade handshake on path, the callback is invoked with three arguments: event (string), connection (HSWebSocketConnection), and message (string). Events: Pass null to remove the WebSocket handler for the path.","url":"HSHTTPServer.html#setWebSocketCallback","kind":"method"},{"fullName":"HSWebSocketConnection","description":"A WebSocket connection to a single client, passed to the callback registered with server.setWebSocketCallback(). Use send() to push messages to the connected client and close() to end the connection. Do not instantiate HSWebSocketConnection directly — it is created by the server when a client performs a WebSocket upgrade.","url":"HSWebSocketConnection.html","kind":"type"},{"fullName":"HSWebSocketConnection.identifier","description":"A unique identifier for this connection (UUID string).","url":"HSWebSocketConnection.html#identifier","kind":"property"},{"fullName":"HSWebSocketConnection.send(message)","description":"Send a text message to the connected WebSocket client.","url":"HSWebSocketConnection.html#send","kind":"method"},{"fullName":"HSWebSocketConnection.close()","description":"Close the WebSocket connection to the client. Sends a WebSocket close frame and cancels the underlying TCP connection.","url":"HSWebSocketConnection.html#close","kind":"method"},{"fullName":"HSWebSocketConnection.destroy()","description":"Destroy this connection object, releasing all resources.","url":"HSWebSocketConnection.html#destroy","kind":"method"},{"fullName":"HSLocationWatcher","description":"An independent location tracking object. Create via hs.location.addWatcher(). Call start() to begin receiving updates, and set a callback to handle them. | Event | Data | |-------|------| | \"location\" | a locationTable | | \"error\" | an error message string | | \"authorizationChanged\" | the new status string (\"authorized\", \"denied\", \"restricted\", \"notDetermined\") |","url":"HSLocationWatcher.html","kind":"type"},{"fullName":"HSLocationWatcher.identifier","description":"The unique identifier assigned to this watcher.","url":"HSLocationWatcher.html#identifier","kind":"property"},{"fullName":"HSLocationWatcher.distanceFilter","description":"The minimum distance in metres the device must move before a new update is delivered. Defaults to kCLDistanceFilterNone (all movements reported).","url":"HSLocationWatcher.html#distanceFilter","kind":"property"},{"fullName":"HSLocationWatcher.start()","description":"Starts location updates. The callback must be set first.","url":"HSLocationWatcher.html#start","kind":"method"},{"fullName":"HSLocationWatcher.stop()","description":"Stops location updates.","url":"HSLocationWatcher.html#stop","kind":"method"},{"fullName":"HSLocationWatcher.setCallback(fn)","description":"Sets the callback function invoked when location events occur.","url":"HSLocationWatcher.html#setCallback","kind":"method"},{"fullName":"HSLocationWatcher.location()","description":"Returns the most recently received location, or null if none yet.","url":"HSLocationWatcher.html#location","kind":"method"},{"fullName":"HSMenuBarItem","description":"Object representing a macOS system menu bar item. Create instances with hs.menubar.create().","url":"HSMenuBarItem.html","kind":"type"},{"fullName":"HSMenuBarItem.title","description":"Get or set the menu item's title.","url":"HSMenuBarItem.html#title","kind":"property"},{"fullName":"HSMenuBarItem.setIcon(image)","description":"Set the icon displayed in the menu bar","url":"HSMenuBarItem.html#setIcon","kind":"method"},{"fullName":"HSMenuBarItem.setTooltip(tooltip)","description":"Set the tooltip shown when hovering over the menu bar item","url":"HSMenuBarItem.html#setTooltip","kind":"method"},{"fullName":"HSMenuBarItem.setClickCallback(fn)","description":"Set a callback invoked when the item is clicked (only fires when no menu is set)","url":"HSMenuBarItem.html#setClickCallback","kind":"method"},{"fullName":"HSMenuBarItem.setMenu(menuOrFn)","description":"Set the menu for this item. Pass an array of menu item objects for a static menu, or a function that returns an array for a dynamic menu populated each time it opens.","url":"HSMenuBarItem.html#setMenu","kind":"method"},{"fullName":"HSMenuBarItem.hide()","description":"Remove this item from the menu bar. The item is retained and can be shown again with show().","url":"HSMenuBarItem.html#hide","kind":"method"},{"fullName":"HSMenuBarItem.show()","description":"Show this item in the menu bar.","url":"HSMenuBarItem.html#show","kind":"method"},{"fullName":"HSMenuBarItem.isVisible()","description":"Check if this item is currently visible in the menu bar.","url":"HSMenuBarItem.html#isVisible","kind":"method"},{"fullName":"HSMenuBarItem.destroy()","description":"Permanently remove this item from the menu bar and release all resources. After calling destroy(), the item is no longer usable. This is called automatically on hs.reload(). Use hide() instead if you only want to temporarily remove the item without freeing it.","url":"HSMenuBarItem.html#destroy","kind":"method"},{"fullName":"HSMIDIDevice","description":"A MIDI device or virtual source, created via hs.midi.deviceNamed() or hs.midi.virtualSourceNamed().","url":"HSMIDIDevice.html","kind":"type"},{"fullName":"HSMIDIDevice.identifier","description":"A unique identifier for this device object.","url":"HSMIDIDevice.html#identifier","kind":"property"},{"fullName":"HSMIDIDevice.name","description":"The device's raw name.","url":"HSMIDIDevice.html#name","kind":"property"},{"fullName":"HSMIDIDevice.displayName","description":"The device's user-facing display name. Falls back to name if unavailable.","url":"HSMIDIDevice.html#displayName","kind":"property"},{"fullName":"HSMIDIDevice.manufacturer","description":"The device's manufacturer name, or an empty string if unavailable.","url":"HSMIDIDevice.html#manufacturer","kind":"property"},{"fullName":"HSMIDIDevice.model","description":"The device's model name, or an empty string if unavailable.","url":"HSMIDIDevice.html#model","kind":"property"},{"fullName":"HSMIDIDevice.isOnline","description":"Whether the device is currently online (connected).","url":"HSMIDIDevice.html#isOnline","kind":"property"},{"fullName":"HSMIDIDevice.isVirtual","description":"Whether this is a virtual source (created via hs.midi.virtualSourceNamed()) rather than a physical device.","url":"HSMIDIDevice.html#isVirtual","kind":"property"},{"fullName":"HSMIDIDevice.setCallback(fn)","description":"Sets or removes the callback fired when a MIDI message is received. The callback receives five arguments: this device object, the device's name, the command type as a string (e.g. \"noteOn\", \"controlChange\", \"systemExclusive\" — see hs.midi.commandTypes for the full set), a human-readable description, and a metadata table of command-specific fields. when released, but some send noteOn with velocity 0 instead of noteOff.","url":"HSMIDIDevice.html#setCallback","kind":"method"},{"fullName":"HSMIDIDevice.sendCommand(commandType, metadata)","description":"Sends a MIDI command to the device.","url":"HSMIDIDevice.html#sendCommand","kind":"method"},{"fullName":"HSMIDIDevice.sendSysex(command)","description":"Sends a System Exclusive command to the device.","url":"HSMIDIDevice.html#sendSysex","kind":"method"},{"fullName":"HSMIDIDevice.identityRequest()","description":"Sends a MIDI Identity Request. The device's reply, if any, arrives via the callback set with setCallback() as a systemExclusive message.","url":"HSMIDIDevice.html#identityRequest","kind":"method"},{"fullName":"HSMIDIDevice.destroy()","description":"Stops receiving from and releases all resources held by this device object. Called automatically when Hammerspoon reloads.","url":"HSMIDIDevice.html#destroy","kind":"method"},{"fullName":"HSNetworkConfigurationWatcher","description":"A watcher for System Configuration dynamic store key changes. Create with hs.network.configurationWatcher().","url":"HSNetworkConfigurationWatcher.html","kind":"type"},{"fullName":"HSNetworkConfigurationWatcher.typeName","description":"Always \"HSNetworkConfigurationWatcher\".","url":"HSNetworkConfigurationWatcher.html#typeName","kind":"property"},{"fullName":"HSNetworkConfigurationWatcher.setKeys(keys, pattern)","description":"Specifies which dynamic store keys (or key patterns) to watch for changes. Must be called before start(). Each element of keys is treated as a string literal when pattern is false (the default), or as a regular expression when pattern is true. Calling setKeys again replaces the previous set of watched keys.","url":"HSNetworkConfigurationWatcher.html#setKeys","kind":"method"},{"fullName":"HSNetworkConfigurationWatcher.setCallback(callback)","description":"Sets the callback invoked when a watched key changes. The callback receives (watcher, changedKeys) where changedKeys is an array of key strings that changed since the last notification. Call hs.network.configurationStore() inside the callback to read the updated values.","url":"HSNetworkConfigurationWatcher.html#setCallback","kind":"method"},{"fullName":"HSNetworkConfigurationWatcher.start()","description":"Starts watching for dynamic store changes. The callback registered with setCallback() will be invoked whenever a key matching the patterns registered with setKeys() changes. Call setKeys() and setCallback() before calling start().","url":"HSNetworkConfigurationWatcher.html#start","kind":"method"},{"fullName":"HSNetworkConfigurationWatcher.stop()","description":"Stops watching for dynamic store changes. The callback will no longer be invoked. Call start() again to resume monitoring.","url":"HSNetworkConfigurationWatcher.html#stop","kind":"method"},{"fullName":"HSNetworkPing","description":"Object representing an active or completed ICMP ping operation. Create instances with hs.network.ping().","url":"HSNetworkPing.html","kind":"type"},{"fullName":"HSNetworkPing.typeName","description":"Always \"HSNetworkPing\".","url":"HSNetworkPing.html#typeName","kind":"property"},{"fullName":"HSNetworkPing.address","description":"The resolved IP address of the target, or \"\" if DNS has not yet completed.","url":"HSNetworkPing.html#address","kind":"property"},{"fullName":"HSNetworkPing.server","description":"The hostname or IP address string originally passed to hs.network.ping().","url":"HSNetworkPing.html#server","kind":"property"},{"fullName":"HSNetworkPing.sent","description":"The number of ICMP Echo Requests sent so far.","url":"HSNetworkPing.html#sent","kind":"property"},{"fullName":"HSNetworkPing.count","description":"The total number of ICMP Echo Requests to send. May be increased while the ping is running provided the new value is greater than the number already sent.","url":"HSNetworkPing.html#count","kind":"property"},{"fullName":"HSNetworkPing.isRunning","description":"true while the ping is actively sending and waiting for replies.","url":"HSNetworkPing.html#isRunning","kind":"property"},{"fullName":"HSNetworkPing.isPaused","description":"true when the ping has been suspended with pause().","url":"HSNetworkPing.html#isPaused","kind":"property"},{"fullName":"HSNetworkPing.packets(sequenceNumber)","description":"Returns packet statistics for all sent packets, or for a single packet by its zero-based sequence number.","url":"HSNetworkPing.html#packets","kind":"method"},{"fullName":"HSNetworkPing.summary()","description":"Returns a human-readable summary of the ping results in standard ping format.","url":"HSNetworkPing.html#summary","kind":"method"},{"fullName":"HSNetworkPing.pause()","description":"Suspends the ping. No further packets are sent until resume() is called.","url":"HSNetworkPing.html#pause","kind":"method"},{"fullName":"HSNetworkPing.resume()","description":"Resumes a paused ping, continuing from where it left off.","url":"HSNetworkPing.html#resume","kind":"method"},{"fullName":"HSNetworkPing.cancel()","description":"Immediately stops the ping, firing the \"didFinish\" callback with statistics collected so far.","url":"HSNetworkPing.html#cancel","kind":"method"},{"fullName":"HSNetworkPing.setCallback(callback)","description":"Replaces the ping's callback function.","url":"HSNetworkPing.html#setCallback","kind":"method"},{"fullName":"HSNetworkReachability","description":"An active or inactive network reachability monitor. Create with hs.network.reachability*().","url":"HSNetworkReachability.html","kind":"type"},{"fullName":"HSNetworkReachability.typeName","description":"Always \"HSNetworkReachability\".","url":"HSNetworkReachability.html#typeName","kind":"property"},{"fullName":"HSNetworkReachability.status()","description":"Returns the current reachability flags as a numeric bitmask. Compare against constants in hs.network.reachabilityFlags. Returns 0 if the network is currently unreachable.","url":"HSNetworkReachability.html#status","kind":"method"},{"fullName":"HSNetworkReachability.statusString()","description":"Returns a human-readable summary of the current reachability flags. The string contains 8 characters in order: t (transient/expensive), R (reachable), c (connectionRequired), C (connectionOnTraffic — always -), i (interventionRequired/constrained), D (connectionOnDemand — always -), l (isLocalAddress — always -), d (isDirect). A letter appears when that flag is set; - appears when it is clear.","url":"HSNetworkReachability.html#statusString","kind":"method"},{"fullName":"HSNetworkReachability.setCallback(callback)","description":"Replaces the callback invoked when reachability changes. The callback receives (reachability, flags) where flags is the same numeric bitmask as returned by status(). Call start() after setCallback() to begin monitoring.","url":"HSNetworkReachability.html#setCallback","kind":"method"},{"fullName":"HSNetworkReachability.start()","description":"Starts monitoring for reachability changes. After calling start(), the callback registered with setCallback() is invoked whenever the reachability status changes.","url":"HSNetworkReachability.html#start","kind":"method"},{"fullName":"HSNetworkReachability.stop()","description":"Stops monitoring for reachability changes. The callback will no longer be invoked. Call start() again to resume monitoring.","url":"HSNetworkReachability.html#stop","kind":"method"},{"fullName":"HSNotification","description":"A notification created by hs.notify.new(). Call .send() to deliver it to macOS Notification Center. You can hold a reference to the object and call .withdraw() later to remove it.","url":"HSNotification.html","kind":"type"},{"fullName":"HSNotification.identifier","description":"The unique identifier assigned to this notification. Use it to correlate with system notification APIs if needed.","url":"HSNotification.html#identifier","kind":"property"},{"fullName":"HSNotification.send()","description":"Deliver this notification immediately to Notification Center.","url":"HSNotification.html#send","kind":"method"},{"fullName":"HSNotification.withdraw()","description":"Remove this notification from Notification Center (if delivered) or cancel it (if pending).","url":"HSNotification.html#withdraw","kind":"method"},{"fullName":"HSOCRObservation","description":"A single region of text recognized in an image. Instances are delivered inside the observations array of an HSOCRResult. Each observation represents a discrete text run found in the source image, along with a confidence score and a normalized bounding box. (0, 0) is the top-left corner of the image and (1, 1) is the bottom-right. This matches the convention used by most image-processing tools and differs from Vision's internal bottom-left-origin system (the conversion is automatic).","url":"HSOCRObservation.html","kind":"type"},{"fullName":"HSOCRObservation.typeName","description":"The Swift type name, for JavaScript introspection.","url":"HSOCRObservation.html#typeName","kind":"property"},{"fullName":"HSOCRObservation.text","description":"The recognized text string for this observation.","url":"HSOCRObservation.html#text","kind":"property"},{"fullName":"HSOCRObservation.confidence","description":"Recognition confidence in the range 0.0 (uncertain) to 1.0 (certain). Use minimumConfidence in the options passed to recognizeText() to pre-filter observations below a threshold rather than filtering here.","url":"HSOCRObservation.html#confidence","kind":"property"},{"fullName":"HSOCRObservation.bounds","description":"Normalized bounding box of this observation in the source image, as an HSRect. All values are in the range 0–1 with top-left origin ((0, 0) = top-left corner, (1, 1) = bottom-right corner). Use bounds.x, bounds.y, bounds.w, and bounds.h to access the components.","url":"HSOCRObservation.html#bounds","kind":"property"},{"fullName":"HSOCRResult","description":"The result of a text recognition operation on an image. An HSOCRResult is returned by hs.ocr.recognizeText() and bundles the full recognized text together with an array of per-region observations, each carrying its own confidence score and bounding box.","url":"HSOCRResult.html","kind":"type"},{"fullName":"HSOCRResult.typeName","description":"The Swift type name, for JavaScript introspection.","url":"HSOCRResult.html#typeName","kind":"property"},{"fullName":"HSOCRResult.text","description":"The full recognized text from the image, with each observation's text joined by newlines in the order Vision returned them. Use this when you only need the raw text and don't care about bounding boxes or per-region confidence scores.","url":"HSOCRResult.html#text","kind":"property"},{"fullName":"HSOCRResult.observations","description":"The individual text observations that make up this result. Each entry in the array is an HSOCRObservation with its own text, confidence, and bounds properties. Observations are returned in the order Vision produced them (typically top-to-bottom, left-to-right, but this is image-dependent).","url":"HSOCRResult.html#observations","kind":"property"},{"fullName":"HSScreen","description":"An object representing a single display attached to the system. ## Coordinate system All geometry is returned in Hammerspoon screen coordinates: the origin (0, 0) is at the top-left of the primary display, and y increases downward. This matches Hammerspoon v1 and is the inverse of the raw macOS/CoreGraphics convention. ## Examples ``javascript const s = hs.screen.main(); console.log(s.name); // e.g. \"Built-in Retina Display\" console.log(s.frame.w); // usable width in points","url":"HSScreen.html","kind":"type"},{"fullName":"HSScreen.id","description":"Unique display identifier (matches CGDirectDisplayID).","url":"HSScreen.html#id","kind":"property"},{"fullName":"HSScreen.name","description":"The manufacturer-assigned localized display name.","url":"HSScreen.html#name","kind":"property"},{"fullName":"HSScreen.uuid","description":"The display's UUID string.","url":"HSScreen.html#uuid","kind":"property"},{"fullName":"HSScreen.frame","description":"The usable screen area in Hammerspoon coordinates, excluding the menu bar and Dock.","url":"HSScreen.html#frame","kind":"property"},{"fullName":"HSScreen.fullFrame","description":"The full screen area in Hammerspoon coordinates, including menu bar and Dock regions.","url":"HSScreen.html#fullFrame","kind":"property"},{"fullName":"HSScreen.position","description":"The screen's top-left corner in global Hammerspoon coordinates.","url":"HSScreen.html#position","kind":"property"},{"fullName":"HSScreen.mode","description":"The currently active display mode. An object with keys: width, height, scale, frequency.","url":"HSScreen.html#mode","kind":"property"},{"fullName":"HSScreen.availableModes","description":"All display modes supported by this screen. Each element has keys: width, height, scale, frequency.","url":"HSScreen.html#availableModes","kind":"property"},{"fullName":"HSScreen.rotation","description":"The current screen rotation in degrees (0, 90, 180, or 270). Assign one of 0, 90, 180, or 270 to rotate the display.","url":"HSScreen.html#rotation","kind":"property"},{"fullName":"HSScreen.desktopImage","description":"The URL string of the current desktop background image for this screen, or null. Assign a new absolute file path or file:// URL string to change the wallpaper.","url":"HSScreen.html#desktopImage","kind":"property"},{"fullName":"HSScreen.ambientLight","description":"The ambient light level measured by this display's built-in sensor, in lux. Returns null if the display does not have an ambient light sensor or if the reading is currently unavailable.","url":"HSScreen.html#ambientLight","kind":"property"},{"fullName":"HSScreen.setMode(width, height, scale, frequency)","description":"Switch to the given display mode. Pass 0 for scale or frequency to match any value.","url":"HSScreen.html#setMode","kind":"method"},{"fullName":"HSScreen.snapshot()","description":"Capture the current contents of this screen as an image. Requires Screen Recording permission.","url":"HSScreen.html#snapshot","kind":"method"},{"fullName":"HSScreen.next()","description":"The next screen in hs.screen.all() order, wrapping around.","url":"HSScreen.html#next","kind":"method"},{"fullName":"HSScreen.previous()","description":"The previous screen in hs.screen.all() order, wrapping around.","url":"HSScreen.html#previous","kind":"method"},{"fullName":"HSScreen.toEast()","description":"The nearest screen whose left edge is at or beyond this screen's right edge, or null.","url":"HSScreen.html#toEast","kind":"method"},{"fullName":"HSScreen.toWest()","description":"The nearest screen whose right edge is at or before this screen's left edge, or null.","url":"HSScreen.html#toWest","kind":"method"},{"fullName":"HSScreen.toNorth()","description":"The nearest screen that is physically above this screen, or null.","url":"HSScreen.html#toNorth","kind":"method"},{"fullName":"HSScreen.toSouth()","description":"The nearest screen that is physically below this screen, or null.","url":"HSScreen.html#toSouth","kind":"method"},{"fullName":"HSScreen.setOrigin(x, y)","description":"Move this screen so its top-left corner is at the given position in global Hammerspoon coordinates.","url":"HSScreen.html#setOrigin","kind":"method"},{"fullName":"HSScreen.setPrimary()","description":"Designate this screen as the primary display (moves the menu bar here).","url":"HSScreen.html#setPrimary","kind":"method"},{"fullName":"HSScreen.mirrorOf(screen)","description":"Configure this screen to mirror another screen.","url":"HSScreen.html#mirrorOf","kind":"method"},{"fullName":"HSScreen.mirrorStop()","description":"Stop mirroring, restoring this screen to an independent display.","url":"HSScreen.html#mirrorStop","kind":"method"},{"fullName":"HSScreen.absoluteToLocal(rect)","description":"Convert a rect in global Hammerspoon coordinates to coordinates local to this screen. The result origin is relative to this screen's top-left corner.","url":"HSScreen.html#absoluteToLocal","kind":"method"},{"fullName":"HSScreen.localToAbsolute(rect)","description":"Convert a rect in local screen coordinates to global Hammerspoon coordinates.","url":"HSScreen.html#localToAbsolute","kind":"method"},{"fullName":"HSScreen.getBrightness()","description":"The current brightness of this display, from 0.0 (darkest) to 1.0 (brightest). Returns null if the display does not support software brightness control (e.g. most third-party monitors, which are controlled via DDC rather than software).","url":"HSScreen.html#getBrightness","kind":"method"},{"fullName":"HSScreen.setBrightness(brightness)","description":"Set the brightness of this display.","url":"HSScreen.html#setBrightness","kind":"method"},{"fullName":"HSSerialPort","description":"A serial port, created via hs.serial.createPortNamed() or hs.serial.createPortAtPath(). The port is not open until you call open(). Configure it (baud rate, data bits, etc.) either before or after opening — configuration changes made while open are applied immediately. Received data, and lifecycle events, are delivered via the callback registered with setCallback().","url":"HSSerialPort.html","kind":"type"},{"fullName":"HSSerialPort.identifier","description":"The unique identifier assigned to this port object.","url":"HSSerialPort.html#identifier","kind":"property"},{"fullName":"HSSerialPort.name","description":"The port's name (e.g. \"usbserial-1420\").","url":"HSSerialPort.html#name","kind":"property"},{"fullName":"HSSerialPort.path","description":"The port's device path (e.g. \"/dev/cu.usbserial-1420\").","url":"HSSerialPort.html#path","kind":"property"},{"fullName":"HSSerialPort.isOpen","description":"Whether the port is currently open.","url":"HSSerialPort.html#isOpen","kind":"property"},{"fullName":"HSSerialPort.baudRate","description":"The baud rate, in bits per second. Default is 115200. Setting a non-standard value (i.e. not one of 300, 1200, 2400, 4800, 9600, 14400, 19200, 28800, 38400, 57600, 115200, 230400) is rejected unless allowNonStandardBaudRates is true.","url":"HSSerialPort.html#baudRate","kind":"property"},{"fullName":"HSSerialPort.allowNonStandardBaudRates","description":"Whether baudRate may be set to a value outside the standard set. Default is false.","url":"HSSerialPort.html#allowNonStandardBaudRates","kind":"property"},{"fullName":"HSSerialPort.dataBits","description":"The number of data bits, 5–8. Default is 8.","url":"HSSerialPort.html#dataBits","kind":"property"},{"fullName":"HSSerialPort.stopBits","description":"The number of stop bits, 1 or 2. Default is 1.","url":"HSSerialPort.html#stopBits","kind":"property"},{"fullName":"HSSerialPort.parity","description":"The parity mode: \"none\", \"odd\", or \"even\". Default is \"none\".","url":"HSSerialPort.html#parity","kind":"property"},{"fullName":"HSSerialPort.dtr","description":"The state of the DTR (Data Terminal Ready) control line. Default is false.","url":"HSSerialPort.html#dtr","kind":"property"},{"fullName":"HSSerialPort.rts","description":"The state of the RTS (Request To Send) control line. Default is false.","url":"HSSerialPort.html#rts","kind":"property"},{"fullName":"HSSerialPort.usesRTSCTSFlowControl","description":"Whether to use hardware RTS/CTS flow control. Default is false.","url":"HSSerialPort.html#usesRTSCTSFlowControl","kind":"property"},{"fullName":"HSSerialPort.usesDTRDSRFlowControl","description":"Whether to use hardware DTR/DSR flow control. Default is false.","url":"HSSerialPort.html#usesDTRDSRFlowControl","kind":"property"},{"fullName":"HSSerialPort.shouldEchoReceivedData","description":"Whether data sent with sendData() is also delivered back to the callback as a \"received\" event, simulating local echo. Default is false.","url":"HSSerialPort.html#shouldEchoReceivedData","kind":"property"},{"fullName":"HSSerialPort.open()","description":"Opens the port using its current configuration.","url":"HSSerialPort.html#open","kind":"method"},{"fullName":"HSSerialPort.close()","description":"Closes the port.","url":"HSSerialPort.html#close","kind":"method"},{"fullName":"HSSerialPort.sendData(value)","description":"Sends data through the port. The string is transmitted as raw bytes: each character's code point (0–255) becomes one byte on the wire. This lets you round-trip arbitrary binary data — build the string with String.fromCharCode() for non-text payloads.","url":"HSSerialPort.html#sendData","kind":"method"},{"fullName":"HSSerialPort.setCallback(fn)","description":"Sets the callback invoked for port lifecycle events and received data. The callback receives two arguments: an event type string and a data string.","url":"HSSerialPort.html#setCallback","kind":"method"},{"fullName":"HSSerialPort.destroy()","description":"Closes the port and releases all resources. Called automatically during shutdown.","url":"HSSerialPort.html#destroy","kind":"method"},{"fullName":"HSSharingService","description":"A configured sharing service, wrapping NSSharingService. Create instances via hs.sharing.createShare() or hs.sharing.servicesFor(). Configure with setCallback(), recipients, and subject as needed, then call shareItems().","url":"HSSharingService.html","kind":"type"},{"fullName":"HSSharingService.identifier","description":"A unique identifier for this share object (UUID string).","url":"HSSharingService.html#identifier","kind":"property"},{"fullName":"HSSharingService.title","description":"The user-visible title of the service, e.g. \"Mail\" or \"AirDrop\".","url":"HSSharingService.html#title","kind":"property"},{"fullName":"HSSharingService.image","description":"The service's icon.","url":"HSSharingService.html#image","kind":"property"},{"fullName":"HSSharingService.alternateImage","description":"An alternate icon for the service, if one is provided, otherwise null.","url":"HSSharingService.html#alternateImage","kind":"property"},{"fullName":"HSSharingService.recipients","description":"Recipients (e.g. email addresses) for services that support them, such as Mail or Messages.","url":"HSSharingService.html#recipients","kind":"property"},{"fullName":"HSSharingService.subject","description":"The subject line, for services that support one, such as Mail.","url":"HSSharingService.html#subject","kind":"property"},{"fullName":"HSSharingService.messageBody","description":"The message body, populated once the share is in progress. Empty until then.","url":"HSSharingService.html#messageBody","kind":"property"},{"fullName":"HSSharingService.permanentLink","description":"A permanent link to the shared content, if the service provides one. Populated once the share is in progress; otherwise null.","url":"HSSharingService.html#permanentLink","kind":"property"},{"fullName":"HSSharingService.accountName","description":"The account name used to perform the share, if applicable. Populated once the share is in progress; otherwise null.","url":"HSSharingService.html#accountName","kind":"property"},{"fullName":"HSSharingService.attachments","description":"File paths of any attachments included in the share, populated once the share completes. Empty until then.","url":"HSSharingService.html#attachments","kind":"property"},{"fullName":"HSSharingService.canShareItems(items)","description":"Checks whether this service can share the given items. Items may be strings (treated as a web/mailto URL if they parse as one, a file path if they start with / or ~ and the file exists, otherwise plain text) or HSImage objects.","url":"HSSharingService.html#canShareItems","kind":"method"},{"fullName":"HSSharingService.shareItems(items)","description":"Attempts to share the given items with this service. If the service cannot handle the items, this logs a warning and returns false without doing anything further. Otherwise the share is started; it is asynchronous — use setCallback() to find out when it completes.","url":"HSSharingService.html#shareItems","kind":"method"},{"fullName":"HSSharingService.setCallback(fn)","description":"Registers a callback for share lifecycle events.","url":"HSSharingService.html#setCallback","kind":"method"},{"fullName":"HSSound","description":"An object representing an audio sound that can be played, paused, and stopped. Create instances using hs.sound.fromFile() or hs.sound.named().","url":"HSSound.html","kind":"type"},{"fullName":"HSSound.identifier","description":"A unique identifier for this sound object.","url":"HSSound.html#identifier","kind":"property"},{"fullName":"HSSound.name","description":"The name of this sound. System sounds loaded by name return their name; file-based sounds return null.","url":"HSSound.html#name","kind":"property"},{"fullName":"HSSound.duration","description":"The total duration of the sound in seconds.","url":"HSSound.html#duration","kind":"property"},{"fullName":"HSSound.currentTime","description":"The current playback position in seconds. Assign a value to seek to that position.","url":"HSSound.html#currentTime","kind":"property"},{"fullName":"HSSound.volume","description":"The playback volume, from 0.0 (silent) to 1.0 (full volume).","url":"HSSound.html#volume","kind":"property"},{"fullName":"HSSound.loops","description":"Whether the sound loops when it reaches the end. Defaults to false.","url":"HSSound.html#loops","kind":"property"},{"fullName":"HSSound.isPlaying","description":"Whether the sound is currently playing.","url":"HSSound.html#isPlaying","kind":"property"},{"fullName":"HSSound.play()","description":"Starts playback from the current position.","url":"HSSound.html#play","kind":"method"},{"fullName":"HSSound.pause()","description":"Pauses playback, preserving the current position.","url":"HSSound.html#pause","kind":"method"},{"fullName":"HSSound.resume()","description":"Resumes playback from a paused position.","url":"HSSound.html#resume","kind":"method"},{"fullName":"HSSound.stop()","description":"Stops playback. The playback position is not reset.","url":"HSSound.html#stop","kind":"method"},{"fullName":"HSSound.setCallback(callback)","description":"Sets a function to be called when playback finishes. The callback receives two arguments: the sound object and a boolean — true if the sound completed naturally, false if it was stopped before finishing.","url":"HSSound.html#setCallback","kind":"method"},{"fullName":"HSSound.removeCallback()","description":"Removes the completion callback previously set with setCallback().","url":"HSSound.html#removeCallback","kind":"method"},{"fullName":"HSSound.destroy()","description":"Stops playback and releases all resources held by this sound. After calling destroy() the sound object should not be used.","url":"HSSound.html#destroy","kind":"method"},{"fullName":"HSSpotlightGroup","description":"A grouped set of Spotlight results that share a common metadata attribute value. Groups are returned by HSSpotlightQuery.groups() when grouping attributes have been configured with setGroupingAttributes(). Do not instantiate HSSpotlightGroup directly. When multiple grouping attributes are specified, groups nest: each group has subgroups() containing the next level of grouping.","url":"HSSpotlightGroup.html","kind":"type"},{"fullName":"HSSpotlightGroup.identifier","description":"A unique identifier for this group object (UUID string).","url":"HSSpotlightGroup.html#identifier","kind":"property"},{"fullName":"HSSpotlightGroup.attribute","description":"The metadata attribute name by which results in this group are clustered.","url":"HSSpotlightGroup.html#attribute","kind":"property"},{"fullName":"HSSpotlightGroup.count","description":"The number of results contained in this group.","url":"HSSpotlightGroup.html#count","kind":"property"},{"fullName":"HSSpotlightGroup.value()","description":"The shared value of the grouping attribute for all results in this group. Returns null only in the unlikely case that the underlying value cannot be bridged.","url":"HSSpotlightGroup.html#value","kind":"method"},{"fullName":"HSSpotlightGroup.results()","description":"Returns the items contained in this group as an array of HSSpotlightItem objects.","url":"HSSpotlightGroup.html#results","kind":"method"},{"fullName":"HSSpotlightGroup.subgroups()","description":"Returns nested subgroups when multiple grouping attributes were specified. Returns an empty array if no subgroups exist for this group.","url":"HSSpotlightGroup.html#subgroups","kind":"method"},{"fullName":"HSSpotlightItem","description":"An individual result returned by a Spotlight query. Instances are returned by HSSpotlightQuery.results() and related methods. Do not instantiate HSSpotlightItem directly. Metadata values are read via valueForAttribute() using standard kMDItem* keys. Call attributes() to discover which keys are populated on a particular item. Common attribute key shortcuts live in hs.spotlight.attribute.","url":"HSSpotlightItem.html","kind":"type"},{"fullName":"HSSpotlightItem.identifier","description":"A unique identifier for this result object (UUID string).","url":"HSSpotlightItem.html#identifier","kind":"property"},{"fullName":"HSSpotlightItem.attributes()","description":"Returns the list of metadata attribute names present on this item. The list is typically not exhaustive — some attributes (such as kMDItemPath) may be readable via valueForAttribute() even when absent from this list.","url":"HSSpotlightItem.html#attributes","kind":"method"},{"fullName":"HSSpotlightItem.valueForAttribute(key)","description":"Returns the value for a specific metadata attribute, or null if absent. The return type depends on the attribute: common types include strings, numbers, dates, and arrays of strings. NSURL-typed values are automatically converted to their string representation.","url":"HSSpotlightItem.html#valueForAttribute","kind":"method"},{"fullName":"HSSpotlightQuery","description":"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.","url":"HSSpotlightQuery.html","kind":"type"},{"fullName":"HSSpotlightQuery.identifier","description":"A unique identifier for this query object (UUID string).","url":"HSSpotlightQuery.html#identifier","kind":"property"},{"fullName":"HSSpotlightQuery.count","description":"The number of results gathered so far.","url":"HSSpotlightQuery.html#count","kind":"property"},{"fullName":"HSSpotlightQuery.isRunning","description":"Whether the query is currently running (gathering or monitoring for live updates).","url":"HSSpotlightQuery.html#isRunning","kind":"property"},{"fullName":"HSSpotlightQuery.isGathering","description":"Whether the query is in the initial gathering phase. true from \"didStart\" until \"didFinish\"; false thereafter while live-monitoring.","url":"HSSpotlightQuery.html#isGathering","kind":"property"},{"fullName":"HSSpotlightQuery.setQuery(predicate)","description":"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.","url":"HSSpotlightQuery.html#setQuery","kind":"method"},{"fullName":"HSSpotlightQuery.setScopes(scopes)","description":"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.","url":"HSSpotlightQuery.html#setScopes","kind":"method"},{"fullName":"HSSpotlightQuery.setSortDescriptors(descriptors)","description":"Sets sort descriptors that control the order of results.","url":"HSSpotlightQuery.html#setSortDescriptors","kind":"method"},{"fullName":"HSSpotlightQuery.setGroupingAttributes(attrs)","description":"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().","url":"HSSpotlightQuery.html#setGroupingAttributes","kind":"method"},{"fullName":"HSSpotlightQuery.setValueListAttributes(attrs)","description":"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.","url":"HSSpotlightQuery.html#setValueListAttributes","kind":"method"},{"fullName":"HSSpotlightQuery.setCallback(fn)","description":"Registers a callback that receives query lifecycle events. of HSSpotlightItem objects describing what changed in this update cycle","url":"HSSpotlightQuery.html#setCallback","kind":"method"},{"fullName":"HSSpotlightQuery.start()","description":"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.","url":"HSSpotlightQuery.html#start","kind":"method"},{"fullName":"HSSpotlightQuery.stop()","description":"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.","url":"HSSpotlightQuery.html#stop","kind":"method"},{"fullName":"HSSpotlightQuery.results()","description":"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.","url":"HSSpotlightQuery.html#results","kind":"method"},{"fullName":"HSSpotlightQuery.groups()","description":"Returns grouped results when grouping attributes have been configured. Returns an empty array if setGroupingAttributes() was not called.","url":"HSSpotlightQuery.html#groups","kind":"method"},{"fullName":"HSSpotlightQuery.valueLists()","description":"Returns aggregate value-list summaries for attributes set via setValueListAttributes(). Returns an empty array if setValueListAttributes() was not called.","url":"HSSpotlightQuery.html#valueLists","kind":"method"},{"fullName":"HSStreamDeckDevice","description":"A Stream Deck device, obtained via hs.streamdeck.all() or a discovery watcher — do not instantiate directly.","url":"HSStreamDeckDevice.html","kind":"type"},{"fullName":"HSStreamDeckDevice.identifier","description":"The unique identifier assigned to this device object.","url":"HSStreamDeckDevice.html#identifier","kind":"property"},{"fullName":"HSStreamDeckDevice.deckType","description":"A human-readable description of the device model (e.g. \"Elgato Stream Deck (XL)\").","url":"HSStreamDeckDevice.html#deckType","kind":"property"},{"fullName":"HSStreamDeckDevice.serialNumber","description":"The device's serial number.","url":"HSStreamDeckDevice.html#serialNumber","kind":"property"},{"fullName":"HSStreamDeckDevice.firmwareVersion","description":"The device's firmware version. Reads live from the hardware on every access.","url":"HSStreamDeckDevice.html#firmwareVersion","kind":"property"},{"fullName":"HSStreamDeckDevice.keyColumns","description":"The number of button columns.","url":"HSStreamDeckDevice.html#keyColumns","kind":"property"},{"fullName":"HSStreamDeckDevice.keyRows","description":"The number of button rows.","url":"HSStreamDeckDevice.html#keyRows","kind":"property"},{"fullName":"HSStreamDeckDevice.keyCount","description":"The total number of buttons (keyColumns * keyRows).","url":"HSStreamDeckDevice.html#keyCount","kind":"property"},{"fullName":"HSStreamDeckDevice.encoderColumns","description":"The number of rotary encoders (Stream Deck Plus only; 0 on other models).","url":"HSStreamDeckDevice.html#encoderColumns","kind":"property"},{"fullName":"HSStreamDeckDevice.encoderRows","description":"The number of encoder rows (Stream Deck Plus only; 0 on other models).","url":"HSStreamDeckDevice.html#encoderRows","kind":"property"},{"fullName":"HSStreamDeckDevice.encoderCount","description":"The total number of encoders (encoderColumns * encoderRows).","url":"HSStreamDeckDevice.html#encoderCount","kind":"property"},{"fullName":"HSStreamDeckDevice.imageSize","description":"The pixel dimensions required for button images.","url":"HSStreamDeckDevice.html#imageSize","kind":"property"},{"fullName":"HSStreamDeckDevice.setBrightness(brightness)","description":"Sets the device's brightness.","url":"HSStreamDeckDevice.html#setBrightness","kind":"method"},{"fullName":"HSStreamDeckDevice.reset()","description":"Resets the device to its power-on state (clears all button images).","url":"HSStreamDeckDevice.html#reset","kind":"method"},{"fullName":"HSStreamDeckDevice.setButtonImage(button, image)","description":"Sets a button's image.","url":"HSStreamDeckDevice.html#setButtonImage","kind":"method"},{"fullName":"HSStreamDeckDevice.setButtonColor(button, color)","description":"Sets a button to a solid color.","url":"HSStreamDeckDevice.html#setButtonColor","kind":"method"},{"fullName":"HSStreamDeckDevice.setScreenImage(encoder, image)","description":"Sets the LCD strip image above one encoder (Stream Deck Plus only; a no-op on other models).","url":"HSStreamDeckDevice.html#setScreenImage","kind":"method"},{"fullName":"HSStreamDeckDevice.buttonCallback(fn)","description":"Sets the callback for button press/release events. Replaces any previously set callback. The callback receives: this device, the button number, and whether it is now pressed.","url":"HSStreamDeckDevice.html#buttonCallback","kind":"method"},{"fullName":"HSStreamDeckDevice.encoderCallback(fn)","description":"Sets the callback for encoder press/release/rotation events (Stream Deck Plus only). Replaces any previously set callback. The callback receives: this device, the encoder number, whether it is now pressed, and two booleans indicating rotation direction (at most one is true per call).","url":"HSStreamDeckDevice.html#encoderCallback","kind":"method"},{"fullName":"HSStreamDeckDevice.screenCallback(fn)","description":"Sets the callback for LCD touch-screen events (Stream Deck Plus only). Replaces any previously set callback. The callback receives: this device, the event type (\"shortPress\", \"longPress\", or \"swipe\"), and the start/end X/Y coordinates (end coordinates are 0 unless swiping).","url":"HSStreamDeckDevice.html#screenCallback","kind":"method"},{"fullName":"HSStreamDeckDevice.destroy()","description":"Stops delivering events and releases all callbacks. Called automatically when the device is disconnected or the module shuts down.","url":"HSStreamDeckDevice.html#destroy","kind":"method"},{"fullName":"HSTask","description":"Object representing an external process task","url":"HSTask.html","kind":"type"},{"fullName":"HSTask.isRunning","description":"Check if the task is currently running","url":"HSTask.html#isRunning","kind":"property"},{"fullName":"HSTask.pid","description":"The process ID of the running task","url":"HSTask.html#pid","kind":"property"},{"fullName":"HSTask.environment","description":"The environment variables for the task","url":"HSTask.html#environment","kind":"property"},{"fullName":"HSTask.workingDirectory","description":"The working directory for the task","url":"HSTask.html#workingDirectory","kind":"property"},{"fullName":"HSTask.terminationStatus","description":"The termination status of the task","url":"HSTask.html#terminationStatus","kind":"property"},{"fullName":"HSTask.terminationReason","description":"The termination reason","url":"HSTask.html#terminationReason","kind":"property"},{"fullName":"HSTask.start()","description":"Start the task","url":"HSTask.html#start","kind":"method"},{"fullName":"HSTask.terminate()","description":"Terminate the task (send SIGTERM)","url":"HSTask.html#terminate","kind":"method"},{"fullName":"HSTask.kill9()","description":"Terminate the task with extreme prejudice (send SIGKILL)","url":"HSTask.html#kill9","kind":"method"},{"fullName":"HSTask.interrupt()","description":"Interrupt the task (send SIGINT)","url":"HSTask.html#interrupt","kind":"method"},{"fullName":"HSTask.pause()","description":"Pause the task (send SIGSTOP)","url":"HSTask.html#pause","kind":"method"},{"fullName":"HSTask.resume()","description":"Resume the task (send SIGCONT)","url":"HSTask.html#resume","kind":"method"},{"fullName":"HSTask.waitUntilExit()","description":"Wait for the task to complete (blocking)","url":"HSTask.html#waitUntilExit","kind":"method"},{"fullName":"HSTask.sendInput(data)","description":"Write data to the task's stdin","url":"HSTask.html#sendInput","kind":"method"},{"fullName":"HSTask.closeInput()","description":"Close the task's stdin","url":"HSTask.html#closeInput","kind":"method"},{"fullName":"TaskBuilder","description":"TaskBuilder class for fluent task construction","url":"TaskBuilder.html","kind":"type"},{"fullName":"TaskBuilder.withArgs(args)","description":"Add arguments","url":"TaskBuilder.html#withArgs","kind":"method"},{"fullName":"TaskBuilder.withEnvironment(environment)","description":"Set environment variables","url":"TaskBuilder.html#withEnvironment","kind":"method"},{"fullName":"TaskBuilder.inDirectory(directory)","description":"Set working directory","url":"TaskBuilder.html#inDirectory","kind":"method"},{"fullName":"TaskBuilder.onOutput(callback)","description":"Set output callback","url":"TaskBuilder.html#onOutput","kind":"method"},{"fullName":"TaskBuilder.run()","description":"Build and run the task","url":"TaskBuilder.html#run","kind":"method"},{"fullName":"TaskBuilder.build()","description":"Build the task without running","url":"TaskBuilder.html#build","kind":"method"},{"fullName":"HSTimer","description":"Object representing a timer. You should not instantiate these yourself, but rather, use the methods in hs.timer to create them for you.","url":"HSTimer.html","kind":"type"},{"fullName":"HSTimer.interval","description":"The timer's interval in seconds","url":"HSTimer.html#interval","kind":"property"},{"fullName":"HSTimer.repeats","description":"Whether the timer repeats","url":"HSTimer.html#repeats","kind":"property"},{"fullName":"HSTimer.start()","description":"Start the timer","url":"HSTimer.html#start","kind":"method"},{"fullName":"HSTimer.stop()","description":"Stop the timer","url":"HSTimer.html#stop","kind":"method"},{"fullName":"HSTimer.fire()","description":"Immediately fire the timer's callback","url":"HSTimer.html#fire","kind":"method"},{"fullName":"HSTimer.running()","description":"Check if the timer is currently running","url":"HSTimer.html#running","kind":"method"},{"fullName":"HSTimer.nextTrigger()","description":"Get the number of seconds until the timer next fires","url":"HSTimer.html#nextTrigger","kind":"method"},{"fullName":"HSTimer.setNextTrigger(seconds)","description":"Set when the timer should next fire","url":"HSTimer.html#setNextTrigger","kind":"method"},{"fullName":"HSTranslationSession","description":"JavaScript-visible API for a translation session bound to a specific language pair.","url":"HSTranslationSession.html","kind":"type"},{"fullName":"HSTranslationSession.typeName","description":"The Swift type name, for JavaScript introspection.","url":"HSTranslationSession.html#typeName","kind":"property"},{"fullName":"HSTranslationSession.sourceLanguage","description":"BCP-47 identifier of the source language (e.g. \"en\").","url":"HSTranslationSession.html#sourceLanguage","kind":"property"},{"fullName":"HSTranslationSession.targetLanguage","description":"BCP-47 identifier of the target language (e.g. \"fr\").","url":"HSTranslationSession.html#targetLanguage","kind":"property"},{"fullName":"HSTranslationSession.translate(text)","description":"Translate a string from the session's source language to its target language.","url":"HSTranslationSession.html#translate","kind":"method"},{"fullName":"HSUIWindow","description":"# HSUIWindow A custom window with declarative UI building HSUIWindow allows you to create custom windows with a SwiftUI-like declarative syntax. Build interfaces using shapes, text, images, and layout containers. Note: Clicking the macOS close button only hides the window (firing the onHide() callback, if you have one configured) — it does not destroy the window while you hold a reference to it in JavaScript. Call destroy() explicitly (for example from within an onHide() handler) if you want to release it. See onShow(), onHide(), and onDestroy() below for the full set of lifecycle callbacks. ## Building UI Elements ## Modifying Elements ## Examples Simple window with text and shapes: ``javascript hs.ui.window({x: 100, y: 100, w: 300, h: 200}) .vstack() .spacing(10) .padding(20) .text(\"Dashboard\") .font(HSFont.largeTitle()) .foregroundColor(\"#FFFFFF\") .rectangle() .fill(\"#4A90E2\") .cornerRadius(10) .frame({w: \"90%\", h: 80}) .end() .backgroundColor(\"#2C3E50\") .show(); ` Window with image: `javascript const img = HSImage.fromPath(\"~/Pictures/photo.jpg\") hs.ui.window({x: 100, y: 100, w: 400, h: 300}) .vstack() .padding(20) .image(img) .resizable() .aspectRatio(\"fit\") .frame({w: 360, h: 240}) .end() .show(); ``","url":"HSUIWindow.html","kind":"type"},{"fullName":"HSUIWindow.show()","description":"Show the window","url":"HSUIWindow.html#show","kind":"method"},{"fullName":"HSUIWindow.hide()","description":"Hide the window (keeps it in memory)","url":"HSUIWindow.html#hide","kind":"method"},{"fullName":"HSUIWindow.destroy()","description":"Destroy the window","url":"HSUIWindow.html#destroy","kind":"method"},{"fullName":"HSUIWindow.onShow(callback)","description":"Set a callback to fire after the window is shown","url":"HSUIWindow.html#onShow","kind":"method"},{"fullName":"HSUIWindow.onHide(callback)","description":"Set a callback to fire when the window is hidden Fires when hide() is called, and when the user clicks the macOS close button — clicking that button only hides the window from Hammerspoon's perspective (see the class-level note above), so this is the callback that reacts to it. Does not fire when the window is destroyed via destroy() — use onDestroy() for that.","url":"HSUIWindow.html#onHide","kind":"method"},{"fullName":"HSUIWindow.onDestroy(callback)","description":"Set a callback to fire after the window is destroyed via destroy() Only fires when destroy() is called explicitly — whether directly, or from within an onHide() handler. It does not fire when the user clicks the macOS close button by itself; that only hides the window, so use onHide() to react to the button click, and call destroy() from that handler if you also want to release the window.","url":"HSUIWindow.html#onDestroy","kind":"method"},{"fullName":"HSUIWindow.titled(show)","description":"Show or hide the window's title bar By default windows have a title bar. Pass false to create a borderless window. .closable(), .miniaturizable(), and .allowResize() only take visual effect when the window is titled.","url":"HSUIWindow.html#titled","kind":"method"},{"fullName":"HSUIWindow.closable(show)","description":"Show or hide the close button on the window Requires .titled(true) to be visible. Enabled by default.","url":"HSUIWindow.html#closable","kind":"method"},{"fullName":"HSUIWindow.miniaturizable(show)","description":"Show or hide the miniaturize (yellow) button on the window Requires .titled(true) to be visible. Enabled by default.","url":"HSUIWindow.html#miniaturizable","kind":"method"},{"fullName":"HSUIWindow.allowResize(enable)","description":"Allow or prevent the user from resizing the window Enabled by default. Only has a visual effect when .titled(true) is also set.","url":"HSUIWindow.html#allowResize","kind":"method"},{"fullName":"HSUIWindow.windowTitle(text)","description":"Set the text shown in the window's title bar Only visible when .titled(true) is set (the default).","url":"HSUIWindow.html#windowTitle","kind":"method"},{"fullName":"HSUIWindow.level(name)","description":"Set the window stacking level Controls where this window sits in the macOS window hierarchy.","url":"HSUIWindow.html#level","kind":"method"},{"fullName":"HSUIWindow.backgroundColor(colorValue)","description":"Set the window's background color","url":"HSUIWindow.html#backgroundColor","kind":"method"},{"fullName":"HSUIWindow.rectangle()","description":"Add a rectangle shape","url":"HSUIWindow.html#rectangle","kind":"method"},{"fullName":"HSUIWindow.circle()","description":"Add a circle shape","url":"HSUIWindow.html#circle","kind":"method"},{"fullName":"HSUIWindow.text(content)","description":"Add a text element or an HSString object (from hs.ui.string()) for reactive text","url":"HSUIWindow.html#text","kind":"method"},{"fullName":"HSUIWindow.image(imageValue)","description":"Add an image element","url":"HSUIWindow.html#image","kind":"method"},{"fullName":"HSUIWindow.video(videoValue)","description":"Add a video element Renders a SwiftUI VideoPlayer for the given HSVideo. Keep a reference to the HSVideo object to control playback (play(), pause(), seek(), volume) after the window is shown.","url":"HSUIWindow.html#video","kind":"method"},{"fullName":"HSUIWindow.button(label)","description":"Add a button element or an HSString object (from hs.ui.string()) for reactive text","url":"HSUIWindow.html#button","kind":"method"},{"fullName":"HSUIWindow.vstack()","description":"Begin a vertical stack (elements arranged top to bottom)","url":"HSUIWindow.html#vstack","kind":"method"},{"fullName":"HSUIWindow.hstack()","description":"Begin a horizontal stack (elements arranged left to right)","url":"HSUIWindow.html#hstack","kind":"method"},{"fullName":"HSUIWindow.zstack()","description":"Begin a z-stack (overlapping elements)","url":"HSUIWindow.html#zstack","kind":"method"},{"fullName":"HSUIWindow.spacer()","description":"Add flexible spacing that expands to fill available space","url":"HSUIWindow.html#spacer","kind":"method"},{"fullName":"HSUIWindow.webview(element)","description":"Embed a web browser element created with hs.ui.webview() (macOS 26+) The element fills the available space in the window layout. Keep a reference to the element to call navigation methods after the window is shown.","url":"HSUIWindow.html#webview","kind":"method"},{"fullName":"HSUIWindow.end()","description":"End the current layout container","url":"HSUIWindow.html#end","kind":"method"},{"fullName":"HSUIWindow.fill(colorValue)","description":"Fill a shape with a color","url":"HSUIWindow.html#fill","kind":"method"},{"fullName":"HSUIWindow.stroke(colorValue)","description":"Add a stroke (border) to a shape","url":"HSUIWindow.html#stroke","kind":"method"},{"fullName":"HSUIWindow.strokeWidth(width)","description":"Set the stroke width","url":"HSUIWindow.html#strokeWidth","kind":"method"},{"fullName":"HSUIWindow.cornerRadius(radius)","description":"Round the corners of a shape","url":"HSUIWindow.html#cornerRadius","kind":"method"},{"fullName":"HSUIWindow.frame(dict)","description":"Set the frame (size) of an element","url":"HSUIWindow.html#frame","kind":"method"},{"fullName":"HSUIWindow.opacity(value)","description":"Set the opacity of an element","url":"HSUIWindow.html#opacity","kind":"method"},{"fullName":"HSUIWindow.font(font)","description":"Set the font for a text element","url":"HSUIWindow.html#font","kind":"method"},{"fullName":"HSUIWindow.foregroundColor(colorValue)","description":"Set the text color","url":"HSUIWindow.html#foregroundColor","kind":"method"},{"fullName":"HSUIWindow.resizable()","description":"Make an image resizable (allows it to scale with frame size)","url":"HSUIWindow.html#resizable","kind":"method"},{"fullName":"HSUIWindow.aspectRatio(mode)","description":"Set the aspect ratio mode for an image","url":"HSUIWindow.html#aspectRatio","kind":"method"},{"fullName":"HSUIWindow.padding(value)","description":"Add padding around a layout container","url":"HSUIWindow.html#padding","kind":"method"},{"fullName":"HSUIWindow.spacing(value)","description":"Set spacing between elements in a stack","url":"HSUIWindow.html#spacing","kind":"method"},{"fullName":"HSUIWindow.onClick(callback)","description":"Set a callback to fire when the element is clicked","url":"HSUIWindow.html#onClick","kind":"method"},{"fullName":"HSUIWindow.onHover(callback)","description":"Set a callback to fire when the cursor enters or leaves the element","url":"HSUIWindow.html#onHover","kind":"method"},{"fullName":"HSUIAlert","description":"# HSUIAlert A temporary on-screen notification Displays a message that automatically fades out after a specified duration. Without an explicit .position(), multiple alerts stack vertically and stay centered as they appear and disappear. With .position(), the alert appears at the given coordinates regardless of other alerts. ## Example ``javascript hs.ui.alert(\"Task completed!\") .font(HSFont.headline()) .duration(5) .padding(30) .show(); ``","url":"HSUIAlert.html","kind":"type"},{"fullName":"HSUIAlert.font(font)","description":"Set the font for the alert text","url":"HSUIAlert.html#font","kind":"method"},{"fullName":"HSUIAlert.duration(seconds)","description":"Set how long the alert is displayed","url":"HSUIAlert.html#duration","kind":"method"},{"fullName":"HSUIAlert.padding(points)","description":"Set the padding around the alert text","url":"HSUIAlert.html#padding","kind":"method"},{"fullName":"HSUIAlert.position(dict)","description":"Set a custom position for the alert When a position is set, the alert is shown at those coordinates and will not be stacked with other alerts. Coordinates are in points from the top-left of the visible screen area (below the menu bar), with y increasing downward.","url":"HSUIAlert.html#position","kind":"method"},{"fullName":"HSUIAlert.show()","description":"Show the alert","url":"HSUIAlert.html#show","kind":"method"},{"fullName":"HSUIAlert.close()","description":"Close the alert immediately","url":"HSUIAlert.html#close","kind":"method"},{"fullName":"HSUIDialog","description":"# HSUIDialog A modal dialog with customizable buttons Shows a blocking dialog with a message, optional informative text, and custom buttons. Use the callback to respond to button presses. ## Example ``javascript hs.ui.dialog(\"Save changes?\") .informativeText(\"Your document has unsaved changes.\") .buttons([\"Save\", \"Don't Save\", \"Cancel\"]) .onButton((index) => { if (index === 0) { console.log(\"Saving...\"); } else if (index === 1) { console.log(\"Discarding changes...\"); } }) .show(); ``","url":"HSUIDialog.html","kind":"type"},{"fullName":"HSUIDialog.informativeText(text)","description":"Set additional informative text below the main message","url":"HSUIDialog.html#informativeText","kind":"method"},{"fullName":"HSUIDialog.buttons(labels)","description":"Set custom button labels","url":"HSUIDialog.html#buttons","kind":"method"},{"fullName":"HSUIDialog.style(style)","description":"Set the dialog style","url":"HSUIDialog.html#style","kind":"method"},{"fullName":"HSUIDialog.onButton(callback)","description":"Set the callback for button presses","url":"HSUIDialog.html#onButton","kind":"method"},{"fullName":"HSUIDialog.show()","description":"Show the dialog","url":"HSUIDialog.html#show","kind":"method"},{"fullName":"HSUIDialog.close()","description":"Close the dialog programmatically","url":"HSUIDialog.html#close","kind":"method"},{"fullName":"HSUIFilePicker","description":"# HSUIFilePicker A file or directory selection dialog Shows a standard macOS open panel for selecting files or directories. Supports multiple selection, file type filtering, and more. ## Examples ### File Picker ``javascript hs.ui.filePicker() .message(\"Choose a file to open\") .allowedFileTypes([\"txt\", \"md\", \"js\"]) .onSelection((path) => { if (path) { console.log(\"Selected: \" + path); } else { console.log(\"User cancelled\"); } }) .show(); ` ### Directory Picker with Multiple Selection `javascript hs.ui.filePicker() .message(\"Choose directories to backup\") .canChooseFiles(false) .canChooseDirectories(true) .allowsMultipleSelection(true) .onSelection((paths) => { if (paths) { paths.forEach(p => console.log(\"Dir: \" + p)); } }) .show(); ``","url":"HSUIFilePicker.html","kind":"type"},{"fullName":"HSUIFilePicker.message(text)","description":"Set the message displayed in the picker","url":"HSUIFilePicker.html#message","kind":"method"},{"fullName":"HSUIFilePicker.defaultPath(path)","description":"Set the starting directory","url":"HSUIFilePicker.html#defaultPath","kind":"method"},{"fullName":"HSUIFilePicker.canChooseFiles(value)","description":"Set whether files can be selected","url":"HSUIFilePicker.html#canChooseFiles","kind":"method"},{"fullName":"HSUIFilePicker.canChooseDirectories(value)","description":"Set whether directories can be selected","url":"HSUIFilePicker.html#canChooseDirectories","kind":"method"},{"fullName":"HSUIFilePicker.allowsMultipleSelection(value)","description":"Set whether multiple items can be selected","url":"HSUIFilePicker.html#allowsMultipleSelection","kind":"method"},{"fullName":"HSUIFilePicker.allowedFileTypes(types)","description":"Restrict to specific file types","url":"HSUIFilePicker.html#allowedFileTypes","kind":"method"},{"fullName":"HSUIFilePicker.resolvesAliases(value)","description":"Set whether to resolve symbolic links","url":"HSUIFilePicker.html#resolvesAliases","kind":"method"},{"fullName":"HSUIFilePicker.onSelection(callback)","description":"Set the callback for file selection","url":"HSUIFilePicker.html#onSelection","kind":"method"},{"fullName":"HSUIFilePicker.show()","description":"Show the file picker dialog","url":"HSUIFilePicker.html#show","kind":"method"},{"fullName":"HSUITextPrompt","description":"# HSUITextPrompt A modal dialog with text input Shows a blocking dialog with a text input field. The callback receives both the button index and the entered text. ## Example ``javascript hs.ui.textPrompt(\"Enter your name\") .informativeText(\"Please provide your full name\") .defaultText(\"John Doe\") .buttons([\"OK\", \"Cancel\"]) .onButton((buttonIndex, text) => { if (buttonIndex === 0) { console.log(\"User entered: \" + text); } }) .show(); ``","url":"HSUITextPrompt.html","kind":"type"},{"fullName":"HSUITextPrompt.informativeText(text)","description":"Set additional informative text below the main message","url":"HSUITextPrompt.html#informativeText","kind":"method"},{"fullName":"HSUITextPrompt.defaultText(text)","description":"Set the default text in the input field","url":"HSUITextPrompt.html#defaultText","kind":"method"},{"fullName":"HSUITextPrompt.buttons(labels)","description":"Set custom button labels","url":"HSUITextPrompt.html#buttons","kind":"method"},{"fullName":"HSUITextPrompt.onButton(callback)","description":"Set the callback for button presses","url":"HSUITextPrompt.html#onButton","kind":"method"},{"fullName":"HSUITextPrompt.show()","description":"Show the prompt dialog","url":"HSUITextPrompt.html#show","kind":"method"},{"fullName":"UIWebView","description":"# hs.ui.webview A web browser element for embedding in hs.ui.window layouts Available on macOS 26.0 or later, hs.ui.webview() creates a web browser element backed by a SwiftUI WebView and WebPage. Embed it in any hs.ui.window using .webview(element) — it fills the available space and can sit alongside other elements in stacks. ``javascript const wv = hs.ui.webview() .toolbar([\"back\", \"forward\", \"reload\", \"url\"]) .loadURL(\"https://apple.com\")","url":"UIWebView.html","kind":"type"},{"fullName":"UIWebView.url","description":"The URL of the current page, or null if no page is loaded","url":"UIWebView.html#url","kind":"property"},{"fullName":"UIWebView.title","description":"The title of the current page","url":"UIWebView.html#title","kind":"property"},{"fullName":"UIWebView.isLoading","description":"Whether the web view is currently loading a page","url":"UIWebView.html#isLoading","kind":"property"},{"fullName":"UIWebView.estimatedProgress","description":"The estimated loading progress from 0.0 to 1.0","url":"UIWebView.html#estimatedProgress","kind":"property"},{"fullName":"UIWebView.canGoBack","description":"Whether the web view can navigate back in history","url":"UIWebView.html#canGoBack","kind":"property"},{"fullName":"UIWebView.canGoForward","description":"Whether the web view can navigate forward in history","url":"UIWebView.html#canGoForward","kind":"property"},{"fullName":"UIWebView.loadURL(urlString)","description":"Load a URL in the web view","url":"UIWebView.html#loadURL","kind":"method"},{"fullName":"UIWebView.loadHTML(html)","description":"Load an HTML string directly into the web view","url":"UIWebView.html#loadHTML","kind":"method"},{"fullName":"UIWebView.goBack()","description":"Navigate back in the browser history","url":"UIWebView.html#goBack","kind":"method"},{"fullName":"UIWebView.goForward()","description":"Navigate forward in the browser history","url":"UIWebView.html#goForward","kind":"method"},{"fullName":"UIWebView.reload()","description":"Reload the current page","url":"UIWebView.html#reload","kind":"method"},{"fullName":"UIWebView.stopLoading()","description":"Stop loading the current page","url":"UIWebView.html#stopLoading","kind":"method"},{"fullName":"UIWebView.userAgent(ua)","description":"Set a custom User-Agent string for HTTP requests","url":"UIWebView.html#userAgent","kind":"method"},{"fullName":"UIWebView.inspectable(value)","description":"Enable or disable the Safari Web Inspector for this web view When enabled, the web view appears in Safari → Develop menu.","url":"UIWebView.html#inspectable","kind":"method"},{"fullName":"UIWebView.toolbar(items)","description":"Configure the toolbar with a list of standard and custom items The toolbar renders above the web view. Each element of the array is either a string naming a standard control or a dictionary describing a custom button. An empty array (or omitting this call) hides the toolbar. Standard string items: \"back\", \"forward\", \"reload\", \"url\", \"spacer\".","url":"UIWebView.html#toolbar","kind":"method"},{"fullName":"UIWebView.backForwardGestures(enabled)","description":"Enable or disable the macOS back/forward trackpad swipe gestures Gestures are enabled by default. Pass false to disable them.","url":"UIWebView.html#backForwardGestures","kind":"method"},{"fullName":"UIWebView.magnificationGestures(enabled)","description":"Enable or disable the trackpad pinch-to-zoom magnification gesture The gesture is enabled by default. Pass false to disable it.","url":"UIWebView.html#magnificationGestures","kind":"method"},{"fullName":"UIWebView.linkPreviews(enabled)","description":"Enable or disable link preview popovers shown on force-click Link previews are enabled by default. Pass false to disable them.","url":"UIWebView.html#linkPreviews","kind":"method"},{"fullName":"UIWebView.contentBackground(visible)","description":"Control whether the web page background is visible Pass false to make the web view background transparent. Enabled (visible) by default.","url":"UIWebView.html#contentBackground","kind":"method"},{"fullName":"UIWebView.onLoadChange(callback)","description":"Register a callback that fires when loading state or progress changes Called whenever isLoading, url, title, or estimatedProgress changes.","url":"UIWebView.html#onLoadChange","kind":"method"},{"fullName":"UIWebView.onNavigate(callback)","description":"Register a callback that fires when navigation to a new page completes","url":"UIWebView.html#onNavigate","kind":"method"},{"fullName":"UIWebView.onTitleChange(callback)","description":"Register a callback that fires when the page title changes","url":"UIWebView.html#onTitleChange","kind":"method"},{"fullName":"UIWebView.onNavigationDecision(callback)","description":"Register a callback that controls whether navigation is allowed Called before each navigation. Return true to allow or false to block.","url":"UIWebView.html#onNavigationDecision","kind":"method"},{"fullName":"UIWebView.execJS(script)","description":"Execute JavaScript in the web page without capturing the result","url":"UIWebView.html#execJS","kind":"method"},{"fullName":"UIWebView.evalJSResult(script, callback)","description":"Execute JavaScript in the web page and deliver the result to a callback The JavaScript method name is evalJSResult — it derives from the internal Objective-C selector evalJS:result:.","url":"UIWebView.html#evalJSResult","kind":"method"},{"fullName":"HSWifiWatcher","description":"A Wi-Fi event watcher that monitors changes to a Wi-Fi interface. Create via hs.wifi.addWatcher(). Set a callback with setCallback(), then call start() to begin receiving events. By default only \"ssidChange\" is watched; use the events property to watch other event types. | Event | Info keys | |-------|-----------| | \"ssidChange\" | interface: string | | \"bssidChange\" | interface: string | | \"countryCodeChange\" | interface: string | | \"linkChange\" | interface: string | | \"linkQualityChange\" | interface: string, rssi: number, transmitRate: number | | \"modeChange\" | interface: string | | \"powerChange\" | interface: string | | \"scanCacheUpdated\" | interface: string |","url":"HSWifiWatcher.html","kind":"type"},{"fullName":"HSWifiWatcher.identifier","description":"The unique identifier assigned to this watcher.","url":"HSWifiWatcher.html#identifier","kind":"property"},{"fullName":"HSWifiWatcher.events","description":"The event types this watcher will invoke its callback for. Defaults to [\"ssidChange\"]. Unrecognized values are ignored with a console warning; see hs.wifi.watcherEventTypes for the list of valid values. Can be changed while the watcher is running.","url":"HSWifiWatcher.html#events","kind":"property"},{"fullName":"HSWifiWatcher.start()","description":"Starts monitoring the event types configured in events.","url":"HSWifiWatcher.html#start","kind":"method"},{"fullName":"HSWifiWatcher.stop()","description":"Stops monitoring Wi-Fi events.","url":"HSWifiWatcher.html#stop","kind":"method"},{"fullName":"HSWifiWatcher.setCallback(fn)","description":"Sets the callback function invoked when a watched Wi-Fi event occurs.","url":"HSWifiWatcher.html#setCallback","kind":"method"},{"fullName":"HSWifiWatcher.destroy()","description":"Stops the watcher and releases all resources. Called automatically during shutdown.","url":"HSWifiWatcher.html#destroy","kind":"method"},{"fullName":"HSWindow","description":"Object representing a window. You should not instantiate these directly, but rather, use the methods in hs.window to create them for you. Note that this type uses private macOS APIs","url":"HSWindow.html","kind":"type"},{"fullName":"HSWindow.title","description":"The window's title","url":"HSWindow.html#title","kind":"property"},{"fullName":"HSWindow.application","description":"The application that owns this window","url":"HSWindow.html#application","kind":"property"},{"fullName":"HSWindow.pid","description":"The process ID of the application that owns this window","url":"HSWindow.html#pid","kind":"property"},{"fullName":"HSWindow.id","description":"The window's underlying ID. A value of 0 or -1 likely means no window ID could be determined.","url":"HSWindow.html#id","kind":"property"},{"fullName":"HSWindow.isMinimized","description":"Whether the window is minimized","url":"HSWindow.html#isMinimized","kind":"property"},{"fullName":"HSWindow.isVisible","description":"Whether the window is visible (not minimized or hidden)","url":"HSWindow.html#isVisible","kind":"property"},{"fullName":"HSWindow.isFocused","description":"Whether the window is focused","url":"HSWindow.html#isFocused","kind":"property"},{"fullName":"HSWindow.isFullscreen","description":"Whether the window is fullscreen","url":"HSWindow.html#isFullscreen","kind":"property"},{"fullName":"HSWindow.isStandard","description":"Whether the window is standard (has a titlebar)","url":"HSWindow.html#isStandard","kind":"property"},{"fullName":"HSWindow.position","description":"The window's position on screen {x: Int, y: Int}","url":"HSWindow.html#position","kind":"property"},{"fullName":"HSWindow.size","description":"The window's size {w: Int, h: Int}","url":"HSWindow.html#size","kind":"property"},{"fullName":"HSWindow.frame","description":"The window's frame {x: Int, y: Int, w: Int, h: Int}","url":"HSWindow.html#frame","kind":"property"},{"fullName":"HSWindow.screen","description":"The screen that contains the largest portion of this window.","url":"HSWindow.html#screen","kind":"property"},{"fullName":"HSWindow.focus()","description":"Focus this window","url":"HSWindow.html#focus","kind":"method"},{"fullName":"HSWindow.minimize()","description":"Minimize this window","url":"HSWindow.html#minimize","kind":"method"},{"fullName":"HSWindow.unminimize()","description":"Unminimize this window","url":"HSWindow.html#unminimize","kind":"method"},{"fullName":"HSWindow.raise()","description":"Raise this window to the front","url":"HSWindow.html#raise","kind":"method"},{"fullName":"HSWindow.toggleFullscreen()","description":"Toggle fullscreen mode","url":"HSWindow.html#toggleFullscreen","kind":"method"},{"fullName":"HSWindow.close()","description":"Close this window","url":"HSWindow.html#close","kind":"method"},{"fullName":"HSWindow.centerOnScreen()","description":"Center the window on the screen","url":"HSWindow.html#centerOnScreen","kind":"method"},{"fullName":"HSWindow.axElement()","description":"Get the underlying AXElement","url":"HSWindow.html#axElement","kind":"method"},{"fullName":"HSColor","description":"Bridge type for working with colors in JavaScript","url":"HSColor.html","kind":"type"},{"fullName":"HSColor.rgb(r, g, b, a)","description":"Create a color from RGB values","url":"HSColor.html#rgb","kind":"method"},{"fullName":"HSColor.hex(hex)","description":"Create a color from a hex string","url":"HSColor.html#hex","kind":"method"},{"fullName":"HSColor.named(name)","description":"Create a color from a named system color","url":"HSColor.html#named","kind":"method"},{"fullName":"HSColor.set(value)","description":"Update this color's value. If this color is bound to a UI element, the canvas re-renders automatically.","url":"HSColor.html#set","kind":"method"},{"fullName":"HSFont","description":"This is a JavaScript object used to represent macOS fonts. It includes a variety of static methods that can instantiate the various font sizes commonly used with UI elements, and also includes static methods for instantiating the system font at various sizes/weights, or any custom font available on the system.","url":"HSFont.html","kind":"type"},{"fullName":"HSFont.body()","description":"Body text style","url":"HSFont.html#body","kind":"method"},{"fullName":"HSFont.callout()","description":"Callout text style","url":"HSFont.html#callout","kind":"method"},{"fullName":"HSFont.caption()","description":"Caption text style","url":"HSFont.html#caption","kind":"method"},{"fullName":"HSFont.caption2()","description":"Caption2 text style","url":"HSFont.html#caption2","kind":"method"},{"fullName":"HSFont.footnote()","description":"Footnote text style","url":"HSFont.html#footnote","kind":"method"},{"fullName":"HSFont.headline()","description":"Headline text style","url":"HSFont.html#headline","kind":"method"},{"fullName":"HSFont.largeTitle()","description":"Large Title text style","url":"HSFont.html#largeTitle","kind":"method"},{"fullName":"HSFont.subheadline()","description":"Sub-headline text style","url":"HSFont.html#subheadline","kind":"method"},{"fullName":"HSFont.title()","description":"Title text style","url":"HSFont.html#title","kind":"method"},{"fullName":"HSFont.title2()","description":"Title2 text style","url":"HSFont.html#title2","kind":"method"},{"fullName":"HSFont.title3()","description":"Title3 text style","url":"HSFont.html#title3","kind":"method"},{"fullName":"HSFont.system(size)","description":"The system font in a custom size","url":"HSFont.html#system","kind":"method"},{"fullName":"HSFont.system(size, weight)","description":"The system font in a custom size with a choice of weights","url":"HSFont.html#system","kind":"method"},{"fullName":"HSFont.custom(name, size)","description":"A font present on the system at a given size","url":"HSFont.html#custom","kind":"method"},{"fullName":"HSImage","description":"Bridge type for working with images in JavaScript HSImage provides a comprehensive API for loading, manipulating, and saving images. It supports various image sources including files, system icons, app bundles, and URLs. ## Loading Images ``javascript // Load from file const img = HSImage.fromPath(\"/path/to/image.png\")","url":"HSImage.html","kind":"type"},{"fullName":"HSImage.size","description":"The size of the image. Setting this resizes the image in place to the exact dimensions.","url":"HSImage.html#size","kind":"property"},{"fullName":"HSImage.name","description":"The name of the image, or null if not set.","url":"HSImage.html#name","kind":"property"},{"fullName":"HSImage.template","description":"Whether the image is a template image. Template images are tinted by the system to match the appearance context (e.g. menu bar icons).","url":"HSImage.html#template","kind":"property"},{"fullName":"HSImage.fromPath(path)","description":"Load an image from a file path","url":"HSImage.html#fromPath","kind":"method"},{"fullName":"HSImage.fromName(name)","description":"Load a system image by name","url":"HSImage.html#fromName","kind":"method"},{"fullName":"HSImage.fromSymbol(name)","description":"Load a system symbol by name","url":"HSImage.html#fromSymbol","kind":"method"},{"fullName":"HSImage.fromAppBundle(bundleID, withFallbackSymbol)","description":"Load an app's icon by bundle identifier","url":"HSImage.html#fromAppBundle","kind":"method"},{"fullName":"HSImage.iconForFile(path)","description":"Get the icon for a file","url":"HSImage.html#iconForFile","kind":"method"},{"fullName":"HSImage.iconForFileType(fileType)","description":"Get the icon for a file type","url":"HSImage.html#iconForFileType","kind":"method"},{"fullName":"HSImage.fromURL(url)","description":"Load an image from a URL (asynchronous)","url":"HSImage.html#fromURL","kind":"method"},{"fullName":"HSImage.copyImage()","description":"Create a copy of the image","url":"HSImage.html#copyImage","kind":"method"},{"fullName":"HSImage.croppedCopy(rect)","description":"Create a cropped copy of the image","url":"HSImage.html#croppedCopy","kind":"method"},{"fullName":"HSImage.saveToFile(path)","description":"Save the image to a file","url":"HSImage.html#saveToFile","kind":"method"},{"fullName":"HSImage.set(value)","description":"Replace this image's content. If this image is bound to a UI element, the canvas re-renders automatically.","url":"HSImage.html#set","kind":"method"},{"fullName":"HSPoint","description":"This is a JavaScript object used to represent coordinates, or \"points\", as used in various places throughout Hammerspoon's API, particularly where dealing with positions on a screen. Behind the scenes it is a wrapper for the CGPoint type in Swift/ObjectiveC.","url":"HSPoint.html","kind":"type"},{"fullName":"HSPoint.x","description":"A coordinate for the x-axis position of this point","url":"HSPoint.html#x","kind":"property"},{"fullName":"HSPoint.y","description":"A coordinate for the y-axis position of this point","url":"HSPoint.html#y","kind":"property"},{"fullName":"HSPoint.angle()","description":"Returns the angle between the positive x axis and this point, treated as a vector","url":"HSPoint.html#angle","kind":"method"},{"fullName":"HSPoint.angleTo(other)","description":"Returns the angle between the positive x axis and the vector from this point to another point or rect's center","url":"HSPoint.html#angleTo","kind":"method"},{"fullName":"HSPoint.distance(other)","description":"Finds the distance between this point and another point or rect's center","url":"HSPoint.html#distance","kind":"method"},{"fullName":"HSPoint.equals(other)","description":"Checks if this point is equal to another point","url":"HSPoint.html#equals","kind":"method"},{"fullName":"HSPoint.floor()","description":"Truncates the coordinates of this point towards negative infinity","url":"HSPoint.html#floor","kind":"method"},{"fullName":"HSPoint.inside(rect)","description":"Checks if this point lies inside a given rect","url":"HSPoint.html#inside","kind":"method"},{"fullName":"HSPoint.move(offset)","description":"Moves this point by an offset","url":"HSPoint.html#move","kind":"method"},{"fullName":"HSPoint.normalize()","description":"Normalizes this point, treated as a vector, to a length of 1","url":"HSPoint.html#normalize","kind":"method"},{"fullName":"HSPoint.rotateCCW(aroundPoint, times)","description":"Rotates this point counter-clockwise around another point","url":"HSPoint.html#rotateCCW","kind":"method"},{"fullName":"HSPoint.scale(factor)","description":"Scales this point, treated as a vector","url":"HSPoint.html#scale","kind":"method"},{"fullName":"HSPoint.vector(other)","description":"Returns the vector from this point to another point or rect's center","url":"HSPoint.html#vector","kind":"method"},{"fullName":"HSRect","description":"This is a JavaScript object used to represent a rectangle, as used in various places throughout Hammerspoon's API, particularly where dealing with portions of a display. Behind the scenes it is a wrapper for the CGRect type in Swift/ObjectiveC.","url":"HSRect.html","kind":"type"},{"fullName":"HSRect.x","description":"An x-axis coordinate for the top-left point of the rectangle","url":"HSRect.html#x","kind":"property"},{"fullName":"HSRect.y","description":"A y-axis coordinate for the top-left point of the rectangle","url":"HSRect.html#y","kind":"property"},{"fullName":"HSRect.w","description":"The width of the rectangle","url":"HSRect.html#w","kind":"property"},{"fullName":"HSRect.h","description":"The height of the rectangle","url":"HSRect.html#h","kind":"property"},{"fullName":"HSRect.origin","description":"The \"origin\" of the rectangle, ie the coordinates of its top left corner, as an HSPoint object","url":"HSRect.html#origin","kind":"property"},{"fullName":"HSRect.size","description":"The size of the rectangle, ie its width and height, as an HSSize object","url":"HSRect.html#size","kind":"property"},{"fullName":"HSRect.angleTo(other)","description":"Returns the angle between the positive x axis and the vector from this rect's center to another point or rect's center","url":"HSRect.html#angleTo","kind":"method"},{"fullName":"HSRect.distance(other)","description":"Finds the distance between this rect's center and another point or rect's center","url":"HSRect.html#distance","kind":"method"},{"fullName":"HSRect.equals(other)","description":"Checks if this rect is equal to another rect","url":"HSRect.html#equals","kind":"method"},{"fullName":"HSRect.fit(bounds)","description":"Ensures this rect is fully inside bounds, scaling it down (preserving aspect ratio) if it's larger, and moving it if necessary","url":"HSRect.html#fit","kind":"method"},{"fullName":"HSRect.floor()","description":"Truncates the origin and size of this rect towards negative infinity","url":"HSRect.html#floor","kind":"method"},{"fullName":"HSRect.fromUnitRect(frame)","description":"Converts a unit rect (coordinates and dimensions between 0 and 1) within a given frame into absolute coordinates","url":"HSRect.html#fromUnitRect","kind":"method"},{"fullName":"HSRect.inside(rect)","description":"Checks if this rect lies fully inside another rect","url":"HSRect.html#inside","kind":"method"},{"fullName":"HSRect.intersect(rect)","description":"Returns the intersection of this rect and another rect","url":"HSRect.html#intersect","kind":"method"},{"fullName":"HSRect.move(offset)","description":"Moves this rect by an offset","url":"HSRect.html#move","kind":"method"},{"fullName":"HSRect.scale(factor)","description":"Scales the size of this rect, keeping its center constant","url":"HSRect.html#scale","kind":"method"},{"fullName":"HSRect.toUnitRect(frame)","description":"Converts this rect into a unit rect (coordinates and dimensions between 0 and 1) within a given frame","url":"HSRect.html#toUnitRect","kind":"method"},{"fullName":"HSRect.union(rect)","description":"Returns the smallest rect that encloses both this rect and another rect","url":"HSRect.html#union","kind":"method"},{"fullName":"HSRect.vector(other)","description":"Returns the vector from this rect's center to another point or rect's center","url":"HSRect.html#vector","kind":"method"},{"fullName":"HSSize","description":"This is a JavaScript object used to represent the size of a rectangle, as used in various places throughout Hammerspoon's API, particularly where dealing with portions of a display. Behind the scenes it is a wrapper for the CGSize type in Swift/ObjectiveC.","url":"HSSize.html","kind":"type"},{"fullName":"HSSize.w","description":"The width of the rectangle","url":"HSSize.html#w","kind":"property"},{"fullName":"HSSize.h","description":"The height of the rectangle","url":"HSSize.html#h","kind":"property"},{"fullName":"HSSize.angle()","description":"Returns the angle between the positive x axis and this size, treated as a vector of (w, h)","url":"HSSize.html#angle","kind":"method"},{"fullName":"HSSize.equals(other)","description":"Checks if this size is equal to another size","url":"HSSize.html#equals","kind":"method"},{"fullName":"HSSize.floor()","description":"Truncates the width and height of this size towards negative infinity","url":"HSSize.html#floor","kind":"method"},{"fullName":"HSSize.scale(factor)","description":"Scales this size","url":"HSSize.html#scale","kind":"method"},{"fullName":"HSString","description":"A reactive string container. Pass to .text() to get automatic re-renders when .set() is called from JavaScript.","url":"HSString.html","kind":"type"},{"fullName":"HSString.value","description":"The current string value","url":"HSString.html#value","kind":"property"},{"fullName":"HSString.set(newValue)","description":"Update the string value, triggering a re-render if bound to a UI element","url":"HSString.html#set","kind":"method"},{"fullName":"HSVideo","description":"Bridge type for working with video playback in JavaScript HSVideo wraps an AVQueuePlayer and can be embedded in an hs.ui.window via .video(), or driven entirely from JavaScript with play(), pause(), seek(), loop(), and volume. ## Loading Video Each entry may be a local file path (~ is expanded) or a remote URL string. Multiple entries are queued and play back to back, in order. ``javascript // A single local file const clip = HSVideo.fromURLs([\"~/Movies/clip.mp4\"])","url":"HSVideo.html","kind":"type"},{"fullName":"HSVideo.volume","description":"The playback volume, from 0.0 (silent) to 1.0 (full volume)","url":"HSVideo.html#volume","kind":"property"},{"fullName":"HSVideo.fromURLs(urls)","description":"Load a playlist of videos to play back to back, in order","url":"HSVideo.html#fromURLs","kind":"method"},{"fullName":"HSVideo.play()","description":"Start (or resume) playback","url":"HSVideo.html#play","kind":"method"},{"fullName":"HSVideo.pause()","description":"Pause playback","url":"HSVideo.html#pause","kind":"method"},{"fullName":"HSVideo.seek(seconds)","description":"Seek to a specific position","url":"HSVideo.html#seek","kind":"method"},{"fullName":"HSVideo.loop(enabled)","description":"Enable or disable gapless looping Only supported when this HSVideo was created from a single-URL playlist. Enabling loop on a multi-URL playlist has no effect and logs a warning.","url":"HSVideo.html#loop","kind":"method"}]; +const searchIndex = [{"fullName":"hs.canvas","description":"A complete guide to hs.canvas: the element/property reference, the action pipeline, and worked examples combining shapes, text, images, gradients, and mouse interaction.","url":"canvas-guide.html","kind":"guide"},{"fullName":"Spoons","description":"How to install, use, and write Spoons - packaged, reusable pieces of Hammerspoon 2 configuration.","url":"spoons-guide.html","kind":"guide"},{"fullName":"Migrating from Hammerspoon 1","description":"A guide for Hammerspoon 1 users on what changed, what moved, and what was removed in Hammerspoon 2.","url":"migration-guide.html","kind":"guide"},{"fullName":"Getting Started","description":"A guide to your first Hammerspoon 2 config: hotkeys, object lifecycle, watchers, and hs.ui.","url":"getting-started.html","kind":"guide"},{"fullName":"console","description":"These functions are provided to maintain convenience with the console.log() function present in many JavaScript instances.","url":"console.html","kind":"module"},{"fullName":"console.log(message)","description":"Log a message to the Hammerspoon Log Window","url":"console.html#log","kind":"method"},{"fullName":"console.error(message)","description":"Log an error to the Hammerspoon Log Window","url":"console.html#error","kind":"method"},{"fullName":"console.warn(message)","description":"Log a warning to the Hammerspoon Log WIndow","url":"console.html#warn","kind":"method"},{"fullName":"console.info(message)","description":"Log an informational message to the Hammerspoon Log Window","url":"console.html#info","kind":"method"},{"fullName":"console.debug(message)","description":"Log a debug message to the Hammerspoon Log Window","url":"console.html#debug","kind":"method"},{"fullName":"hs","description":"","url":"hs.html","kind":"module"},{"fullName":"hs.spoons","description":"A namespace holding every Spoon loaded so far via loadSpoon(), keyed by name - e.g. a Spoon loaded with hs.loadSpoon(\"MySpoon\") is also reachable as hs.spoons.MySpoon. Empty until at least one Spoon has been loaded.","url":"hs.html#spoons","kind":"property"},{"fullName":"hs.reload()","description":"Destroy the current JavaScript runtime and start a new one, loading all configuration from disk again","url":"hs.html#reload","kind":"method"},{"fullName":"hs.collectGarbage()","description":"Force garbage collection of JavaScript objects that no longer have any references","url":"hs.html#collectGarbage","kind":"method"},{"fullName":"hs.openConsole()","description":"Open the Hammerspoon Console window","url":"hs.html#openConsole","kind":"method"},{"fullName":"hs.closeConsole()","description":"Close the Hammerspoon Console window","url":"hs.html#closeConsole","kind":"method"},{"fullName":"hs.clearConsole()","description":"Clear the Hammerspoon Console log","url":"hs.html#clearConsole","kind":"method"},{"fullName":"hs.loadSpoon(name)","description":"Load a Spoon - a packaged, reusable piece of configuration - by name, from the Spoons directory inside your config directory. A Spoon must contain a well-formed spoon.json (with non-empty name, author, version, and description fields) and an init.js, or loading fails with an exception. init.js is loaded through the same require() used for the rest of your config, so it can itself require() further files from within the Spoon's own directory using relative paths. On success, the Spoon's module.exports is also stored on hs.spoons under its name, so other code can reach an already-loaded Spoon without needing to call loadSpoon() again. init.js must set module.exports to an object (or a function, since functions are objects too) - loading fails with an exception otherwise. Its author, description, and version properties are then set from spoon.json, overwriting any of the same name the Spoon's own init.js set, so that information is always present and always reflects what's on disk. If the resulting object has an init() method, it's called automatically (with this bound to the object) before loadSpoon() returns - matching Hammerspoon 1's behavior. An exception thrown from init() fails the load: nothing is stored on hs.spoons, and loadSpoon() throws. Unlike init.js itself (which require() only ever evaluates once), init() runs again on every loadSpoon() call for the same Spoon, since the same cached object is returned each time - write it to be safe to call more than once, or do one-time setup at init.js's top level instead.","url":"hs.html#loadSpoon","kind":"method"},{"fullName":"hs.appinfo","description":"Module for accessing information about the Hammerspoon application itself","url":"hs.appinfo.html","kind":"module"},{"fullName":"hs.appinfo.appName","description":"The application's internal name (e.g., \"Hammerspoon 2\")","url":"hs.appinfo.html#appName","kind":"property"},{"fullName":"hs.appinfo.displayName","description":"The application's display name shown to users","url":"hs.appinfo.html#displayName","kind":"property"},{"fullName":"hs.appinfo.version","description":"The application's version string (e.g., \"2.0.0\")","url":"hs.appinfo.html#version","kind":"property"},{"fullName":"hs.appinfo.build","description":"The application's build number","url":"hs.appinfo.html#build","kind":"property"},{"fullName":"hs.appinfo.minimumOSVersion","description":"The minimum macOS version required to run this application","url":"hs.appinfo.html#minimumOSVersion","kind":"property"},{"fullName":"hs.appinfo.copyrightNotice","description":"The copyright notice for this application","url":"hs.appinfo.html#copyrightNotice","kind":"property"},{"fullName":"hs.appinfo.bundleIdentifier","description":"The application's bundle identifier (e.g., \"com.hammerspoon.Hammerspoon-2\")","url":"hs.appinfo.html#bundleIdentifier","kind":"property"},{"fullName":"hs.appinfo.bundlePath","description":"The filesystem path to the application bundle","url":"hs.appinfo.html#bundlePath","kind":"property"},{"fullName":"hs.appinfo.resourcePath","description":"The filesystem path to the application's resource directory","url":"hs.appinfo.html#resourcePath","kind":"property"},{"fullName":"hs.appinfo.configPath","description":"The filesystem path to the main Hammerspoon 2 configuration file","url":"hs.appinfo.html#configPath","kind":"property"},{"fullName":"hs.appinfo.configDir","description":"The filesystem path to the directory Hammerspoon 2 loaded its config from","url":"hs.appinfo.html#configDir","kind":"property"},{"fullName":"hs.appinfo.machineName","description":"The user-assigned name of this Mac, as shown in System Settings > Sharing","url":"hs.appinfo.html#machineName","kind":"property"},{"fullName":"hs.appinfo.pid","description":"Hammerspoon 2's Process Identifier (PID)","url":"hs.appinfo.html#pid","kind":"property"},{"fullName":"hs.appinfo.arguments","description":"The command-line arguments Hammerspoon 2 was launched with","url":"hs.appinfo.html#arguments","kind":"property"},{"fullName":"hs.appinfo.environment","description":"The environment variables Hammerspoon 2 was launched with","url":"hs.appinfo.html#environment","kind":"property"},{"fullName":"hs.appinfo.osVersion","description":"The version of macOS Hammerspoon 2 is currently running on (e.g., \"Version 26.5.2 (Build 25F84)\")","url":"hs.appinfo.html#osVersion","kind":"property"},{"fullName":"hs.appinfo.osVersionParts","description":"The version of macOS Hammerspoon 2 is currently running on, broken into its numeric components Keys: major, minor, patch.","url":"hs.appinfo.html#osVersionParts","kind":"property"},{"fullName":"hs.appinfo.cpuCount","description":"The number of logical CPU cores available on this Mac","url":"hs.appinfo.html#cpuCount","kind":"property"},{"fullName":"hs.appinfo.ramAmount","description":"The amount of physical RAM installed on this Mac, in gigabytes","url":"hs.appinfo.html#ramAmount","kind":"property"},{"fullName":"hs.application","description":"Module for interacting with applications","url":"hs.application.html","kind":"module"},{"fullName":"hs.application.runningApplications()","description":"Fetch all running applications","url":"hs.application.html#runningApplications","kind":"method"},{"fullName":"hs.application.matchingName(name)","description":"Fetch the first running application that matches a name","url":"hs.application.html#matchingName","kind":"method"},{"fullName":"hs.application.matchingBundleID(bundleID)","description":"Fetch the first running application that matches a Bundle ID","url":"hs.application.html#matchingBundleID","kind":"method"},{"fullName":"hs.application.fromPID(pid)","description":"Fetch the running application that matches a POSIX PID","url":"hs.application.html#fromPID","kind":"method"},{"fullName":"hs.application.frontmost()","description":"Fetch the currently focused application","url":"hs.application.html#frontmost","kind":"method"},{"fullName":"hs.application.menuBarOwner()","description":"Fetch the application which currently owns the menu bar","url":"hs.application.html#menuBarOwner","kind":"method"},{"fullName":"hs.application.pathForBundleID(bundleID)","description":"Fetch the filesystem path for an application","url":"hs.application.html#pathForBundleID","kind":"method"},{"fullName":"hs.application.pathsForBundleID(bundleID)","description":"Fetch filesystem paths for an application","url":"hs.application.html#pathsForBundleID","kind":"method"},{"fullName":"hs.application.pathForFileType(fileType)","description":"Fetch filesystem path for an application able to open a given file type","url":"hs.application.html#pathForFileType","kind":"method"},{"fullName":"hs.application.pathsForFileType(fileType)","description":"Fetch filesystem paths for applications able to open a given file type","url":"hs.application.html#pathsForFileType","kind":"method"},{"fullName":"hs.application.launchOrFocus(bundleID)","description":"Launch an application, or give it focus if it's already running","url":"hs.application.html#launchOrFocus","kind":"method"},{"fullName":"hs.application.addWatcher(listener)","description":"Create a watcher for application events","url":"hs.application.html#addWatcher","kind":"method"},{"fullName":"hs.application.removeWatcher(listener)","description":"Remove a watcher for application events","url":"hs.application.html#removeWatcher","kind":"method"},{"fullName":"hs.audiodevice","description":"Module for discovering and controlling audio devices.","url":"hs.audiodevice.html","kind":"module"},{"fullName":"hs.audiodevice.all()","description":"All audio devices attached to the system.","url":"hs.audiodevice.html#all","kind":"method"},{"fullName":"hs.audiodevice.allOutputDevices()","description":"All audio devices that have at least one output stream.","url":"hs.audiodevice.html#allOutputDevices","kind":"method"},{"fullName":"hs.audiodevice.allInputDevices()","description":"All audio devices that have at least one input stream.","url":"hs.audiodevice.html#allInputDevices","kind":"method"},{"fullName":"hs.audiodevice.defaultOutputDevice()","description":"The current system default output device.","url":"hs.audiodevice.html#defaultOutputDevice","kind":"method"},{"fullName":"hs.audiodevice.defaultInputDevice()","description":"The current system default input device.","url":"hs.audiodevice.html#defaultInputDevice","kind":"method"},{"fullName":"hs.audiodevice.defaultEffectDevice()","description":"The current system alert sound device.","url":"hs.audiodevice.html#defaultEffectDevice","kind":"method"},{"fullName":"hs.audiodevice.findDeviceByName(name)","description":"Find the first audio device whose name matches the given string.","url":"hs.audiodevice.html#findDeviceByName","kind":"method"},{"fullName":"hs.audiodevice.findDeviceByUID(uid)","description":"Find the audio device with the given unique identifier.","url":"hs.audiodevice.html#findDeviceByUID","kind":"method"},{"fullName":"hs.audiodevice.addWatcher(listener)","description":"Register a listener for all system-level audio configuration events.","url":"hs.audiodevice.html#addWatcher","kind":"method"},{"fullName":"hs.audiodevice.removeWatcher(listener)","description":"Remove a previously registered system-level listener.","url":"hs.audiodevice.html#removeWatcher","kind":"method"},{"fullName":"hs.ax","description":"# Accessibility API Module","url":"hs.ax.html","kind":"module"},{"fullName":"hs.ax.notificationTypes","description":"A dictionary containing all of the notification types that can be used with hs.ax.addWatcher()","url":"hs.ax.html#notificationTypes","kind":"property"},{"fullName":"hs.ax.systemWideElement()","description":"Get the system-wide accessibility element","url":"hs.ax.html#systemWideElement","kind":"method"},{"fullName":"hs.ax.applicationElement(element)","description":"Get the accessibility element for an application","url":"hs.ax.html#applicationElement","kind":"method"},{"fullName":"hs.ax.windowElement(window)","description":"Get the accessibility element for a window","url":"hs.ax.html#windowElement","kind":"method"},{"fullName":"hs.ax.elementAtPoint(point)","description":"Get the accessibility element at the specific screen position","url":"hs.ax.html#elementAtPoint","kind":"method"},{"fullName":"hs.ax.addWatcher(application, notification, listener)","description":"Add a watcher for application AX events","url":"hs.ax.html#addWatcher","kind":"method"},{"fullName":"hs.ax.removeWatcher(application, notification, listener)","description":"Remove a watcher for application AX events","url":"hs.ax.html#removeWatcher","kind":"method"},{"fullName":"hs.ax.focusedElement()","description":"Fetch the focused UI element","url":"hs.ax.html#focusedElement","kind":"method"},{"fullName":"hs.ax.findByRole(role, parent)","description":"Find AX elements matching a given role","url":"hs.ax.html#findByRole","kind":"method"},{"fullName":"hs.ax.findByTitle(title, parent)","description":"Find AX elements whose title contains a given string","url":"hs.ax.html#findByTitle","kind":"method"},{"fullName":"hs.ax.printHierarchy(element, maxDepth)","description":"Print the accessibility hierarchy of an element to the Console","url":"hs.ax.html#printHierarchy","kind":"method"},{"fullName":"hs.bonjour","description":"Discover and publish Bonjour (mDNS / Zeroconf) network services.","url":"hs.bonjour.html","kind":"module"},{"fullName":"hs.bonjour.serviceTypes","description":"A frozen object mapping short service-type names to their mDNS strings. Populated by the JavaScript enhancement layer.","url":"hs.bonjour.html#serviceTypes","kind":"property"},{"fullName":"hs.bonjour.createSearch()","description":"Creates a new Bonjour search for discovering services or domains. Call one of the find… methods on the returned search to start discovering. Remove it with removeSearch() when finished.","url":"hs.bonjour.html#createSearch","kind":"method"},{"fullName":"hs.bonjour.removeSearch(search)","description":"Stops and removes a previously created search.","url":"hs.bonjour.html#removeSearch","kind":"method"},{"fullName":"hs.bonjour.advertise(name, type, port, domain, callback)","description":"Starts advertising a local service on the network. If domain is omitted or not a string, it defaults to \"local.\". If the 4th argument is a function, it is used as the callback and domain defaults to \"local.\".","url":"hs.bonjour.html#advertise","kind":"method"},{"fullName":"hs.bonjour.stopAdvertising(name, type)","description":"Stops advertising a service previously started with advertise().","url":"hs.bonjour.html#stopAdvertising","kind":"method"},{"fullName":"hs.bonjour.networkServices(timeout)","description":"Returns a Promise that resolves to an array of service-type strings currently advertised on the local network. Internally searches for _services._dns-sd._udp. services, collects results for up to timeout seconds (or until the browser signals no more results), then resolves.","url":"hs.bonjour.html#networkServices","kind":"method"},{"fullName":"hs.camera","description":"Module for discovering and interacting with camera devices.","url":"hs.camera.html","kind":"module"},{"fullName":"hs.camera.all()","description":"All video camera devices currently connected to the system.","url":"hs.camera.html#all","kind":"method"},{"fullName":"hs.camera.findByName(name)","description":"Find the first camera whose name matches the given string.","url":"hs.camera.html#findByName","kind":"method"},{"fullName":"hs.camera.findByUID(uid)","description":"Find the camera with the given unique identifier.","url":"hs.camera.html#findByUID","kind":"method"},{"fullName":"hs.camera.addWatcher(listener)","description":"Register a listener for camera device connect/disconnect events.","url":"hs.camera.html#addWatcher","kind":"method"},{"fullName":"hs.camera.removeWatcher(listener)","description":"Remove a previously registered module-level event listener.","url":"hs.camera.html#removeWatcher","kind":"method"},{"fullName":"hs.canvas","description":"# hs.canvas","url":"hs.canvas.html","kind":"module"},{"fullName":"hs.canvas.windowLevels","description":"Named window levels, exposed as raw numeric values (not opaque strings) so scripts can do arithmetic on them, matching v1 behavior.","url":"hs.canvas.html#windowLevels","kind":"property"},{"fullName":"hs.canvas.windowBehaviors","description":"Named window Spaces/Exposé collection behaviors, exposed as raw numeric bit values.","url":"hs.canvas.html#windowBehaviors","kind":"property"},{"fullName":"hs.canvas.compositeTypes","description":"Named compositing/blend rules usable as an element's compositeRule attribute.","url":"hs.canvas.html#compositeTypes","kind":"property"},{"fullName":"hs.canvas.create(rect)","description":"Create a new canvas Named create() rather than v1's new() -- new cannot be used as a JavaScriptCore-exported method name (it collides with the JS new operator keyword at the bridging layer), and this codebase's conventions additionally forbid method names starting with new/alloc/copy (an ARC/ObjC hazard).","url":"hs.canvas.html#create","kind":"method"},{"fullName":"hs.chooser","description":"# hs.chooser","url":"hs.chooser.html","kind":"module"},{"fullName":"hs.chooser.create()","description":"Create a new chooser.","url":"hs.chooser.html#create","kind":"method"},{"fullName":"hs.docs","description":"# hs.docs","url":"hs.docs.html","kind":"module"},{"fullName":"hs.docs.show(moduleName, showTS)","description":"Open the Hammerspoon 2 API documentation in a new window","url":"hs.docs.html#show","kind":"method"},{"fullName":"hs.docs.get(identifier)","description":"Return documentation for a module, method, or property","url":"hs.docs.html#get","kind":"method"},{"fullName":"hs.docs.jsDocsPath()","description":"Return the filesystem path to the bundled JS documentation directory","url":"hs.docs.html#jsDocsPath","kind":"method"},{"fullName":"hs.docs.tsDocsPath()","description":"Return the filesystem path to the bundled TypeScript documentation directory","url":"hs.docs.html#tsDocsPath","kind":"method"},{"fullName":"hs.docs.apiJSON()","description":"Return the contents of the bundled api.json file","url":"hs.docs.html#apiJSON","kind":"method"},{"fullName":"hs.eventtap","description":"Monitor and synthesise macOS input events: keyboard, mouse, and scroll wheel.","url":"hs.eventtap.html","kind":"module"},{"fullName":"hs.eventtap.eventTypes","description":"A dictionary mapping event type names to their numeric values. Pass values from this dictionary to addWatcher() to specify which events to monitor.","url":"hs.eventtap.html#eventTypes","kind":"property"},{"fullName":"hs.eventtap.modifierFlags","description":"A dictionary mapping modifier key names to their bitmask values for use with rawFlags. Includes generic names (cmd, shift, alt, ctrl) and side-specific names (leftCmd, rightCmd, leftShift, rightShift, leftAlt, rightAlt, leftCtrl, rightCtrl) for distinguishing physical keys.","url":"hs.eventtap.html#modifierFlags","kind":"property"},{"fullName":"hs.eventtap.consume","description":"Return this from an event tap callback to suppress the event (prevent other apps from receiving it).","url":"hs.eventtap.html#consume","kind":"property"},{"fullName":"hs.eventtap.emit","description":"Return this from an event tap callback to allow the event to pass through to other applications.","url":"hs.eventtap.html#emit","kind":"property"},{"fullName":"hs.eventtap.addWatcher(types, callback, listenOnly)","description":"Create an event tap that calls a function for matching events. Call .start() to activate it. The callback receives an HSEventTapEvent. For modify taps (listenOnly omitted or false), return hs.eventtap.consume (false) to suppress the event or hs.eventtap.emit (true) to pass it through. For listen-only taps the callback's return value is ignored — events are always delivered to other applications. Requires Accessibility permission.","url":"hs.eventtap.html#addWatcher","kind":"method"},{"fullName":"hs.eventtap.removeWatcher(tap)","description":"Stop and remove a previously created watcher","url":"hs.eventtap.html#removeWatcher","kind":"method"},{"fullName":"hs.eventtap.makeKeyEvent(key, isDown)","description":"Create a keyboard event","url":"hs.eventtap.html#makeKeyEvent","kind":"method"},{"fullName":"hs.eventtap.makeKeyEventWithCode(keyCode, isDown)","description":"Create a keyboard event using a raw key code","url":"hs.eventtap.html#makeKeyEventWithCode","kind":"method"},{"fullName":"hs.eventtap.makeMouseEvent(type, x, y, button)","description":"Create a mouse event at the given position. Coordinates are in Hammerspoon screen coordinates (top-left origin of the primary display, y increases downward), matching the values returned by hs.screen.","url":"hs.eventtap.html#makeMouseEvent","kind":"method"},{"fullName":"hs.eventtap.makeScrollWheelEvent(deltaX, deltaY, x, y)","description":"Create a scroll wheel event at the given position. Coordinates are in Hammerspoon screen coordinates (top-left origin, y increases downward).","url":"hs.eventtap.html#makeScrollWheelEvent","kind":"method"},{"fullName":"hs.eventtap.keyStroke(mods, key)","description":"Send a key down and key up event with optional modifier keys. A 5 ms pause is inserted between the key-down and key-up events to improve compatibility with applications that miss very fast synthetic keystrokes.","url":"hs.eventtap.html#keyStroke","kind":"method"},{"fullName":"hs.eventtap.keyStrokes(text)","description":"Type a string of characters as individual key events. A 5 ms pause is inserted between each key-down and key-up event. This blocks the calling thread (the main thread) for the duration of typing — for long strings, prefer keyStrokesAsync() to avoid stalling the rest of Hammerspoon while typing.","url":"hs.eventtap.html#keyStrokes","kind":"method"},{"fullName":"hs.eventtap.keyStrokesAsync(text)","description":"Type a string of characters as individual key events, without blocking the main thread. Behaves like keyStrokes(), but the key events are posted from a background task, so JavaScript execution and the rest of Hammerspoon continue running while typing proceeds.","url":"hs.eventtap.html#keyStrokesAsync","kind":"method"},{"fullName":"hs.eventtap.leftClick(x, y)","description":"Post a left mouse button click at the given position. Coordinates are in Hammerspoon screen coordinates (top-left origin, y increases downward).","url":"hs.eventtap.html#leftClick","kind":"method"},{"fullName":"hs.eventtap.rightClick(x, y)","description":"Post a right mouse button click at the given position. Coordinates are in Hammerspoon screen coordinates (top-left origin, y increases downward).","url":"hs.eventtap.html#rightClick","kind":"method"},{"fullName":"hs.eventtap.doubleLeftClick(x, y)","description":"Post a left mouse button double-click at the given position. Coordinates are in Hammerspoon screen coordinates (top-left origin, y increases downward).","url":"hs.eventtap.html#doubleLeftClick","kind":"method"},{"fullName":"hs.eventtap.middleClick(x, y)","description":"Post a middle mouse button click at the given position. Coordinates are in Hammerspoon screen coordinates (top-left origin, y increases downward).","url":"hs.eventtap.html#middleClick","kind":"method"},{"fullName":"hs.eventtap.scrollWheel(deltaX, deltaY, x, y)","description":"Post a scroll wheel event at the given position. Coordinates are in Hammerspoon screen coordinates (top-left origin, y increases downward).","url":"hs.eventtap.html#scrollWheel","kind":"method"},{"fullName":"hs.eventtap.currentModifiers()","description":"Returns the currently held modifier keys","url":"hs.eventtap.html#currentModifiers","kind":"method"},{"fullName":"hs.eventtap.checkMouseButtons()","description":"Returns the currently pressed mouse buttons","url":"hs.eventtap.html#checkMouseButtons","kind":"method"},{"fullName":"hs.eventtap.mouseLocation()","description":"Returns the current mouse cursor position in Hammerspoon screen coordinates (top-left origin of primary display, y increases downward, matching hs.screen).","url":"hs.eventtap.html#mouseLocation","kind":"method"},{"fullName":"hs.eventtap.doubleClickInterval()","description":"Returns the system double-click interval in seconds","url":"hs.eventtap.html#doubleClickInterval","kind":"method"},{"fullName":"hs.eventtap.keyRepeatDelay()","description":"Returns the system key repeat delay in seconds","url":"hs.eventtap.html#keyRepeatDelay","kind":"method"},{"fullName":"hs.eventtap.keyRepeatInterval()","description":"Returns the system key repeat interval in seconds","url":"hs.eventtap.html#keyRepeatInterval","kind":"method"},{"fullName":"hs.eventtap.bindHotkey(mods, key, callbackPressed, callbackReleased)","description":"Bind a keyboard shortcut using an event tap. Unlike hs.hotkey.bind(), this supports the fn modifier and left/right modifier key distinction (e.g. leftCmd, rightAlt). The hotkey is active immediately and consumes (suppresses) the key events. It's important to note that this a much heavier-weight tool than hs.hotkey - every single key you press will be examined by Hammerspoon to see if it matches one of the EventTap hotkeys (where hs.hotkey relies on macOS to efficiently deliver only matching keypresses). Please consider this when choosing to use hs.eventtap for hotkeys. Requires Accessibility permission. ctrl, fn) and side-specific names (leftCmd, rightCmd, leftAlt, rightAlt, leftCtrl, rightCtrl, leftShift, rightShift).","url":"hs.eventtap.html#bindHotkey","kind":"method"},{"fullName":"hs.eventtap.removeHotkey(hotkey)","description":"Remove a previously bound hotkey and stop it from firing","url":"hs.eventtap.html#removeHotkey","kind":"method"},{"fullName":"hs.fs","description":"Module for filesystem operations.","url":"hs.fs.html","kind":"module"},{"fullName":"hs.fs.read(path, offset, length)","description":"Read part or all of a file as a UTF-8 string.","url":"hs.fs.html#read","kind":"method"},{"fullName":"hs.fs.readLines(path, callback)","description":"Read a file line-by-line, invoking a callback for each line. Lines are delivered with newline characters stripped. Both \\n and \\r\\n line endings are handled.","url":"hs.fs.html#readLines","kind":"method"},{"fullName":"hs.fs.write(path, content, inPlace)","description":"Write a UTF-8 string to a file, creating it or overwriting any existing content. Intermediate directories are not created automatically; use mkdir first if needed.","url":"hs.fs.html#write","kind":"method"},{"fullName":"hs.fs.append(path, content)","description":"Append a UTF-8 string to a file, creating it if it does not exist.","url":"hs.fs.html#append","kind":"method"},{"fullName":"hs.fs.exists(path)","description":"Determine if a filesystem object exists at the given path Unlike isFile and isDirectory, this follows symlinks.","url":"hs.fs.html#exists","kind":"method"},{"fullName":"hs.fs.isFile(path)","description":"Determine if a file exists at the given path This does not follow symlinks; a symlink pointing at a file returns false.","url":"hs.fs.html#isFile","kind":"method"},{"fullName":"hs.fs.isDirectory(path)","description":"Determine if a directory exists at the given path This does not follow symlinks; a symlink pointing at a directory returns false.","url":"hs.fs.html#isDirectory","kind":"method"},{"fullName":"hs.fs.isSymlink(path)","description":"Determine if a symlink exists at the given path","url":"hs.fs.html#isSymlink","kind":"method"},{"fullName":"hs.fs.isReadable(path)","description":"Determine if a given filesystem path is readable","url":"hs.fs.html#isReadable","kind":"method"},{"fullName":"hs.fs.isWritable(path)","description":"Determine if a given filesystem path is writable","url":"hs.fs.html#isWritable","kind":"method"},{"fullName":"hs.fs.copy(source, destination)","description":"Copy a file or directory to a new location. The destination must not already exist. If source is a directory, its entire contents are copied recursively.","url":"hs.fs.html#copy","kind":"method"},{"fullName":"hs.fs.move(source, destination)","description":"Move (rename) a file or directory. The destination must not already exist.","url":"hs.fs.html#move","kind":"method"},{"fullName":"hs.fs.deletePath(path)","description":"Delete a file or directory at the given path. Directories are removed recursively. To remove only an empty directory, use rmdir instead.","url":"hs.fs.html#deletePath","kind":"method"},{"fullName":"hs.fs.list(path)","description":"List the immediate contents of a directory. Returns bare filenames (not full paths), sorted alphabetically. The . and .. entries are never included.","url":"hs.fs.html#list","kind":"method"},{"fullName":"hs.fs.listRecursive(path)","description":"Recursively list all entries under a directory. Returns paths relative to path, sorted alphabetically.","url":"hs.fs.html#listRecursive","kind":"method"},{"fullName":"hs.fs.mkdir(path)","description":"Create a directory, including all necessary intermediate directories. Succeeds silently if the directory already exists.","url":"hs.fs.html#mkdir","kind":"method"},{"fullName":"hs.fs.rmdir(path)","description":"Remove an empty directory. Fails if the directory is not empty. Use deletePath to remove a non-empty directory recursively.","url":"hs.fs.html#rmdir","kind":"method"},{"fullName":"hs.fs.currentDir()","description":"Returns the current working directory of the process.","url":"hs.fs.html#currentDir","kind":"method"},{"fullName":"hs.fs.chdir(path)","description":"Change the current working directory of the process.","url":"hs.fs.html#chdir","kind":"method"},{"fullName":"hs.fs.pathToAbsolute(path)","description":"Resolve a path to its absolute, canonical form. Expands ~, resolves . and .., and follows all symbolic links. Returns null if any component of the path does not exist.","url":"hs.fs.html#pathToAbsolute","kind":"method"},{"fullName":"hs.fs.displayName(path)","description":"Return the localised display name for a file or directory as shown by Finder. For example, /Library appears as \"Library\" in Finder even though its on-disk name is the same.","url":"hs.fs.html#displayName","kind":"method"},{"fullName":"hs.fs.temporaryDirectory()","description":"Returns the temporary directory for the current user.","url":"hs.fs.html#temporaryDirectory","kind":"method"},{"fullName":"hs.fs.homeDirectory()","description":"Returns the home directory for the current user.","url":"hs.fs.html#homeDirectory","kind":"method"},{"fullName":"hs.fs.urlFromPath(path)","description":"Returns a file:// URL string for the given path.","url":"hs.fs.html#urlFromPath","kind":"method"},{"fullName":"hs.fs.attributes(path)","description":"Get metadata attributes for a file or directory. Does not follow symbolic links. Use isSymlink to detect links before calling this if needed.","url":"hs.fs.html#attributes","kind":"method"},{"fullName":"hs.fs.touch(path)","description":"Update the modification timestamp of a file to the current time. Creates the file if it does not exist (equivalent to the POSIX touch command).","url":"hs.fs.html#touch","kind":"method"},{"fullName":"hs.fs.link(source, destination)","description":"Create a hard link at destination pointing at source. Both paths must be on the same filesystem volume.","url":"hs.fs.html#link","kind":"method"},{"fullName":"hs.fs.symlink(source, destination)","description":"Create a symbolic link at destination pointing at source. Unlike hard links, symlinks may cross filesystem boundaries and may point to paths that do not yet exist.","url":"hs.fs.html#symlink","kind":"method"},{"fullName":"hs.fs.readlink(path)","description":"Read the target of a symbolic link without resolving it.","url":"hs.fs.html#readlink","kind":"method"},{"fullName":"hs.fs.tags(path)","description":"Get the Finder tags assigned to a file or directory.","url":"hs.fs.html#tags","kind":"method"},{"fullName":"hs.fs.fileUTI(path)","description":"Replace all Finder tags on a file or directory. This function is only available on macOS Tahoe (26) or later.","url":"hs.fs.html#fileUTI","kind":"method"},{"fullName":"hs.fs.pathToBookmark(path)","description":"Encode a file path as a persistent bookmark that survives file moves and renames. The returned string is base64-encoded bookmark data that can be stored and later resolved with pathFromBookmark.","url":"hs.fs.html#pathToBookmark","kind":"method"},{"fullName":"hs.fs.pathFromBookmark(data)","description":"Resolve a base64-encoded bookmark back to a file path.","url":"hs.fs.html#pathFromBookmark","kind":"method"},{"fullName":"hs.fs.volumes(showHidden)","description":"Return information about all currently mounted filesystem volumes.","url":"hs.fs.html#volumes","kind":"method"},{"fullName":"hs.fs.ejectVolume(path)","description":"Unmount and eject the volume at the given path.","url":"hs.fs.html#ejectVolume","kind":"method"},{"fullName":"hs.fs.addVolumeWatcher()","description":"Create a new volume event watcher. Call setCallback() and start() on the returned object to begin receiving volume mount/unmount/rename events.","url":"hs.fs.html#addVolumeWatcher","kind":"method"},{"fullName":"hs.fs.removeVolumeWatcher(watcher)","description":"Stop and destroy a volume watcher previously created with addVolumeWatcher.","url":"hs.fs.html#removeVolumeWatcher","kind":"method"},{"fullName":"hs.fs.createPathWatcher(path)","description":"Create a watcher for filesystem events at a given path. Events are batched and delivered with a latency of approximately one second. Call setCallback() and start() on the returned object to begin receiving events.","url":"hs.fs.html#createPathWatcher","kind":"method"},{"fullName":"hs.fs.xattrGet(path, attribute, options, position)","description":"Get the value of an extended attribute for a file or directory. Attribute values are returned as ISO Latin-1 encoded strings so that arbitrary byte sequences are represented without loss. ASCII text attribute values appear readable as-is.","url":"hs.fs.html#xattrGet","kind":"method"},{"fullName":"hs.fs.xattrList(path, options)","description":"List all extended attributes defined for a file or directory.","url":"hs.fs.html#xattrList","kind":"method"},{"fullName":"hs.fs.xattrSet(path, attribute, value, options, position)","description":"Set the value of an extended attribute for a file or directory. The value is written as ISO Latin-1 bytes, providing a lossless round-trip with xattrGet. Plain ASCII strings work directly without any encoding.","url":"hs.fs.html#xattrSet","kind":"method"},{"fullName":"hs.fs.xattrRemove(path, attribute, options)","description":"Remove an extended attribute from a file or directory.","url":"hs.fs.html#xattrRemove","kind":"method"},{"fullName":"hs.hash","description":"Module for hashing and encoding operations","url":"hs.hash.html","kind":"module"},{"fullName":"hs.hash.base64Encode(data)","description":"Encode a string to base64","url":"hs.hash.html#base64Encode","kind":"method"},{"fullName":"hs.hash.base64Decode(data)","description":"Decode a base64 string","url":"hs.hash.html#base64Decode","kind":"method"},{"fullName":"hs.hash.md5(data)","description":"Generate MD5 hash of a string","url":"hs.hash.html#md5","kind":"method"},{"fullName":"hs.hash.sha1(data)","description":"Generate SHA1 hash of a string","url":"hs.hash.html#sha1","kind":"method"},{"fullName":"hs.hash.sha256(data)","description":"Generate SHA256 hash of a string","url":"hs.hash.html#sha256","kind":"method"},{"fullName":"hs.hash.sha512(data)","description":"Generate SHA512 hash of a string","url":"hs.hash.html#sha512","kind":"method"},{"fullName":"hs.hash.hmacMD5(key, data)","description":"Generate HMAC-MD5 of a string with a key","url":"hs.hash.html#hmacMD5","kind":"method"},{"fullName":"hs.hash.hmacSHA1(key, data)","description":"Generate HMAC-SHA1 of a string with a key","url":"hs.hash.html#hmacSHA1","kind":"method"},{"fullName":"hs.hash.hmacSHA256(key, data)","description":"Generate HMAC-SHA256 of a string with a key","url":"hs.hash.html#hmacSHA256","kind":"method"},{"fullName":"hs.hash.hmacSHA512(key, data)","description":"Generate HMAC-SHA512 of a string with a key","url":"hs.hash.html#hmacSHA512","kind":"method"},{"fullName":"hs.hotkey","description":"Module for creating and managing system-wide hotkeys","url":"hs.hotkey.html","kind":"module"},{"fullName":"hs.hotkey.alertDuration","description":"Duration in seconds for the on-screen toast shown when a hotkey with a message set fires. Default is 1.","url":"hs.hotkey.html#alertDuration","kind":"property"},{"fullName":"hs.hotkey.bind(mods, key, callbackPressed, callbackReleased, callbackRepeat)","description":"Bind a hotkey cmd / command / ⌘, shift / ⇧, alt / option / ⌥, ctrl / control / ⌃.","url":"hs.hotkey.html#bind","kind":"method"},{"fullName":"hs.hotkey.getKeyCodeMap()","description":"Get the system-wide mapping of key names to key codes","url":"hs.hotkey.html#getKeyCodeMap","kind":"method"},{"fullName":"hs.hotkey.getModifierMap()","description":"Get the mapping of modifier names to modifier flags","url":"hs.hotkey.html#getModifierMap","kind":"method"},{"fullName":"hs.hotkey.create(mods, key, callbackPressed, callbackReleased, callbackRepeat)","description":"Create a hotkey without enabling it cmd / command / ⌘, shift / ⇧, alt / option / ⌥, ctrl / control / ⌃.","url":"hs.hotkey.html#create","kind":"method"},{"fullName":"hs.hotkey.getHotkeys()","description":"Get a list of all currently-enabled hotkeys","url":"hs.hotkey.html#getHotkeys","kind":"method"},{"fullName":"hs.hotkey.systemAssigned(mods, key)","description":"Check whether macOS itself has already claimed a key combination (e.g. for Spotlight, screenshots, etc.)","url":"hs.hotkey.html#systemAssigned","kind":"method"},{"fullName":"hs.hotkey.assignable(mods, key)","description":"Check whether a key combination is available to be bound (i.e. not already claimed by macOS)","url":"hs.hotkey.html#assignable","kind":"method"},{"fullName":"hs.hotkey.deleteAll(mods, key)","description":"Disable and remove every hotkey currently bound to a key combination","url":"hs.hotkey.html#deleteAll","kind":"method"},{"fullName":"hs.hotkey.disableAll(mods, key)","description":"Disable every hotkey currently bound to a key combination, without removing them","url":"hs.hotkey.html#disableAll","kind":"method"},{"fullName":"hs.hotkey.bindSpec(spec)","description":"Bind a hotkey from a single options object. Like hs.hotkey.bind()/create(), but also accepts a message and a repeat callback. message is available on any hotkey (not just ones created via bindSpec()) by setting .message directly on the returned object; see hs.hotkey's message property for exactly when it is shown.","url":"hs.hotkey.html#bindSpec","kind":"method"},{"fullName":"hs.hotkey.createModal(mods, key)","description":"Create a new modal hotkey group, optionally entered via a trigger key combination","url":"hs.hotkey.html#createModal","kind":"method"},{"fullName":"hs.hotkey.showHotkeys(mods, key)","description":"Create and enable a hotkey that, while held down, displays a list of all currently enabled hotkeys (and their messages, if any) as an on-screen toast.","url":"hs.hotkey.html#showHotkeys","kind":"method"},{"fullName":"hs.http","description":"HTTP client module for making network requests from JavaScript.","url":"hs.http.html","kind":"module"},{"fullName":"hs.http.get(url, headers)","description":"Perform an HTTP GET request.","url":"hs.http.html#get","kind":"method"},{"fullName":"hs.http.post(url, body, headers)","description":"Perform an HTTP POST request.","url":"hs.http.html#post","kind":"method"},{"fullName":"hs.http.put(url, body, headers)","description":"Perform an HTTP PUT request.","url":"hs.http.html#put","kind":"method"},{"fullName":"hs.http.doRequest(url, method, body, headers)","description":"Perform an HTTP request with any method (GET, POST, PUT, DELETE, PATCH, etc.). Use this for methods not covered by the convenience helpers, such as DELETE or PATCH.","url":"hs.http.html#doRequest","kind":"method"},{"fullName":"hs.http.encodeForQuery(string)","description":"URL-encode a string for use as a query parameter value. Encodes characters that are illegal in a URL query string (including ?, =, +, &, #) using percent-encoding.","url":"hs.http.html#encodeForQuery","kind":"method"},{"fullName":"hs.http.urlParts(url)","description":"Parse a URL into its component parts. Returns an object containing only the fields present in the URL. The queryItems field is an array of {name, value} objects from the query string.","url":"hs.http.html#urlParts","kind":"method"},{"fullName":"hs.http.convertHtmlEntities(string)","description":"Convert HTML entities in a string to their UTF-8 character equivalents. Handles named entities (e.g. &, <, ©), decimal numeric references (&), and hexadecimal numeric references (&).","url":"hs.http.html#convertHtmlEntities","kind":"method"},{"fullName":"hs.http.openWebSocket(url)","description":"Open a WebSocket connection to the given URL. The connection begins immediately. Use the returned object's chainable setter methods to register event callbacks. The connection is automatically closed when hs.reload() is called or the engine shuts down.","url":"hs.http.html#openWebSocket","kind":"method"},{"fullName":"hs.httpserver","description":"Module for creating and managing HTTP servers.","url":"hs.httpserver.html","kind":"module"},{"fullName":"hs.httpserver.create()","description":"Create a new HTTP server instance. The server is not running until you call start() on the returned object.","url":"hs.httpserver.html#create","kind":"method"},{"fullName":"hs.ipc","description":"Module for enabling CLI access to Hammerspoon 2 via the hs2 command-line tool.","url":"hs.ipc.html","kind":"module"},{"fullName":"hs.ipc.isListening","description":"Whether the IPC server is currently accepting connections.","url":"hs.ipc.html#isListening","kind":"property"},{"fullName":"hs.ipc.start()","description":"Start the IPC server. The server listens on a named XPC Mach service (net.tenshu.Hammerspoon-2.ipc). In release builds, only processes signed with the same Team ID can connect. Calling start() when already running logs a warning and does nothing.","url":"hs.ipc.html#start","kind":"method"},{"fullName":"hs.ipc.stop()","description":"Stop the IPC server and disconnect all connected clients.","url":"hs.ipc.html#stop","kind":"method"},{"fullName":"hs.ipc.installBinary(directory)","description":"Install the hs2 command-line tool to the given directory as a symlink. Creates a symlink in the target directory that points to the hs2 binary inside the Hammerspoon 2 app bundle. Using a symlink means the CLI automatically reflects any app update without reinstalling. Any existing hs2 file at that path is replaced. The directory must be on your $PATH for hs2 to work without a full path. Permissions: /usr/local/bin is typically user-writable on Intel Macs with Homebrew. On Apple Silicon, prefer /opt/homebrew/bin. On a stock Mac (no Homebrew), both directories require root — if this method returns false, run the logged command in a terminal with sudo.","url":"hs.ipc.html#installBinary","kind":"method"},{"fullName":"hs.ipc.uninstallBinary(directory)","description":"Remove the hs2 command-line tool from the given directory.","url":"hs.ipc.html#uninstallBinary","kind":"method"},{"fullName":"hs.ipc.isBinaryInstalled(directory)","description":"Check whether the hs2 command-line tool exists at the given directory.","url":"hs.ipc.html#isBinaryInstalled","kind":"method"},{"fullName":"hs.keyboard","description":"Module for querying and controlling CapsLock state, and for enumerating attached keyboards and controlling their LEDs individually.","url":"hs.keyboard.html","kind":"module"},{"fullName":"hs.keyboard.capsLockState()","description":"Checks the system-wide state of CapsLock. This reflects a single, global lock state shared by every attached keyboard — macOS has no public API to query the functional (character-affecting) CapsLock state independently per keyboard. For a genuinely per-keyboard signal, see keyboardCapsLockState(), which reads each keyboard's own CapsLock LED.","url":"hs.keyboard.html#capsLockState","kind":"method"},{"fullName":"hs.keyboard.setCapsLockState(state)","description":"Sets the system-wide state of CapsLock.","url":"hs.keyboard.html#setCapsLockState","kind":"method"},{"fullName":"hs.keyboard.toggleCapsLockState()","description":"Toggles the system-wide state of CapsLock.","url":"hs.keyboard.html#toggleCapsLockState","kind":"method"},{"fullName":"hs.keyboard.setLED(name, state)","description":"Sets a keyboard LED on every attached keyboard that has one.","url":"hs.keyboard.html#setLED","kind":"method"},{"fullName":"hs.keyboard.attachedKeyboards()","description":"Returns all currently attached keyboard HID devices. Each object has keyboardID (number — pass to keyboardCapsLockState()/setKeyboardLED()), productName (string), vendorName (string), productID (number), and vendorID (number). serialNumber (string) and locationID (number) are included when available.","url":"hs.keyboard.html#attachedKeyboards","kind":"method"},{"fullName":"hs.keyboard.keyboardCapsLockState(keyboardID)","description":"Checks a specific keyboard's own CapsLock LED state. Unlike capsLockState(), this queries the individual keyboard identified by keyboardID (from attachedKeyboards()), reflecting how modern macOS tracks CapsLock independently per physical keyboard.","url":"hs.keyboard.html#keyboardCapsLockState","kind":"method"},{"fullName":"hs.keyboard.setKeyboardLED(keyboardID, name, state)","description":"Sets a specific keyboard's LED, leaving all other attached keyboards untouched.","url":"hs.keyboard.html#setKeyboardLED","kind":"method"},{"fullName":"hs.keycodes","description":"Access information about the current keyboard layout and input sources, and respond to changes.","url":"hs.keycodes.html","kind":"module"},{"fullName":"hs.keycodes.map","description":"A bidirectional mapping between key names and their macOS virtual key codes. Entries exist for both directions: look up a name to get its integer keycode, or look up a keycode (as a string) to get the key name. The map is rebuilt automatically whenever the keyboard input source changes.","url":"hs.keycodes.html#map","kind":"property"},{"fullName":"hs.keycodes.currentLayout()","description":"Returns the localized name of the current keyboard layout. Uses the base keyboard layout, which is the underlying layout even when an input method (such as a CJK input method) is also active.","url":"hs.keycodes.html#currentLayout","kind":"method"},{"fullName":"hs.keycodes.currentMethod()","description":"Returns the localized name of the active input method, or null if none is active. Input methods are distinct from keyboard layouts. They provide complex character composition such as CJK input. Returns null when using a plain keyboard layout with no input method overlay.","url":"hs.keycodes.html#currentMethod","kind":"method"},{"fullName":"hs.keycodes.currentSourceID()","description":"Returns the reverse-DNS identifier of the currently selected keyboard input source.","url":"hs.keycodes.html#currentSourceID","kind":"method"},{"fullName":"hs.keycodes.layouts()","description":"Returns the localized names of all currently enabled keyboard layouts.","url":"hs.keycodes.html#layouts","kind":"method"},{"fullName":"hs.keycodes.methods()","description":"Returns the localized names of all currently enabled input methods.","url":"hs.keycodes.html#methods","kind":"method"},{"fullName":"hs.keycodes.setLayout(layoutName)","description":"Switches the active keyboard layout to the one with the given localized name. Use layouts() to enumerate valid names.","url":"hs.keycodes.html#setLayout","kind":"method"},{"fullName":"hs.keycodes.setMethod(methodName)","description":"Switches the active input method to the one with the given localized name. Use methods() to enumerate valid names.","url":"hs.keycodes.html#setMethod","kind":"method"},{"fullName":"hs.keycodes.setSourceID(sourceID)","description":"Switches the active input source to the one with the given reverse-DNS identifier. Use currentSourceID() to see the current value.","url":"hs.keycodes.html#setSourceID","kind":"method"},{"fullName":"hs.keycodes.addWatcher(listener)","description":"Registers a listener that fires whenever the keyboard input source changes. The listener is called with no arguments. Read currentLayout(), currentSourceID(), or map inside the callback to inspect the new state. The OS subscription starts lazily on the first listener and is released automatically when the last listener is removed via removeWatcher.","url":"hs.keycodes.html#addWatcher","kind":"method"},{"fullName":"hs.keycodes.removeWatcher(listener)","description":"Removes a previously registered input source change listener.","url":"hs.keycodes.html#removeWatcher","kind":"method"},{"fullName":"hs.locale","description":"Retrieve information about the user's Language & Region settings, and respond to changes.","url":"hs.locale.html","kind":"module"},{"fullName":"hs.locale.availableLocales()","description":"Returns the identifiers for all locales available on the system.","url":"hs.locale.html#availableLocales","kind":"method"},{"fullName":"hs.locale.current()","description":"Returns the user's currently selected locale identifier.","url":"hs.locale.html#current","kind":"method"},{"fullName":"hs.locale.preferredLanguages()","description":"Returns the user's preferred languages, in priority order.","url":"hs.locale.html#preferredLanguages","kind":"method"},{"fullName":"hs.locale.details(identifier)","description":"Returns detailed information about the current or a specified locale. user's currently selected locale is used.","url":"hs.locale.html#details","kind":"method"},{"fullName":"hs.locale.localizedName(localeCode, baseLocaleCode)","description":"Returns the localized display name for a locale identifier. of the strings returned by availableLocales(). currently selected locale is used. Must be one of the strings returned by availableLocales().","url":"hs.locale.html#localizedName","kind":"method"},{"fullName":"hs.locale.addWatcher(listener)","description":"Registers a listener that fires whenever any of the user's locale settings change. The listener is called with no arguments. Read current() or details() inside the callback to inspect the new state. The OS subscription starts lazily on the first listener and is released automatically when the last listener is removed via removeWatcher.","url":"hs.locale.html#addWatcher","kind":"method"},{"fullName":"hs.locale.removeWatcher(listener)","description":"Removes a previously registered locale change listener.","url":"hs.locale.html#removeWatcher","kind":"method"},{"fullName":"hs.location","description":"Determine the Mac's location via macOS Location Services.","url":"hs.location.html","kind":"module"},{"fullName":"hs.location.lookupAddress(address)","description":"Geocodes an address string into an array of placemarkTables. Returns a Promise that resolves with an array of placemarkTable objects (sorted by relevance) or rejects with an error message.","url":"hs.location.html#lookupAddress","kind":"method"},{"fullName":"hs.location.lookupLocation(locationTable)","description":"Reverse-geocodes a locationTable into an array of placemarkTables. Returns a Promise that resolves with matching placemarks or rejects with an error.","url":"hs.location.html#lookupLocation","kind":"method"},{"fullName":"hs.location.servicesEnabled()","description":"Returns true if Location Services are enabled system-wide.","url":"hs.location.html#servicesEnabled","kind":"method"},{"fullName":"hs.location.authorizationStatus()","description":"Returns the app's current Location Services authorization status as a string.","url":"hs.location.html#authorizationStatus","kind":"method"},{"fullName":"hs.location.get()","description":"Returns the most recently cached location as a locationTable, or null. Activates Location Services if not already running. The cache is updated periodically while any watcher is running.","url":"hs.location.html#get","kind":"method"},{"fullName":"hs.location.distance(from, to)","description":"Calculates the straight-line distance in metres between two locationTables. Does not require Location Services.","url":"hs.location.html#distance","kind":"method"},{"fullName":"hs.location.sunrise(latitude, longitude, date)","description":"Returns the time of sunrise for the given coordinates and date, or null if the sun does not rise on that date (polar night).","url":"hs.location.html#sunrise","kind":"method"},{"fullName":"hs.location.sunset(latitude, longitude, date)","description":"Returns the time of sunset for the given coordinates and date, or null if the sun does not set on that date (midnight sun).","url":"hs.location.html#sunset","kind":"method"},{"fullName":"hs.location.addWatcher()","description":"Creates a new location watcher object. Call .start() on it to begin receiving updates. The watcher is automatically stopped when the module shuts down.","url":"hs.location.html#addWatcher","kind":"method"},{"fullName":"hs.location.removeWatcher(watcher)","description":"Removes a previously created watcher and stops it if running.","url":"hs.location.html#removeWatcher","kind":"method"},{"fullName":"hs.menubar","description":"Module for creating and managing macOS system menu bar items.","url":"hs.menubar.html","kind":"module"},{"fullName":"hs.menubar.create(hidden)","description":"Create a new menu bar item","url":"hs.menubar.html#create","kind":"method"},{"fullName":"hs.midi","description":"A module for enumerating, watching, and communicating with MIDI devices. IMPORTANT NOTE: This module has not had very much real-world testing yet. Please report positive or negative feedback via GitHub Issues.","url":"hs.midi.html","kind":"module"},{"fullName":"hs.midi.commandTypes","description":"A table mapping each MIDI command type name to a stable numeric identifier.","url":"hs.midi.html#commandTypes","kind":"property"},{"fullName":"hs.midi.devices()","description":"Returns the names of all currently connected (online) physical MIDI devices.","url":"hs.midi.html#devices","kind":"method"},{"fullName":"hs.midi.virtualSources()","description":"Returns the names of all available virtual MIDI sources — endpoints published by other apps/drivers (e.g. the IAC Driver, virtual instruments) rather than belonging to a physical device.","url":"hs.midi.html#virtualSources","kind":"method"},{"fullName":"hs.midi.deviceCallback(fn)","description":"Sets or removes a callback fired whenever the set of connected MIDI devices or virtual sources changes. The callback receives two arguments: the current result of devices() and the current result of virtualSources().","url":"hs.midi.html#deviceCallback","kind":"method"},{"fullName":"hs.midi.deviceNamed(deviceName)","description":"Creates an hs.midi object for a physical device. new/alloc/copy-prefixed method names, which have special meaning under Objective-C's ARC ownership conventions.","url":"hs.midi.html#deviceNamed","kind":"method"},{"fullName":"hs.midi.virtualSourceNamed(virtualSourceName)","description":"Creates an hs.midi object for an existing virtual source (receive-only — a \"source\" endpoint can only be read from). the same ARC-related reason as deviceNamed().","url":"hs.midi.html#virtualSourceNamed","kind":"method"},{"fullName":"hs.mouse","description":"Control and inspect the mouse pointer and attached mouse devices.","url":"hs.mouse.html","kind":"module"},{"fullName":"hs.mouse.absolutePosition()","description":"Returns the current mouse pointer position in Hammerspoon screen coordinates. Hammerspoon coordinates have (0, 0) at the top-left of the primary display, with y increasing downward.","url":"hs.mouse.html#absolutePosition","kind":"method"},{"fullName":"hs.mouse.setAbsolutePosition(x, y)","description":"Moves the mouse pointer to the specified absolute position in Hammerspoon screen coordinates.","url":"hs.mouse.html#setAbsolutePosition","kind":"method"},{"fullName":"hs.mouse.getRelativePosition()","description":"Returns the mouse pointer position relative to the screen it is currently on. The returned coordinates have (0, 0) at the top-left corner of the screen that the cursor is on.","url":"hs.mouse.html#getRelativePosition","kind":"method"},{"fullName":"hs.mouse.setRelativePosition(x, y)","description":"Moves the mouse pointer to a position relative to the screen it is currently on.","url":"hs.mouse.html#setRelativePosition","kind":"method"},{"fullName":"hs.mouse.getCurrentScreen()","description":"Returns the screen that the mouse pointer is currently on.","url":"hs.mouse.html#getCurrentScreen","kind":"method"},{"fullName":"hs.mouse.count(includeInternal)","description":"Returns the number of mouse devices currently attached to the system.","url":"hs.mouse.html#count","kind":"method"},{"fullName":"hs.mouse.names(includeInternal)","description":"Returns the product names of all mouse devices currently attached to the system.","url":"hs.mouse.html#names","kind":"method"},{"fullName":"hs.mouse.trackingSpeed()","description":"Returns the current mouse tracking speed (acceleration level). Values range from -1.0 (system default, acceleration disabled) to 3.0 (maximum acceleration). Returns -1.0 if the value cannot be read.","url":"hs.mouse.html#trackingSpeed","kind":"method"},{"fullName":"hs.mouse.setTrackingSpeed(speed)","description":"Sets the mouse tracking speed (acceleration level). The change takes effect immediately for the current login session and is also persisted to preferences so it survives a restart. Values outside the valid range or non-finite values are rejected with a warning and no change is made.","url":"hs.mouse.html#setTrackingSpeed","kind":"method"},{"fullName":"hs.mouse.scrollDirection()","description":"Returns the current scroll wheel direction setting.","url":"hs.mouse.html#scrollDirection","kind":"method"},{"fullName":"hs.mouse.currentCursorType()","description":"Returns the name of the cursor type currently set by this application. has the keyboard focus, the visible system cursor may differ.","url":"hs.mouse.html#currentCursorType","kind":"method"},{"fullName":"hs.network","description":"Module for inspecting network interfaces, resolving hostnames, and reading system configuration","url":"hs.network.html","kind":"module"},{"fullName":"hs.network.reachabilityFlags","description":"A dictionary of named flag constants for use with HSNetworkReachability.status(). Compare individual bits against these constants to determine which network conditions apply. The numeric values match the deprecated SCNetworkReachabilityFlags for backward compatibility. Keys: transientConnection, reachable, connectionRequired, connectionOnTraffic, interventionRequired, connectionOnDemand, isLocalAddress, isDirect.","url":"hs.network.html#reachabilityFlags","kind":"property"},{"fullName":"hs.network.interfaces()","description":"Returns all network interfaces present on this system. Each object contains name (string), isLoopback (boolean), isUp (boolean), and isRunning (boolean). A displayName string is included when the system provides a human-readable label for the interface (e.g. \"Wi-Fi\" or \"Ethernet\").","url":"hs.network.html#interfaces","kind":"method"},{"fullName":"hs.network.primaryInterface()","description":"Returns the name of the primary network interface, i.e. the one currently providing the default route.","url":"hs.network.html#primaryInterface","kind":"method"},{"fullName":"hs.network.addresses()","description":"Returns all IP addresses assigned to this host. Each object contains interface (the BSD name of the interface), address (the address string), and family (\"ipv4\" or \"ipv6\").","url":"hs.network.html#addresses","kind":"method"},{"fullName":"hs.network.hostnames()","description":"Returns all hostnames known for this Mac.","url":"hs.network.html#hostnames","kind":"method"},{"fullName":"hs.network.resolve(hostname, family)","description":"Asynchronously resolves a hostname to its IP addresses using the system DNS resolver. Uses CFHost, which respects the system's network configuration including VPN routes and proxy settings.","url":"hs.network.html#resolve","kind":"method"},{"fullName":"hs.network.reachabilityForAddress(address)","description":"Creates a reachability monitor for a specific IP address. Returns null if address is not a valid IPv4 or IPv6 address literal. Under the hood this monitors general system connectivity (the same as reachabilityInternet()), because NWPathMonitor does not support per-address targeting.","url":"hs.network.html#reachabilityForAddress","kind":"method"},{"fullName":"hs.network.reachabilityForAddressPair(localAddress, remoteAddress)","description":"Creates a reachability monitor for a source/destination IP address pair. Returns null if either address is not a valid IPv4 or IPv6 address literal. Under the hood this monitors general system connectivity (the same as reachabilityInternet()), because NWPathMonitor does not support per-address targeting.","url":"hs.network.html#reachabilityForAddressPair","kind":"method"},{"fullName":"hs.network.reachabilityForHostName(hostName)","description":"Creates a reachability monitor for a given hostname. Returns null if hostName is empty. Under the hood this monitors general system connectivity (the same as reachabilityInternet()), because NWPathMonitor does not support per-hostname targeting.","url":"hs.network.html#reachabilityForHostName","kind":"method"},{"fullName":"hs.network.reachabilityInternet()","description":"Creates a reachability monitor for general internet connectivity. This is the most common factory method. Use it when you want to know whether the device currently has a working internet connection.","url":"hs.network.html#reachabilityInternet","kind":"method"},{"fullName":"hs.network.reachabilityLinkLocal()","description":"Creates a reachability monitor for link-local connectivity. Link-local addresses cover the 169.254.x.x (IPv4) and fe80::/10 (IPv6) ranges used for direct device-to-device communication without a router. Under the hood this monitors general system connectivity (the same as reachabilityInternet()), because NWPathMonitor does not distinguish link-local reachability.","url":"hs.network.html#reachabilityLinkLocal","kind":"method"},{"fullName":"hs.network.configurationStore(pattern)","description":"Returns the contents of the macOS System Configuration dynamic store as a dictionary. The store holds live network configuration for the running system — interface addresses, routing, DNS servers, proxy settings, VPN state, and more. Keys follow a hierarchical path convention (e.g. \"State:/Network/Global/IPv4\"). Omit or pass null to return all keys (equivalent to \".*\").","url":"hs.network.html#configurationStore","kind":"method"},{"fullName":"hs.network.configurationLocations()","description":"Returns a mapping of all configured network location UUIDs to their display names. Use this to discover available locations before calling configurationSetLocation().","url":"hs.network.html#configurationLocations","kind":"method"},{"fullName":"hs.network.configurationSetLocation(location)","description":"Switches the active network location to the one with the given name or UUID. Pass the location's display name (e.g. \"Home\") or its UUID from configurationLocations(). The change is applied immediately. Returns false if the location was not found or the preferences could not be committed (e.g. insufficient privileges).","url":"hs.network.html#configurationSetLocation","kind":"method"},{"fullName":"hs.network.configurationWatcher()","description":"Creates a watcher that fires a callback when System Configuration dynamic store keys change. Call setKeys() to specify which keys (or patterns) to watch, setCallback() to register the handler, then start() to begin monitoring. The module automatically stops and destroys all watchers on hs.reload().","url":"hs.network.html#configurationWatcher","kind":"method"},{"fullName":"hs.network.ping(server, options)","description":"Sends ICMP Echo Requests to server and reports results via a callback. DNS resolution and the first ping begin immediately. The returned object can be used to pause, resume, or cancel the ping, and to read statistics. timeout (seconds per packet, default 2.0), family (\"any\" | \"ipv4\" | \"ipv6\", default \"any\"), and callback (function).","url":"hs.network.html#ping","kind":"method"},{"fullName":"hs.notify","description":"Module for creating and displaying macOS system notifications.","url":"hs.notify.html","kind":"module"},{"fullName":"hs.notify.show(title, body, callback)","description":"Display a notification immediately.","url":"hs.notify.html#show","kind":"method"},{"fullName":"hs.notify.create(options)","description":"Create a richly configured notification without sending it yet.","url":"hs.notify.html#create","kind":"method"},{"fullName":"hs.notify.removeAllDelivered()","description":"Remove all delivered Hammerspoon notifications from Notification Center.","url":"hs.notify.html#removeAllDelivered","kind":"method"},{"fullName":"hs.notify.removeAllPending()","description":"Cancel all pending (not yet delivered) Hammerspoon notifications.","url":"hs.notify.html#removeAllPending","kind":"method"},{"fullName":"hs.ocr","description":"Recognize text in images using Apple's Vision framework.","url":"hs.ocr.html","kind":"module"},{"fullName":"hs.ocr.recognizeText(path, options)","description":"Recognize text in the image at the given file path. Returns a Promise that resolves with an HSOCRResult containing all recognized text and per-region observations. The image must exist on disk; URLs and data buffers are not supported. Recognition is performed on a background thread; the main thread is not blocked during the operation. \"accurate\" uses a larger neural network for better results; \"fast\" trades accuracy for speed. Observations whose confidence is below this threshold are excluded from result.observations (and therefore from result.text). Hints Vision toward specific languages. Use supportedLanguages() to enumerate the available codes for the current device. When true, Vision selects recognition languages automatically. Overrides languages when set.","url":"hs.ocr.html#recognizeText","kind":"method"},{"fullName":"hs.ocr.supportedLanguages()","description":"Returns the BCP-47 language codes supported by the Vision text recognizer on this device. The set of languages varies between macOS versions and hardware. Call this at runtime to discover which codes are valid for the languages option passed to recognizeText().","url":"hs.ocr.html#supportedLanguages","kind":"method"},{"fullName":"hs.osascript","description":"Run AppleScript and OSA JavaScript from Hammerspoon scripts.","url":"hs.osascript.html","kind":"module"},{"fullName":"hs.osascript.applescript(source)","description":"Run an AppleScript source string.","url":"hs.osascript.html#applescript","kind":"method"},{"fullName":"hs.osascript.javascript(source)","description":"Run an OSA JavaScript source string. OSA JavaScript is Apple's Open Scripting Architecture dialect of JavaScript, distinct from the JavaScriptCore engine that runs Hammerspoon scripts themselves.","url":"hs.osascript.html#javascript","kind":"method"},{"fullName":"hs.osascript.applescriptFromFile(path)","description":"Read a file from disk and execute its contents as AppleScript. The file is read in the main process before being sent to the XPC helper. If the file cannot be read the promise resolves immediately with { success: false, result: null, raw: \"Failed to read file: \" }.","url":"hs.osascript.html#applescriptFromFile","kind":"method"},{"fullName":"hs.osascript.javascriptFromFile(path)","description":"Read a file from disk and execute its contents as OSA JavaScript. The file is read in the main process before being sent to the XPC helper. If the file cannot be read the promise resolves immediately with { success: false, result: null, raw: \"Failed to read file: \" }.","url":"hs.osascript.html#javascriptFromFile","kind":"method"},{"fullName":"hs.osascript._execute(source, language)","description":"Low-level execution entry point used by the higher-level helpers. Prefer applescript() or javascript() over calling this directly.","url":"hs.osascript.html#_execute","kind":"method"},{"fullName":"hs.osascript.applescriptSync(source)","description":"Run an AppleScript source string synchronously. Blocks the JS thread until the script completes.","url":"hs.osascript.html#applescriptSync","kind":"method"},{"fullName":"hs.osascript.javascriptSync(source)","description":"Run an OSA JavaScript source string synchronously. Blocks the JS thread until the script completes.","url":"hs.osascript.html#javascriptSync","kind":"method"},{"fullName":"hs.osascript.applescriptSyncFromFile(path)","description":"Read a file from disk and execute its contents as AppleScript synchronously.","url":"hs.osascript.html#applescriptSyncFromFile","kind":"method"},{"fullName":"hs.osascript.javascriptSyncFromFile(path)","description":"Read a file from disk and execute its contents as OSA JavaScript synchronously.","url":"hs.osascript.html#javascriptSyncFromFile","kind":"method"},{"fullName":"hs.osascript._executeSync(source, language)","description":"Low-level synchronous execution entry point. Prefer applescriptSync() or javascriptSync() over calling this directly.","url":"hs.osascript.html#_executeSync","kind":"method"},{"fullName":"hs.pasteboard","description":"Module for interacting with the macOS pasteboard (clipboard)","url":"hs.pasteboard.html","kind":"module"},{"fullName":"hs.pasteboard.changeCount","description":"The pasteboard change count. Increments each time any application writes to the pasteboard. Comparing a saved value to the current value is the standard way to detect external changes.","url":"hs.pasteboard.html#changeCount","kind":"property"},{"fullName":"hs.pasteboard.watcherInterval","description":"The polling interval for the pasteboard watcher, in seconds. Defaults to 0.5. Changes take effect the next time a watcher is started (i.e. after removing and re-adding).","url":"hs.pasteboard.html#watcherInterval","kind":"property"},{"fullName":"hs.pasteboard.readString()","description":"Read plain text from the pasteboard","url":"hs.pasteboard.html#readString","kind":"method"},{"fullName":"hs.pasteboard.readHTML()","description":"Read HTML from the pasteboard","url":"hs.pasteboard.html#readHTML","kind":"method"},{"fullName":"hs.pasteboard.readRTF()","description":"Read RTF from the pasteboard","url":"hs.pasteboard.html#readRTF","kind":"method"},{"fullName":"hs.pasteboard.readURL()","description":"Read a URL from the pasteboard","url":"hs.pasteboard.html#readURL","kind":"method"},{"fullName":"hs.pasteboard.readImage()","description":"Read an image from the pasteboard","url":"hs.pasteboard.html#readImage","kind":"method"},{"fullName":"hs.pasteboard.readData(uti)","description":"Read raw data for a specific UTI type, returned as a base64-encoded string. Use this for types not covered by the convenience read methods.","url":"hs.pasteboard.html#readData","kind":"method"},{"fullName":"hs.pasteboard.writeString(str)","description":"Write plain text to the pasteboard, replacing all current contents","url":"hs.pasteboard.html#writeString","kind":"method"},{"fullName":"hs.pasteboard.writeHTML(html)","description":"Write HTML to the pasteboard, replacing all current contents","url":"hs.pasteboard.html#writeHTML","kind":"method"},{"fullName":"hs.pasteboard.writeRTF(rtf)","description":"Write RTF to the pasteboard, replacing all current contents","url":"hs.pasteboard.html#writeRTF","kind":"method"},{"fullName":"hs.pasteboard.writeURL(url)","description":"Write a URL to the pasteboard, replacing all current contents","url":"hs.pasteboard.html#writeURL","kind":"method"},{"fullName":"hs.pasteboard.writeImage(image)","description":"Write an image to the pasteboard, replacing all current contents","url":"hs.pasteboard.html#writeImage","kind":"method"},{"fullName":"hs.pasteboard.writeData(base64, uti)","description":"Write raw base64-encoded data for a specific UTI type, replacing all current contents. Use this for types not covered by the convenience write methods.","url":"hs.pasteboard.html#writeData","kind":"method"},{"fullName":"hs.pasteboard.writeObjects(representations)","description":"Write multiple type representations to the pasteboard atomically, replacing all current contents. Keys must be UTI type strings; values must be strings. This is how you provide both a plain-text fallback and a richer representation (such as HTML) in a single clipboard operation.","url":"hs.pasteboard.html#writeObjects","kind":"method"},{"fullName":"hs.pasteboard.types()","description":"Get all UTI type strings currently on the pasteboard, across all items","url":"hs.pasteboard.html#types","kind":"method"},{"fullName":"hs.pasteboard.hasType(uti)","description":"Check whether a specific UTI type is currently available on the pasteboard","url":"hs.pasteboard.html#hasType","kind":"method"},{"fullName":"hs.pasteboard.clear()","description":"Clear all contents from the pasteboard","url":"hs.pasteboard.html#clear","kind":"method"},{"fullName":"hs.pasteboard.addWatcher(listener)","description":"Add a watcher that is called whenever the pasteboard contents change. Multiple watchers may be registered; they are each called independently. Because macOS provides no pasteboard change notification API, this is implemented by polling changeCount at the interval specified by watcherInterval.","url":"hs.pasteboard.html#addWatcher","kind":"method"},{"fullName":"hs.pasteboard.removeWatcher(listener)","description":"Remove a previously registered pasteboard watcher","url":"hs.pasteboard.html#removeWatcher","kind":"method"},{"fullName":"hs.permissions","description":"Module for checking and requesting system permissions","url":"hs.permissions.html","kind":"module"},{"fullName":"hs.permissions.checkAccessibility()","description":"Check if the app has Accessibility permission","url":"hs.permissions.html#checkAccessibility","kind":"method"},{"fullName":"hs.permissions.requestAccessibility()","description":"Request Accessibility permission (shows system dialog if not granted)","url":"hs.permissions.html#requestAccessibility","kind":"method"},{"fullName":"hs.permissions.checkScreenRecording()","description":"Check if the app has Screen Recording permission","url":"hs.permissions.html#checkScreenRecording","kind":"method"},{"fullName":"hs.permissions.requestScreenRecording()","description":"Request Screen Recording permission","url":"hs.permissions.html#requestScreenRecording","kind":"method"},{"fullName":"hs.permissions.checkCamera()","description":"Check if the app has Camera permission","url":"hs.permissions.html#checkCamera","kind":"method"},{"fullName":"hs.permissions.requestCamera()","description":"Request Camera permission (shows system dialog if not granted)","url":"hs.permissions.html#requestCamera","kind":"method"},{"fullName":"hs.permissions.checkMicrophone()","description":"Check if the app has Microphone permission","url":"hs.permissions.html#checkMicrophone","kind":"method"},{"fullName":"hs.permissions.requestMicrophone()","description":"Request Microphone permission (shows system dialog if not granted)","url":"hs.permissions.html#requestMicrophone","kind":"method"},{"fullName":"hs.permissions.checkNotifications()","description":"Check if the app has permission to display notifications. The result is cached from the last request or check; the cache is refreshed asynchronously, so the very first call in a session may return false before the cached value is populated. Use requestNotifications() on first launch to ensure the result is accurate.","url":"hs.permissions.html#checkNotifications","kind":"method"},{"fullName":"hs.permissions.requestNotifications()","description":"Request notification permission (shows the system dialog if the user has not yet decided). It is safe to call this on every launch — the dialog only appears once; subsequent calls resolve immediately with the previously granted or denied state.","url":"hs.permissions.html#requestNotifications","kind":"method"},{"fullName":"hs.permissions.checkLocation()","description":"Check if the app has Location permission.","url":"hs.permissions.html#checkLocation","kind":"method"},{"fullName":"hs.permissions.requestLocation()","description":"Request Location permission (shows the system dialog if the user has not yet decided).","url":"hs.permissions.html#requestLocation","kind":"method"},{"fullName":"hs.permissions.checkInputMonitoring()","description":"Check if the app has Input Monitoring permission. Input Monitoring is required for hs.keyboard to query and control CapsLock state and LEDs on a per-keyboard basis.","url":"hs.permissions.html#checkInputMonitoring","kind":"method"},{"fullName":"hs.permissions.requestInputMonitoring()","description":"Request Input Monitoring permission (shows the system dialog if the user has not yet decided).","url":"hs.permissions.html#requestInputMonitoring","kind":"method"},{"fullName":"hs.plist","description":"Module for reading and writing macOS property list (plist) files.","url":"hs.plist.html","kind":"module"},{"fullName":"hs.plist.fromFile(path)","description":"Read a plist file and return its contents as a JavaScript value. Supports both XML and binary plist formats. Returns a JavaScript object for dictionary-rooted plists, an array for array-rooted plists, or a string or number for scalar-rooted plists.","url":"hs.plist.html#fromFile","kind":"method"},{"fullName":"hs.plist.fromString(plistString)","description":"Read a plist from an XML string and return its contents as a JavaScript value.","url":"hs.plist.html#fromString","kind":"method"},{"fullName":"hs.plist.toFile(path, data, binary)","description":"Write a JavaScript object to a plist file on disk. Keys must be strings. Values may be strings, numbers, booleans, arrays, or nested objects. JavaScript null values are not plist-compatible and will cause the write to fail.","url":"hs.plist.html#toFile","kind":"method"},{"fullName":"hs.plist.toString(data, binary)","description":"Serialize a JavaScript object to a plist string. With binary set to false (default), returns an XML plist string suitable for storing in text files or passing to readString. With binary set to true, returns a base64-encoded binary plist string.","url":"hs.plist.html#toString","kind":"method"},{"fullName":"hs.power","description":"Monitor and control system power: prevent sleep, read battery state, respond to power events, and lock or sleep the machine.","url":"hs.power.html","kind":"module"},{"fullName":"hs.power.percentage","description":"The current battery charge percentage (0–100), or -1 if no battery is present.","url":"hs.power.html#percentage","kind":"property"},{"fullName":"hs.power.isCharging","description":"Whether the battery is currently charging. Returns false when no battery is present.","url":"hs.power.html#isCharging","kind":"property"},{"fullName":"hs.power.powerSource","description":"The current power source. Returns \"ac\" when plugged in, \"battery\" when on battery power, \"ups\" when powered by a UPS, or \"unknown\" if the source cannot be determined.","url":"hs.power.html#powerSource","kind":"property"},{"fullName":"hs.power.isLowPowerMode","description":"Whether Low Power Mode is currently active.","url":"hs.power.html#isLowPowerMode","kind":"property"},{"fullName":"hs.power.thermalState","description":"The current thermal state of the system. Returns one of: \"nominal\", \"fair\", \"serious\", \"critical\".","url":"hs.power.html#thermalState","kind":"property"},{"fullName":"hs.power.preventSleep(type)","description":"Prevents the specified type of system sleep. Creates an IOKit power assertion that stops macOS from allowing the specified type of sleep. Call allowSleep with the same type to release the assertion. idle sleep), \"systemIdle\" (prevent system idle sleep), \"system\" (prevent all system sleep, including from power button or lid close).","url":"hs.power.html#preventSleep","kind":"method"},{"fullName":"hs.power.allowSleep(type)","description":"Releases a previously created sleep prevention assertion.","url":"hs.power.html#allowSleep","kind":"method"},{"fullName":"hs.power.isSleepPrevented(type)","description":"Returns whether Hammerspoon is currently preventing the specified type of sleep.","url":"hs.power.html#isSleepPrevented","kind":"method"},{"fullName":"hs.power.declareActivity()","description":"Simulates user activity, briefly resetting the display idle timer. Equivalent to moving the mouse — does not create a persistent assertion.","url":"hs.power.html#declareActivity","kind":"method"},{"fullName":"hs.power.currentAssertions()","description":"Returns the active power management assertions from all processes on the system.","url":"hs.power.html#currentAssertions","kind":"method"},{"fullName":"hs.power.systemSleep()","description":"Puts the system to sleep immediately. Requires the Automation permission for System Events.","url":"hs.power.html#systemSleep","kind":"method"},{"fullName":"hs.power.lockScreen()","description":"Locks the screen immediately.","url":"hs.power.html#lockScreen","kind":"method"},{"fullName":"hs.power.startScreensaver()","description":"Starts the screensaver immediately.","url":"hs.power.html#startScreensaver","kind":"method"},{"fullName":"hs.power.batteryInfo()","description":"Returns a snapshot of all available battery information, or null if no battery is present.","url":"hs.power.html#batteryInfo","kind":"method"},{"fullName":"hs.power.addEventWatcher(listener)","description":"Registers a listener that fires when system power events occur. \"screensDidSleep\", \"screensDidWake\", \"screensDidLock\", \"screensDidUnlock\", \"screensaverDidStart\", \"screensaverDidStop\", \"screensaverWillStop\", \"systemWillSleep\", \"systemDidWake\", \"systemWillPowerOff\", \"sessionDidBecomeActive\", \"sessionDidResignActive\". The OS notification subscription starts lazily on the first listener and is released automatically when the last listener is removed.","url":"hs.power.html#addEventWatcher","kind":"method"},{"fullName":"hs.power.removeEventWatcher(listener)","description":"Removes a previously registered power event listener.","url":"hs.power.html#removeEventWatcher","kind":"method"},{"fullName":"hs.power.addBatteryWatcher(listener)","description":"Registers a listener that fires whenever battery state changes. The listener receives no arguments; call batteryInfo() or read individual properties inside the callback to determine what changed. The OS notification subscription starts lazily on the first listener and is released automatically when the last listener is removed.","url":"hs.power.html#addBatteryWatcher","kind":"method"},{"fullName":"hs.power.removeBatteryWatcher(listener)","description":"Removes a previously registered battery change listener.","url":"hs.power.html#removeBatteryWatcher","kind":"method"},{"fullName":"hs.screen","description":"Inspect and control the displays attached to the system.","url":"hs.screen.html","kind":"module"},{"fullName":"hs.screen.all()","description":"All connected screens.","url":"hs.screen.html#all","kind":"method"},{"fullName":"hs.screen.main()","description":"The screen that currently contains the focused window, or the screen with the keyboard focus if no window is focused.","url":"hs.screen.html#main","kind":"method"},{"fullName":"hs.screen.primary()","description":"The primary display — the one that contains the global menu bar.","url":"hs.screen.html#primary","kind":"method"},{"fullName":"hs.screen.addWatcher(listener)","description":"Registers a listener that fires whenever the display configuration changes — monitors connected/disconnected, resolution or arrangement changed, or the menu bar moved to a different display. The listener receives no arguments; call all()/main()/primary() inside the callback to inspect the new configuration. The OS notification subscription starts lazily on the first listener and is released automatically when the last listener is removed.","url":"hs.screen.html#addWatcher","kind":"method"},{"fullName":"hs.screen.removeWatcher(listener)","description":"Removes a previously registered display-configuration listener.","url":"hs.screen.html#removeWatcher","kind":"method"},{"fullName":"hs.serial","description":"Communicate with devices connected to serial ports (RS-232, USB-serial adapters, etc).","url":"hs.serial.html","kind":"module"},{"fullName":"hs.serial.availablePortNames()","description":"Returns the names of all currently connected serial ports.","url":"hs.serial.html#availablePortNames","kind":"method"},{"fullName":"hs.serial.availablePortPaths()","description":"Returns the device paths of all currently connected serial ports.","url":"hs.serial.html#availablePortPaths","kind":"method"},{"fullName":"hs.serial.availablePortDetails()","description":"Returns IOKit registry details for all currently connected serial ports.","url":"hs.serial.html#availablePortDetails","kind":"method"},{"fullName":"hs.serial.createPortNamed(name)","description":"Creates a serial port object for a port discovered via availablePortNames().","url":"hs.serial.html#createPortNamed","kind":"method"},{"fullName":"hs.serial.createPortAtPath(path)","description":"Creates a serial port object for an arbitrary device path. Unlike createPortNamed(), the path does not need to correspond to a port currently discoverable via IOKit — it is only validated when you call open().","url":"hs.serial.html#createPortAtPath","kind":"method"},{"fullName":"hs.serial.addWatcher(listener)","description":"Register a listener for serial port connection and disconnection events. The listener is called with two arguments: the event type string (\"added\" or \"removed\") and a port-info object with name and path fields.","url":"hs.serial.html#addWatcher","kind":"method"},{"fullName":"hs.serial.removeWatcher(listener)","description":"Remove a previously registered serial port event listener.","url":"hs.serial.html#removeWatcher","kind":"method"},{"fullName":"hs.sharing","description":"Share data with other people and apps via macOS sharing services (Mail, Messages, AirDrop, and more).","url":"hs.sharing.html","kind":"module"},{"fullName":"hs.sharing.builtinServices","description":"A table of shortcut names for the sharing services that are still functional on modern macOS, mapped to the raw service identifiers createShare() expects. | Key | Service | |-----|---------| | mail | Compose an email in Mail | | message | Compose a message in Messages | | airdrop | Send via AirDrop | | safariReadingList | Add to Safari's Reading List | | photos | Add to the Photos library | | desktopPicture | Use as the desktop picture |","url":"hs.sharing.html#builtinServices","kind":"property"},{"fullName":"hs.sharing.createShare(name)","description":"Creates a sharing service for the given name.","url":"hs.sharing.html#createShare","kind":"method"},{"fullName":"hs.sharing.servicesFor(items)","description":"Finds every sharing service — built-in and third-party (e.g. Notes, Reminders, installed apps' Share Extensions) — that can handle the given items.","url":"hs.sharing.html#servicesFor","kind":"method"},{"fullName":"hs.shortcuts","description":"Run and interact with macOS Shortcuts from JavaScript.","url":"hs.shortcuts.html","kind":"module"},{"fullName":"hs.shortcuts.list()","description":"Returns an array of all available shortcuts. | Key | Type | Description | |-----|------|-------------| | name | string | The display name of the shortcut | | id | string | A UUID uniquely identifying the shortcut | | acceptsInput | boolean | Whether the shortcut expects input when run | | actionCount | number | How many actions the shortcut contains |","url":"hs.shortcuts.html#list","kind":"method"},{"fullName":"hs.shortcuts.run(name)","description":"Runs a Shortcuts shortcut by name and returns any output. Executes the shortcut in the background via the shortcuts CLI tool. If the shortcut produces output (via a \"Stop and Output\" action), the Promise resolves with that string. If the shortcut produces no output, the Promise resolves with null. The Promise rejects if the shortcut cannot be found or exits with a non-zero status.","url":"hs.shortcuts.html#run","kind":"method"},{"fullName":"hs.shortcuts.open(name)","description":"Opens a shortcut in the Shortcuts app for viewing or editing. Uses the shortcuts://open-shortcut URL scheme to bring Shortcuts to the foreground and navigate directly to the named shortcut.","url":"hs.shortcuts.html#open","kind":"method"},{"fullName":"hs.sound","description":"Play audio from files on disk or from the system's built-in sound library.","url":"hs.sound.html","kind":"module"},{"fullName":"hs.sound.fromFile(path)","description":"Loads an audio file from the given path and returns a sound object. Returns null if the file cannot be loaded.","url":"hs.sound.html#fromFile","kind":"method"},{"fullName":"hs.sound.named(name)","description":"Creates a sound object for a built-in system sound by name. Returns null if no sound with that name can be found. Use hs.sound.systemSounds() to discover available names.","url":"hs.sound.html#named","kind":"method"},{"fullName":"hs.sound.systemSounds()","description":"Returns a sorted array of all available system sound names. These names can be passed directly to hs.sound.named(). Scans /System/Library/Sounds, /Library/Sounds, and ~/Library/Sounds.","url":"hs.sound.html#systemSounds","kind":"method"},{"fullName":"hs.spotlight","description":"Query the macOS Spotlight metadata database.","url":"hs.spotlight.html","kind":"module"},{"fullName":"hs.spotlight.scope","description":"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) |","url":"hs.spotlight.html#scope","kind":"property"},{"fullName":"hs.spotlight.attribute","description":"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 |","url":"hs.spotlight.html#attribute","kind":"property"},{"fullName":"hs.spotlight.create()","description":"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.","url":"hs.spotlight.html#create","kind":"method"},{"fullName":"hs.spotlight.search(predicate, callback)","description":"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.","url":"hs.spotlight.html#search","kind":"method"},{"fullName":"hs.streamdeck","description":"Direct hardware control of Elgato Stream Deck devices — buttons, encoders, and the LCD touch strip on the Stream Deck Plus.","url":"hs.streamdeck.html","kind":"module"},{"fullName":"hs.streamdeck.all()","description":"All Stream Deck devices currently connected to the system.","url":"hs.streamdeck.html#all","kind":"method"},{"fullName":"hs.streamdeck.findBySerialNumber(serialNumber)","description":"Find the connected device with the given serial number.","url":"hs.streamdeck.html#findBySerialNumber","kind":"method"},{"fullName":"hs.streamdeck.addWatcher(listener)","description":"Register a listener for Stream Deck connect/disconnect events.","url":"hs.streamdeck.html#addWatcher","kind":"method"},{"fullName":"hs.streamdeck.removeWatcher(listener)","description":"Remove a previously registered connect/disconnect listener.","url":"hs.streamdeck.html#removeWatcher","kind":"method"},{"fullName":"hs.task","description":"Module for running external processes","url":"hs.task.html","kind":"module"},{"fullName":"hs.task.sequence","description":"Run multiple tasks in sequence. Swift-retained storage for the JS implementation.","url":"hs.task.html#sequence","kind":"property"},{"fullName":"hs.task.TaskBuilder","description":"TaskBuilder class. Swift-retained storage for the JS implementation.","url":"hs.task.html#TaskBuilder","kind":"property"},{"fullName":"hs.task.create(launchPath, arguments, completionCallback, environment, streamingCallback)","description":"Create a new task","url":"hs.task.html#create","kind":"method"},{"fullName":"hs.task.runAsync(launchPath, args, options, legacyStreamCallback)","description":"Create and run a task asynchronously","url":"hs.task.html#runAsync","kind":"method"},{"fullName":"hs.task.shell(command, options)","description":"Run a shell command asynchronously","url":"hs.task.html#shell","kind":"method"},{"fullName":"hs.task.parallel(tasks)","description":"Run multiple tasks in parallel","url":"hs.task.html#parallel","kind":"method"},{"fullName":"hs.task.builder(launchPath)","description":"Create a task builder for fluent API","url":"hs.task.html#builder","kind":"method"},{"fullName":"hs.timer","description":"Module for creating and managing timers","url":"hs.timer.html","kind":"module"},{"fullName":"hs.timer.create(interval, callback, continueOnError)","description":"Create a new timer","url":"hs.timer.html#create","kind":"method"},{"fullName":"hs.timer.doAfter(seconds, callback)","description":"Create and start a one-shot timer","url":"hs.timer.html#doAfter","kind":"method"},{"fullName":"hs.timer.doEvery(interval, callback)","description":"Create and start a repeating timer","url":"hs.timer.html#doEvery","kind":"method"},{"fullName":"hs.timer.doAt(time, repeatInterval, callback, continueOnError)","description":"Create and start a timer that fires at a specific time","url":"hs.timer.html#doAt","kind":"method"},{"fullName":"hs.timer.usleep(microseconds)","description":"Block execution for a specified number of microseconds (strongly discouraged)","url":"hs.timer.html#usleep","kind":"method"},{"fullName":"hs.timer.secondsSinceEpoch()","description":"Get the current time as seconds since the UNIX epoch with sub-second precision","url":"hs.timer.html#secondsSinceEpoch","kind":"method"},{"fullName":"hs.timer.absoluteTime()","description":"Get the number of nanoseconds since the system was booted (excluding sleep time)","url":"hs.timer.html#absoluteTime","kind":"method"},{"fullName":"hs.timer.localTime()","description":"Get the number of seconds since local midnight","url":"hs.timer.html#localTime","kind":"method"},{"fullName":"hs.timer.minutes(n)","description":"Converts minutes to seconds","url":"hs.timer.html#minutes","kind":"method"},{"fullName":"hs.timer.hours(n)","description":"Converts hours to seconds","url":"hs.timer.html#hours","kind":"method"},{"fullName":"hs.timer.days(n)","description":"Converts days to seconds","url":"hs.timer.html#days","kind":"method"},{"fullName":"hs.timer.weeks(n)","description":"Converts weeks to seconds","url":"hs.timer.html#weeks","kind":"method"},{"fullName":"hs.timer.doUntil(predicateFn, actionFn, checkInterval)","description":"Repeat a function/lambda until a given predicate function/lambda returns true","url":"hs.timer.html#doUntil","kind":"method"},{"fullName":"hs.timer.doWhile(predicateFn, actionFn, checkInterval)","description":"Repeat a function/lambda while a given predicate function/lambda returns true","url":"hs.timer.html#doWhile","kind":"method"},{"fullName":"hs.timer.waitUntil(predicateFn, actionFn, checkInterval)","description":"Wait to call a function/lambda until a given predicate function/lambda returns true","url":"hs.timer.html#waitUntil","kind":"method"},{"fullName":"hs.timer.waitWhile(predicateFn, actionFn, checkInterval)","description":"Wait to call a function/lambda until a given predicate function/lambda returns false","url":"hs.timer.html#waitWhile","kind":"method"},{"fullName":"hs.translation","description":"Translate text between languages using the macOS on-device Translation framework.","url":"hs.translation.html","kind":"module"},{"fullName":"hs.translation.supportedLanguages()","description":"All language codes supported by the on-device translation engine. Resolves to an array of BCP-47 identifiers (e.g. [\"ar\", \"de\", \"en\", \"es\", \"fr\"]). This covers every language the framework knows about, regardless of whether the packs are installed locally. Use status() to distinguish installed pairs from merely supported ones.","url":"hs.translation.html#supportedLanguages","kind":"method"},{"fullName":"hs.translation.status(sourceLanguage, targetLanguage)","description":"Check the installation status of a language pair.","url":"hs.translation.html#status","kind":"method"},{"fullName":"hs.translation.session(sourceLanguage, targetLanguage)","description":"Create a translation session for a language pair. Returns an HSTranslationSession, or null if the system is running macOS older than 26.0.","url":"hs.translation.html#session","kind":"method"},{"fullName":"hs.ui","description":"# hs.ui","url":"hs.ui.html","kind":"module"},{"fullName":"hs.ui.window(dict)","description":"Create a custom UI window Creates a borderless window that can contain custom UI elements built using a declarative, SwiftUI-like syntax with shapes, text, and layout containers.","url":"hs.ui.html#window","kind":"method"},{"fullName":"hs.ui.alert(message)","description":"Create a temporary on-screen alert Displays a temporary notification that automatically dismisses after the specified duration. Similar to the old hs.alert module but with more features.","url":"hs.ui.html#alert","kind":"method"},{"fullName":"hs.ui.dialog(message)","description":"Create a modal dialog with buttons Shows a blocking dialog with customizable message, informative text, and buttons. Use the callback to handle button presses.","url":"hs.ui.html#dialog","kind":"method"},{"fullName":"hs.ui.textPrompt(message)","description":"Create a text input prompt Shows a modal dialog with a text input field. The callback receives the button index and the entered text.","url":"hs.ui.html#textPrompt","kind":"method"},{"fullName":"hs.ui.string(initialValue)","description":"Create a reactive string for binding text element content to a dynamic value An HSString is a reactive value container. When passed to .text(), the canvas automatically re-renders whenever .set() is called from JavaScript.","url":"hs.ui.html#string","kind":"method"},{"fullName":"hs.ui.filePicker()","description":"Create a file or directory picker Shows a standard macOS file picker dialog. Can be configured to select files, directories, or both, with support for file type filtering and multiple selection.","url":"hs.ui.html#filePicker","kind":"method"},{"fullName":"hs.ui.webview()","description":"Create a web browser element for embedding in hs.ui.window (macOS 26+) Returns a UIWebView element that you configure and then embed in any hs.ui.window via .webview(element). The element fills the available space inside the window layout. Keep a reference to call navigation methods after the window is shown.","url":"hs.ui.html#webview","kind":"method"},{"fullName":"hs.urlevent","description":"Handle URL events received by Hammerspoon 2.","url":"hs.urlevent.html","kind":"module"},{"fullName":"hs.urlevent.httpCallback","description":"Callback invoked when Hammerspoon 2 receives an http:// or https:// URL. Fires only when Hammerspoon 2 is the system default handler for http/https. Assign null to remove the callback.","url":"hs.urlevent.html#httpCallback","kind":"property"},{"fullName":"hs.urlevent.mailtoCallback","description":"Callback invoked when Hammerspoon 2 receives a mailto: URL. Fires only when Hammerspoon 2 is the system default handler for mailto. Assign null to remove the callback.","url":"hs.urlevent.html#mailtoCallback","kind":"property"},{"fullName":"hs.urlevent.bind(eventName, callback)","description":"Register or remove a callback for a named hammerspoon2:// URL event. The URL format is hammerspoon2://eventName?key=value. The host component (eventName) selects the callback to invoke.","url":"hs.urlevent.html#bind","kind":"method"},{"fullName":"hs.urlevent.openURL(urlString)","description":"Open a URL using the system default application for its scheme.","url":"hs.urlevent.html#openURL","kind":"method"},{"fullName":"hs.urlevent.openURLWithBundle(urlString, bundleID)","description":"Open a URL with a specific application identified by bundle ID.","url":"hs.urlevent.html#openURLWithBundle","kind":"method"},{"fullName":"hs.urlevent.getDefaultHandler(scheme)","description":"Returns the bundle identifier of the default application for a URL scheme.","url":"hs.urlevent.html#getDefaultHandler","kind":"method"},{"fullName":"hs.urlevent.getAllHandlersForScheme(scheme)","description":"Returns all bundle identifiers capable of handling a URL scheme.","url":"hs.urlevent.html#getAllHandlersForScheme","kind":"method"},{"fullName":"hs.urlevent.setDefaultHandler(scheme, bundleID)","description":"Set the default application for a URL scheme. macOS may display a confirmation dialog for sensitive schemes such as http and https. For custom schemes (hammerspoon2) no dialog is shown.","url":"hs.urlevent.html#setDefaultHandler","kind":"method"},{"fullName":"hs.usb","description":"Module for monitoring USB device connections and disconnections","url":"hs.usb.html","kind":"module"},{"fullName":"hs.usb.attachedDevices()","description":"Returns all currently attached USB devices.","url":"hs.usb.html#attachedDevices","kind":"method"},{"fullName":"hs.usb.addWatcher(listener)","description":"Register a listener for USB device connection and disconnection events. The listener is called with two arguments: the event type string (\"added\" or \"removed\") and a device-info object with the same fields as attachedDevices().","url":"hs.usb.html#addWatcher","kind":"method"},{"fullName":"hs.usb.removeWatcher(listener)","description":"Remove a previously registered USB event listener.","url":"hs.usb.html#removeWatcher","kind":"method"},{"fullName":"hs.userdefaults","description":"Module for storing small amounts of data that persists across Hammerspoon restarts.","url":"hs.userdefaults.html","kind":"module"},{"fullName":"hs.userdefaults.set(key, value)","description":"Store a value under the given key. The value persists across Hammerspoon restarts. Values must be storable as a property list: strings, numbers, booleans, Dates, arrays, or objects (which may themselves nest any of those types). is rejected with a logged error and nothing is stored. JavaScript functions have no property-list representation; if passed directly, or nested inside an array or object, they are silently stored as an empty object.","url":"hs.userdefaults.html#set","kind":"method"},{"fullName":"hs.userdefaults.get(key)","description":"Retrieve a previously stored value.","url":"hs.userdefaults.html#get","kind":"method"},{"fullName":"hs.userdefaults.clear(key)","description":"Delete a previously stored value.","url":"hs.userdefaults.html#clear","kind":"method"},{"fullName":"hs.userdefaults.getKeys()","description":"Get the names of all currently stored settings.","url":"hs.userdefaults.html#getKeys","kind":"method"},{"fullName":"hs.userdefaults.addWatcher(key, listener)","description":"Watch a key for changes.","url":"hs.userdefaults.html#addWatcher","kind":"method"},{"fullName":"hs.userdefaults.removeWatcher(key, listener)","description":"Remove a previously registered watcher.","url":"hs.userdefaults.html#removeWatcher","kind":"method"},{"fullName":"hs.wifi","description":"Control and query Wi-Fi interfaces, scan for networks, and watch for Wi-Fi events.","url":"hs.wifi.html","kind":"module"},{"fullName":"hs.wifi.watcherEventTypes","description":"The Wi-Fi event types that can be passed to HSWifiWatcher.events.","url":"hs.wifi.html#watcherEventTypes","kind":"property"},{"fullName":"hs.wifi.interfaces()","description":"Returns the names of all Wi-Fi interfaces attached to the system (e.g. [\"en0\"]).","url":"hs.wifi.html#interfaces","kind":"method"},{"fullName":"hs.wifi.interfaceDetails(interface)","description":"Returns detailed information about a Wi-Fi interface.","url":"hs.wifi.html#interfaceDetails","kind":"method"},{"fullName":"hs.wifi.currentNetwork(interface)","description":"Returns the SSID of the network currently joined on an interface.","url":"hs.wifi.html#currentNetwork","kind":"method"},{"fullName":"hs.wifi.setPower(state, interface)","description":"Turns a Wi-Fi interface on or off.","url":"hs.wifi.html#setPower","kind":"method"},{"fullName":"hs.wifi.disassociate(interface)","description":"Disconnects an interface from its current network.","url":"hs.wifi.html#disassociate","kind":"method"},{"fullName":"hs.wifi.associate(ssid, passphrase, interface)","description":"Scans for a network by SSID and joins it. Enterprise networks are not supported. This can take several seconds; it runs off the main thread so it does not block the app.","url":"hs.wifi.html#associate","kind":"method"},{"fullName":"hs.wifi.scanNetworks(interface)","description":"Scans for visible Wi-Fi networks. This can take a few seconds; it runs off the main thread so it does not block the app.","url":"hs.wifi.html#scanNetworks","kind":"method"},{"fullName":"hs.wifi.addWatcher()","description":"Creates a new Wi-Fi event watcher. Call .setCallback() and .start() to activate it. The watcher is stopped automatically when the module shuts down.","url":"hs.wifi.html#addWatcher","kind":"method"},{"fullName":"hs.window","description":"Module for interacting with windows","url":"hs.window.html","kind":"module"},{"fullName":"hs.window.focusedWindow()","description":"Get the currently focused window","url":"hs.window.html#focusedWindow","kind":"method"},{"fullName":"hs.window.allWindows()","description":"Get all windows from all applications","url":"hs.window.html#allWindows","kind":"method"},{"fullName":"hs.window.visibleWindows()","description":"Get all visible (not minimized) windows","url":"hs.window.html#visibleWindows","kind":"method"},{"fullName":"hs.window.windowsForApp(app)","description":"Get windows for a specific application","url":"hs.window.html#windowsForApp","kind":"method"},{"fullName":"hs.window.windowsOnScreen(screenIndex)","description":"Get all windows on a specific screen","url":"hs.window.html#windowsOnScreen","kind":"method"},{"fullName":"hs.window.windowAtPoint(point)","description":"Get the window at a specific screen position","url":"hs.window.html#windowAtPoint","kind":"method"},{"fullName":"hs.window.orderedWindows()","description":"Get ordered windows (front to back)","url":"hs.window.html#orderedWindows","kind":"method"},{"fullName":"hs.window.snapshotForID(id, keepTransparency)","description":"Capture the current on-screen contents of the window with the given ID. Requires Screen Recording permission.","url":"hs.window.html#snapshotForID","kind":"method"},{"fullName":"hs.window.findByTitle(title)","description":"Find windows by title Parameter title: The window title to search for. All windows with titles that include this string, will be matched","url":"hs.window.html#findByTitle","kind":"method"},{"fullName":"hs.window.currentWindows()","description":"Get all windows for the current application","url":"hs.window.html#currentWindows","kind":"method"},{"fullName":"hs.window.moveToLeftHalf(win)","description":"Move a window to left half of screen Parameter win: An HSWindow object","url":"hs.window.html#moveToLeftHalf","kind":"method"},{"fullName":"hs.window.moveToRightHalf(win)","description":"Move a window to right half of screen Parameter win: An HSWindow object","url":"hs.window.html#moveToRightHalf","kind":"method"},{"fullName":"hs.window.maximize(win)","description":"Maximize a window Parameter win: An HSWindow object","url":"hs.window.html#maximize","kind":"method"},{"fullName":"HSApplication","description":"Object representing an application. You should not instantiate this directly in JavaScript, but rather, use the methods from hs.application which will return appropriate HSApplication objects.","url":"HSApplication.html","kind":"type"},{"fullName":"HSApplication.pid","description":"POSIX Process Identifier","url":"HSApplication.html#pid","kind":"property"},{"fullName":"HSApplication.bundleID","description":"Bundle Identifier (e.g. com.apple.Safari)","url":"HSApplication.html#bundleID","kind":"property"},{"fullName":"HSApplication.title","description":"The application's title","url":"HSApplication.html#title","kind":"property"},{"fullName":"HSApplication.bundlePath","description":"Location of the application on disk","url":"HSApplication.html#bundlePath","kind":"property"},{"fullName":"HSApplication.isHidden","description":"Is the application hidden","url":"HSApplication.html#isHidden","kind":"property"},{"fullName":"HSApplication.isActive","description":"Is the application focused","url":"HSApplication.html#isActive","kind":"property"},{"fullName":"HSApplication.mainWindow","description":"The main window of this application, or nil if there is no main window","url":"HSApplication.html#mainWindow","kind":"property"},{"fullName":"HSApplication.focusedWindow","description":"The focused window of this application, or nil if there is no focused window","url":"HSApplication.html#focusedWindow","kind":"property"},{"fullName":"HSApplication.allWindows","description":"All windows of this application","url":"HSApplication.html#allWindows","kind":"property"},{"fullName":"HSApplication.visibleWindows","description":"All visible (ie non-hidden) windows of this application","url":"HSApplication.html#visibleWindows","kind":"property"},{"fullName":"HSApplication.isRunning","description":"Whether the application process is still running","url":"HSApplication.html#isRunning","kind":"property"},{"fullName":"HSApplication.kind","description":"The kind of application: \"standard\" (regular dock app), \"accessory\" (no dock), or \"background\" (agent)","url":"HSApplication.html#kind","kind":"property"},{"fullName":"HSApplication.kill()","description":"Terminate the application","url":"HSApplication.html#kill","kind":"method"},{"fullName":"HSApplication.kill9()","description":"Force-terminate the application","url":"HSApplication.html#kill9","kind":"method"},{"fullName":"HSApplication.axElement()","description":"The application's HSAXElement object, for use with the hs.ax APIs","url":"HSApplication.html#axElement","kind":"method"},{"fullName":"HSApplication.activate(allWindows)","description":"Bring this application to the foreground","url":"HSApplication.html#activate","kind":"method"},{"fullName":"HSApplication.hide()","description":"Hide this application and all its windows","url":"HSApplication.html#hide","kind":"method"},{"fullName":"HSApplication.unhide()","description":"Unhide this application","url":"HSApplication.html#unhide","kind":"method"},{"fullName":"HSApplication.getMenuItems()","description":"Get the full menu structure of this application","url":"HSApplication.html#getMenuItems","kind":"method"},{"fullName":"HSApplication.findMenuItemByName(name)","description":"Find a menu item by searching all menus for a matching title (case-insensitive)","url":"HSApplication.html#findMenuItemByName","kind":"method"},{"fullName":"HSApplication.findMenuItemByPath(path)","description":"Find a menu item by following a hierarchical path of titles","url":"HSApplication.html#findMenuItemByPath","kind":"method"},{"fullName":"HSApplication.selectMenuItemByName(name)","description":"Click a menu item found by searching all menus for a matching title (case-insensitive)","url":"HSApplication.html#selectMenuItemByName","kind":"method"},{"fullName":"HSApplication.selectMenuItemByPath(path)","description":"Click a menu item found by following a hierarchical path of titles","url":"HSApplication.html#selectMenuItemByPath","kind":"method"},{"fullName":"HSApplication.findWindow(pattern)","description":"Find windows whose title contains the given string (case-insensitive)","url":"HSApplication.html#findWindow","kind":"method"},{"fullName":"HSApplication.getWindow(title)","description":"Get the first window with exactly the given title","url":"HSApplication.html#getWindow","kind":"method"},{"fullName":"HSAudioDevice","description":"An audio device attached to the system. Obtain instances via `hs.audiodevice module methods — do not instantiate directly. ## Getting and setting volume `javascript const dev = hs.audiodevice.defaultOutputDevice(); if (dev) { console.log(dev.volume); // 0.0 – 1.0, or null dev.volume = 0.5; } ` ## Watching for changes `javascript const dev = hs.audiodevice.defaultOutputDevice(); if (dev) { var fn = function(event) { console.log(\"Device event:\", event); }; dev.addWatcher(fn); // later… dev.removeWatcher(fn); } ``","url":"HSAudioDevice.html","kind":"type"},{"fullName":"HSAudioDevice.id","description":"The CoreAudio object ID of this device.","url":"HSAudioDevice.html#id","kind":"property"},{"fullName":"HSAudioDevice.name","description":"The human-readable name of this device (e.g. \"Built-in Output\").","url":"HSAudioDevice.html#name","kind":"property"},{"fullName":"HSAudioDevice.uid","description":"The persistent unique identifier for this device.","url":"HSAudioDevice.html#uid","kind":"property"},{"fullName":"HSAudioDevice.isOutput","description":"Whether this device has output streams (can play audio).","url":"HSAudioDevice.html#isOutput","kind":"property"},{"fullName":"HSAudioDevice.isInput","description":"Whether this device has input streams (can record audio).","url":"HSAudioDevice.html#isInput","kind":"property"},{"fullName":"HSAudioDevice.transportType","description":"The transport mechanism: \"built-in\", \"usb\", \"bluetooth\", \"bluetooth-le\", \"hdmi\", \"display-port\", \"firewire\", \"airplay\", \"avb\", \"thunderbolt\", \"virtual\", \"aggregate\", \"pci\", or \"unknown\".","url":"HSAudioDevice.html#transportType","kind":"property"},{"fullName":"HSAudioDevice.outputChannels","description":"Number of output channels, or 0 if the device has no output.","url":"HSAudioDevice.html#outputChannels","kind":"property"},{"fullName":"HSAudioDevice.inputChannels","description":"Number of input channels, or 0 if the device has no input.","url":"HSAudioDevice.html#inputChannels","kind":"property"},{"fullName":"HSAudioDevice.volume","description":"Output volume scalar in the range 0.0–1.0, or null if the device has no controllable output volume. Setting null is a no-op.","url":"HSAudioDevice.html#volume","kind":"property"},{"fullName":"HSAudioDevice.muted","description":"Whether output is muted. Always false if the device has no mutable output.","url":"HSAudioDevice.html#muted","kind":"property"},{"fullName":"HSAudioDevice.balance","description":"Output stereo balance in the range 0.0 (full left)–1.0 (full right), or null if balance control is not available.","url":"HSAudioDevice.html#balance","kind":"property"},{"fullName":"HSAudioDevice.inputVolume","description":"Input (microphone) volume scalar in the range 0.0–1.0, or null if the device has no controllable input volume.","url":"HSAudioDevice.html#inputVolume","kind":"property"},{"fullName":"HSAudioDevice.inputMuted","description":"Whether input is muted. Always false if the device has no mutable input.","url":"HSAudioDevice.html#inputMuted","kind":"property"},{"fullName":"HSAudioDevice.sampleRate","description":"The current nominal sample rate in Hz (e.g. 44100), or null if unknown.","url":"HSAudioDevice.html#sampleRate","kind":"property"},{"fullName":"HSAudioDevice.availableSampleRates","description":"All sample rates (in Hz) that this device supports. For devices that support a range, both the minimum and maximum are included.","url":"HSAudioDevice.html#availableSampleRates","kind":"property"},{"fullName":"HSAudioDevice.currentOutputDataSource()","description":"The current output data source as { id, name }, or null if unavailable.","url":"HSAudioDevice.html#currentOutputDataSource","kind":"method"},{"fullName":"HSAudioDevice.currentInputDataSource()","description":"The current input data source as { id, name }, or null if unavailable.","url":"HSAudioDevice.html#currentInputDataSource","kind":"method"},{"fullName":"HSAudioDevice.outputDataSources()","description":"All available output data sources as an array of { id, name } objects.","url":"HSAudioDevice.html#outputDataSources","kind":"method"},{"fullName":"HSAudioDevice.inputDataSources()","description":"All available input data sources as an array of { id, name } objects.","url":"HSAudioDevice.html#inputDataSources","kind":"method"},{"fullName":"HSAudioDevice.setCurrentOutputDataSource(sourceID)","description":"Select an output data source by its numeric ID.","url":"HSAudioDevice.html#setCurrentOutputDataSource","kind":"method"},{"fullName":"HSAudioDevice.setCurrentInputDataSource(sourceID)","description":"Select an input data source by its numeric ID.","url":"HSAudioDevice.html#setCurrentInputDataSource","kind":"method"},{"fullName":"HSAudioDevice.setDefaultOutputDevice()","description":"Make this device the system default output device.","url":"HSAudioDevice.html#setDefaultOutputDevice","kind":"method"},{"fullName":"HSAudioDevice.setDefaultInputDevice()","description":"Make this device the system default input device.","url":"HSAudioDevice.html#setDefaultInputDevice","kind":"method"},{"fullName":"HSAudioDevice.setDefaultEffectDevice()","description":"Make this device the system alert sound (effect) device.","url":"HSAudioDevice.html#setDefaultEffectDevice","kind":"method"},{"fullName":"HSAudioDevice.addWatcher(listener)","description":"Register a listener for a per-device property-change event.","url":"HSAudioDevice.html#addWatcher","kind":"method"},{"fullName":"HSAudioDevice.removeWatcher(listener)","description":"Remove a previously registered per-device listener.","url":"HSAudioDevice.html#removeWatcher","kind":"method"},{"fullName":"HSAXElement","description":"Object representing an Accessibility element. You should not instantiate this directly, but rather, use the hs.ax methods to create these as required.","url":"HSAXElement.html","kind":"type"},{"fullName":"HSAXElement.role","description":"The element's role (e.g., \"AXWindow\", \"AXButton\")","url":"HSAXElement.html#role","kind":"property"},{"fullName":"HSAXElement.subrole","description":"The element's subrole","url":"HSAXElement.html#subrole","kind":"property"},{"fullName":"HSAXElement.title","description":"The element's title","url":"HSAXElement.html#title","kind":"property"},{"fullName":"HSAXElement.value","description":"The element's value","url":"HSAXElement.html#value","kind":"property"},{"fullName":"HSAXElement.elementDescription","description":"The element's description","url":"HSAXElement.html#elementDescription","kind":"property"},{"fullName":"HSAXElement.isEnabled","description":"Whether the element is enabled","url":"HSAXElement.html#isEnabled","kind":"property"},{"fullName":"HSAXElement.isFocused","description":"Whether the element is focused","url":"HSAXElement.html#isFocused","kind":"property"},{"fullName":"HSAXElement.position","description":"The element's position on screen","url":"HSAXElement.html#position","kind":"property"},{"fullName":"HSAXElement.size","description":"The element's size","url":"HSAXElement.html#size","kind":"property"},{"fullName":"HSAXElement.frame","description":"The element's frame (position and size combined)","url":"HSAXElement.html#frame","kind":"property"},{"fullName":"HSAXElement.parent","description":"The element's parent","url":"HSAXElement.html#parent","kind":"property"},{"fullName":"HSAXElement.pid","description":"Get the process ID of the application that owns this element","url":"HSAXElement.html#pid","kind":"property"},{"fullName":"HSAXElement.children()","description":"The element's children","url":"HSAXElement.html#children","kind":"method"},{"fullName":"HSAXElement.childAtIndex(index)","description":"Get a specific child by index","url":"HSAXElement.html#childAtIndex","kind":"method"},{"fullName":"HSAXElement.attributeNames()","description":"Get all available attribute names","url":"HSAXElement.html#attributeNames","kind":"method"},{"fullName":"HSAXElement.attributeValue(attribute)","description":"Get the value of a specific attribute","url":"HSAXElement.html#attributeValue","kind":"method"},{"fullName":"HSAXElement.setAttributeValue(attribute, value)","description":"Set the value of a specific attribute","url":"HSAXElement.html#setAttributeValue","kind":"method"},{"fullName":"HSAXElement.isAttributeSettable(attribute)","description":"Check if an attribute is settable","url":"HSAXElement.html#isAttributeSettable","kind":"method"},{"fullName":"HSAXElement.actionNames()","description":"Get all available action names","url":"HSAXElement.html#actionNames","kind":"method"},{"fullName":"HSAXElement.performAction(action)","description":"Perform a specific action","url":"HSAXElement.html#performAction","kind":"method"},{"fullName":"HSBonjourSearch","description":"Discovers Bonjour services and domains advertised on the local network. Create via hs.bonjour.newSearch(), then call one of the find… methods. Each search type uses its own underlying NetServiceBrowser, so service and domain searches can run concurrently. Restarting any single search type stops only that browser before beginning the new one. ## Service search callback events | Event | Data | Description | |-------|------|-------------| | \"serviceFound\" | HSBonjourService | A matching service appeared | | \"serviceRemoved\" | HSBonjourService | A previously found service disappeared | | \"error\" | error string | The search failed | ## Domain search callback events | Event | Data | Description | |-------|------|-------------| | \"domainFound\" | domain string | A domain was discovered | | \"domainRemoved\" | domain string | A domain disappeared | | \"error\" | error string | The search failed |","url":"HSBonjourSearch.html","kind":"type"},{"fullName":"HSBonjourSearch.identifier","description":"A unique identifier for this search object.","url":"HSBonjourSearch.html#identifier","kind":"property"},{"fullName":"HSBonjourSearch.includesPeerToPeer","description":"Whether to search over peer-to-peer Bluetooth/Wi-Fi in addition to standard network interfaces. Defaults to false.","url":"HSBonjourSearch.html#includesPeerToPeer","kind":"property"},{"fullName":"HSBonjourSearch.findServices(type, domain, callback)","description":"Searches for services of the given type in the given domain. If a service search is already active it is stopped before starting the new one. Domain searches are unaffected. The callback receives (event, service, moreComing) — see the type documentation for the complete event table.","url":"HSBonjourSearch.html#findServices","kind":"method"},{"fullName":"HSBonjourSearch.findBrowsableDomains(callback)","description":"Searches for domains visible to this machine (browsable domains). If a browsable-domain search is already active it is stopped before starting the new one. Service and registration-domain searches are unaffected. The callback receives (event, domain, moreComing).","url":"HSBonjourSearch.html#findBrowsableDomains","kind":"method"},{"fullName":"HSBonjourSearch.findRegistrationDomains(callback)","description":"Searches for domains on which this machine can register services. If a registration-domain search is already active it is stopped before starting the new one. Service and browsable-domain searches are unaffected. The callback receives (event, domain, moreComing).","url":"HSBonjourSearch.html#findRegistrationDomains","kind":"method"},{"fullName":"HSBonjourSearch.stop()","description":"Stops all active searches. Safe to call when no search is active.","url":"HSBonjourSearch.html#stop","kind":"method"},{"fullName":"HSBonjourService","description":"A discovered Bonjour service record. Call resolve() to look up its hostname, port, and addresses. Instances are delivered by an HSBonjourSearch callback. Call resolve() to discover their hostname, port, and addresses, and optionally monitor() to watch for TXT record changes. ## Callback events | Method | Event | Extra data | |--------|-------|------------| | resolve() | \"resolved\" | _(none)_ | | resolve() | \"stopped\" | _(none)_ | | resolve() | \"error\" | error message string | | monitor() | \"txtRecord\" | updated TXT record dict |","url":"HSBonjourService.html","kind":"type"},{"fullName":"HSBonjourService.identifier","description":"A unique identifier assigned to this service object.","url":"HSBonjourService.html#identifier","kind":"property"},{"fullName":"HSBonjourService.name","description":"The service name (e.g. \"My Web Server\").","url":"HSBonjourService.html#name","kind":"property"},{"fullName":"HSBonjourService.type","description":"The service type string (e.g. \"_http._tcp.\").","url":"HSBonjourService.html#type","kind":"property"},{"fullName":"HSBonjourService.domain","description":"The mDNS domain (almost always \"local.\").","url":"HSBonjourService.html#domain","kind":"property"},{"fullName":"HSBonjourService.hostname","description":"The resolved hostname, or null before resolve() completes.","url":"HSBonjourService.html#hostname","kind":"property"},{"fullName":"HSBonjourService.port","description":"The service port. -1 until resolve() completes.","url":"HSBonjourService.html#port","kind":"property"},{"fullName":"HSBonjourService.addresses","description":"IP address strings (IPv4 and/or IPv6) populated after resolve() completes.","url":"HSBonjourService.html#addresses","kind":"property"},{"fullName":"HSBonjourService.txtRecord","description":"The TXT record as a {key: value} object, or null if none is available. Populated after resolve() completes or when updated via monitor().","url":"HSBonjourService.html#txtRecord","kind":"property"},{"fullName":"HSBonjourService.includesPeerToPeer","description":"Whether peer-to-peer Bluetooth/Wi-Fi is included in resolution.","url":"HSBonjourService.html#includesPeerToPeer","kind":"property"},{"fullName":"HSBonjourService.resolve(timeout, callback)","description":"Resolves the hostname, port, addresses, and TXT record of this service.","url":"HSBonjourService.html#resolve","kind":"method"},{"fullName":"HSBonjourService.monitor(callback)","description":"Starts monitoring the TXT record for changes. The callback fires whenever the TXT record is updated. Call stopMonitoring() to unsubscribe.","url":"HSBonjourService.html#monitor","kind":"method"},{"fullName":"HSBonjourService.stop()","description":"Stops any active resolution.","url":"HSBonjourService.html#stop","kind":"method"},{"fullName":"HSBonjourService.stopMonitoring()","description":"Stops TXT record monitoring started by monitor().","url":"HSBonjourService.html#stopMonitoring","kind":"method"},{"fullName":"HSCamera","description":"A camera device attached to the system. Obtain instances via the `hs.camera module — do not instantiate directly. ## Reading camera properties `javascript const cam = hs.camera.all()[0] console.log(cam.name + \" uid=\" + cam.uid + \" inUse=\" + cam.isInUse) ` ## Watching for in-use state changes `javascript const cam = hs.camera.all()[0] const fn = (isInUse) => { console.log(cam.name + \" is now \" + (isInUse ? \"in use\" : \"not in use\")) } cam.addWatcher(fn) // later… cam.removeWatcher(fn) ` ## Capturing a still image `javascript const cam = hs.camera.all()[0] cam.captureImage() .then(img => img.saveToFile(\"/tmp/shot.png\")) .catch(err => console.error(\"Capture failed: \" + err)) ``","url":"HSCamera.html","kind":"type"},{"fullName":"HSCamera.typeName","description":"The type name for JavaScript introspection. Always \"HSCamera\".","url":"HSCamera.html#typeName","kind":"property"},{"fullName":"HSCamera.uid","description":"The persistent unique identifier for this camera.","url":"HSCamera.html#uid","kind":"property"},{"fullName":"HSCamera.name","description":"The human-readable name of this camera (e.g. \"FaceTime HD Camera\").","url":"HSCamera.html#name","kind":"property"},{"fullName":"HSCamera.isInUse","description":"Whether this camera is currently being used by any application. Queries the underlying CoreMediaIO device state each time it is read.","url":"HSCamera.html#isInUse","kind":"property"},{"fullName":"HSCamera.addWatcher(listener)","description":"Register a listener that fires whenever this camera's in-use state changes. The listener receives one argument: a boolean that is true when the camera starts being used and false when it is released.","url":"HSCamera.html#addWatcher","kind":"method"},{"fullName":"HSCamera.removeWatcher(listener)","description":"Remove a previously registered per-camera in-use listener.","url":"HSCamera.html#removeWatcher","kind":"method"},{"fullName":"HSCamera.captureImage()","description":"Capture a still image from this camera. Camera permission must be granted via hs.permissions.requestCamera() before calling this method. The returned HSImage can be saved, displayed in a UI element, or passed to other image-processing APIs.","url":"HSCamera.html#captureImage","kind":"method"},{"fullName":"HSCanvas","description":"# HSCanvas A single canvas window: an absolutely-positioned, low-level drawing surface mirroring v1 Hammerspoon's hs.canvas. Elements are plain JS objects (matching v1's Lua tables) added with appendElements() and mutated in place with setElementAttribute()/elementAttribute(). Supports the same fill/stroke/ strokeAndFill/clip/build/skip action pipeline as v1, including the build+clip+reversePath technique used to punch holes in shapes (see hs.canvas.windowLevels/hs.canvas.windowBehaviors for the window-level/Spaces controls needed alongside this for overlay-style canvases). ## Example ``javascript const c = hs.canvas.create({x: 100, y: 100, w: 200, h: 200}) c.appendElements([ { type: \"rectangle\", action: \"fill\", fillColor: { red: 0.2, green: 0.5, blue: 0.9, alpha: 1 } } ]) c.show() ``","url":"HSCanvas.html","kind":"type"},{"fullName":"HSCanvas.show()","description":"Show the canvas window","url":"HSCanvas.html#show","kind":"method"},{"fullName":"HSCanvas.hide()","description":"Hide the canvas window (keeps it in memory; elements and window config are preserved)","url":"HSCanvas.html#hide","kind":"method"},{"fullName":"HSCanvas.destroy()","description":"Destroy the canvas window and release its resources Named destroy() rather than v1's delete() -- delete cannot be used as a JavaScriptCore-exported method name in this codebase's bridging layer.","url":"HSCanvas.html#destroy","kind":"method"},{"fullName":"HSCanvas.isShowing()","description":"Whether the canvas window is currently ordered onto the screen","url":"HSCanvas.html#isShowing","kind":"method"},{"fullName":"HSCanvas.isVisible()","description":"Whether the canvas is showing AND at least partially visible (not fully occluded or off-screen)","url":"HSCanvas.html#isVisible","kind":"method"},{"fullName":"HSCanvas.isOccluded()","description":"Whether the canvas is hidden behind other windows, or off-screen entirely","url":"HSCanvas.html#isOccluded","kind":"method"},{"fullName":"HSCanvas.frame()","description":"The canvas window's current position and size","url":"HSCanvas.html#frame","kind":"method"},{"fullName":"HSCanvas.setFrame(rect)","description":"Move and/or resize the canvas window","url":"HSCanvas.html#setFrame","kind":"method"},{"fullName":"HSCanvas.topLeft()","description":"The canvas window's current top-left corner the point at the window's highest y (its screen-visual top), not y = 0.","url":"HSCanvas.html#topLeft","kind":"method"},{"fullName":"HSCanvas.setTopLeft(point)","description":"Move the canvas window without changing its size","url":"HSCanvas.html#setTopLeft","kind":"method"},{"fullName":"HSCanvas.size()","description":"The canvas window's current size","url":"HSCanvas.html#size","kind":"method"},{"fullName":"HSCanvas.setSize(dimensions)","description":"Resize the canvas window without moving its top-left corner","url":"HSCanvas.html#setSize","kind":"method"},{"fullName":"HSCanvas.level(name)","description":"Set the window level by name","url":"HSCanvas.html#level","kind":"method"},{"fullName":"HSCanvas.levelValue(value)","description":"Set the window level to a raw numeric value Split out from level(_:) (rather than accepting a string-or-number union) because JSExport parameters must have a single concrete type -- see hs.canvas.windowLevels, which exposes raw numeric values (not opaque name strings) so scripts can do arithmetic on them, matching v1 behavior.","url":"HSCanvas.html#levelValue","kind":"method"},{"fullName":"HSCanvas.behavior(name)","description":"Set the window's Spaces/Exposé collection behavior to a single named behavior","url":"HSCanvas.html#behavior","kind":"method"},{"fullName":"HSCanvas.behaviorList(names)","description":"Set the window's Spaces/Exposé collection behavior to a combination of named behaviors","url":"HSCanvas.html#behaviorList","kind":"method"},{"fullName":"HSCanvas.behaviorValue(value)","description":"Set the window's Spaces/Exposé collection behavior to a raw bitmask","url":"HSCanvas.html#behaviorValue","kind":"method"},{"fullName":"HSCanvas.clickActivating(flag)","description":"Set whether clicking the canvas activates the Hammerspoon app","url":"HSCanvas.html#clickActivating","kind":"method"},{"fullName":"HSCanvas.ignoreMouseEvents(flag)","description":"Set whether the canvas window ignores all mouse events, passing clicks through to whatever is behind it This is a capability beyond v1's hs.canvas API surface (not a literal v1 method name) -- v1 has no direct equivalent for full click pass-through.","url":"HSCanvas.html#ignoreMouseEvents","kind":"method"},{"fullName":"HSCanvas.appendElements(elements)","description":"Append one or more elements to the end of the canvas Element frame/center/coordinates values are y-down (y = 0 at the top of the canvas) -- a different sense from the canvas window's own x/y position, which is unflipped AppKit screen coordinates. See hs.canvas's module-level docs for the full explanation.","url":"HSCanvas.html#appendElements","kind":"method"},{"fullName":"HSCanvas.insertElement(element, index)","description":"Insert an element at a specific index","url":"HSCanvas.html#insertElement","kind":"method"},{"fullName":"HSCanvas.assignElement(element, index)","description":"Replace the element at an index, or append if the index equals the current element count","url":"HSCanvas.html#assignElement","kind":"method"},{"fullName":"HSCanvas.removeElement(index)","description":"Remove the element at a specific index","url":"HSCanvas.html#removeElement","kind":"method"},{"fullName":"HSCanvas.removeLastElement()","description":"Remove the last element","url":"HSCanvas.html#removeLastElement","kind":"method"},{"fullName":"HSCanvas.replaceElements(elements)","description":"Replace all elements on the canvas","url":"HSCanvas.html#replaceElements","kind":"method"},{"fullName":"HSCanvas.elementCount()","description":"The number of elements on the canvas","url":"HSCanvas.html#elementCount","kind":"method"},{"fullName":"HSCanvas.canvasElements()","description":"All elements currently on the canvas","url":"HSCanvas.html#canvasElements","kind":"method"},{"fullName":"HSCanvas.elementKeys(index)","description":"The attribute keys present on an element","url":"HSCanvas.html#elementKeys","kind":"method"},{"fullName":"HSCanvas.elementAttribute(index, key)","description":"Get a single attribute value from an element Returns Any? (mirroring hs.userdefaults.get()) rather than a concrete Swift type because an element attribute's value is genuinely heterogeneous -- a string, number, boolean, nested object, or array, matching v1's dynamically-typed Lua table values.","url":"HSCanvas.html#elementAttribute","kind":"method"},{"fullName":"HSCanvas.setElementAttribute(index, key, value)","description":"Set a single attribute value on an element","url":"HSCanvas.html#setElementAttribute","kind":"method"},{"fullName":"HSCanvas.removeElementAttribute(index, key)","description":"Remove a single attribute from an element","url":"HSCanvas.html#removeElementAttribute","kind":"method"},{"fullName":"HSCanvas.elementBounds(index)","description":"The smallest rectangle enclosing an element's rendered shape","url":"HSCanvas.html#elementBounds","kind":"method"},{"fullName":"HSCanvas.minimumTextSize(index, text)","description":"The smallest size that can fully render a string of text, using a text element's font attributes (textFont/textSize/textWeight/textDesign/textItalic) Mirrors v1's hs.canvas:minimumTextSize(). Multi-line strings (separated by \\n) are measured correctly -- the height covers every line and the width is the longest line's width, not a fixed single-line size.","url":"HSCanvas.html#minimumTextSize","kind":"method"},{"fullName":"HSCanvas.mouseCallback(callback)","description":"Set the callback fired for tracked mouse events Fires for elements with trackMouseDown/trackMouseUp/trackMouseEnterExit/ trackMouseMove set to true in their element dictionary, and for whole-canvas regions enabled via canvasMouseEvents() (delivered with id \"_canvas\").","url":"HSCanvas.html#mouseCallback","kind":"method"},{"fullName":"HSCanvas.canvasMouseEvents(down, up, enterExit, move)","description":"Enable whole-canvas mouse tracking for regions not covered by any individually tracked element. Delivered through mouseCallback() with id \"_canvas\".","url":"HSCanvas.html#canvasMouseEvents","kind":"method"},{"fullName":"HSCanvas.rotateElement(index, angle)","description":"Rotate an element about its own bounding-box center","url":"HSCanvas.html#rotateElement","kind":"method"},{"fullName":"HSCanvas.rotateElementAroundPoint(index, angle, point)","description":"Rotate an element about a specific point","url":"HSCanvas.html#rotateElementAroundPoint","kind":"method"},{"fullName":"HSCanvas.setElementTransformation(index, matrix)","description":"Apply a raw 2D affine transformation matrix to a single element","url":"HSCanvas.html#setElementTransformation","kind":"method"},{"fullName":"HSCanvas.setTransformation(matrix)","description":"Apply a raw 2D affine transformation matrix to the whole canvas","url":"HSCanvas.html#setTransformation","kind":"method"},{"fullName":"HSCanvas.clearTransformation()","description":"Remove the whole-canvas transformation set by setTransformation()","url":"HSCanvas.html#clearTransformation","kind":"method"},{"fullName":"HSCanvas.imageFromCanvas()","description":"Render the canvas's current contents to an image","url":"HSCanvas.html#imageFromCanvas","kind":"method"},{"fullName":"HSCanvas.duplicate()","description":"Create an independent copy of this canvas, with the same frame, elements, and window configuration Named duplicate() rather than v1's copy() -- this codebase's conventions forbid method names starting with copy (an ARC/ObjC hazard), the same rule that renamed new() to create().","url":"HSCanvas.html#duplicate","kind":"method"},{"fullName":"HSCanvas.setAccessibilitySubrole(subrole)","description":"Set the accessibility subrole reported for this canvas's window","url":"HSCanvas.html#setAccessibilitySubrole","kind":"method"},{"fullName":"HSCanvas.draggingCallback(callback)","description":"Set a callback fired when files or text are dropped onto the canvas","url":"HSCanvas.html#draggingCallback","kind":"method"},{"fullName":"HSChooser","description":"A keyboard-driven floating chooser panel. Create via hs.chooser.create(). Configure choices, set callbacks, then call .show(). ## Choice format Each choice is a plain object with required text and optional subText, image, valid, and contextMenu fields. All other fields are passed through to the onSelect callback unchanged. The contextMenu array defines per-row right-click menu entries. Each entry is either ``javascript { text: \"Open Safari\", subText: \"com.apple.Safari\", image: HSImage.fromAppBundle(\"com.apple.Safari\"), valid: true, myData: 42, contextMenu: [ { title: \"Open\", action: () => hs.urlevent.openURL(\"https://apple.com\") }, { type: \"divider\" }, { title: \"Copy bundle ID\", action: () => hs.pasteboard.writeString(\"com.apple.Safari\") } ] } `` ## Keyboard shortcuts","url":"HSChooser.html","kind":"type"},{"fullName":"HSChooser.typeName","description":"Read-only type identifier.","url":"HSChooser.html#typeName","kind":"property"},{"fullName":"HSChooser.identifier","description":"Stable UUID string for this chooser instance.","url":"HSChooser.html#identifier","kind":"property"},{"fullName":"HSChooser.query","description":"The current text in the search field. Setting this from JS updates the display but does not invoke the onQueryChange callback.","url":"HSChooser.html#query","kind":"property"},{"fullName":"HSChooser.placeholder","description":"Placeholder text shown in the empty search field (default: \"Search...\").","url":"HSChooser.html#placeholder","kind":"property"},{"fullName":"HSChooser.searchSubText","description":"Whether searches match against subText in addition to text (default: false). Only applies when a static choices array is provided.","url":"HSChooser.html#searchSubText","kind":"property"},{"fullName":"HSChooser.enableDefaultForQuery","description":"When true and the query is non-empty but there are no matching choices, onSelect is called with { text: } instead of null (default: false).","url":"HSChooser.html#enableDefaultForQuery","kind":"property"},{"fullName":"HSChooser.selectedRow","description":"The zero-based index of the currently highlighted row (-1 when empty).","url":"HSChooser.html#selectedRow","kind":"property"},{"fullName":"HSChooser.width","description":"Width of the chooser as a fraction of the screen width (default: 0.5 = 50 %).","url":"HSChooser.html#width","kind":"property"},{"fullName":"HSChooser.visibleRows","description":"Maximum number of rows visible at once without scrolling (default: 10).","url":"HSChooser.html#visibleRows","kind":"property"},{"fullName":"HSChooser.isVisible","description":"true if the chooser panel is currently on screen.","url":"HSChooser.html#isVisible","kind":"property"},{"fullName":"HSChooser.onSelect","description":"Called when the user confirms a selection, or null to remove the handler. The argument is the chosen row object (the original dict you passed to setChoices, with text, subText, image, valid, and any custom fields intact). The argument is null when dismissed (Escape).","url":"HSChooser.html#onSelect","kind":"property"},{"fullName":"HSChooser.onQueryChange","description":"Called on every keystroke with the new query string, or null to remove the handler. Use this to debounce expensive searches or trigger async data fetching.","url":"HSChooser.html#onQueryChange","kind":"property"},{"fullName":"HSChooser.onShow","description":"Called after the panel becomes visible, or null to remove the handler.","url":"HSChooser.html#onShow","kind":"property"},{"fullName":"HSChooser.onHide","description":"Called after the panel is hidden (for any reason: selection, Escape, or hide()), or null to remove the handler.","url":"HSChooser.html#onHide","kind":"property"},{"fullName":"HSChooser.onInvalid","description":"Called when the user activates a row whose valid field is false, or null to remove the handler. The chooser stays open; the argument is the row dict (same shape as onSelect). If unset, activating an invalid row is silently ignored.","url":"HSChooser.html#onInvalid","kind":"property"},{"fullName":"HSChooser.setChoices(choices)","description":"on show. The function is responsible for filtering; the chooser displays all items it returns.","url":"HSChooser.html#setChoices","kind":"method"},{"fullName":"HSChooser.refreshChoices()","description":"Re-apply filtering (static choices) or re-invoke the choices function (dynamic). Call after updating an external data source in an async onQueryChange handler.","url":"HSChooser.html#refreshChoices","kind":"method"},{"fullName":"HSChooser.show()","description":"Show the chooser.","url":"HSChooser.html#show","kind":"method"},{"fullName":"HSChooser.hide()","description":"Hide the chooser without making a selection. Restores focus to the previously active window.","url":"HSChooser.html#hide","kind":"method"},{"fullName":"HSChooser.select(row)","description":"Programmatically confirm a selection. Omit row to confirm the currently highlighted row. Fires onSelect (or onInvalid for rows with valid: false) and hides the chooser.","url":"HSChooser.html#select","kind":"method"},{"fullName":"HSChooser.selectedRowContents(row)","description":"Returns the dict for the highlighted row, or for a specific row by index. Returns null if the index is out of range or no choices are set.","url":"HSChooser.html#selectedRowContents","kind":"method"},{"fullName":"HSEventTap","description":"An event tap watcher that intercepts input events from the system. Obtain instances via hs.eventtap.addWatcher() — do not instantiate directly. ## Monitoring keyboard events ``js const tap = hs.eventtap.addWatcher([hs.eventtap.eventTypes.keyDown], (event) => { console.log(\"Key pressed: \" + event.keyCode) }) ``","url":"HSEventTap.html","kind":"type"},{"fullName":"HSEventTap.identifier","description":"A unique identifier for this tap","url":"HSEventTap.html#identifier","kind":"property"},{"fullName":"HSEventTap.listenOnly","description":"Whether this tap was created as listen-only (events are observed but never modified or suppressed)","url":"HSEventTap.html#listenOnly","kind":"property"},{"fullName":"HSEventTap.start()","description":"Start receiving events. Requires Accessibility permission.","url":"HSEventTap.html#start","kind":"method"},{"fullName":"HSEventTap.stop()","description":"Stop receiving events","url":"HSEventTap.html#stop","kind":"method"},{"fullName":"HSEventTap.setCallback(callback)","description":"Replace the callback function","url":"HSEventTap.html#setCallback","kind":"method"},{"fullName":"HSEventTap.isEnabled()","description":"Whether this tap is currently active","url":"HSEventTap.html#isEnabled","kind":"method"},{"fullName":"HSEventTap.isCreated()","description":"Whether this tap has been registered with macOS","url":"HSEventTap.html#isCreated","kind":"method"},{"fullName":"HSEventTapEvent","description":"An input event captured or constructed by hs.eventtap. Objects of this type are passed to event tap callbacks and can also be created directly via the factory methods on hs.eventtap. Properties can be inspected and modified before the event is passed through or posted back to the system.","url":"HSEventTapEvent.html","kind":"type"},{"fullName":"HSEventTapEvent.typeName","description":"Type name for introspection","url":"HSEventTapEvent.html#typeName","kind":"property"},{"fullName":"HSEventTapEvent.type","description":"The numeric event type, matching a value in hs.eventtap.eventTypes","url":"HSEventTapEvent.html#type","kind":"property"},{"fullName":"HSEventTapEvent.keyCode","description":"The virtual key code for keyboard events (get/set)","url":"HSEventTapEvent.html#keyCode","kind":"property"},{"fullName":"HSEventTapEvent.rawFlags","description":"The raw modifier flags bitmask (get/set). Use values from hs.eventtap.modifierFlags.","url":"HSEventTapEvent.html#rawFlags","kind":"property"},{"fullName":"HSEventTapEvent.flags","description":"An array of active modifier key names (e.g. [\"cmd\", \"shift\"]). When a device-specific modifier is detected, both the generic and side-specific names are included — e.g. pressing the left Command key yields [\"cmd\", \"leftCmd\"].","url":"HSEventTapEvent.html#flags","kind":"property"},{"fullName":"HSEventTapEvent.location","description":"The event's screen position as {x, y} in Hammerspoon screen coordinates (top-left origin of primary display, y increases downward, matching hs.screen).","url":"HSEventTapEvent.html#location","kind":"property"},{"fullName":"HSEventTapEvent.buttonNumber","description":"The mouse button number for mouse events (0=left, 1=right, 2=middle)","url":"HSEventTapEvent.html#buttonNumber","kind":"property"},{"fullName":"HSEventTapEvent.scrollingDeltaX","description":"The horizontal scroll delta for scroll wheel events","url":"HSEventTapEvent.html#scrollingDeltaX","kind":"property"},{"fullName":"HSEventTapEvent.scrollingDeltaY","description":"The vertical scroll delta for scroll wheel events","url":"HSEventTapEvent.html#scrollingDeltaY","kind":"property"},{"fullName":"HSEventTapEvent.characters","description":"The Unicode characters produced by this keyboard event, or null for non-keyboard events","url":"HSEventTapEvent.html#characters","kind":"property"},{"fullName":"HSEventTapEvent.duplicate()","description":"Create an independent copy of this event","url":"HSEventTapEvent.html#duplicate","kind":"method"},{"fullName":"HSEventTapEvent.post(app)","description":"Post this event to the HID event stream, optionally targeting a specific application. When app is omitted or null, the event is posted to the global HID stream and delivered by the OS as if a real input device generated it. When an application is provided, the event is delivered directly to that process by PID.","url":"HSEventTapEvent.html#post","kind":"method"},{"fullName":"HSEventTapHotkey","description":"A keyboard shortcut binding backed by an event tap. Supports fn modifier and left/right modifier key distinction. Obtain instances via hs.eventtap.bindHotkey() — do not instantiate directly.","url":"HSEventTapHotkey.html","kind":"type"},{"fullName":"HSEventTapHotkey.callbackPressed","description":"The callback function to be called when the hotkey is pressed, or null to remove it","url":"HSEventTapHotkey.html#callbackPressed","kind":"property"},{"fullName":"HSEventTapHotkey.callbackReleased","description":"The callback function to be called when the hotkey is released, or null to remove it","url":"HSEventTapHotkey.html#callbackReleased","kind":"property"},{"fullName":"HSEventTapHotkey.enable()","description":"Enable the hotkey","url":"HSEventTapHotkey.html#enable","kind":"method"},{"fullName":"HSEventTapHotkey.disable()","description":"Disable the hotkey","url":"HSEventTapHotkey.html#disable","kind":"method"},{"fullName":"HSEventTapHotkey.isEnabled()","description":"Check if the hotkey is currently enabled","url":"HSEventTapHotkey.html#isEnabled","kind":"method"},{"fullName":"HSPathWatcher","description":"Watches a filesystem path for changes and invokes a callback when they occur. Created via hs.fs.createPathWatcher(path). Set a callback with setCallback(), then call start() to begin receiving events. | Flag | Meaning | |------|---------| | \"itemCreated\" | Item was created | | \"itemRemoved\" | Item was removed | | \"itemRenamed\" | Item was renamed or moved | | \"itemModified\" | File data was modified | | \"itemInodeMetaMod\" | Inode metadata changed (permissions, timestamps, etc.) | | \"itemFinderInfoMod\" | Finder info changed | | \"itemChangeOwner\" | Ownership or group changed | | \"itemXattrMod\" | Extended attributes changed | | \"itemIsFile\" | The item is a file | | \"itemIsDir\" | The item is a directory | | \"itemIsSymlink\" | The item is a symbolic link | | \"itemIsHardlink\" | The item is a hard link | | \"itemIsLastHardlink\" | This is the last hard link to the inode | | \"itemCloned\" | Item was cloned | | \"ownEvent\" | Event was generated by this process | | \"mustScanSubDirs\" | Subtree must be rescanned (events may have been dropped) | | \"userDropped\" | Events were dropped at the user-space level | | \"kernelDropped\" | Events were dropped at the kernel level | | \"rootChanged\" | The watched root path itself changed | | \"mount\" | A volume was mounted under the watched path | | \"unmount\" | A volume was unmounted from under the watched path |","url":"HSPathWatcher.html","kind":"type"},{"fullName":"HSPathWatcher.identifier","description":"The unique identifier assigned to this watcher.","url":"HSPathWatcher.html#identifier","kind":"property"},{"fullName":"HSPathWatcher.start()","description":"Starts monitoring the watched path for filesystem changes.","url":"HSPathWatcher.html#start","kind":"method"},{"fullName":"HSPathWatcher.stop()","description":"Stops monitoring the watched path.","url":"HSPathWatcher.html#stop","kind":"method"},{"fullName":"HSPathWatcher.setCallback(fn)","description":"Sets the callback invoked when filesystem changes are detected.","url":"HSPathWatcher.html#setCallback","kind":"method"},{"fullName":"HSPathWatcher.destroy()","description":"Stops the watcher and releases all resources. Called automatically during shutdown.","url":"HSPathWatcher.html#destroy","kind":"method"},{"fullName":"HSVolumeWatcher","description":"A volume event watcher that monitors filesystem mount/unmount/rename events. Create via hs.fs.addVolumeWatcher(). Set a callback with setCallback(), then call start() to begin receiving events. | Event | Info keys | |-------|-----------| | \"didMount\" | path: string | | \"didUnmount\" | path: string | | \"willUnmount\" | path: string | | \"didRename\" | path: string, name: string, oldPath?: string, oldName?: string |","url":"HSVolumeWatcher.html","kind":"type"},{"fullName":"HSVolumeWatcher.identifier","description":"The unique identifier assigned to this watcher.","url":"HSVolumeWatcher.html#identifier","kind":"property"},{"fullName":"HSVolumeWatcher.start()","description":"Starts monitoring volume events.","url":"HSVolumeWatcher.html#start","kind":"method"},{"fullName":"HSVolumeWatcher.stop()","description":"Stops monitoring volume events.","url":"HSVolumeWatcher.html#stop","kind":"method"},{"fullName":"HSVolumeWatcher.setCallback(fn)","description":"Sets the callback function invoked when volume events occur.","url":"HSVolumeWatcher.html#setCallback","kind":"method"},{"fullName":"HSVolumeWatcher.destroy()","description":"Stops the watcher and releases all resources. Called automatically during shutdown.","url":"HSVolumeWatcher.html#destroy","kind":"method"},{"fullName":"HSHotkey","description":"Object representing a system-wide hotkey. You should not create these objects directly, but rather, use the methods in hs.hotkey to instantiate these.","url":"HSHotkey.html","kind":"type"},{"fullName":"HSHotkey.mods","description":"The modifier keys this hotkey was bound with, as originally passed to bind()/create()","url":"HSHotkey.html#mods","kind":"property"},{"fullName":"HSHotkey.key","description":"The key this hotkey was bound with, as originally passed to bind()/create()","url":"HSHotkey.html#key","kind":"property"},{"fullName":"HSHotkey.message","description":"An optional description of what this hotkey does, or null if none was set. When set, it is shown as an on-screen toast via hs.ui.alert() (duration controlled by hs.hotkey.alertDuration) just before the hotkey's callback runs: before the pressed callback if one exists, otherwise before the released callback if one exists.","url":"HSHotkey.html#message","kind":"property"},{"fullName":"HSHotkey.callbackRepeat","description":"The callback function to be called repeatedly while the hotkey is held down, or null to remove it. Repeats at the system keyboard-repeat delay/interval, matching how held-down keys repeat elsewhere in macOS.","url":"HSHotkey.html#callbackRepeat","kind":"property"},{"fullName":"HSHotkey.callbackPressed","description":"The callback function to be called when the hotkey is pressed, or null to remove it","url":"HSHotkey.html#callbackPressed","kind":"property"},{"fullName":"HSHotkey.callbackReleased","description":"The callback function to be called when the hotkey is released, or null to remove it","url":"HSHotkey.html#callbackReleased","kind":"property"},{"fullName":"HSHotkey.enable()","description":"Enable the hotkey","url":"HSHotkey.html#enable","kind":"method"},{"fullName":"HSHotkey.disable()","description":"Disable the hotkey","url":"HSHotkey.html#disable","kind":"method"},{"fullName":"HSHotkey.isEnabled()","description":"Check if the hotkey is currently enabled","url":"HSHotkey.html#isEnabled","kind":"method"},{"fullName":"HSHotkey.destroy()","description":"Disable and permanently remove this hotkey, releasing all associated resources","url":"HSHotkey.html#destroy","kind":"method"},{"fullName":"HSHotkeyModal","description":"A modal hotkey group returned by hs.hotkey.createModal(). Hotkeys bound to the modal via bind() are only enabled while the modal is active (i.e. between enter() and exit()).","url":"HSHotkeyModal.html","kind":"type"},{"fullName":"HSHotkeyModal.isActive","description":"Whether the modal is currently active","url":"HSHotkeyModal.html#isActive","kind":"property"},{"fullName":"HSHotkeyModal.enterFn","description":"Callback invoked when the modal is entered","url":"HSHotkeyModal.html#enterFn","kind":"property"},{"fullName":"HSHotkeyModal.exitFn","description":"Callback invoked when the modal is exited","url":"HSHotkeyModal.html#exitFn","kind":"property"},{"fullName":"HSHotkeyModal.bind(mods, key, callbackPressed, callbackReleased)","description":"Bind a hotkey to this modal. The hotkey is only enabled while the modal is active.","url":"HSHotkeyModal.html#bind","kind":"method"},{"fullName":"HSHotkeyModal.enter()","description":"Enter the modal: its trigger (if any) is disabled and its bound hotkeys are enabled.","url":"HSHotkeyModal.html#enter","kind":"method"},{"fullName":"HSHotkeyModal.exit()","description":"Exit the modal: its bound hotkeys are disabled and its trigger (if any) is re-enabled.","url":"HSHotkeyModal.html#exit","kind":"method"},{"fullName":"HSHotkeyModal.destroy()","description":"Destroy the modal, along with its trigger and all hotkeys bound to it.","url":"HSHotkeyModal.html#destroy","kind":"method"},{"fullName":"HSWebSocket","description":"A WebSocket client connection created by hs.http.openWebSocket(). The connection opens immediately when returned. Use the chainable setter methods to register event callbacks, then call send() to transmit messages. Do not instantiate HSWebSocket directly — use hs.http.openWebSocket().","url":"HSWebSocket.html","kind":"type"},{"fullName":"HSWebSocket.identifier","description":"A unique identifier for this connection (UUID string).","url":"HSWebSocket.html#identifier","kind":"property"},{"fullName":"HSWebSocket.readyState","description":"The current connection state.","url":"HSWebSocket.html#readyState","kind":"property"},{"fullName":"HSWebSocket.setOpenCallback(callback)","description":"Set the callback invoked when the connection is established.","url":"HSWebSocket.html#setOpenCallback","kind":"method"},{"fullName":"HSWebSocket.setMessageCallback(callback)","description":"Set the callback invoked when a text message is received from the server.","url":"HSWebSocket.html#setMessageCallback","kind":"method"},{"fullName":"HSWebSocket.setCloseCallback(callback)","description":"Set the callback invoked when the connection is closed by the remote end.","url":"HSWebSocket.html#setCloseCallback","kind":"method"},{"fullName":"HSWebSocket.setErrorCallback(callback)","description":"Set the callback invoked when a connection or protocol error occurs.","url":"HSWebSocket.html#setErrorCallback","kind":"method"},{"fullName":"HSWebSocket.send(message)","description":"Send a text message to the server. The connection must be open (readyState === 1).","url":"HSWebSocket.html#send","kind":"method"},{"fullName":"HSWebSocket.close()","description":"Close the WebSocket connection with a normal closure code (1000). If a close callback is registered, it is invoked synchronously.","url":"HSWebSocket.html#close","kind":"method"},{"fullName":"HSWebSocket.destroy()","description":"Destroy this WebSocket, releasing all resources without invoking callbacks. Called automatically by hs.http.shutdown(). After destroy(), do not use this object.","url":"HSWebSocket.html#destroy","kind":"method"},{"fullName":"HSHTTPServer","description":"An HTTP server instance created by hs.httpserver.create(). Configure with chainable setter methods, then call start() to begin accepting connections. The server supports synchronous and async (Promise-returning) request callbacks, optional static file serving, HTTP Basic authentication, Bonjour advertisement, and TLS via PKCS#12. Do not instantiate HSHTTPServer directly — use hs.httpserver.create().","url":"HSHTTPServer.html","kind":"type"},{"fullName":"HSHTTPServer.identifier","description":"A unique identifier for this server instance (UUID string).","url":"HSHTTPServer.html#identifier","kind":"property"},{"fullName":"HSHTTPServer.setPort(port)","description":"Set the TCP port to listen on. Must be called before start(). Pass 0 to let the OS assign an available port (use getPort() after start() to discover it).","url":"HSHTTPServer.html#setPort","kind":"method"},{"fullName":"HSHTTPServer.setInterface(iface)","description":"Set the network interface to listen on. Pass null to listen on all interfaces (the default). Pass \"localhost\" or \"loopback\" to restrict to the loopback interface only.","url":"HSHTTPServer.html#setInterface","kind":"method"},{"fullName":"HSHTTPServer.setPassword(password)","description":"Set a password required for Basic authentication. When set, every request must supply an Authorization: Basic header with any username and the configured password. Pass null to disable authentication.","url":"HSHTTPServer.html#setPassword","kind":"method"},{"fullName":"HSHTTPServer.setMaxBodySize(size)","description":"Set the maximum allowed incoming request body size in bytes. Requests with a body exceeding this limit receive a 413 response. Defaults to 10 MB.","url":"HSHTTPServer.html#setMaxBodySize","kind":"method"},{"fullName":"HSHTTPServer.setName(name)","description":"Set the Bonjour service name advertised on the local network. Only used when Bonjour is enabled via setBonjour(true).","url":"HSHTTPServer.html#setName","kind":"method"},{"fullName":"HSHTTPServer.setBonjour(enable)","description":"Enable or disable Bonjour advertisement of this server on the local network.","url":"HSHTTPServer.html#setBonjour","kind":"method"},{"fullName":"HSHTTPServer.setCallback(callback)","description":"Set the request handler callback. If the callback returns null or undefined, the server falls through to static file serving (if a document root is set), or responds with 404.","url":"HSHTTPServer.html#setCallback","kind":"method"},{"fullName":"HSHTTPServer.setDocumentRoot(path)","description":"Set the filesystem path to serve static files from. When a document root is set, requests not handled by the callback are served as static files from this directory. Pass null to disable static file serving.","url":"HSHTTPServer.html#setDocumentRoot","kind":"method"},{"fullName":"HSHTTPServer.setDirectoryIndex(files)","description":"Set the list of index filenames checked when a directory is requested. Defaults to [\"index.html\", \"index.htm\"]. Files are checked in order.","url":"HSHTTPServer.html#setDirectoryIndex","kind":"method"},{"fullName":"HSHTTPServer.setAllowDirectoryListing(allow)","description":"Enable or disable directory listing for requests that map to a directory with no index file. When disabled (the default), directory requests without an index file return 403.","url":"HSHTTPServer.html#setAllowDirectoryListing","kind":"method"},{"fullName":"HSHTTPServer.setTLSFromPKCS12(path, password)","description":"Configure TLS using a PKCS#12 (.p12) identity file. When TLS is configured, the server accepts HTTPS connections. The .p12 file must contain both the certificate and the private key.","url":"HSHTTPServer.html#setTLSFromPKCS12","kind":"method"},{"fullName":"HSHTTPServer.start()","description":"Start the server and begin accepting connections. The server must be configured before calling start(). To restart the server with new settings, call stop() followed by start().","url":"HSHTTPServer.html#start","kind":"method"},{"fullName":"HSHTTPServer.stop()","description":"Stop the server and close all connections.","url":"HSHTTPServer.html#stop","kind":"method"},{"fullName":"HSHTTPServer.destroy()","description":"Destroy this server, releasing all resources. After calling destroy(), the server object should not be used.","url":"HSHTTPServer.html#destroy","kind":"method"},{"fullName":"HSHTTPServer.getPort()","description":"Get the TCP port the server is currently listening on. Returns 0 if the server is not running.","url":"HSHTTPServer.html#getPort","kind":"method"},{"fullName":"HSHTTPServer.getName()","description":"Get the configured Bonjour service name.","url":"HSHTTPServer.html#getName","kind":"method"},{"fullName":"HSHTTPServer.getInterface()","description":"Get the configured network interface, or null if listening on all interfaces.","url":"HSHTTPServer.html#getInterface","kind":"method"},{"fullName":"HSHTTPServer.setWebSocketCallback(path, callback)","description":"Register a WebSocket handler for a URL path. When a client connects and performs a WebSocket upgrade handshake on path, the callback is invoked with three arguments: event (string), connection (HSWebSocketConnection), and message (string). Events: Pass null to remove the WebSocket handler for the path.","url":"HSHTTPServer.html#setWebSocketCallback","kind":"method"},{"fullName":"HSWebSocketConnection","description":"A WebSocket connection to a single client, passed to the callback registered with server.setWebSocketCallback(). Use send() to push messages to the connected client and close() to end the connection. Do not instantiate HSWebSocketConnection directly — it is created by the server when a client performs a WebSocket upgrade.","url":"HSWebSocketConnection.html","kind":"type"},{"fullName":"HSWebSocketConnection.identifier","description":"A unique identifier for this connection (UUID string).","url":"HSWebSocketConnection.html#identifier","kind":"property"},{"fullName":"HSWebSocketConnection.send(message)","description":"Send a text message to the connected WebSocket client.","url":"HSWebSocketConnection.html#send","kind":"method"},{"fullName":"HSWebSocketConnection.close()","description":"Close the WebSocket connection to the client. Sends a WebSocket close frame and cancels the underlying TCP connection.","url":"HSWebSocketConnection.html#close","kind":"method"},{"fullName":"HSWebSocketConnection.destroy()","description":"Destroy this connection object, releasing all resources.","url":"HSWebSocketConnection.html#destroy","kind":"method"},{"fullName":"HSLocationWatcher","description":"An independent location tracking object. Create via hs.location.addWatcher(). Call start() to begin receiving updates, and set a callback to handle them. | Event | Data | |-------|------| | \"location\" | a locationTable | | \"error\" | an error message string | | \"authorizationChanged\" | the new status string (\"authorized\", \"denied\", \"restricted\", \"notDetermined\") |","url":"HSLocationWatcher.html","kind":"type"},{"fullName":"HSLocationWatcher.identifier","description":"The unique identifier assigned to this watcher.","url":"HSLocationWatcher.html#identifier","kind":"property"},{"fullName":"HSLocationWatcher.distanceFilter","description":"The minimum distance in metres the device must move before a new update is delivered. Defaults to kCLDistanceFilterNone (all movements reported).","url":"HSLocationWatcher.html#distanceFilter","kind":"property"},{"fullName":"HSLocationWatcher.start()","description":"Starts location updates. The callback must be set first.","url":"HSLocationWatcher.html#start","kind":"method"},{"fullName":"HSLocationWatcher.stop()","description":"Stops location updates.","url":"HSLocationWatcher.html#stop","kind":"method"},{"fullName":"HSLocationWatcher.setCallback(fn)","description":"Sets the callback function invoked when location events occur.","url":"HSLocationWatcher.html#setCallback","kind":"method"},{"fullName":"HSLocationWatcher.location()","description":"Returns the most recently received location, or null if none yet.","url":"HSLocationWatcher.html#location","kind":"method"},{"fullName":"HSMenuBarItem","description":"Object representing a macOS system menu bar item. Create instances with hs.menubar.create().","url":"HSMenuBarItem.html","kind":"type"},{"fullName":"HSMenuBarItem.title","description":"Get or set the menu item's title.","url":"HSMenuBarItem.html#title","kind":"property"},{"fullName":"HSMenuBarItem.setIcon(image)","description":"Set the icon displayed in the menu bar","url":"HSMenuBarItem.html#setIcon","kind":"method"},{"fullName":"HSMenuBarItem.setTooltip(tooltip)","description":"Set the tooltip shown when hovering over the menu bar item","url":"HSMenuBarItem.html#setTooltip","kind":"method"},{"fullName":"HSMenuBarItem.setClickCallback(fn)","description":"Set a callback invoked when the item is clicked (only fires when no menu is set)","url":"HSMenuBarItem.html#setClickCallback","kind":"method"},{"fullName":"HSMenuBarItem.setMenu(menuOrFn)","description":"Set the menu for this item. Pass an array of menu item objects for a static menu, or a function that returns an array for a dynamic menu populated each time it opens.","url":"HSMenuBarItem.html#setMenu","kind":"method"},{"fullName":"HSMenuBarItem.hide()","description":"Remove this item from the menu bar. The item is retained and can be shown again with show().","url":"HSMenuBarItem.html#hide","kind":"method"},{"fullName":"HSMenuBarItem.show()","description":"Show this item in the menu bar.","url":"HSMenuBarItem.html#show","kind":"method"},{"fullName":"HSMenuBarItem.isVisible()","description":"Check if this item is currently visible in the menu bar.","url":"HSMenuBarItem.html#isVisible","kind":"method"},{"fullName":"HSMenuBarItem.destroy()","description":"Permanently remove this item from the menu bar and release all resources. After calling destroy(), the item is no longer usable. This is called automatically on hs.reload(). Use hide() instead if you only want to temporarily remove the item without freeing it.","url":"HSMenuBarItem.html#destroy","kind":"method"},{"fullName":"HSMIDIDevice","description":"A MIDI device or virtual source, created via hs.midi.deviceNamed() or hs.midi.virtualSourceNamed().","url":"HSMIDIDevice.html","kind":"type"},{"fullName":"HSMIDIDevice.identifier","description":"A unique identifier for this device object.","url":"HSMIDIDevice.html#identifier","kind":"property"},{"fullName":"HSMIDIDevice.name","description":"The device's raw name.","url":"HSMIDIDevice.html#name","kind":"property"},{"fullName":"HSMIDIDevice.displayName","description":"The device's user-facing display name. Falls back to name if unavailable.","url":"HSMIDIDevice.html#displayName","kind":"property"},{"fullName":"HSMIDIDevice.manufacturer","description":"The device's manufacturer name, or an empty string if unavailable.","url":"HSMIDIDevice.html#manufacturer","kind":"property"},{"fullName":"HSMIDIDevice.model","description":"The device's model name, or an empty string if unavailable.","url":"HSMIDIDevice.html#model","kind":"property"},{"fullName":"HSMIDIDevice.isOnline","description":"Whether the device is currently online (connected).","url":"HSMIDIDevice.html#isOnline","kind":"property"},{"fullName":"HSMIDIDevice.isVirtual","description":"Whether this is a virtual source (created via hs.midi.virtualSourceNamed()) rather than a physical device.","url":"HSMIDIDevice.html#isVirtual","kind":"property"},{"fullName":"HSMIDIDevice.setCallback(fn)","description":"Sets or removes the callback fired when a MIDI message is received. The callback receives five arguments: this device object, the device's name, the command type as a string (e.g. \"noteOn\", \"controlChange\", \"systemExclusive\" — see hs.midi.commandTypes for the full set), a human-readable description, and a metadata table of command-specific fields. when released, but some send noteOn with velocity 0 instead of noteOff.","url":"HSMIDIDevice.html#setCallback","kind":"method"},{"fullName":"HSMIDIDevice.sendCommand(commandType, metadata)","description":"Sends a MIDI command to the device.","url":"HSMIDIDevice.html#sendCommand","kind":"method"},{"fullName":"HSMIDIDevice.sendSysex(command)","description":"Sends a System Exclusive command to the device.","url":"HSMIDIDevice.html#sendSysex","kind":"method"},{"fullName":"HSMIDIDevice.identityRequest()","description":"Sends a MIDI Identity Request. The device's reply, if any, arrives via the callback set with setCallback() as a systemExclusive message.","url":"HSMIDIDevice.html#identityRequest","kind":"method"},{"fullName":"HSMIDIDevice.destroy()","description":"Stops receiving from and releases all resources held by this device object. Called automatically when Hammerspoon reloads.","url":"HSMIDIDevice.html#destroy","kind":"method"},{"fullName":"HSNetworkConfigurationWatcher","description":"A watcher for System Configuration dynamic store key changes. Create with hs.network.configurationWatcher().","url":"HSNetworkConfigurationWatcher.html","kind":"type"},{"fullName":"HSNetworkConfigurationWatcher.typeName","description":"Always \"HSNetworkConfigurationWatcher\".","url":"HSNetworkConfigurationWatcher.html#typeName","kind":"property"},{"fullName":"HSNetworkConfigurationWatcher.setKeys(keys, pattern)","description":"Specifies which dynamic store keys (or key patterns) to watch for changes. Must be called before start(). Each element of keys is treated as a string literal when pattern is false (the default), or as a regular expression when pattern is true. Calling setKeys again replaces the previous set of watched keys.","url":"HSNetworkConfigurationWatcher.html#setKeys","kind":"method"},{"fullName":"HSNetworkConfigurationWatcher.setCallback(callback)","description":"Sets the callback invoked when a watched key changes. The callback receives (watcher, changedKeys) where changedKeys is an array of key strings that changed since the last notification. Call hs.network.configurationStore() inside the callback to read the updated values.","url":"HSNetworkConfigurationWatcher.html#setCallback","kind":"method"},{"fullName":"HSNetworkConfigurationWatcher.start()","description":"Starts watching for dynamic store changes. The callback registered with setCallback() will be invoked whenever a key matching the patterns registered with setKeys() changes. Call setKeys() and setCallback() before calling start().","url":"HSNetworkConfigurationWatcher.html#start","kind":"method"},{"fullName":"HSNetworkConfigurationWatcher.stop()","description":"Stops watching for dynamic store changes. The callback will no longer be invoked. Call start() again to resume monitoring.","url":"HSNetworkConfigurationWatcher.html#stop","kind":"method"},{"fullName":"HSNetworkPing","description":"Object representing an active or completed ICMP ping operation. Create instances with hs.network.ping().","url":"HSNetworkPing.html","kind":"type"},{"fullName":"HSNetworkPing.typeName","description":"Always \"HSNetworkPing\".","url":"HSNetworkPing.html#typeName","kind":"property"},{"fullName":"HSNetworkPing.address","description":"The resolved IP address of the target, or \"\" if DNS has not yet completed.","url":"HSNetworkPing.html#address","kind":"property"},{"fullName":"HSNetworkPing.server","description":"The hostname or IP address string originally passed to hs.network.ping().","url":"HSNetworkPing.html#server","kind":"property"},{"fullName":"HSNetworkPing.sent","description":"The number of ICMP Echo Requests sent so far.","url":"HSNetworkPing.html#sent","kind":"property"},{"fullName":"HSNetworkPing.count","description":"The total number of ICMP Echo Requests to send. May be increased while the ping is running provided the new value is greater than the number already sent.","url":"HSNetworkPing.html#count","kind":"property"},{"fullName":"HSNetworkPing.isRunning","description":"true while the ping is actively sending and waiting for replies.","url":"HSNetworkPing.html#isRunning","kind":"property"},{"fullName":"HSNetworkPing.isPaused","description":"true when the ping has been suspended with pause().","url":"HSNetworkPing.html#isPaused","kind":"property"},{"fullName":"HSNetworkPing.packets(sequenceNumber)","description":"Returns packet statistics for all sent packets, or for a single packet by its zero-based sequence number.","url":"HSNetworkPing.html#packets","kind":"method"},{"fullName":"HSNetworkPing.summary()","description":"Returns a human-readable summary of the ping results in standard ping format.","url":"HSNetworkPing.html#summary","kind":"method"},{"fullName":"HSNetworkPing.pause()","description":"Suspends the ping. No further packets are sent until resume() is called.","url":"HSNetworkPing.html#pause","kind":"method"},{"fullName":"HSNetworkPing.resume()","description":"Resumes a paused ping, continuing from where it left off.","url":"HSNetworkPing.html#resume","kind":"method"},{"fullName":"HSNetworkPing.cancel()","description":"Immediately stops the ping, firing the \"didFinish\" callback with statistics collected so far.","url":"HSNetworkPing.html#cancel","kind":"method"},{"fullName":"HSNetworkPing.setCallback(callback)","description":"Replaces the ping's callback function.","url":"HSNetworkPing.html#setCallback","kind":"method"},{"fullName":"HSNetworkReachability","description":"An active or inactive network reachability monitor. Create with hs.network.reachability*().","url":"HSNetworkReachability.html","kind":"type"},{"fullName":"HSNetworkReachability.typeName","description":"Always \"HSNetworkReachability\".","url":"HSNetworkReachability.html#typeName","kind":"property"},{"fullName":"HSNetworkReachability.status()","description":"Returns the current reachability flags as a numeric bitmask. Compare against constants in hs.network.reachabilityFlags. Returns 0 if the network is currently unreachable.","url":"HSNetworkReachability.html#status","kind":"method"},{"fullName":"HSNetworkReachability.statusString()","description":"Returns a human-readable summary of the current reachability flags. The string contains 8 characters in order: t (transient/expensive), R (reachable), c (connectionRequired), C (connectionOnTraffic — always -), i (interventionRequired/constrained), D (connectionOnDemand — always -), l (isLocalAddress — always -), d (isDirect). A letter appears when that flag is set; - appears when it is clear.","url":"HSNetworkReachability.html#statusString","kind":"method"},{"fullName":"HSNetworkReachability.setCallback(callback)","description":"Replaces the callback invoked when reachability changes. The callback receives (reachability, flags) where flags is the same numeric bitmask as returned by status(). Call start() after setCallback() to begin monitoring.","url":"HSNetworkReachability.html#setCallback","kind":"method"},{"fullName":"HSNetworkReachability.start()","description":"Starts monitoring for reachability changes. After calling start(), the callback registered with setCallback() is invoked whenever the reachability status changes.","url":"HSNetworkReachability.html#start","kind":"method"},{"fullName":"HSNetworkReachability.stop()","description":"Stops monitoring for reachability changes. The callback will no longer be invoked. Call start() again to resume monitoring.","url":"HSNetworkReachability.html#stop","kind":"method"},{"fullName":"HSNotification","description":"A notification created by hs.notify.new(). Call .send() to deliver it to macOS Notification Center. You can hold a reference to the object and call .withdraw() later to remove it.","url":"HSNotification.html","kind":"type"},{"fullName":"HSNotification.identifier","description":"The unique identifier assigned to this notification. Use it to correlate with system notification APIs if needed.","url":"HSNotification.html#identifier","kind":"property"},{"fullName":"HSNotification.send()","description":"Deliver this notification immediately to Notification Center.","url":"HSNotification.html#send","kind":"method"},{"fullName":"HSNotification.withdraw()","description":"Remove this notification from Notification Center (if delivered) or cancel it (if pending).","url":"HSNotification.html#withdraw","kind":"method"},{"fullName":"HSOCRObservation","description":"A single region of text recognized in an image. Instances are delivered inside the observations array of an HSOCRResult. Each observation represents a discrete text run found in the source image, along with a confidence score and a normalized bounding box. (0, 0) is the top-left corner of the image and (1, 1) is the bottom-right. This matches the convention used by most image-processing tools and differs from Vision's internal bottom-left-origin system (the conversion is automatic).","url":"HSOCRObservation.html","kind":"type"},{"fullName":"HSOCRObservation.typeName","description":"The Swift type name, for JavaScript introspection.","url":"HSOCRObservation.html#typeName","kind":"property"},{"fullName":"HSOCRObservation.text","description":"The recognized text string for this observation.","url":"HSOCRObservation.html#text","kind":"property"},{"fullName":"HSOCRObservation.confidence","description":"Recognition confidence in the range 0.0 (uncertain) to 1.0 (certain). Use minimumConfidence in the options passed to recognizeText() to pre-filter observations below a threshold rather than filtering here.","url":"HSOCRObservation.html#confidence","kind":"property"},{"fullName":"HSOCRObservation.bounds","description":"Normalized bounding box of this observation in the source image, as an HSRect. All values are in the range 0–1 with top-left origin ((0, 0) = top-left corner, (1, 1) = bottom-right corner). Use bounds.x, bounds.y, bounds.w, and bounds.h to access the components.","url":"HSOCRObservation.html#bounds","kind":"property"},{"fullName":"HSOCRResult","description":"The result of a text recognition operation on an image. An HSOCRResult is returned by hs.ocr.recognizeText() and bundles the full recognized text together with an array of per-region observations, each carrying its own confidence score and bounding box.","url":"HSOCRResult.html","kind":"type"},{"fullName":"HSOCRResult.typeName","description":"The Swift type name, for JavaScript introspection.","url":"HSOCRResult.html#typeName","kind":"property"},{"fullName":"HSOCRResult.text","description":"The full recognized text from the image, with each observation's text joined by newlines in the order Vision returned them. Use this when you only need the raw text and don't care about bounding boxes or per-region confidence scores.","url":"HSOCRResult.html#text","kind":"property"},{"fullName":"HSOCRResult.observations","description":"The individual text observations that make up this result. Each entry in the array is an HSOCRObservation with its own text, confidence, and bounds properties. Observations are returned in the order Vision produced them (typically top-to-bottom, left-to-right, but this is image-dependent).","url":"HSOCRResult.html#observations","kind":"property"},{"fullName":"HSScreen","description":"An object representing a single display attached to the system. ## Coordinate system All geometry is returned in Hammerspoon screen coordinates: the origin (0, 0) is at the top-left of the primary display, and y increases downward. This matches Hammerspoon v1 and is the inverse of the raw macOS/CoreGraphics convention. ## Examples ``javascript const s = hs.screen.main(); console.log(s.name); // e.g. \"Built-in Retina Display\" console.log(s.frame.w); // usable width in points","url":"HSScreen.html","kind":"type"},{"fullName":"HSScreen.id","description":"Unique display identifier (matches CGDirectDisplayID).","url":"HSScreen.html#id","kind":"property"},{"fullName":"HSScreen.name","description":"The manufacturer-assigned localized display name.","url":"HSScreen.html#name","kind":"property"},{"fullName":"HSScreen.uuid","description":"The display's UUID string.","url":"HSScreen.html#uuid","kind":"property"},{"fullName":"HSScreen.frame","description":"The usable screen area in Hammerspoon coordinates, excluding the menu bar and Dock.","url":"HSScreen.html#frame","kind":"property"},{"fullName":"HSScreen.fullFrame","description":"The full screen area in Hammerspoon coordinates, including menu bar and Dock regions.","url":"HSScreen.html#fullFrame","kind":"property"},{"fullName":"HSScreen.position","description":"The screen's top-left corner in global Hammerspoon coordinates.","url":"HSScreen.html#position","kind":"property"},{"fullName":"HSScreen.mode","description":"The currently active display mode. An object with keys: width, height, scale, frequency.","url":"HSScreen.html#mode","kind":"property"},{"fullName":"HSScreen.availableModes","description":"All display modes supported by this screen. Each element has keys: width, height, scale, frequency.","url":"HSScreen.html#availableModes","kind":"property"},{"fullName":"HSScreen.rotation","description":"The current screen rotation in degrees (0, 90, 180, or 270). Assign one of 0, 90, 180, or 270 to rotate the display.","url":"HSScreen.html#rotation","kind":"property"},{"fullName":"HSScreen.desktopImage","description":"The URL string of the current desktop background image for this screen, or null. Assign a new absolute file path or file:// URL string to change the wallpaper.","url":"HSScreen.html#desktopImage","kind":"property"},{"fullName":"HSScreen.ambientLight","description":"The ambient light level measured by this display's built-in sensor, in lux. Returns null if the display does not have an ambient light sensor or if the reading is currently unavailable.","url":"HSScreen.html#ambientLight","kind":"property"},{"fullName":"HSScreen.setMode(width, height, scale, frequency)","description":"Switch to the given display mode. Pass 0 for scale or frequency to match any value.","url":"HSScreen.html#setMode","kind":"method"},{"fullName":"HSScreen.snapshot()","description":"Capture the current contents of this screen as an image. Requires Screen Recording permission.","url":"HSScreen.html#snapshot","kind":"method"},{"fullName":"HSScreen.next()","description":"The next screen in hs.screen.all() order, wrapping around.","url":"HSScreen.html#next","kind":"method"},{"fullName":"HSScreen.previous()","description":"The previous screen in hs.screen.all() order, wrapping around.","url":"HSScreen.html#previous","kind":"method"},{"fullName":"HSScreen.toEast()","description":"The nearest screen whose left edge is at or beyond this screen's right edge, or null.","url":"HSScreen.html#toEast","kind":"method"},{"fullName":"HSScreen.toWest()","description":"The nearest screen whose right edge is at or before this screen's left edge, or null.","url":"HSScreen.html#toWest","kind":"method"},{"fullName":"HSScreen.toNorth()","description":"The nearest screen that is physically above this screen, or null.","url":"HSScreen.html#toNorth","kind":"method"},{"fullName":"HSScreen.toSouth()","description":"The nearest screen that is physically below this screen, or null.","url":"HSScreen.html#toSouth","kind":"method"},{"fullName":"HSScreen.setOrigin(x, y)","description":"Move this screen so its top-left corner is at the given position in global Hammerspoon coordinates.","url":"HSScreen.html#setOrigin","kind":"method"},{"fullName":"HSScreen.setPrimary()","description":"Designate this screen as the primary display (moves the menu bar here).","url":"HSScreen.html#setPrimary","kind":"method"},{"fullName":"HSScreen.mirrorOf(screen)","description":"Configure this screen to mirror another screen.","url":"HSScreen.html#mirrorOf","kind":"method"},{"fullName":"HSScreen.mirrorStop()","description":"Stop mirroring, restoring this screen to an independent display.","url":"HSScreen.html#mirrorStop","kind":"method"},{"fullName":"HSScreen.absoluteToLocal(rect)","description":"Convert a rect in global Hammerspoon coordinates to coordinates local to this screen. The result origin is relative to this screen's top-left corner.","url":"HSScreen.html#absoluteToLocal","kind":"method"},{"fullName":"HSScreen.localToAbsolute(rect)","description":"Convert a rect in local screen coordinates to global Hammerspoon coordinates.","url":"HSScreen.html#localToAbsolute","kind":"method"},{"fullName":"HSScreen.getBrightness()","description":"The current brightness of this display, from 0.0 (darkest) to 1.0 (brightest). Returns null if the display does not support software brightness control (e.g. most third-party monitors, which are controlled via DDC rather than software).","url":"HSScreen.html#getBrightness","kind":"method"},{"fullName":"HSScreen.setBrightness(brightness)","description":"Set the brightness of this display.","url":"HSScreen.html#setBrightness","kind":"method"},{"fullName":"HSSerialPort","description":"A serial port, created via hs.serial.createPortNamed() or hs.serial.createPortAtPath(). The port is not open until you call open(). Configure it (baud rate, data bits, etc.) either before or after opening — configuration changes made while open are applied immediately. Received data, and lifecycle events, are delivered via the callback registered with setCallback().","url":"HSSerialPort.html","kind":"type"},{"fullName":"HSSerialPort.identifier","description":"The unique identifier assigned to this port object.","url":"HSSerialPort.html#identifier","kind":"property"},{"fullName":"HSSerialPort.name","description":"The port's name (e.g. \"usbserial-1420\").","url":"HSSerialPort.html#name","kind":"property"},{"fullName":"HSSerialPort.path","description":"The port's device path (e.g. \"/dev/cu.usbserial-1420\").","url":"HSSerialPort.html#path","kind":"property"},{"fullName":"HSSerialPort.isOpen","description":"Whether the port is currently open.","url":"HSSerialPort.html#isOpen","kind":"property"},{"fullName":"HSSerialPort.baudRate","description":"The baud rate, in bits per second. Default is 115200. Setting a non-standard value (i.e. not one of 300, 1200, 2400, 4800, 9600, 14400, 19200, 28800, 38400, 57600, 115200, 230400) is rejected unless allowNonStandardBaudRates is true.","url":"HSSerialPort.html#baudRate","kind":"property"},{"fullName":"HSSerialPort.allowNonStandardBaudRates","description":"Whether baudRate may be set to a value outside the standard set. Default is false.","url":"HSSerialPort.html#allowNonStandardBaudRates","kind":"property"},{"fullName":"HSSerialPort.dataBits","description":"The number of data bits, 5–8. Default is 8.","url":"HSSerialPort.html#dataBits","kind":"property"},{"fullName":"HSSerialPort.stopBits","description":"The number of stop bits, 1 or 2. Default is 1.","url":"HSSerialPort.html#stopBits","kind":"property"},{"fullName":"HSSerialPort.parity","description":"The parity mode: \"none\", \"odd\", or \"even\". Default is \"none\".","url":"HSSerialPort.html#parity","kind":"property"},{"fullName":"HSSerialPort.dtr","description":"The state of the DTR (Data Terminal Ready) control line. Default is false.","url":"HSSerialPort.html#dtr","kind":"property"},{"fullName":"HSSerialPort.rts","description":"The state of the RTS (Request To Send) control line. Default is false.","url":"HSSerialPort.html#rts","kind":"property"},{"fullName":"HSSerialPort.usesRTSCTSFlowControl","description":"Whether to use hardware RTS/CTS flow control. Default is false.","url":"HSSerialPort.html#usesRTSCTSFlowControl","kind":"property"},{"fullName":"HSSerialPort.usesDTRDSRFlowControl","description":"Whether to use hardware DTR/DSR flow control. Default is false.","url":"HSSerialPort.html#usesDTRDSRFlowControl","kind":"property"},{"fullName":"HSSerialPort.shouldEchoReceivedData","description":"Whether data sent with sendData() is also delivered back to the callback as a \"received\" event, simulating local echo. Default is false.","url":"HSSerialPort.html#shouldEchoReceivedData","kind":"property"},{"fullName":"HSSerialPort.open()","description":"Opens the port using its current configuration.","url":"HSSerialPort.html#open","kind":"method"},{"fullName":"HSSerialPort.close()","description":"Closes the port.","url":"HSSerialPort.html#close","kind":"method"},{"fullName":"HSSerialPort.sendData(value)","description":"Sends data through the port. The string is transmitted as raw bytes: each character's code point (0–255) becomes one byte on the wire. This lets you round-trip arbitrary binary data — build the string with String.fromCharCode() for non-text payloads.","url":"HSSerialPort.html#sendData","kind":"method"},{"fullName":"HSSerialPort.setCallback(fn)","description":"Sets the callback invoked for port lifecycle events and received data. The callback receives two arguments: an event type string and a data string.","url":"HSSerialPort.html#setCallback","kind":"method"},{"fullName":"HSSerialPort.destroy()","description":"Closes the port and releases all resources. Called automatically during shutdown.","url":"HSSerialPort.html#destroy","kind":"method"},{"fullName":"HSSharingService","description":"A configured sharing service, wrapping NSSharingService. Create instances via hs.sharing.createShare() or hs.sharing.servicesFor(). Configure with setCallback(), recipients, and subject as needed, then call shareItems().","url":"HSSharingService.html","kind":"type"},{"fullName":"HSSharingService.identifier","description":"A unique identifier for this share object (UUID string).","url":"HSSharingService.html#identifier","kind":"property"},{"fullName":"HSSharingService.title","description":"The user-visible title of the service, e.g. \"Mail\" or \"AirDrop\".","url":"HSSharingService.html#title","kind":"property"},{"fullName":"HSSharingService.image","description":"The service's icon.","url":"HSSharingService.html#image","kind":"property"},{"fullName":"HSSharingService.alternateImage","description":"An alternate icon for the service, if one is provided, otherwise null.","url":"HSSharingService.html#alternateImage","kind":"property"},{"fullName":"HSSharingService.recipients","description":"Recipients (e.g. email addresses) for services that support them, such as Mail or Messages.","url":"HSSharingService.html#recipients","kind":"property"},{"fullName":"HSSharingService.subject","description":"The subject line, for services that support one, such as Mail.","url":"HSSharingService.html#subject","kind":"property"},{"fullName":"HSSharingService.messageBody","description":"The message body, populated once the share is in progress. Empty until then.","url":"HSSharingService.html#messageBody","kind":"property"},{"fullName":"HSSharingService.permanentLink","description":"A permanent link to the shared content, if the service provides one. Populated once the share is in progress; otherwise null.","url":"HSSharingService.html#permanentLink","kind":"property"},{"fullName":"HSSharingService.accountName","description":"The account name used to perform the share, if applicable. Populated once the share is in progress; otherwise null.","url":"HSSharingService.html#accountName","kind":"property"},{"fullName":"HSSharingService.attachments","description":"File paths of any attachments included in the share, populated once the share completes. Empty until then.","url":"HSSharingService.html#attachments","kind":"property"},{"fullName":"HSSharingService.canShareItems(items)","description":"Checks whether this service can share the given items. Items may be strings (treated as a web/mailto URL if they parse as one, a file path if they start with / or ~ and the file exists, otherwise plain text) or HSImage objects.","url":"HSSharingService.html#canShareItems","kind":"method"},{"fullName":"HSSharingService.shareItems(items)","description":"Attempts to share the given items with this service. If the service cannot handle the items, this logs a warning and returns false without doing anything further. Otherwise the share is started; it is asynchronous — use setCallback() to find out when it completes.","url":"HSSharingService.html#shareItems","kind":"method"},{"fullName":"HSSharingService.setCallback(fn)","description":"Registers a callback for share lifecycle events.","url":"HSSharingService.html#setCallback","kind":"method"},{"fullName":"HSSound","description":"An object representing an audio sound that can be played, paused, and stopped. Create instances using hs.sound.fromFile() or hs.sound.named().","url":"HSSound.html","kind":"type"},{"fullName":"HSSound.identifier","description":"A unique identifier for this sound object.","url":"HSSound.html#identifier","kind":"property"},{"fullName":"HSSound.name","description":"The name of this sound. System sounds loaded by name return their name; file-based sounds return null.","url":"HSSound.html#name","kind":"property"},{"fullName":"HSSound.duration","description":"The total duration of the sound in seconds.","url":"HSSound.html#duration","kind":"property"},{"fullName":"HSSound.currentTime","description":"The current playback position in seconds. Assign a value to seek to that position.","url":"HSSound.html#currentTime","kind":"property"},{"fullName":"HSSound.volume","description":"The playback volume, from 0.0 (silent) to 1.0 (full volume).","url":"HSSound.html#volume","kind":"property"},{"fullName":"HSSound.loops","description":"Whether the sound loops when it reaches the end. Defaults to false.","url":"HSSound.html#loops","kind":"property"},{"fullName":"HSSound.isPlaying","description":"Whether the sound is currently playing.","url":"HSSound.html#isPlaying","kind":"property"},{"fullName":"HSSound.play()","description":"Starts playback from the current position.","url":"HSSound.html#play","kind":"method"},{"fullName":"HSSound.pause()","description":"Pauses playback, preserving the current position.","url":"HSSound.html#pause","kind":"method"},{"fullName":"HSSound.resume()","description":"Resumes playback from a paused position.","url":"HSSound.html#resume","kind":"method"},{"fullName":"HSSound.stop()","description":"Stops playback. The playback position is not reset.","url":"HSSound.html#stop","kind":"method"},{"fullName":"HSSound.setCallback(callback)","description":"Sets a function to be called when playback finishes. The callback receives two arguments: the sound object and a boolean — true if the sound completed naturally, false if it was stopped before finishing.","url":"HSSound.html#setCallback","kind":"method"},{"fullName":"HSSound.removeCallback()","description":"Removes the completion callback previously set with setCallback().","url":"HSSound.html#removeCallback","kind":"method"},{"fullName":"HSSound.destroy()","description":"Stops playback and releases all resources held by this sound. After calling destroy() the sound object should not be used.","url":"HSSound.html#destroy","kind":"method"},{"fullName":"HSSpotlightGroup","description":"A grouped set of Spotlight results that share a common metadata attribute value. Groups are returned by HSSpotlightQuery.groups() when grouping attributes have been configured with setGroupingAttributes(). Do not instantiate HSSpotlightGroup directly. When multiple grouping attributes are specified, groups nest: each group has subgroups() containing the next level of grouping.","url":"HSSpotlightGroup.html","kind":"type"},{"fullName":"HSSpotlightGroup.identifier","description":"A unique identifier for this group object (UUID string).","url":"HSSpotlightGroup.html#identifier","kind":"property"},{"fullName":"HSSpotlightGroup.attribute","description":"The metadata attribute name by which results in this group are clustered.","url":"HSSpotlightGroup.html#attribute","kind":"property"},{"fullName":"HSSpotlightGroup.count","description":"The number of results contained in this group.","url":"HSSpotlightGroup.html#count","kind":"property"},{"fullName":"HSSpotlightGroup.value()","description":"The shared value of the grouping attribute for all results in this group. Returns null only in the unlikely case that the underlying value cannot be bridged.","url":"HSSpotlightGroup.html#value","kind":"method"},{"fullName":"HSSpotlightGroup.results()","description":"Returns the items contained in this group as an array of HSSpotlightItem objects.","url":"HSSpotlightGroup.html#results","kind":"method"},{"fullName":"HSSpotlightGroup.subgroups()","description":"Returns nested subgroups when multiple grouping attributes were specified. Returns an empty array if no subgroups exist for this group.","url":"HSSpotlightGroup.html#subgroups","kind":"method"},{"fullName":"HSSpotlightItem","description":"An individual result returned by a Spotlight query. Instances are returned by HSSpotlightQuery.results() and related methods. Do not instantiate HSSpotlightItem directly. Metadata values are read via valueForAttribute() using standard kMDItem* keys. Call attributes() to discover which keys are populated on a particular item. Common attribute key shortcuts live in hs.spotlight.attribute.","url":"HSSpotlightItem.html","kind":"type"},{"fullName":"HSSpotlightItem.identifier","description":"A unique identifier for this result object (UUID string).","url":"HSSpotlightItem.html#identifier","kind":"property"},{"fullName":"HSSpotlightItem.attributes()","description":"Returns the list of metadata attribute names present on this item. The list is typically not exhaustive — some attributes (such as kMDItemPath) may be readable via valueForAttribute() even when absent from this list.","url":"HSSpotlightItem.html#attributes","kind":"method"},{"fullName":"HSSpotlightItem.valueForAttribute(key)","description":"Returns the value for a specific metadata attribute, or null if absent. The return type depends on the attribute: common types include strings, numbers, dates, and arrays of strings. NSURL-typed values are automatically converted to their string representation.","url":"HSSpotlightItem.html#valueForAttribute","kind":"method"},{"fullName":"HSSpotlightQuery","description":"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.","url":"HSSpotlightQuery.html","kind":"type"},{"fullName":"HSSpotlightQuery.identifier","description":"A unique identifier for this query object (UUID string).","url":"HSSpotlightQuery.html#identifier","kind":"property"},{"fullName":"HSSpotlightQuery.count","description":"The number of results gathered so far.","url":"HSSpotlightQuery.html#count","kind":"property"},{"fullName":"HSSpotlightQuery.isRunning","description":"Whether the query is currently running (gathering or monitoring for live updates).","url":"HSSpotlightQuery.html#isRunning","kind":"property"},{"fullName":"HSSpotlightQuery.isGathering","description":"Whether the query is in the initial gathering phase. true from \"didStart\" until \"didFinish\"; false thereafter while live-monitoring.","url":"HSSpotlightQuery.html#isGathering","kind":"property"},{"fullName":"HSSpotlightQuery.setQuery(predicate)","description":"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.","url":"HSSpotlightQuery.html#setQuery","kind":"method"},{"fullName":"HSSpotlightQuery.setScopes(scopes)","description":"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.","url":"HSSpotlightQuery.html#setScopes","kind":"method"},{"fullName":"HSSpotlightQuery.setSortDescriptors(descriptors)","description":"Sets sort descriptors that control the order of results.","url":"HSSpotlightQuery.html#setSortDescriptors","kind":"method"},{"fullName":"HSSpotlightQuery.setGroupingAttributes(attrs)","description":"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().","url":"HSSpotlightQuery.html#setGroupingAttributes","kind":"method"},{"fullName":"HSSpotlightQuery.setValueListAttributes(attrs)","description":"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.","url":"HSSpotlightQuery.html#setValueListAttributes","kind":"method"},{"fullName":"HSSpotlightQuery.setCallback(fn)","description":"Registers a callback that receives query lifecycle events. of HSSpotlightItem objects describing what changed in this update cycle","url":"HSSpotlightQuery.html#setCallback","kind":"method"},{"fullName":"HSSpotlightQuery.start()","description":"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.","url":"HSSpotlightQuery.html#start","kind":"method"},{"fullName":"HSSpotlightQuery.stop()","description":"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.","url":"HSSpotlightQuery.html#stop","kind":"method"},{"fullName":"HSSpotlightQuery.results()","description":"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.","url":"HSSpotlightQuery.html#results","kind":"method"},{"fullName":"HSSpotlightQuery.groups()","description":"Returns grouped results when grouping attributes have been configured. Returns an empty array if setGroupingAttributes() was not called.","url":"HSSpotlightQuery.html#groups","kind":"method"},{"fullName":"HSSpotlightQuery.valueLists()","description":"Returns aggregate value-list summaries for attributes set via setValueListAttributes(). Returns an empty array if setValueListAttributes() was not called.","url":"HSSpotlightQuery.html#valueLists","kind":"method"},{"fullName":"HSStreamDeckDevice","description":"A Stream Deck device, obtained via hs.streamdeck.all() or a discovery watcher — do not instantiate directly.","url":"HSStreamDeckDevice.html","kind":"type"},{"fullName":"HSStreamDeckDevice.identifier","description":"The unique identifier assigned to this device object.","url":"HSStreamDeckDevice.html#identifier","kind":"property"},{"fullName":"HSStreamDeckDevice.deckType","description":"A human-readable description of the device model (e.g. \"Elgato Stream Deck (XL)\").","url":"HSStreamDeckDevice.html#deckType","kind":"property"},{"fullName":"HSStreamDeckDevice.serialNumber","description":"The device's serial number.","url":"HSStreamDeckDevice.html#serialNumber","kind":"property"},{"fullName":"HSStreamDeckDevice.firmwareVersion","description":"The device's firmware version. Reads live from the hardware on every access.","url":"HSStreamDeckDevice.html#firmwareVersion","kind":"property"},{"fullName":"HSStreamDeckDevice.keyColumns","description":"The number of button columns.","url":"HSStreamDeckDevice.html#keyColumns","kind":"property"},{"fullName":"HSStreamDeckDevice.keyRows","description":"The number of button rows.","url":"HSStreamDeckDevice.html#keyRows","kind":"property"},{"fullName":"HSStreamDeckDevice.keyCount","description":"The total number of buttons (keyColumns * keyRows).","url":"HSStreamDeckDevice.html#keyCount","kind":"property"},{"fullName":"HSStreamDeckDevice.encoderColumns","description":"The number of rotary encoders (Stream Deck Plus only; 0 on other models).","url":"HSStreamDeckDevice.html#encoderColumns","kind":"property"},{"fullName":"HSStreamDeckDevice.encoderRows","description":"The number of encoder rows (Stream Deck Plus only; 0 on other models).","url":"HSStreamDeckDevice.html#encoderRows","kind":"property"},{"fullName":"HSStreamDeckDevice.encoderCount","description":"The total number of encoders (encoderColumns * encoderRows).","url":"HSStreamDeckDevice.html#encoderCount","kind":"property"},{"fullName":"HSStreamDeckDevice.imageSize","description":"The pixel dimensions required for button images.","url":"HSStreamDeckDevice.html#imageSize","kind":"property"},{"fullName":"HSStreamDeckDevice.setBrightness(brightness)","description":"Sets the device's brightness.","url":"HSStreamDeckDevice.html#setBrightness","kind":"method"},{"fullName":"HSStreamDeckDevice.reset()","description":"Resets the device to its power-on state (clears all button images).","url":"HSStreamDeckDevice.html#reset","kind":"method"},{"fullName":"HSStreamDeckDevice.setButtonImage(button, image)","description":"Sets a button's image.","url":"HSStreamDeckDevice.html#setButtonImage","kind":"method"},{"fullName":"HSStreamDeckDevice.setButtonColor(button, color)","description":"Sets a button to a solid color.","url":"HSStreamDeckDevice.html#setButtonColor","kind":"method"},{"fullName":"HSStreamDeckDevice.setScreenImage(encoder, image)","description":"Sets the LCD strip image above one encoder (Stream Deck Plus only; a no-op on other models).","url":"HSStreamDeckDevice.html#setScreenImage","kind":"method"},{"fullName":"HSStreamDeckDevice.buttonCallback(fn)","description":"Sets the callback for button press/release events. Replaces any previously set callback. The callback receives: this device, the button number, and whether it is now pressed.","url":"HSStreamDeckDevice.html#buttonCallback","kind":"method"},{"fullName":"HSStreamDeckDevice.encoderCallback(fn)","description":"Sets the callback for encoder press/release/rotation events (Stream Deck Plus only). Replaces any previously set callback. The callback receives: this device, the encoder number, whether it is now pressed, and two booleans indicating rotation direction (at most one is true per call).","url":"HSStreamDeckDevice.html#encoderCallback","kind":"method"},{"fullName":"HSStreamDeckDevice.screenCallback(fn)","description":"Sets the callback for LCD touch-screen events (Stream Deck Plus only). Replaces any previously set callback. The callback receives: this device, the event type (\"shortPress\", \"longPress\", or \"swipe\"), and the start/end X/Y coordinates (end coordinates are 0 unless swiping).","url":"HSStreamDeckDevice.html#screenCallback","kind":"method"},{"fullName":"HSStreamDeckDevice.destroy()","description":"Stops delivering events and releases all callbacks. Called automatically when the device is disconnected or the module shuts down.","url":"HSStreamDeckDevice.html#destroy","kind":"method"},{"fullName":"HSTask","description":"Object representing an external process task","url":"HSTask.html","kind":"type"},{"fullName":"HSTask.isRunning","description":"Check if the task is currently running","url":"HSTask.html#isRunning","kind":"property"},{"fullName":"HSTask.pid","description":"The process ID of the running task","url":"HSTask.html#pid","kind":"property"},{"fullName":"HSTask.environment","description":"The environment variables for the task","url":"HSTask.html#environment","kind":"property"},{"fullName":"HSTask.workingDirectory","description":"The working directory for the task","url":"HSTask.html#workingDirectory","kind":"property"},{"fullName":"HSTask.terminationStatus","description":"The termination status of the task","url":"HSTask.html#terminationStatus","kind":"property"},{"fullName":"HSTask.terminationReason","description":"The termination reason","url":"HSTask.html#terminationReason","kind":"property"},{"fullName":"HSTask.start()","description":"Start the task","url":"HSTask.html#start","kind":"method"},{"fullName":"HSTask.terminate()","description":"Terminate the task (send SIGTERM)","url":"HSTask.html#terminate","kind":"method"},{"fullName":"HSTask.kill9()","description":"Terminate the task with extreme prejudice (send SIGKILL)","url":"HSTask.html#kill9","kind":"method"},{"fullName":"HSTask.interrupt()","description":"Interrupt the task (send SIGINT)","url":"HSTask.html#interrupt","kind":"method"},{"fullName":"HSTask.pause()","description":"Pause the task (send SIGSTOP)","url":"HSTask.html#pause","kind":"method"},{"fullName":"HSTask.resume()","description":"Resume the task (send SIGCONT)","url":"HSTask.html#resume","kind":"method"},{"fullName":"HSTask.waitUntilExit()","description":"Wait for the task to complete (blocking)","url":"HSTask.html#waitUntilExit","kind":"method"},{"fullName":"HSTask.sendInput(data)","description":"Write data to the task's stdin","url":"HSTask.html#sendInput","kind":"method"},{"fullName":"HSTask.closeInput()","description":"Close the task's stdin","url":"HSTask.html#closeInput","kind":"method"},{"fullName":"TaskBuilder","description":"TaskBuilder class for fluent task construction","url":"TaskBuilder.html","kind":"type"},{"fullName":"TaskBuilder.withArgs(args)","description":"Add arguments","url":"TaskBuilder.html#withArgs","kind":"method"},{"fullName":"TaskBuilder.withEnvironment(environment)","description":"Set environment variables","url":"TaskBuilder.html#withEnvironment","kind":"method"},{"fullName":"TaskBuilder.inDirectory(directory)","description":"Set working directory","url":"TaskBuilder.html#inDirectory","kind":"method"},{"fullName":"TaskBuilder.onOutput(callback)","description":"Set output callback","url":"TaskBuilder.html#onOutput","kind":"method"},{"fullName":"TaskBuilder.run()","description":"Build and run the task","url":"TaskBuilder.html#run","kind":"method"},{"fullName":"TaskBuilder.build()","description":"Build the task without running","url":"TaskBuilder.html#build","kind":"method"},{"fullName":"HSTimer","description":"Object representing a timer. You should not instantiate these yourself, but rather, use the methods in hs.timer to create them for you.","url":"HSTimer.html","kind":"type"},{"fullName":"HSTimer.interval","description":"The timer's interval in seconds","url":"HSTimer.html#interval","kind":"property"},{"fullName":"HSTimer.repeats","description":"Whether the timer repeats","url":"HSTimer.html#repeats","kind":"property"},{"fullName":"HSTimer.start()","description":"Start the timer","url":"HSTimer.html#start","kind":"method"},{"fullName":"HSTimer.stop()","description":"Stop the timer","url":"HSTimer.html#stop","kind":"method"},{"fullName":"HSTimer.fire()","description":"Immediately fire the timer's callback","url":"HSTimer.html#fire","kind":"method"},{"fullName":"HSTimer.running()","description":"Check if the timer is currently running","url":"HSTimer.html#running","kind":"method"},{"fullName":"HSTimer.nextTrigger()","description":"Get the number of seconds until the timer next fires","url":"HSTimer.html#nextTrigger","kind":"method"},{"fullName":"HSTimer.setNextTrigger(seconds)","description":"Set when the timer should next fire","url":"HSTimer.html#setNextTrigger","kind":"method"},{"fullName":"HSTranslationSession","description":"JavaScript-visible API for a translation session bound to a specific language pair.","url":"HSTranslationSession.html","kind":"type"},{"fullName":"HSTranslationSession.typeName","description":"The Swift type name, for JavaScript introspection.","url":"HSTranslationSession.html#typeName","kind":"property"},{"fullName":"HSTranslationSession.sourceLanguage","description":"BCP-47 identifier of the source language (e.g. \"en\").","url":"HSTranslationSession.html#sourceLanguage","kind":"property"},{"fullName":"HSTranslationSession.targetLanguage","description":"BCP-47 identifier of the target language (e.g. \"fr\").","url":"HSTranslationSession.html#targetLanguage","kind":"property"},{"fullName":"HSTranslationSession.translate(text)","description":"Translate a string from the session's source language to its target language.","url":"HSTranslationSession.html#translate","kind":"method"},{"fullName":"HSUIWindow","description":"# HSUIWindow A custom window with declarative UI building HSUIWindow allows you to create custom windows with a SwiftUI-like declarative syntax. Build interfaces using shapes, text, images, and layout containers. Note: Clicking the macOS close button only hides the window (firing the onHide() callback, if you have one configured) — it does not destroy the window while you hold a reference to it in JavaScript. Call destroy() explicitly (for example from within an onHide() handler) if you want to release it. See onShow(), onHide(), and onDestroy() below for the full set of lifecycle callbacks. ## Building UI Elements ## Modifying Elements ## Examples Simple window with text and shapes: ``javascript hs.ui.window({x: 100, y: 100, w: 300, h: 200}) .vstack() .spacing(10) .padding(20) .text(\"Dashboard\") .font(HSFont.largeTitle()) .foregroundColor(\"#FFFFFF\") .rectangle() .fill(\"#4A90E2\") .cornerRadius(10) .frame({w: \"90%\", h: 80}) .end() .backgroundColor(\"#2C3E50\") .show(); ` Window with image: `javascript const img = HSImage.fromPath(\"~/Pictures/photo.jpg\") hs.ui.window({x: 100, y: 100, w: 400, h: 300}) .vstack() .padding(20) .image(img) .resizable() .aspectRatio(\"fit\") .frame({w: 360, h: 240}) .end() .show(); ``","url":"HSUIWindow.html","kind":"type"},{"fullName":"HSUIWindow.show()","description":"Show the window","url":"HSUIWindow.html#show","kind":"method"},{"fullName":"HSUIWindow.hide()","description":"Hide the window (keeps it in memory)","url":"HSUIWindow.html#hide","kind":"method"},{"fullName":"HSUIWindow.destroy()","description":"Destroy the window","url":"HSUIWindow.html#destroy","kind":"method"},{"fullName":"HSUIWindow.onShow(callback)","description":"Set a callback to fire after the window is shown","url":"HSUIWindow.html#onShow","kind":"method"},{"fullName":"HSUIWindow.onHide(callback)","description":"Set a callback to fire when the window is hidden Fires when hide() is called, and when the user clicks the macOS close button — clicking that button only hides the window from Hammerspoon's perspective (see the class-level note above), so this is the callback that reacts to it. Does not fire when the window is destroyed via destroy() — use onDestroy() for that.","url":"HSUIWindow.html#onHide","kind":"method"},{"fullName":"HSUIWindow.onDestroy(callback)","description":"Set a callback to fire after the window is destroyed via destroy() Only fires when destroy() is called explicitly — whether directly, or from within an onHide() handler. It does not fire when the user clicks the macOS close button by itself; that only hides the window, so use onHide() to react to the button click, and call destroy() from that handler if you also want to release the window.","url":"HSUIWindow.html#onDestroy","kind":"method"},{"fullName":"HSUIWindow.titled(show)","description":"Show or hide the window's title bar By default windows have a title bar. Pass false to create a borderless window. .closable(), .miniaturizable(), and .allowResize() only take visual effect when the window is titled.","url":"HSUIWindow.html#titled","kind":"method"},{"fullName":"HSUIWindow.closable(show)","description":"Show or hide the close button on the window Requires .titled(true) to be visible. Enabled by default.","url":"HSUIWindow.html#closable","kind":"method"},{"fullName":"HSUIWindow.miniaturizable(show)","description":"Show or hide the miniaturize (yellow) button on the window Requires .titled(true) to be visible. Enabled by default.","url":"HSUIWindow.html#miniaturizable","kind":"method"},{"fullName":"HSUIWindow.allowResize(enable)","description":"Allow or prevent the user from resizing the window Enabled by default. Only has a visual effect when .titled(true) is also set.","url":"HSUIWindow.html#allowResize","kind":"method"},{"fullName":"HSUIWindow.windowTitle(text)","description":"Set the text shown in the window's title bar Only visible when .titled(true) is set (the default).","url":"HSUIWindow.html#windowTitle","kind":"method"},{"fullName":"HSUIWindow.level(name)","description":"Set the window stacking level Controls where this window sits in the macOS window hierarchy.","url":"HSUIWindow.html#level","kind":"method"},{"fullName":"HSUIWindow.backgroundColor(colorValue)","description":"Set the window's background color","url":"HSUIWindow.html#backgroundColor","kind":"method"},{"fullName":"HSUIWindow.rectangle()","description":"Add a rectangle shape","url":"HSUIWindow.html#rectangle","kind":"method"},{"fullName":"HSUIWindow.circle()","description":"Add a circle shape","url":"HSUIWindow.html#circle","kind":"method"},{"fullName":"HSUIWindow.text(content)","description":"Add a text element or an HSString object (from hs.ui.string()) for reactive text","url":"HSUIWindow.html#text","kind":"method"},{"fullName":"HSUIWindow.image(imageValue)","description":"Add an image element","url":"HSUIWindow.html#image","kind":"method"},{"fullName":"HSUIWindow.video(videoValue)","description":"Add a video element Renders a SwiftUI VideoPlayer for the given HSVideo. Keep a reference to the HSVideo object to control playback (play(), pause(), seek(), volume) after the window is shown.","url":"HSUIWindow.html#video","kind":"method"},{"fullName":"HSUIWindow.button(label)","description":"Add a button element or an HSString object (from hs.ui.string()) for reactive text","url":"HSUIWindow.html#button","kind":"method"},{"fullName":"HSUIWindow.vstack()","description":"Begin a vertical stack (elements arranged top to bottom)","url":"HSUIWindow.html#vstack","kind":"method"},{"fullName":"HSUIWindow.hstack()","description":"Begin a horizontal stack (elements arranged left to right)","url":"HSUIWindow.html#hstack","kind":"method"},{"fullName":"HSUIWindow.zstack()","description":"Begin a z-stack (overlapping elements)","url":"HSUIWindow.html#zstack","kind":"method"},{"fullName":"HSUIWindow.spacer()","description":"Add flexible spacing that expands to fill available space","url":"HSUIWindow.html#spacer","kind":"method"},{"fullName":"HSUIWindow.webview(element)","description":"Embed a web browser element created with hs.ui.webview() (macOS 26+) The element fills the available space in the window layout. Keep a reference to the element to call navigation methods after the window is shown.","url":"HSUIWindow.html#webview","kind":"method"},{"fullName":"HSUIWindow.end()","description":"End the current layout container","url":"HSUIWindow.html#end","kind":"method"},{"fullName":"HSUIWindow.fill(colorValue)","description":"Fill a shape with a color","url":"HSUIWindow.html#fill","kind":"method"},{"fullName":"HSUIWindow.stroke(colorValue)","description":"Add a stroke (border) to a shape","url":"HSUIWindow.html#stroke","kind":"method"},{"fullName":"HSUIWindow.strokeWidth(width)","description":"Set the stroke width","url":"HSUIWindow.html#strokeWidth","kind":"method"},{"fullName":"HSUIWindow.cornerRadius(radius)","description":"Round the corners of a shape","url":"HSUIWindow.html#cornerRadius","kind":"method"},{"fullName":"HSUIWindow.frame(dict)","description":"Set the frame (size) of an element","url":"HSUIWindow.html#frame","kind":"method"},{"fullName":"HSUIWindow.opacity(value)","description":"Set the opacity of an element","url":"HSUIWindow.html#opacity","kind":"method"},{"fullName":"HSUIWindow.font(font)","description":"Set the font for a text element","url":"HSUIWindow.html#font","kind":"method"},{"fullName":"HSUIWindow.foregroundColor(colorValue)","description":"Set the text color","url":"HSUIWindow.html#foregroundColor","kind":"method"},{"fullName":"HSUIWindow.resizable()","description":"Make an image resizable (allows it to scale with frame size)","url":"HSUIWindow.html#resizable","kind":"method"},{"fullName":"HSUIWindow.aspectRatio(mode)","description":"Set the aspect ratio mode for an image","url":"HSUIWindow.html#aspectRatio","kind":"method"},{"fullName":"HSUIWindow.padding(value)","description":"Add padding around a layout container","url":"HSUIWindow.html#padding","kind":"method"},{"fullName":"HSUIWindow.spacing(value)","description":"Set spacing between elements in a stack","url":"HSUIWindow.html#spacing","kind":"method"},{"fullName":"HSUIWindow.onClick(callback)","description":"Set a callback to fire when the element is clicked","url":"HSUIWindow.html#onClick","kind":"method"},{"fullName":"HSUIWindow.onHover(callback)","description":"Set a callback to fire when the cursor enters or leaves the element","url":"HSUIWindow.html#onHover","kind":"method"},{"fullName":"HSUIAlert","description":"# HSUIAlert A temporary on-screen notification Displays a message that automatically fades out after a specified duration. Without an explicit .position(), multiple alerts stack vertically and stay centered as they appear and disappear. With .position(), the alert appears at the given coordinates regardless of other alerts. ## Example ``javascript hs.ui.alert(\"Task completed!\") .font(HSFont.headline()) .duration(5) .padding(30) .show(); ``","url":"HSUIAlert.html","kind":"type"},{"fullName":"HSUIAlert.font(font)","description":"Set the font for the alert text","url":"HSUIAlert.html#font","kind":"method"},{"fullName":"HSUIAlert.duration(seconds)","description":"Set how long the alert is displayed","url":"HSUIAlert.html#duration","kind":"method"},{"fullName":"HSUIAlert.padding(points)","description":"Set the padding around the alert text","url":"HSUIAlert.html#padding","kind":"method"},{"fullName":"HSUIAlert.position(dict)","description":"Set a custom position for the alert When a position is set, the alert is shown at those coordinates and will not be stacked with other alerts. Coordinates are in points from the top-left of the visible screen area (below the menu bar), with y increasing downward.","url":"HSUIAlert.html#position","kind":"method"},{"fullName":"HSUIAlert.show()","description":"Show the alert","url":"HSUIAlert.html#show","kind":"method"},{"fullName":"HSUIAlert.close()","description":"Close the alert immediately","url":"HSUIAlert.html#close","kind":"method"},{"fullName":"HSUIDialog","description":"# HSUIDialog A modal dialog with customizable buttons Shows a blocking dialog with a message, optional informative text, and custom buttons. Use the callback to respond to button presses. ## Example ``javascript hs.ui.dialog(\"Save changes?\") .informativeText(\"Your document has unsaved changes.\") .buttons([\"Save\", \"Don't Save\", \"Cancel\"]) .onButton((index) => { if (index === 0) { console.log(\"Saving...\"); } else if (index === 1) { console.log(\"Discarding changes...\"); } }) .show(); ``","url":"HSUIDialog.html","kind":"type"},{"fullName":"HSUIDialog.informativeText(text)","description":"Set additional informative text below the main message","url":"HSUIDialog.html#informativeText","kind":"method"},{"fullName":"HSUIDialog.buttons(labels)","description":"Set custom button labels","url":"HSUIDialog.html#buttons","kind":"method"},{"fullName":"HSUIDialog.style(style)","description":"Set the dialog style","url":"HSUIDialog.html#style","kind":"method"},{"fullName":"HSUIDialog.onButton(callback)","description":"Set the callback for button presses","url":"HSUIDialog.html#onButton","kind":"method"},{"fullName":"HSUIDialog.show()","description":"Show the dialog","url":"HSUIDialog.html#show","kind":"method"},{"fullName":"HSUIDialog.close()","description":"Close the dialog programmatically","url":"HSUIDialog.html#close","kind":"method"},{"fullName":"HSUIFilePicker","description":"# HSUIFilePicker A file or directory selection dialog Shows a standard macOS open panel for selecting files or directories. Supports multiple selection, file type filtering, and more. ## Examples ### File Picker ``javascript hs.ui.filePicker() .message(\"Choose a file to open\") .allowedFileTypes([\"txt\", \"md\", \"js\"]) .onSelection((path) => { if (path) { console.log(\"Selected: \" + path); } else { console.log(\"User cancelled\"); } }) .show(); ` ### Directory Picker with Multiple Selection `javascript hs.ui.filePicker() .message(\"Choose directories to backup\") .canChooseFiles(false) .canChooseDirectories(true) .allowsMultipleSelection(true) .onSelection((paths) => { if (paths) { paths.forEach(p => console.log(\"Dir: \" + p)); } }) .show(); ``","url":"HSUIFilePicker.html","kind":"type"},{"fullName":"HSUIFilePicker.message(text)","description":"Set the message displayed in the picker","url":"HSUIFilePicker.html#message","kind":"method"},{"fullName":"HSUIFilePicker.defaultPath(path)","description":"Set the starting directory","url":"HSUIFilePicker.html#defaultPath","kind":"method"},{"fullName":"HSUIFilePicker.canChooseFiles(value)","description":"Set whether files can be selected","url":"HSUIFilePicker.html#canChooseFiles","kind":"method"},{"fullName":"HSUIFilePicker.canChooseDirectories(value)","description":"Set whether directories can be selected","url":"HSUIFilePicker.html#canChooseDirectories","kind":"method"},{"fullName":"HSUIFilePicker.allowsMultipleSelection(value)","description":"Set whether multiple items can be selected","url":"HSUIFilePicker.html#allowsMultipleSelection","kind":"method"},{"fullName":"HSUIFilePicker.allowedFileTypes(types)","description":"Restrict to specific file types","url":"HSUIFilePicker.html#allowedFileTypes","kind":"method"},{"fullName":"HSUIFilePicker.resolvesAliases(value)","description":"Set whether to resolve symbolic links","url":"HSUIFilePicker.html#resolvesAliases","kind":"method"},{"fullName":"HSUIFilePicker.onSelection(callback)","description":"Set the callback for file selection","url":"HSUIFilePicker.html#onSelection","kind":"method"},{"fullName":"HSUIFilePicker.show()","description":"Show the file picker dialog","url":"HSUIFilePicker.html#show","kind":"method"},{"fullName":"HSUITextPrompt","description":"# HSUITextPrompt A modal dialog with text input Shows a blocking dialog with a text input field. The callback receives both the button index and the entered text. ## Example ``javascript hs.ui.textPrompt(\"Enter your name\") .informativeText(\"Please provide your full name\") .defaultText(\"John Doe\") .buttons([\"OK\", \"Cancel\"]) .onButton((buttonIndex, text) => { if (buttonIndex === 0) { console.log(\"User entered: \" + text); } }) .show(); ``","url":"HSUITextPrompt.html","kind":"type"},{"fullName":"HSUITextPrompt.informativeText(text)","description":"Set additional informative text below the main message","url":"HSUITextPrompt.html#informativeText","kind":"method"},{"fullName":"HSUITextPrompt.defaultText(text)","description":"Set the default text in the input field","url":"HSUITextPrompt.html#defaultText","kind":"method"},{"fullName":"HSUITextPrompt.buttons(labels)","description":"Set custom button labels","url":"HSUITextPrompt.html#buttons","kind":"method"},{"fullName":"HSUITextPrompt.onButton(callback)","description":"Set the callback for button presses","url":"HSUITextPrompt.html#onButton","kind":"method"},{"fullName":"HSUITextPrompt.show()","description":"Show the prompt dialog","url":"HSUITextPrompt.html#show","kind":"method"},{"fullName":"UIWebView","description":"# hs.ui.webview A web browser element for embedding in hs.ui.window layouts Available on macOS 26.0 or later, hs.ui.webview() creates a web browser element backed by a SwiftUI WebView and WebPage. Embed it in any hs.ui.window using .webview(element) — it fills the available space and can sit alongside other elements in stacks. ``javascript const wv = hs.ui.webview() .toolbar([\"back\", \"forward\", \"reload\", \"url\"]) .loadURL(\"https://apple.com\")","url":"UIWebView.html","kind":"type"},{"fullName":"UIWebView.url","description":"The URL of the current page, or null if no page is loaded","url":"UIWebView.html#url","kind":"property"},{"fullName":"UIWebView.title","description":"The title of the current page","url":"UIWebView.html#title","kind":"property"},{"fullName":"UIWebView.isLoading","description":"Whether the web view is currently loading a page","url":"UIWebView.html#isLoading","kind":"property"},{"fullName":"UIWebView.estimatedProgress","description":"The estimated loading progress from 0.0 to 1.0","url":"UIWebView.html#estimatedProgress","kind":"property"},{"fullName":"UIWebView.canGoBack","description":"Whether the web view can navigate back in history","url":"UIWebView.html#canGoBack","kind":"property"},{"fullName":"UIWebView.canGoForward","description":"Whether the web view can navigate forward in history","url":"UIWebView.html#canGoForward","kind":"property"},{"fullName":"UIWebView.loadURL(urlString)","description":"Load a URL in the web view","url":"UIWebView.html#loadURL","kind":"method"},{"fullName":"UIWebView.loadHTML(html)","description":"Load an HTML string directly into the web view","url":"UIWebView.html#loadHTML","kind":"method"},{"fullName":"UIWebView.goBack()","description":"Navigate back in the browser history","url":"UIWebView.html#goBack","kind":"method"},{"fullName":"UIWebView.goForward()","description":"Navigate forward in the browser history","url":"UIWebView.html#goForward","kind":"method"},{"fullName":"UIWebView.reload()","description":"Reload the current page","url":"UIWebView.html#reload","kind":"method"},{"fullName":"UIWebView.stopLoading()","description":"Stop loading the current page","url":"UIWebView.html#stopLoading","kind":"method"},{"fullName":"UIWebView.userAgent(ua)","description":"Set a custom User-Agent string for HTTP requests","url":"UIWebView.html#userAgent","kind":"method"},{"fullName":"UIWebView.inspectable(value)","description":"Enable or disable the Safari Web Inspector for this web view When enabled, the web view appears in Safari → Develop menu.","url":"UIWebView.html#inspectable","kind":"method"},{"fullName":"UIWebView.toolbar(items)","description":"Configure the toolbar with a list of standard and custom items The toolbar renders above the web view. Each element of the array is either a string naming a standard control or a dictionary describing a custom button. An empty array (or omitting this call) hides the toolbar. Standard string items: \"back\", \"forward\", \"reload\", \"url\", \"spacer\".","url":"UIWebView.html#toolbar","kind":"method"},{"fullName":"UIWebView.backForwardGestures(enabled)","description":"Enable or disable the macOS back/forward trackpad swipe gestures Gestures are enabled by default. Pass false to disable them.","url":"UIWebView.html#backForwardGestures","kind":"method"},{"fullName":"UIWebView.magnificationGestures(enabled)","description":"Enable or disable the trackpad pinch-to-zoom magnification gesture The gesture is enabled by default. Pass false to disable it.","url":"UIWebView.html#magnificationGestures","kind":"method"},{"fullName":"UIWebView.linkPreviews(enabled)","description":"Enable or disable link preview popovers shown on force-click Link previews are enabled by default. Pass false to disable them.","url":"UIWebView.html#linkPreviews","kind":"method"},{"fullName":"UIWebView.contentBackground(visible)","description":"Control whether the web page background is visible Pass false to make the web view background transparent. Enabled (visible) by default.","url":"UIWebView.html#contentBackground","kind":"method"},{"fullName":"UIWebView.onLoadChange(callback)","description":"Register a callback that fires when loading state or progress changes Called whenever isLoading, url, title, or estimatedProgress changes.","url":"UIWebView.html#onLoadChange","kind":"method"},{"fullName":"UIWebView.onNavigate(callback)","description":"Register a callback that fires when navigation to a new page completes","url":"UIWebView.html#onNavigate","kind":"method"},{"fullName":"UIWebView.onTitleChange(callback)","description":"Register a callback that fires when the page title changes","url":"UIWebView.html#onTitleChange","kind":"method"},{"fullName":"UIWebView.onNavigationDecision(callback)","description":"Register a callback that controls whether navigation is allowed Called before each navigation. Return true to allow or false to block.","url":"UIWebView.html#onNavigationDecision","kind":"method"},{"fullName":"UIWebView.execJS(script)","description":"Execute JavaScript in the web page without capturing the result","url":"UIWebView.html#execJS","kind":"method"},{"fullName":"UIWebView.evalJSResult(script, callback)","description":"Execute JavaScript in the web page and deliver the result to a callback The JavaScript method name is evalJSResult — it derives from the internal Objective-C selector evalJS:result:.","url":"UIWebView.html#evalJSResult","kind":"method"},{"fullName":"HSWifiWatcher","description":"A Wi-Fi event watcher that monitors changes to a Wi-Fi interface. Create via hs.wifi.addWatcher(). Set a callback with setCallback(), then call start() to begin receiving events. By default only \"ssidChange\" is watched; use the events property to watch other event types. | Event | Info keys | |-------|-----------| | \"ssidChange\" | interface: string | | \"bssidChange\" | interface: string | | \"countryCodeChange\" | interface: string | | \"linkChange\" | interface: string | | \"linkQualityChange\" | interface: string, rssi: number, transmitRate: number | | \"modeChange\" | interface: string | | \"powerChange\" | interface: string | | \"scanCacheUpdated\" | interface: string |","url":"HSWifiWatcher.html","kind":"type"},{"fullName":"HSWifiWatcher.identifier","description":"The unique identifier assigned to this watcher.","url":"HSWifiWatcher.html#identifier","kind":"property"},{"fullName":"HSWifiWatcher.events","description":"The event types this watcher will invoke its callback for. Defaults to [\"ssidChange\"]. Unrecognized values are ignored with a console warning; see hs.wifi.watcherEventTypes for the list of valid values. Can be changed while the watcher is running.","url":"HSWifiWatcher.html#events","kind":"property"},{"fullName":"HSWifiWatcher.start()","description":"Starts monitoring the event types configured in events.","url":"HSWifiWatcher.html#start","kind":"method"},{"fullName":"HSWifiWatcher.stop()","description":"Stops monitoring Wi-Fi events.","url":"HSWifiWatcher.html#stop","kind":"method"},{"fullName":"HSWifiWatcher.setCallback(fn)","description":"Sets the callback function invoked when a watched Wi-Fi event occurs.","url":"HSWifiWatcher.html#setCallback","kind":"method"},{"fullName":"HSWifiWatcher.destroy()","description":"Stops the watcher and releases all resources. Called automatically during shutdown.","url":"HSWifiWatcher.html#destroy","kind":"method"},{"fullName":"HSWindow","description":"Object representing a window. You should not instantiate these directly, but rather, use the methods in hs.window to create them for you. Note that this type uses private macOS APIs","url":"HSWindow.html","kind":"type"},{"fullName":"HSWindow.title","description":"The window's title","url":"HSWindow.html#title","kind":"property"},{"fullName":"HSWindow.application","description":"The application that owns this window","url":"HSWindow.html#application","kind":"property"},{"fullName":"HSWindow.pid","description":"The process ID of the application that owns this window","url":"HSWindow.html#pid","kind":"property"},{"fullName":"HSWindow.id","description":"The window's underlying ID. A value of 0 or -1 likely means no window ID could be determined.","url":"HSWindow.html#id","kind":"property"},{"fullName":"HSWindow.isMinimized","description":"Whether the window is minimized","url":"HSWindow.html#isMinimized","kind":"property"},{"fullName":"HSWindow.isVisible","description":"Whether the window is visible (not minimized or hidden)","url":"HSWindow.html#isVisible","kind":"property"},{"fullName":"HSWindow.isFocused","description":"Whether the window is focused","url":"HSWindow.html#isFocused","kind":"property"},{"fullName":"HSWindow.isFullscreen","description":"Whether the window is fullscreen","url":"HSWindow.html#isFullscreen","kind":"property"},{"fullName":"HSWindow.isStandard","description":"Whether the window is standard (has a titlebar)","url":"HSWindow.html#isStandard","kind":"property"},{"fullName":"HSWindow.position","description":"The window's position on screen {x: Int, y: Int}","url":"HSWindow.html#position","kind":"property"},{"fullName":"HSWindow.size","description":"The window's size {w: Int, h: Int}","url":"HSWindow.html#size","kind":"property"},{"fullName":"HSWindow.frame","description":"The window's frame {x: Int, y: Int, w: Int, h: Int}","url":"HSWindow.html#frame","kind":"property"},{"fullName":"HSWindow.screen","description":"The screen that contains the largest portion of this window.","url":"HSWindow.html#screen","kind":"property"},{"fullName":"HSWindow.focus()","description":"Focus this window","url":"HSWindow.html#focus","kind":"method"},{"fullName":"HSWindow.minimize()","description":"Minimize this window","url":"HSWindow.html#minimize","kind":"method"},{"fullName":"HSWindow.unminimize()","description":"Unminimize this window","url":"HSWindow.html#unminimize","kind":"method"},{"fullName":"HSWindow.raise()","description":"Raise this window to the front","url":"HSWindow.html#raise","kind":"method"},{"fullName":"HSWindow.toggleFullscreen()","description":"Toggle fullscreen mode","url":"HSWindow.html#toggleFullscreen","kind":"method"},{"fullName":"HSWindow.close()","description":"Close this window","url":"HSWindow.html#close","kind":"method"},{"fullName":"HSWindow.centerOnScreen()","description":"Center the window on the screen","url":"HSWindow.html#centerOnScreen","kind":"method"},{"fullName":"HSWindow.snapshot(keepTransparency)","description":"Capture the current on-screen contents of this window as an image. Requires Screen Recording permission.","url":"HSWindow.html#snapshot","kind":"method"},{"fullName":"HSWindow.axElement()","description":"Get the underlying AXElement","url":"HSWindow.html#axElement","kind":"method"},{"fullName":"HSColor","description":"Bridge type for working with colors in JavaScript","url":"HSColor.html","kind":"type"},{"fullName":"HSColor.rgb(r, g, b, a)","description":"Create a color from RGB values","url":"HSColor.html#rgb","kind":"method"},{"fullName":"HSColor.hex(hex)","description":"Create a color from a hex string","url":"HSColor.html#hex","kind":"method"},{"fullName":"HSColor.named(name)","description":"Create a color from a named system color","url":"HSColor.html#named","kind":"method"},{"fullName":"HSColor.set(value)","description":"Update this color's value. If this color is bound to a UI element, the canvas re-renders automatically.","url":"HSColor.html#set","kind":"method"},{"fullName":"HSFont","description":"This is a JavaScript object used to represent macOS fonts. It includes a variety of static methods that can instantiate the various font sizes commonly used with UI elements, and also includes static methods for instantiating the system font at various sizes/weights, or any custom font available on the system.","url":"HSFont.html","kind":"type"},{"fullName":"HSFont.body()","description":"Body text style","url":"HSFont.html#body","kind":"method"},{"fullName":"HSFont.callout()","description":"Callout text style","url":"HSFont.html#callout","kind":"method"},{"fullName":"HSFont.caption()","description":"Caption text style","url":"HSFont.html#caption","kind":"method"},{"fullName":"HSFont.caption2()","description":"Caption2 text style","url":"HSFont.html#caption2","kind":"method"},{"fullName":"HSFont.footnote()","description":"Footnote text style","url":"HSFont.html#footnote","kind":"method"},{"fullName":"HSFont.headline()","description":"Headline text style","url":"HSFont.html#headline","kind":"method"},{"fullName":"HSFont.largeTitle()","description":"Large Title text style","url":"HSFont.html#largeTitle","kind":"method"},{"fullName":"HSFont.subheadline()","description":"Sub-headline text style","url":"HSFont.html#subheadline","kind":"method"},{"fullName":"HSFont.title()","description":"Title text style","url":"HSFont.html#title","kind":"method"},{"fullName":"HSFont.title2()","description":"Title2 text style","url":"HSFont.html#title2","kind":"method"},{"fullName":"HSFont.title3()","description":"Title3 text style","url":"HSFont.html#title3","kind":"method"},{"fullName":"HSFont.system(size)","description":"The system font in a custom size","url":"HSFont.html#system","kind":"method"},{"fullName":"HSFont.system(size, weight)","description":"The system font in a custom size with a choice of weights","url":"HSFont.html#system","kind":"method"},{"fullName":"HSFont.custom(name, size)","description":"A font present on the system at a given size","url":"HSFont.html#custom","kind":"method"},{"fullName":"HSImage","description":"Bridge type for working with images in JavaScript HSImage provides a comprehensive API for loading, manipulating, and saving images. It supports various image sources including files, system icons, app bundles, and URLs. ## Loading Images ``javascript // Load from file const img = HSImage.fromPath(\"/path/to/image.png\")","url":"HSImage.html","kind":"type"},{"fullName":"HSImage.size","description":"The size of the image. Setting this resizes the image in place to the exact dimensions.","url":"HSImage.html#size","kind":"property"},{"fullName":"HSImage.name","description":"The name of the image, or null if not set.","url":"HSImage.html#name","kind":"property"},{"fullName":"HSImage.template","description":"Whether the image is a template image. Template images are tinted by the system to match the appearance context (e.g. menu bar icons).","url":"HSImage.html#template","kind":"property"},{"fullName":"HSImage.fromPath(path)","description":"Load an image from a file path","url":"HSImage.html#fromPath","kind":"method"},{"fullName":"HSImage.fromName(name)","description":"Load a system image by name","url":"HSImage.html#fromName","kind":"method"},{"fullName":"HSImage.fromSymbol(name)","description":"Load a system symbol by name","url":"HSImage.html#fromSymbol","kind":"method"},{"fullName":"HSImage.fromAppBundle(bundleID, withFallbackSymbol)","description":"Load an app's icon by bundle identifier","url":"HSImage.html#fromAppBundle","kind":"method"},{"fullName":"HSImage.iconForFile(path)","description":"Get the icon for a file","url":"HSImage.html#iconForFile","kind":"method"},{"fullName":"HSImage.iconForFileType(fileType)","description":"Get the icon for a file type","url":"HSImage.html#iconForFileType","kind":"method"},{"fullName":"HSImage.fromURL(url)","description":"Load an image from a URL (asynchronous)","url":"HSImage.html#fromURL","kind":"method"},{"fullName":"HSImage.copyImage()","description":"Create a copy of the image","url":"HSImage.html#copyImage","kind":"method"},{"fullName":"HSImage.croppedCopy(rect)","description":"Create a cropped copy of the image","url":"HSImage.html#croppedCopy","kind":"method"},{"fullName":"HSImage.saveToFile(path)","description":"Save the image to a file","url":"HSImage.html#saveToFile","kind":"method"},{"fullName":"HSImage.set(value)","description":"Replace this image's content. If this image is bound to a UI element, the canvas re-renders automatically.","url":"HSImage.html#set","kind":"method"},{"fullName":"HSPoint","description":"This is a JavaScript object used to represent coordinates, or \"points\", as used in various places throughout Hammerspoon's API, particularly where dealing with positions on a screen. Behind the scenes it is a wrapper for the CGPoint type in Swift/ObjectiveC.","url":"HSPoint.html","kind":"type"},{"fullName":"HSPoint.x","description":"A coordinate for the x-axis position of this point","url":"HSPoint.html#x","kind":"property"},{"fullName":"HSPoint.y","description":"A coordinate for the y-axis position of this point","url":"HSPoint.html#y","kind":"property"},{"fullName":"HSPoint.angle()","description":"Returns the angle between the positive x axis and this point, treated as a vector","url":"HSPoint.html#angle","kind":"method"},{"fullName":"HSPoint.angleTo(other)","description":"Returns the angle between the positive x axis and the vector from this point to another point or rect's center","url":"HSPoint.html#angleTo","kind":"method"},{"fullName":"HSPoint.distance(other)","description":"Finds the distance between this point and another point or rect's center","url":"HSPoint.html#distance","kind":"method"},{"fullName":"HSPoint.equals(other)","description":"Checks if this point is equal to another point","url":"HSPoint.html#equals","kind":"method"},{"fullName":"HSPoint.floor()","description":"Truncates the coordinates of this point towards negative infinity","url":"HSPoint.html#floor","kind":"method"},{"fullName":"HSPoint.inside(rect)","description":"Checks if this point lies inside a given rect","url":"HSPoint.html#inside","kind":"method"},{"fullName":"HSPoint.move(offset)","description":"Moves this point by an offset","url":"HSPoint.html#move","kind":"method"},{"fullName":"HSPoint.normalize()","description":"Normalizes this point, treated as a vector, to a length of 1","url":"HSPoint.html#normalize","kind":"method"},{"fullName":"HSPoint.rotateCCW(aroundPoint, times)","description":"Rotates this point counter-clockwise around another point","url":"HSPoint.html#rotateCCW","kind":"method"},{"fullName":"HSPoint.scale(factor)","description":"Scales this point, treated as a vector","url":"HSPoint.html#scale","kind":"method"},{"fullName":"HSPoint.vector(other)","description":"Returns the vector from this point to another point or rect's center","url":"HSPoint.html#vector","kind":"method"},{"fullName":"HSRect","description":"This is a JavaScript object used to represent a rectangle, as used in various places throughout Hammerspoon's API, particularly where dealing with portions of a display. Behind the scenes it is a wrapper for the CGRect type in Swift/ObjectiveC.","url":"HSRect.html","kind":"type"},{"fullName":"HSRect.x","description":"An x-axis coordinate for the top-left point of the rectangle","url":"HSRect.html#x","kind":"property"},{"fullName":"HSRect.y","description":"A y-axis coordinate for the top-left point of the rectangle","url":"HSRect.html#y","kind":"property"},{"fullName":"HSRect.w","description":"The width of the rectangle","url":"HSRect.html#w","kind":"property"},{"fullName":"HSRect.h","description":"The height of the rectangle","url":"HSRect.html#h","kind":"property"},{"fullName":"HSRect.origin","description":"The \"origin\" of the rectangle, ie the coordinates of its top left corner, as an HSPoint object","url":"HSRect.html#origin","kind":"property"},{"fullName":"HSRect.size","description":"The size of the rectangle, ie its width and height, as an HSSize object","url":"HSRect.html#size","kind":"property"},{"fullName":"HSRect.angleTo(other)","description":"Returns the angle between the positive x axis and the vector from this rect's center to another point or rect's center","url":"HSRect.html#angleTo","kind":"method"},{"fullName":"HSRect.distance(other)","description":"Finds the distance between this rect's center and another point or rect's center","url":"HSRect.html#distance","kind":"method"},{"fullName":"HSRect.equals(other)","description":"Checks if this rect is equal to another rect","url":"HSRect.html#equals","kind":"method"},{"fullName":"HSRect.fit(bounds)","description":"Ensures this rect is fully inside bounds, scaling it down (preserving aspect ratio) if it's larger, and moving it if necessary","url":"HSRect.html#fit","kind":"method"},{"fullName":"HSRect.floor()","description":"Truncates the origin and size of this rect towards negative infinity","url":"HSRect.html#floor","kind":"method"},{"fullName":"HSRect.fromUnitRect(frame)","description":"Converts a unit rect (coordinates and dimensions between 0 and 1) within a given frame into absolute coordinates","url":"HSRect.html#fromUnitRect","kind":"method"},{"fullName":"HSRect.inside(rect)","description":"Checks if this rect lies fully inside another rect","url":"HSRect.html#inside","kind":"method"},{"fullName":"HSRect.intersect(rect)","description":"Returns the intersection of this rect and another rect","url":"HSRect.html#intersect","kind":"method"},{"fullName":"HSRect.move(offset)","description":"Moves this rect by an offset","url":"HSRect.html#move","kind":"method"},{"fullName":"HSRect.scale(factor)","description":"Scales the size of this rect, keeping its center constant","url":"HSRect.html#scale","kind":"method"},{"fullName":"HSRect.toUnitRect(frame)","description":"Converts this rect into a unit rect (coordinates and dimensions between 0 and 1) within a given frame","url":"HSRect.html#toUnitRect","kind":"method"},{"fullName":"HSRect.union(rect)","description":"Returns the smallest rect that encloses both this rect and another rect","url":"HSRect.html#union","kind":"method"},{"fullName":"HSRect.vector(other)","description":"Returns the vector from this rect's center to another point or rect's center","url":"HSRect.html#vector","kind":"method"},{"fullName":"HSSize","description":"This is a JavaScript object used to represent the size of a rectangle, as used in various places throughout Hammerspoon's API, particularly where dealing with portions of a display. Behind the scenes it is a wrapper for the CGSize type in Swift/ObjectiveC.","url":"HSSize.html","kind":"type"},{"fullName":"HSSize.w","description":"The width of the rectangle","url":"HSSize.html#w","kind":"property"},{"fullName":"HSSize.h","description":"The height of the rectangle","url":"HSSize.html#h","kind":"property"},{"fullName":"HSSize.angle()","description":"Returns the angle between the positive x axis and this size, treated as a vector of (w, h)","url":"HSSize.html#angle","kind":"method"},{"fullName":"HSSize.equals(other)","description":"Checks if this size is equal to another size","url":"HSSize.html#equals","kind":"method"},{"fullName":"HSSize.floor()","description":"Truncates the width and height of this size towards negative infinity","url":"HSSize.html#floor","kind":"method"},{"fullName":"HSSize.scale(factor)","description":"Scales this size","url":"HSSize.html#scale","kind":"method"},{"fullName":"HSString","description":"A reactive string container. Pass to .text() to get automatic re-renders when .set() is called from JavaScript.","url":"HSString.html","kind":"type"},{"fullName":"HSString.value","description":"The current string value","url":"HSString.html#value","kind":"property"},{"fullName":"HSString.set(newValue)","description":"Update the string value, triggering a re-render if bound to a UI element","url":"HSString.html#set","kind":"method"},{"fullName":"HSVideo","description":"Bridge type for working with video playback in JavaScript HSVideo wraps an AVQueuePlayer and can be embedded in an hs.ui.window via .video(), or driven entirely from JavaScript with play(), pause(), seek(), loop(), and volume. ## Loading Video Each entry may be a local file path (~ is expanded) or a remote URL string. Multiple entries are queued and play back to back, in order. ``javascript // A single local file const clip = HSVideo.fromURLs([\"~/Movies/clip.mp4\"])","url":"HSVideo.html","kind":"type"},{"fullName":"HSVideo.volume","description":"The playback volume, from 0.0 (silent) to 1.0 (full volume)","url":"HSVideo.html#volume","kind":"property"},{"fullName":"HSVideo.fromURLs(urls)","description":"Load a playlist of videos to play back to back, in order","url":"HSVideo.html#fromURLs","kind":"method"},{"fullName":"HSVideo.play()","description":"Start (or resume) playback","url":"HSVideo.html#play","kind":"method"},{"fullName":"HSVideo.pause()","description":"Pause playback","url":"HSVideo.html#pause","kind":"method"},{"fullName":"HSVideo.seek(seconds)","description":"Seek to a specific position","url":"HSVideo.html#seek","kind":"method"},{"fullName":"HSVideo.loop(enabled)","description":"Enable or disable gapless looping Only supported when this HSVideo was created from a single-URL playlist. Enabling loop on a multi-URL playlist has no effect and logs a warning.","url":"HSVideo.html#loop","kind":"method"}]; // Load navigation links into left sidebar function loadNavigation(currentPage) { diff --git a/docs/ts/html/assets/navigation.js b/docs/ts/html/assets/navigation.js index ec7c5138c..ee329d1b3 100644 --- a/docs/ts/html/assets/navigation.js +++ b/docs/ts/html/assets/navigation.js @@ -1 +1 @@ -window.navigationData = "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" \ No newline at end of file +window.navigationData = "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" \ No newline at end of file diff --git a/docs/ts/html/assets/search.js b/docs/ts/html/assets/search.js index 104696e72..eb67de0b5 100644 --- a/docs/ts/html/assets/search.js +++ b/docs/ts/html/assets/search.js @@ -1 +1 @@ -window.searchData = "eJy0vVuT4zaWrv1fPLcOTxJnzF0d7Lany3ZNZbW9d0xM7FBKzEp2KUU1KWVV9cT33z8SoCRy8QUIkeqbdldyYb2QtHAgngXgf7+ryi/1d//x3//73edit/nuP8T33+1Wz/l3//HdutzV5Tb/7vvvjtW2+fdzuTlu8/rfu7//8HR43jYP19tVXeeNi++++/++P3lRFzeb/OH46ezk8bhbH4rGw9mNew6cff/dflXlu0OvJtB/XlVlFfHvni/wX+wey4j79vEC79sy9t00Txf4/rKqdhHn7eNrvV+cP9WjwHiqozFxKbva7wffas9B9yher0b74pazvt/f2v938vuyqorVA/HcGU0pnOwDStWn43NjWk9oncyWqT0ci+0mruRMlqrsNtv8l01jXTwWeTUlOLS+hfb71eEpRbW1W6bXRPZj8eltMfEhz2a3UJv+dBe7pXr7b1Xx6enwW3ko1hPtgRgvVN4f35THxjQu2Vkt09oU9X67+jbd4nuGyxTz3UtRlbu2RccVe4bLFJ9X66dil09/xp7hQsViVzwfn3+//yOv6ma8mJAl1su0yzpJ9Gx2I7X3q2qqIx/aLtPdFxN9eWOwTKFaPb96nm6GZ7OFanldHqt1Qu/dt1ym+ZISJy+zo2QwVdkW69WhLzacrpweXzFl6c3RVpvNn6vD+ilHU1gicLFN+UjnakPdx6p8fv/L22nRzvAmirvDc1kfkjS96XLV7aoRefq9+qlcH+tp5YH5cvXn9ucqdp9e+8lSwtdNS9yuDoMxZFI/dSCZ0M53x9er6vcvu5T47lsv1943ncxPZZX+1ZMCN6vBT8U2//htn/DlkwK3qUF99ZdQ3/xbqK/+Guqbfg9V/ly+5Mkd7cD8BurH3a5pUq8udgk9ESg0sya9wea4KcpN/tJ/J+gPZpfH/6LBrCdwzWDWqzbW3W4TBLfbmyj9stsfD2+dTehnHKr2C9ykBr8fD1dWYVBieR02+ePquD38+PiYrzuv09UAhW5Wk95XnFyRXpmb1aP/PSdXpF9oeU0emz94X6+/RYb8XjVoidvW4W/BUSdQhb+lDDpTNUjp8Hv6V3b4UL3XRL/C3vXrvEXNXdkusPlevR0NQ2+qX38YWU5/kq8zO/KvV/XfIZXLcPXjNh+sqozURqazVXNf/tXhfVlEFIdms9XayH797UOfo1Cli8lClY/FYVLG2czXaV+L8s3UrzU0m622r5pv/ucir1bV+ulbUG1oNlstpcv4em1PEdCqv9WH/PnPYpNPfZUjy9maX5o/lF+m9AZW12ldpB7K3d/L4+VL7PWC3aN5XWGdV22nG+kFT+77lpOf4lTdQFf4kleHog40rJPg2WyZ2rrKV4f8Pm9DOS7Yt1ymucsPX8rq873/ygITypMsMV6m7BtTyqftWy7TrA/l/lX3YzXvV3FZYjxDuffTNv+pVqhN+Cf/mleuzvcVo3VXz+tetE4yCe9YMf9+jApPWzuZi9kN1IIT1IFYyqw0ppUwunR6140wI81+wO1eVpDS+yfz+uB1+bwv6+IQ64U7/0PThI/i6gtV/bD0On9avRRlFZcltjfQfZe/5NsUUW94veJoBAhFiP9encn1Kj2Rp7KsczhAd4/m9UbRyneOU2vfVRFVf1OuYVy3f5/Zje6L/7z//Tdcc+e2s5ist6sb1PiUB6Zdzn/zdIHvv9dvm2cDAjeWuBgtUKqfyi8RjfbxAu+HlM9xmP05em+BL43NYbVHYXR6NreD3NXHEK4/u+6sJj/AuZ44IeG5CDDes1BrslSlfRrp7i9aZ8OFis2P4ZKKftquPk2JDmzn6F4xmzqLXjGfiis+NH/4uTx8zgPvt2fFi+FCxabS68+/ls0L+uvj4RBkEZdIpfZL9Y9Va/pr97NNyhPzheqb8thE0Jttsf78y+7QvMWsAjPacwVAiZvU4V3+eHBek/TP1gu1m/j5kO+bEfhtvl1NxdzQ+FbKid/7yH65/v2hKj8Hpid9XW93K72pCL8Y3kzxVf1tt06WddYLtbeJ0by9URw/rz7nf82//fgSXMy6DBA90xuq/lkcnt6Um6lwQkVuUAvXIad++ovxDZTv11W53f75lOfbVH1aZGktis2m65GnxC+WSzXbr/BdSTLBAqp924W6fjUgaYbQN72JatpU6Lr1igndNg855Ye9GC5UrC+hOSHZs5yj2Vt2gu+uj3PfXDebP8pt8yoR/bUa79Rw8kM8Bt+V9/luE9Zxj+d7Pxyq4uF4CA2brcLZZLbK+mlThL8q93S+73IfaKqt6+bhfM9u6aR98Z36sUeW8zX9/Ptt7Os6m8xW2eTb/JCH3/sblYvJfBWwY2Akc8VmgZBO/vd8ffCNLajTs5mv87WoD+F24h/P9v5YbPO/ffwl6L57Ptv/U/mcNzHTfA1lFW4wA6vZWkU9rdSzWaDTJi1GJNrHC7x/yFebdgkkonAyWaBy/+15W+wCY7AT6SwWaPxZFYeJT3Iyma0S/RCL6r8tQnnsznNC5nrM84e86VLr4iX85QysZms9f46Ngu7pfN9lpPrtw9meXZZ0VT6/LsvPz6sq/AtTw0WKH8tXD3XTXYfwRqd3MVuolvTpLmaz1ZqJQngu1z5c5PldsYtM5M4WizSirfxksEChDda0KTawna/7HGub7uls3/VE/14v7N0P/VV76vyQskwf9Jw/78tqVX2bHs7HpvNVy2MoQaUVap/O9t34bPuo6NS3ZzNb58VFZfhn6Z7P9v+lGazDXaN7Otv31/aN7y8hfNq4PxksU3gXG9TPFss0PuTRgbFns0znfurbur/22+pN3Ff1JVb7hz80f5+3iPGwqnMl3ubr4Hqq8903m6y8q2VE7cddkpo3W6D29Lxa//pWRoQ6i4Ua9z+/yiZEWpPlKkyqaZ3GaLmSzNi0UmO0QOl5E/tlmqcLfNdPq9gv0j5e5j3+S3iDZQrxX8AbXKvQXwEYLGv3u5KkVWycPLDa5tXh7bEaLtUPkgc69wPL6Y/ha4tXLeu6+LQLv8+eBM9mi9TaXICoTmuwWOF+nwcYYk+lNVqkFEsZ63QSM8amVX4tNyHsPJBydov0/GLlq1C6bKd2tlqmVdRtRE2Knc0WqX3KDx4xBaaSndrFbKnaX/NvLTP9tZerFRC8WC7VPGWbJIj2TBeptolzKV9sz26ZnttY8sp1SHm8NxmaXq/a6/APB5hx1/59ZsZpuWvT839uyv64OxSHIvSK4ySA9fTHaescyOP5kP/jmIdeGpzi2WaBTu6moD+V1X8d89ALrxMbGi5QDKaqOpmUVNWw73Kf7/7MH+7L9eeoysBugd4+eOSIk9mnHDMS8X6MOj8u8d14fT84mmgscDK5VmXYJNvdUjgb/PJ0ZvOMje4X36kj/KWu6KMU+zX6DM2f500ki7p93893/W1Cg2lk67lnNFn/toIYh+zqw2q7fV3sVqEG7rT6ZgvUau/hF+8u1Pv7T0dM56s2DqpAW2mV3OMl3svAUO2dl9Ojc9D3cZf4+xDDKxUHiXwP5araoGg+PZuZLXI4rNZP+eavnZdA33IWGdlPfqZz3XF/sNrX75oe/f4Q7BbO2gPbhbqnp2+u0IdlFtajzg/XVIGaL1c//ZDvfgzseutr94yXKycpLlc6lJ8+bfNrvmRQYk4dBsHWzsNgmtfp2bwR6bn3PjIYic5unxNeQ871m7UH4ix1xR6IuGKXP/Ru9a0MzabOogPb2+j+mh+eysAYSHW97W10791ZiKHdp1T5ZL1Qe+u+uHC37zU7q4Vaz+7LmtLqrBZqJWSsnhWvy1iN67Z9Vkrcnu2W6yXF69luuV5inPYs52j2QrRcr8Cx800x/2R2nmw0OjrfV3RqXT2x2suq2La98ztnFGgDJ01ivEi56y6igp3NIp1NfmhqHf9gnc0iHfes+Ge+CWdtdmoDy0Wa+yp/zJuvaPNutft0XH2a+P3G5ovUE7qyTvi6jmykOfySB7SENLoUPjK/2TnvVzY8V1useGy6var4pzNpZ3Ohc18v0uMSC+uwKZrXwF3oDLiz8MlsoVpwte4slLJiF9fYluXn4/7VZlPl9dT3ObC9iW584w0RTt55E1dObIZO6fqGGNbtji6qf3ScMDDOn5WJ9VLt464KHnV00fRWy7XqycD1RnOU+tPQ3fFhBZc3u0e3X9s8OU5c2DxVEVa/2BSw7s3f571Frsvn59VuE9nR73z3zaY/QVvLwEShDdA3q+32YRXa1+X0hoaLFdtZQKD19OSc1WKtQI/Y01nyDb4U1eG42vrZ9dTHGhvfSjn2IYeG1yr2s8aPNZz6uwczpyBdQvb79iyi4CDiBajt9CdxFQ6gyWNoHu7F1kl3L8QU/Dz+zbGqyyp8tnanRo2XKDcTijfdukTTxeXR75TaLtT9kG+bvv4l6ecE5kvU2/+EWoHTcwZLFPwmU5+xPPHZiOki1fzw6opGAswXql/zmwLzheofq2a8KXaf7vd5sGs9SQ9sl+geUkUPixR7wetPbkSda/do3myimeGsn1YPxbY4fIuc13PSGJlPfqRTxUPvl+1bRqhZnlTPZsvU/AVdXcLg6T1jQhqXuWE97vND/P0I1qRX6pZ1OZRVYBTCtWjtb6gffV2DNUh9aYvW4amsD5HB4dy+TmbL1Ir2QJzHVXBGdpK72C3T2wfPST0p7VOyH+IaVfHs8gy6Kk/oEetl2oMuqayiixywGzuX+VfU4/0qtA8sXpe23E3r83MTveFF2EBlToVuVxP3o+9CKweoGqcSt6vDu2L32S3Wp1fiXGRpLZqJV2gD0UXXGc1Q6k0X2ssEYG6+f3L7NZPOb+KSSVe/yNLdq2Z2nG+baWIVmmB1imPz26i/z3ebcNdJtDvjRcrhszk7taTTOUcKvdzNNVxGa/48Lxyad5fy0674Z/4x/xpo0K3vgdlk/dtKBlYc9/uyOkxinVZybHulbu9Lq1fNu1qxP8Cv7vRw3hf4//Kv+Tq4J/3i/GQ3/SHOlY3q3QfPlxtr3qecLjeh297/kZNvMSDbM72harv/Nny0B1Q/FblhLVK+dmJ+Y/UZ30O/2NLa/H31QhtToAIXy9tppn74cYnb1SElBIbWt9W+/jtY/Pv33hJW9SEPpsZens7kIk9NX59H7q/uCfRsJz9Tr9ZQ94t/BR2dixrSJvbz9K9g9D3pKyj9lOp6m6+mBZ3VYq2nVR1eHu+HjbdbrNeeOvJ2dVhNCp4Mb6L488df3yUptoY3UfzluZkZJUk6y5tofvj4U5JiY3cTvftDFZzEE0lvehPVv31I+ykbuxvoTWY6DFSvyXWY0j4MIHRI85DEoKe03CEkSc3ybHkbzaSGeba8jWZa07yY3kb194f2WMPpH7RvfBvllG7hZHgbxcSOoWd7G92UruFkOE+xN+HKq+eirgeUoz/jujyeuR7UXi7war3OGyd+nSzw0XpC4zLTn7L3McL1eLMa3NAVr4A3vpGyu4v213JXHMpITNEqkFI3qkucJY0qkQyR0tR/LdZVuX8qd6G+i+pfCtyoBr/1blENdWS0EoMyN6qHT5b4kK/LKryKOKoJKbW8LpXfvn5lG0WlblaX1HY6ML+Z+tVtFZe7WX3S2yspcLMaXNNmR0VuVosr2y0qdbO6XN12cbmZ9ekN34NzavsDd8oZtfgjPkYXgLzjx9TlHl/BoE50inVWSp1chbUO5dQn8hbLNKY/zcnmap3eT15+wUc5uAfzFsaK+s3TqvoUPAfBu75YTVffVTKg9a788r59/mv/eD6o17dcotk0o3Vj139hAnoXq0Va7SOfJxsVu5gtUTs07+jPq+1wGzSQ69tdrTdcSny9Ohzy6lt8OcGJjowXKvs7dpJ0+6aLVLfb8sv9Ns8Dh090gmerJVoP/rv6ZfdYxsR6ZkvUunThV03BKjakOs2R8RLlTd6UqvJXjchLeLLpdInpEtWidj/Q+8rd3RLKGDj1PEPbJbrb8jRpjylerJZo7X2FJ+O1b7dEzy8VpncIyH65fmq3MLZeou3Os/E/Wb16iStT20W67rC2yZ+4Z3a12iBdvR+4vdlGnRSs83hU5/sKFtXVM9SFx2USDkyM+X9eFYGm3Qm0BosUumzIqEhns0gngRN0atcxgpHmYDNk0SOi/QBzT/5FAeZ9XxNgvp5Y7bS9/31ZHd7Gts2fdEGB29Xgt3CeMtL/LSlfOVm9PcP+CnVnvki9uwmr8fXqED5kv9OmxjdSbr/DwIRiJOxsF+mmNFOvemUzpZr9xMPV4NW23079o3kvng/HYnsodvfdJmf8BnNSIMbTn6erdOTHu29MAssCJ9We4TLF007un8rQj9Yp9gxnKA6yRavDun8Y0OBn6x7O62HD9yNdHCddk3SpJNRpDwmd0mltlupUx0mZxmSWSu8HKY87mNjkHvwrVuu84+TVOl/B4NbIUBfnRHZp/VpYoZuxtgahAcQJ9e2u1uvJ7cvDtr1lFP4gp4fzurXzBZaBDu3s/Ww4/UHO1YWK9brcT6o5o1lKiRn+F6nEJP8JrTpfVaGLeXofy1nN0uq/zjU1ft7ka7iB8vL0XzQhvfi/ZlJ6qfOVbz49uZS3nwmdx+YPr7/du+nDb8fnh4RPOS6yuBYp06JLBa6cGiHt3tL/qoZh0/59Xg9St7xoF1pCdn5PJpOVd7WDKh+bJ6+bWdWm94WNhXpW12r1VzeJzuCHcToPizVifZOTSOyWwgqNVXtMcqBdOY2TyQKVZqrxqg7mgTuVk8kClfopD3UQPsDa59f67zWK4hmDKvdgZj/aHUvwsXERqLlz3reb/gSuotcHlFNKjaiwxmYVuhHCK7TPF/kvXz0egg3PS3iThSqBF4KzxPTLQNT/jy/ByxFOEs5kmcrfdoci1Cg6FWeyTOXPp+CU/aTiTJaoPJXHKhpYzmCJgjtwcKopno2WKD0Xu/CN8V6nM1miUufrsnmpuC+aUfXHfRmaeXq9kfES5WMdXs/3ct5iicaXVXGYjO6z0VKlyQg/Gy1SyvPP0ahwBlcr9AaxarWrt8GzM3uP5w1ode6yewIfoee9M5z+KL0Kh7hV8MTMgWDaOZnTeombcgfa12/OxfXotTB4xt7xmhP2Bm9Weeiui8alezpZ42PoxLnmlagMZBE1zv3j2d4fmxb3vlh/Dk0IGoWLyWyVOpIJ1SjUaUlQIe+H/OvhfVU+hzaJNgoXk9kqX/KHlyIP7LdvJLrn8/03fwht52/du8fXee+Fe7V1iB8Gffds3ptpe0fP6LDHwUtjz//FdPqDnGoMVZ9XxfZQJuoOjeco999bi11g3fOsl3QbY1zlU354td3+vNptmr6jXfm/Xz/loYnVWThQanld3uaPq+P20HmersXQfqF+u54f3ANzVu2sbqP1Z3F4en1sK5+merFfqF9f+V2P7Ofo9+edD7CHqB/+NeucreMrFjjb6mGd7tqit7HTWZ3Y0HC+YsLqYqt33bLiUK3/s+TVxv/MEN71n/+rfqiewlW/WK/meEklvC18IJq2MXxaL3h4+kAt5QD1JK2/Bu/3pHp/Tbnhc1ozKTB7ytdG6JR+8IzvgWrKId8Brf6M6RHO4tu/z5vMdCctuJzAyHHZTmBkO/mBXH1nNT8neEWziyjVdbkugouYXuhks0CnyxD+jRxCOhYbGi5QbO87TvhwfbMFauezFqMJXk6Rmt5CNUlviVK9Xu263ySm1TdbopYf3g/2sQClzuRaleAL1qDDSHm3CkLVP13x4NfkfF/MEj6Aq2esWaUoDk0XqXo6+7E4hObDnWTPbpleuW46/82fkTfik2LfcpHm8+pr8Vz8M/4BT0bLlJrx9mP5Ln9s5uzbx7jewPQGqh/ahIdE2bPtIt2yGcOr0y8Uj9ih6SLVl6IumtE6RXVoukjVP3vVdFTFLjAL6kQHljfQbF/2X+0DxGCg2VneQvP3XWwjy1D1ZHu9bj8LYl/2NybRtKaEfUiRd5A3TfEy1MH1LeZqlHU+oXGxmKlRbrf5+vCXVfUQPAxmaDMz27Ncbe7b7xtLnB/P896uqUS/qJ7BPIUqb6uInftnV/jNmDk7/vm+aVrbgmzQ75z8++ApULj4lFn/9p5dfaiO60MvTzjs8d+G5rj+w2r2Psodi05sIrKN9Zez9QLVB7eK1rt8MqLpbYvNLRQHWwUmNffeeoEqnuJEhLsC50nsAu2idhso8xTZ5m3pZLtI8edis8lTmkSj+HSyXaT44bjb9aFTVLI6Gy/Q/NxHAxG5zm6BUruFLD10WutbxM2+SPp4+6Ut8jB40YgonQwXaAUmihHRrsTc3o7dict44dpWf70i1sNebJcofv1xmz/3SWBM8mt+Nl6g2b4W/prvjr8c8ufX335bPSd93rZUe09e0ZR6+LbzpW5Wi9T+fliLWf3+qBZXdPqN5cyWO1D91N4O7T96Uow39qcPvTDCG0/pH7cxvsWnbcaPpAjr7BYofS56GbPRHn8bnk0mK9lUKbtMq87bN4TrW6wvd8s2S2uS2mppTZa32+MuNarOlleOSsPXiOOmKD2kRJqXp7d6jSAeU18jetUMvUactvfer5732/zDqp+3GanAuVztylVduQU1eVhtB3c0R8Qvpgv08GyJSsUnSwkq7TFzb55Wu12+TfpiXYH1pcBS7V+P/dNTpoSfO+ulqn+U2yPulaDsy8l8iW7tjvRL0qyLznSR3u/HQ7JgebJdoPic+lPe4FfcBQYVKjU1iEwr+W/mmibiS9ymjdTnbi9F+dLZLVN16a9tzuzgGPyI8LnAwRdYoH1M6/iOS3u+l+QuYGbrH744jRF9bPTabL6crReodhDPdTzt+eTkILnYAO5Lun5o05SsTyWX18Z3S7Oq41vWrepTDL+W9OHvUoHrW/egBiX5Kq7oXm5WB5zxE9H3BW4Sn/X5rucZIdoU/ldE6aVOcwL1UqnbxuolU/PHx8fm5SR5ct/WqEuDyl3JzankTWrjf7cZlfG/2U3r0v1eMyrT/VbzakNevf5PZIXs9OxWr10Df6kvXecKBgbGbtHubXcfVwBFDaW7MptBmdk1eKwCs7uh6Mlstk5R/7hr3xHhhGOoVdT52XSB3k8ew6ToPZ5NZ+t1tpNiZ7v5SnjSRmTiU7ZJDXrbe1joYjlbrSoxRBgqdVazVep+ylBQpbOar3J8SPs4F8PZWkH6MlSaZC9TOi+r7TFB52R2jc6IsZS7dg0TTs6Gat541xnP1zyd45Mqe7K/nfIfaV/v2X7x97x+KrabV818YpN/TRjqWutVM4nw1stUK0yWgWIV58pTakX96vR93eeHQzuepIwE5y+5vhSaXYd9Xj2W1fOrdWJX6s1X6xn9KZ2mvboyuJoii+JrODF7Xe7+3kzE74eHQF3EB89vNEEb+0ycpA0rG1whbt99Hgv42gakB/bLlHfr7bGZ7L3P8+pj2f5vYg26cvumxKHc57NqMgKir6vyS922i7dlm6uAOkxQl7bkw6nk5lxycW0+5J+K5hd2gObqClW9wjes0+hEzMmK1JcSi9Tr5mdOU+0sr45L3MirwEvg0ODWzbzqrVhd186rKATbNIHhyqdp9+2XKfsYTJQ9Gy/TfCrrQ2B5H6n2zJfppnWnPeXr+tO49lUdar8Os3rUaF2u+O5v8r232CBRrzNdpnf4evBXJiWKNvbVyX6hMqYpUDTOUYJ6g8732V8flih5sV6m2nQ95RamhyLVi/Uy1amBpieZOtJM6oFr3aaVn/uFro+nwXBHrra7iAcvsZszvPWcJQ5rXb0iJPxvNQqQvlILwY91LDDiKoFurC8x0X3F/bctNJDa1NdozRbpYB7al4ij0JH3dC7ZF0lCknGt9Wp/OFbkquFAmHnTojOdpzdFtvqCqVBr/FuRBrl7WaFpmn9wswZ5dpbcIF29QkGwb2J0071AT9T+37xxfjGeqVnXxaddmJUMJJ3tdDJxXPEhf1q9FJNfaM9smc67/qH2ca3u/PtleqFVFSQ4tZwSV1y7p4nx4o0Xx4t382vZDAnuzIQ02efWPn9Zptxu3vvYJri4lbDAutlAuy1xoCXmqhft9dUueR9PNIbKjfWqbz1PtXmjOFTltwm1i9VMlWr1qb0AcnQQV0CuM19fzGfqHn0K7VRr6dvNU+rC/tXoBH8s2Jn3D/xfpPt6eP1BVPThZLtI8U3jZarX60zXnekivcEBOVG5z95ynlqISPd1pnB0XCGQH94XmEgMj/tvBtCyytP7T29/i/7TTeJ+qsrnlMnRvznr9oqR9cl6puquvVwybX7hbZfOL4r697VbjMHz9Z5cXV4M52rdP5VfpseDoq7PdnOV/vA71iaVXs5285Tag+XQdpi+yslmgULKNMkZLpsjPRe74vn4/DH/erjHkL8v2Fm354xOwP4J1ba9Jg6nznbxWNpdg5nUzrzt0nY2UEwdWQfSy8dX7+7dqk7sYbx982hxL1Pl++1qnSdOvjvrxbPvqmyvek78rM528efsK76q2snJ8FyUBPGVK7bvis2rR8ut1+v2uOyHYlscvt0Hc2n61WjRdb/UdGLNZC2uDPimxM2i/aJ+1WvQpQo3ehdqHP6UMBFrzJbNxRoHCX12Y7Wor27Kfyz37elM00KHcr/1hvO1rvzpbvWbPcHNuwOxp+iW3Qn/CT/Ukl/pkPQTzfh9yMLhU1nWeJXSP7nV0mHPW+raYVe1ULqwy4vtUrB/Kqv/OvYvVgkod8m0vlATZP/oCs2sQxTdDoSTmO2UWmxKPBBLmRPHtcrdz4EXw75QObVpeFLllyY6t5g0DIWKs+FsLRch7YY6jAGGei4y1ifj2Zr3bkv3tFx9spuvFOjwiM5EnxdXcZO6p3JwA1pAamg6U+8fKW16YRv29y4206v2lWlKyxs3s6qDN56t2f7a+ebD9E92Mq2W/G4xZtgXS4GGcaWu4/mAT6UZiHWmVfw4mgm9L8UGnq0wUDoZpWskLZH1Ja7uB8nL1WOV10+NVSBbbqDVWa/P1jNV66S+aUbPBFRcrL8pd4fQy2Mg5teXIrP1D4nfa7uHbvF3mtALX98HD6ds5RZPsdq/32q6dvaVOllzlQr/BHENbzDL9xNM2+/5fopm6kd9t/+BU5OL95PJLP/Vp4e4d2+Q6nsYJv6E9xVKTjo9ulGwDNwlxsu5dnNm1kPBpKn1lF5LwvPd77stmm4M9bxp6U2v0CPL22/clZsovMjHq9dny/lq4Q2HVG16v+GUWtvjhpeCh3ptnzu9FDypeFjBXE6i1VnNV4GpflQkmuSH4hA22x8H916N1X4M3H21pAFffF7Zin8kV/OQk0oPh3JHbtSOivsSu1OJRerNK1y1aiYTFRr+0Qfv2y9SftyuPiWKnkwX6X3Ov70p4UwVKDbG6zI6ZU3SbK9FDSzrAdGe9SLVavXlp/Qvt7G+yffb9MPldlvsPr3Nt4fV/0kTPxfatIViM5EZdfi/c+qQMmpF6xDIJgfCE8nkyWqBV9eA4sQLbEg1OVMHyKYk7CTp7kuYuwckO8urv1s42PxctmkqEWFvcOPhpuf0yvGmq2+oy+8mFO/dZqTYnGdQg67U/lzqNrX40LzMrq6vRnUpdnU9hqFc1IENv0j+Yr1M1c8iE0XPxss0U2a5fdlr5rrj33rQkH4q4WSt/fONGs3ZVWJTcTUKZe6WG9TYLxKdwRzfbfyW8PS/3ic428xTCB0O01eYOgwmQYGlSLC5GsfmTeE5rnAymeP/sSwPuxIOYBeFntEcjad8tWnmFXGNntEcje2q+pR/DBzucVFxZlOHe8R06uND0scZ2s1S+lYf8vgvfzaZ4z90EsrF/ZLvyZWNt4yzyWz/fNo/T/c/7KqDc52bznGun9ssndPMm8ssnsPMnLuk6u7zFRpLsGpnPE9zMij+zVvM8/7c/BB4+1lf4WI1U6WEWfcDiTKabD8xlwxuzxjMISe3Z8ydsV43U505Q71qZjp/RnrtTHRiBuof/1puViiXuff0ph3cxeNVvZyvZjCx55BXP6H53UjTmT7Gpnkpel+LQ6JcY7lUrQjfYjTSS7jFCCsOZ/vtnxLUOrsFSlPdQ08stY+I6rmfPzlOFmo1v31qjFwfIcOm/PHj+3YHPv5s54e3ashDh6nt+FLHOQSPiiYxPKiZGoBEMCH+JtWaF45fTpcWJ0i27yc980W6gRVRIDmxGpqk9h6flALUJg5KmVZr09632/LL26LK2xD81u5mxvuNqHyb+94W3ZyKbs9FF9WnOxMjrQYPZ+NFmhF+CkQTCGqS6vlL/yVwGiLQPn/bxcSZiGk1KNfHNnH/Q1mmRFyr35WofIlF6te05vpWrblx9Ovq6+ty8y2Q+w+Un1df2yW6iQTzJO3EnqS+QU/S3oXelP2Cj0ACivuL9TLVtP6rvk3/9fHdfbvr9P1f39xnaKEEyB62dbv1dP95XWexhZMk/T/zh/ty/fnaTuRL/lC7YrfpTQIZGSPhiZyMFCWYlTEWiuZl4PnMYFoWOj/G/f1Gk7GLr8R5mK9UYAq2w227JzLRpqPeAztget4n+qeo90P+vN9iANtT6FmlqgxX4cv9t+nf9d9as6kzgeI6Vbnf55s3jZ8JJW+49oaztOrVS/6x/KmAixv9X6exO5SPRXR9I64E8zr7EtG8zqjvtj98td+/dhcXx1Va09V+/3Ayna0XGAuJ1JVtZqQSuA2QqEzc/Tepcv/t+aFES0FEpz7ZzVb624d30zLt45kaRdMT/lRW0wHdGj6W1ZKI7mkFrqDCehOZLqOebjCwvOvSosInhhGLGw02yGvisEOrHOjEN80bWHsjYfN94pUaWIVTqcdTqYW1iK5EwBokLUeE1YcAM5wiB7UTkuQSlePvkVA87WUyVT8wB8TKExPBZE04GwxIRqeEkegaNN/2ntfXq+oXDHV7T2/UbKnHxCbbr2ZozhUgxyPFKYCMtRKX6kZq02t1CXqBTVwjsYmNXAlKsW26I7mUrboJmm1Tb49gi7T3kXTb1tsyCQ0+rQa/rGEvh4SLdbSDS9NrrRL1nr3pMr2PZbk9FKh7QZKHs/USVbydbKwX31IWaPvDbuyXt78E7zC7PLxVJzZ0mNqHXeoYnnE0L4Shu7+pamc9MaOfVo3OMKho0uQiQbP+fRfIVhop1uVuImEpRe+PojocIV4eC76cbecrPq92x8fVuj2QN+V7JeYLdMsNPBBsJNjZzVcKLNBQoTnxmTrY0hYxPdZOqvkAP3z7kP/jmMN8dtwkDt+qc4n56nW+27wpn5toQKvMVLm1Xp+tl6nef6shNUGadWe7RDE2ux9rpkzsccQOhonf8sOXsvr8pnn1LT4dq4kX14j1jQaSKYXEkSX2sa7fmTJZqYR9Kmk1uiIkJiuVFiPz6hU4LzWlThMHqM6pT+DFdLo2Ey+ps+oCX1gTqhJ9eU2MZ9S032Pc3nt626Z79nhdU3XVDDTN7iKiFM2L6QK9deD0YfAJ42cPJ2gV9ftV4C7XkVwzvV1NXOaapPjhuNulRUUjWZ2NF2jWedoX2tktUgpkWgGtznKB2vSgcdFLHySIItnMslvD6ew4OE+WC9T2qxYhJ7W8i+kivSO80QWoxS91SdBq+olj2i93tlygljSY94PzisE7qntsZsPw1K2x5tn0yhaBhp0P+Wr9tPLHlobF+1a3HYZGnq8bjgbVn934x5VI7wQCNbg+qMaVuCq4kuoRn4GBGqTNvBK1D8dIDwXFfYmbqd8fArd3TdShPkxc4HVVTWIzT1SDlBlnqB0Mm3zZLoAFuVj/8a0aOXWZ2rr7NZ2z+jcWTlr/C+iO1hySFDvDJVpfisPTplqhxeixXs/42u91ECa/v/nw+0M76woFytDgRqECnCYGC6lvIFweQpejIOHJ21HSNNtMhTbu4OJ+4ANfCizTPuBzNZHqxKmaiXrhURZqTg+wYV0arh+aid828Gn9s9sFac9fenx2FQx8deXlUwYCtC9KrGerhgOkrzYdGxMq0bAYKCVFxFhtEAxtlld4XbT39EYBQT0mhkS/mnOGt5Fs0uiGVRORxUhymlkk6MVnxiPNtBlxim5gJjxWnJgBJ2nBGR+Qis70AjEzDP/AnRnu77cK+bOv1GB3lQqEOSI3PYUYrIn6hSF88RsNW+J38GOudp9giknP98lkvv+PZYLCoZyrccr0i4v0rGap5P84rrZoPOtpnG1mKTxuy6kIPZnM8l/sapy+1BM428xSaK8JivvvLGZ537XXeWzxfoGeRN9slo6/hefNmz/jOt5svY69oER16qbvn/gsJ5NZ/l/y6S7vbJPcKw066A/46O/2zzfqns+uEntnV6NAJ4oS5i/+Y4nyMa9lVXwq0HvlxfXZZI7/wA6Zi/eJDTIx3+hN/OI4Ftkxr2gQvHiNjYExr2gIvHiNjYDEa+IAdfE9PT7FFCLD00UiYXSKaQQHp4vC5NgU8/8Ijy24OH+MHlcQ9RwY9Hq+J8a8qPd2Z8muOEz1U353SWNYxW8piGkFh9eLyuToGvffnic89UH6VnNUAkP4RWBiBI/5Dg14va5sYryLeT+USb/0oVz4OzfF4TLiReJkMcd7cNC+uJ8cs2kvOhiy79dVnqP6+wc3GrZ7zhIH7q5eoVyM54eisXxXfHpCP29frjPddqYz9V5WxbY9TOnXcpOjjnWgeDJ+7oznaTZlPzfvzKGdpH3FznRqN2lcL3QtdF9o6irCCYXjdhu683Cg0tgtU4KXf/Ulopd+xX0/4/PQ+96f46egx/0H8nf7/icWEuP+92VdBNBHX6NnNk/HvRBN6/TM5ukcj5O/dmeS7H84JXyoy+3x0MwK281bKOll0Pg760O57aznqX7KD6+rts/a4ZyzvmZj+9C3nafo6vuxfNV9gAlNZ30oVxfrearPRVWV1e+PUy3KmZWPC3Xu8WLlWGlitTKutcPsYdCC4+Ah7n9f5S9FCdMNBi34YjZPp74iBuubxGC7AWu6e233Xl3Zw1KV30Nv6URn8lV9Uul9VQRSn4jU/mw4U2u32tdP8IijgdLFbJ7OofxxBTdg9FUOZb6K7rmY0vitrOCJBkORXWc1V+W+PCao1J3VXJU/8YaVociX+B6V8Rg4nMbnVbHaBs4kujy81XR+6DB1Sn+pY2ia3R619lu5uz+sdptVtXm9Om4+rA54xk3q4Mru2or4sg9N2aorO79GD10NEipwElykt1kdVq8LmOtK9VrThyKa65qgd0j5fb3VfJUo7aViSbA3QbP+fY9fbKleXXrD+VqhKTtRmpq2T+o0xjiRlSqdDZdo4Z5xpBTvGid1qqRgrxbGeTPiHbebH9dP5Yd8nRcv+eZt03wShH3BvClYdQU3vuCCujRzy8Q23poubuPHptjbjx/e3n/4aevvS63gIT5UvC3XtPxNXT1u/aWpVfRQn7SafPh4/+bj/fU1aSJgfagX1GS4gWFbwhT/0cjW2c1XCuecjHrZyZSTabUyrc+b0+ON0kRTW1BjOqfNXJFJM5ZMSaTB8TqcVj2t2tzo9hA/fIbB0OBW06ux09Qp1rC+oWnW2m0ZCySuIfWuxNQAlqbeHsC0ayZKwZVNVIFTock1zrQ6HA6r9VN7xCvshVEFBiWWqcenQ0A8bUqUpn3Fl36b77q7f+I1vh8K6XYlJi6MSlPf59XzaudYwQ52HUD/XGbryyyrQTNvKPbFFaE2KLBMuz4+/B0TMCR8sV6mGjryCWlOnfoUVKT7EVvDvD2MJvVrbsrUbZmiK7OsBhMDFPq20wapNPVrP/yyT04GSZyR0v75VgPiyVXqMNjW6Iqsn4v/6LtMxCvKnLl4jWXOEK9J6ZgXz1PZmDHvwSyRi/vJLJGY/1Aux8X9VC5HzHsoe+DifSp7gP6ew6Bu98gg9+3fbxXWZ1+pce0qFdqOc6xaw48FntX1tLzhoYhP5mJam+70h7hQz2qWSnyedNFJmx5Fler329U3vHuyL+RO9opvlozqNPG+hy3uonEymeU/tBB1cT81hY95fym3eK96z//ZJlUh9WW5F1bT78kxjdDu/p7C1L7+uP/tauIDdBazvFd5m3EVm2pcdLxtyiQjrhg4oWCgNHE2QVRhYu50kUmcMkW1AgS4JzKBfmkLGQ4b+9KnGv2lKo9QaGBwq4Fk7DR1RBnWN/y6XBUPgaQAoN23X6YcOgQHf+L4OThpivFBB8imjT4h7VFT2+L3RCB8sV6m2rz2fWqfp+r27Zcpv6y2x9SYOtle/+viBho4Wnnw/NbN89rjlYeVXRSwvdOBr4rX2EGy52YejZyL8sB+kbILhp/K6lVKx3SpgCv2WFZX9U/RA27PVv91zHGSx8Dg1gF1cXptRPn6zu11B7qJvW5UMS2Ie7LXRXFcu/7L6vCUBw5PgeL1p16Jperhg9Cw9vRZaEHlYYrhZKffk03v8aOaCSNcT/SKES6qOjHBBMqJM81UdTcmNb/Zq6Qec1iPT13Z63rPqRpd0V+1lfhHZ75Y935d7q/59PXJfrlyWR3e5vW6KvZNH3lNFZqCm0HBxXX5ox2I2lso5wSEG8XaeyhvGRGBEwNgFSYODUhVxC9iUDD+Rpak93L6ylO/6fPXPOvbJdOEQ5Wvnt/m68/B0/Cpya2mCsht6mSB1jq4U2X9OXCzEZZvC0zcbpSqne/W5Sav3rTLTvB8GVyDrtj6XOxm9QjMnOK1mJhCXVeHD+WXq7+IypdZWoPHonr+0hT7I6/qwPIwrMWp3Mu53NKaxCeUsBJpU8pU/Zadh8gYlm9LTGzeTlX/nH+7tkU0RW7XGpz+NS3Bqd+mFTSurmoBjf2Nor92CUW/HZ8frog6X2h3KjSjDoNhrpkOHMpdbLYLa+GLpUx5E+sRWckPDAmTi/qJyqee+Nqv4NQZ3+47aF5f4GWWWP9kvVS1djsFrv74vtgNP/3k7qFAc0jcR3RFLXyTKLdXTJDaavgm0RW7WT2CWW/xekzmYqXXw28luboePkAW1GM0JQ4sergHt5v+XnkTQFevEAINrVj3dCZXqqkC/YEm/E92E7GDsT+uatQntH++0Vd+dpX4hbsaBWe0L0VV7tq0y6jS0G6OUmwZ7qKTsvgWU9nDrcoX//voPuWY50NePRc7l27xIV/VcO590elZVyfrhar3oROwoerk6dcx1fZI6OY3eFtU7ugLNMm4iHbGm55xouZ4w8Avu/0xHojOrOjM5ui4A1uq4z4u07eao/K52G5tVOFkMcd7KMOiF+cTCRYx78F8hIv7yXSEmP92v8L0D91aLfmdQwtuPYWJZbaY91NLi39Nfas5Kl9WxeFvzSvz9sev8ECoXiNsLI+tZf41ejQUbfXDoat4hu9V7u+3GrzOvlJHL1ep0KDSNtMXeGZET6hnNUulyvf5Ci5r9kQuRqka5MSvCsbSRaCzmOW9PQ3hYzPr/zTx+7pjEw5nw1laVXiY731b06N8TKOZof2W+pEa2xt8qmB30hOa6k/i/uFq/cB9dJF+FMHDpl2tdvXWzyOa9z68dDg2ulWjx45Te4Bx3UPrQ+WxWufvVrtPR/zuFaqIL7i9FFxelyYYPuWHGXXxBW9bl/Ap6sFaTB+nHtUfjpad5VUV6JWZ9w0MGsDffnm1zWEL7p7cKNT73hLj+1S12MR4UmliG+2ERiTdfCCTkHA+ofRYwjfNgUpnM1Nhv9ps8PgzELmYzdUJH/M1FJo+52tCKXCf+EBl4i7xsQJtHm+L1bbE35p/dLMG0nOX3EK62kXX5NEEbah2sZurFG6Mg0812RrjKsXusT1U+1C85B/xUVdDvZ79xIUbU8rlzi+iTkqWu4eT4VytYFj3dSbjekLj8A1uYiIindUVKrT5/NS8er0v1p/hbLT/+GbNiLhMbkq9mobSTtuTfvJNa9hmHeB2ReW7Qo/Nnw/f4hlFyXWofz1uD8V+m9/n23wd7GxhVernrmzdK7ukRuvV7s1T2TTs07JYkfjNtDd0uoKbQcGb1KU1vbIWj12RJfqb/HHVfL3v8RE2Y/HOfuIsmxTlbut6kurFdoliO7e8JvqaZnijiKvyuty+5PWrbbGqE3/mU5nVucySGgS7aCo72U1DLdqJtoPd+6p8houz/cc360SJy+ROtFfTGXMSqpoyL5lW7BpZcMZAVTv7yRnDtHLKfIWqXzNnma5BdN5CpZPmLtOawcZB9SYbB9SijePP5q8BQf/oZo2i5y65QXS1i43mH/LA1RpDRWdbTSVqTSrW+6YP/tC+rU4rOtuqs52r2GZ1tKnku00oE2KoerGfSoGYVA6H/kBwOujjOuuiWgdm04OQOZnN1mlen9rj3aeVLoaztcpql1cfVpsCslXaGFrj6mQ8VzOcujWUm07ZmlLCd80OVeLXzE4pNLNJRF+GEp3RbI3QmtFAY2rRaEqjyq9pvRf7pa03dC0A0Zs4rn9K5QnflTIUeYrfljKpUR9wQhxROZnN1QkdsTWUmUqkmlLZ5i/5dGifrOaqPBe7YnU4VsU/k3q8kflc3XL3Zlsk/Fjlbt3ZzVd6m9jflbvlPV65+zkl0svdwlhvdMqXwGIPEers5ivdhyaaQ6HJaeaEzn61xoffEqGz3Vyl2Ap9XylliT6u1K63hM54Gmr1Leer1YnNuG85Vy34+tEXWhgTdfNbJwT52WyJTkpEXOxmKzX9y+fpH+hstkznz2ITWCEbi33pbOcqBi7kHkpNvmpPaLSHCU5PKc9mc3Vems55+r3tZDVbJW2+8rJ0vvIlf3gp8unGerGbreSefgwcD0nU3P+fOh5ySvGfad/hP2d8h8MFkD8CIeH+fqOlj4uvxHUPX6lQKnvoNK+ezORpXlRhOEUtYdJQz39nMct7KMu0534qzTTuH5/j1XcfP8cr6r3OcxSWPe+dxSzv7qLLD+/QkkFPwd1yWUXPdxxF0DDoXXicrm0HWv3nt2oEI5+pjWFQ2VDGZmzbKJBO2jMaUk5cdQGy0y8iSZrxczGAbtqxGGnagYxFpDqRuZiohzsjJBfvlEJxNGgaf+YP9+X6M9zMc352oyYx9JfYHC4VnNMUiGRSM5hUrPLV5lu7jwR160TR2daHeAIeUkzKl6Hf6ETCzKROuHETpemGPalV41VVIlTH11UTVA5v2m8l0n+MFA/ue0zoQFLUf2yv6btKvT3lIGV7b4r6r57dX6Xf8f4b1aC93egq+fbOj5naga7tTbnbBTMPgNWtuzvi+dqOr1f9RV0grcZ1nSGsxXWd1Oh7SO2uprUTOi6qfkUXNq0/1ZlR8dRuDf/2wzBvfsLw1Lb39FZhTTymhnOvmoEwzl9yfPvESPJsuUAt3mioYlpjgaqpgUolEwJ0Wi8+dR5ppk2cU3QD0+ax4sSkOUkLTpmBVHTCHIgZ0tgC2SM3zR25PnNkvOozOBd5v98W69DWhEEOx8BynlqIxF7DYeMKcHf6AFpGO9e47/qncn2s4fLsQKJ+PNvNVjput/64immxvulcvV+LXfFc/DPhsz33LOeqnW5HnRSrL4Zztf4o6gITo6HUy9lunhI+GGFA2xbEXmQvzEBieitMXCcp5hZGWyBJbaAQz02L+w9d3jQCKNcoDHPfvv64zQNHegz6zK/52W6e0jpvt1b/vrtP+V28cTMqXP37pM3W+1JTE/Sogusfp8aBzmaewqmXmhDpmc3TqVbF5Hd1spmncCg/fdrmyeOBN583Jgx0j7vE73BgmN5ie5On9syE18diuwET7t6zm0yhqL+kWVS/gsEU0ebxtNrJbLZOsQsfGjNSa4pPHhqToFnufj8e0HEiI8FyV54sZ6tVx3GMj4S80WyNL8Xh6VX1adwHjYRay5W3XKT2Y+QcKCiaciAU1u43rb/98mf+8Adi4+cnN2lWQ29JjepStcA4vl7t/lK+Rq+nVG21+1RGX0zTtH4qqy9oVorkHs+2MxWbV/jieXXIN++r8lOFDhgksucC+0uBmdpF/a5cwQwxolnU27PhTC08GyM68enYpEbre0LBm6T7H+086ILjL83PcGy+/Sm9tkgXI58uRWbqt/eFN6avzxsaEtpfW+ChX2Cmdv6y2v7n/Qd3j8FkiDa2f6+rk+1cxa/5+j/vJ7Uaq78v+E4/JXUtM/oVopLYqczrUcjUwG2zgfmRtF0PTGfqtXcLv6/yNqNqsjm0tvuL7VzFpjP6+eOv7ybVGrvxqHat0t8+JAkt6lmeV592xWO3rpbatwwKLe9dyl07Grx5aoa1ycApd+1HXp9sZyv+tnopPiFMPtLbXSyXqhVtpvy6gIczhXSLNmf+XGZ2DVzGYOpX7EbDpd9xlbe/1JTY2WqmSrtwnjiXaE3nzCbI23C5fVhNzj8vZjN1jnVevfqEJut0XtEYrj7FJuk9rf/5vumkN/nX7/7jf787XRTwH9+xH/gP7UGVj0W+3TSl/9tXovFXPnfT/025Prr/+z+d2R/ura419tb/fvfd9/99973SP2TW/M//fP/fp8LugfvDycflL65g1vwrQwWzUcFsUJA1/2KoIBsVZIOCvPkXRwX5qCAfFBTNvwQqKEYFxaCgbP4lUUE5KigHBVXzL4UKqlFBNSiom39pVFCPCupBQdP8y6CCZlTQDAo2EfTfFhW0o4J2GABtPGRN7LAf7uwwAsaxk5HgcdGDwwfEzzCAsjYsmvdLIDwOoWwYQ1kbGRmMomwcRtkwjrI2OjIYSdk4lLJhLGVthGQwmrJxOGXDeMraKMlgRGXjkMqGMZW1kZLp76X5QTM5LDwOq2wYV1kbLZlBX/Y4srJhaGVtwGQwuLJxdGXD8GJtxDDYNbFxfLFhfLE2YhiMLzaOL0Y6KNdD4S4K9FHDAGNtyDD+vRQ/sLvhl83GAcaGAcbakGEwwNg4wNgwwFgbMgwGGBsHGBsGGGtDhsEAY+MAY8MAY23IMA1ihI3jiw3ji7Uhw8z3gv2geDYsPA4wNgww1oYMgwHGxgHGhgHG25DhMMD4OMD4MMB4GzIcBhgfBxgfBhhvQ4bDAOPjAONkFHTDIB4HwUA4DDDehgyHAcbHAcaHAcbbkOEwwPg4wPgwwHgbMhwGGB8HGB8GGG9jhsNxkY8jjA8jjLcxw+HYyMcRxocRxtuY4fZ7wX9g2TC2+TjC+DDCRBszAkaYGEeYGEaYaGNGwAgT4wgTwwgTLNiqxDjCxDDCRBszgn0vVfOZ2bDwOMIEmWu5yRYMTwGmW8MIE23MCDxVG0eYGEaYaGNGwPAU4wgTwwgTbcwIGJ5iHGFiGGGijRkBw1OMI0wMI0y0MSNgeIpxhIlhhEkXYbADlOMIk8MIk1kwtuU4wuQwwmQbMxLGthxHmBxGmGxjRsLYluMIk8MIkyIY23IcYZLM6N2UHna9EkzqhxEm25iRMLblOMLkMMJkGzMSxrYcR5gcRphsY0ZKMMLKcYDJYYDJNmQkDG05DjA5DDDVhoyEoa3GAaaGAabCAabGAaaGAaZcgMF2ocYBpoYBplyAwXahxgGmhgGm2pBRMLTVOMDUMMBUGzIKhrYaB5gir43uvRFGpwJvjsMAU23IKBidahxgahhgqo0ZBaNTjSNMDSNMtTGjYM+rxhGmhhGm25hRMDz1OML0MMJ0GzMKvzCPI0wPI0yHB0k9jjA9jDAdHiT1OML0MMK0izAY23ocYXoYYdpFGIxtPY4wPYwwrYJNUo8jTJPFCbc6ARuGBusTwwjTbcxo2DD0OML0MMJ0GzMaNgw9jjA9jDDTxoyGDcOMI8wMI8y0MaPF96J5eRbDsuMAM8MAM23IaNguzDjAzDDADA8Kj+PLDOPLtBGjYZsy4/gyw/gybcRo2KbMOL7MML5MGzHaoGZhxvFlhvFlXHzByDbj+DJkAcytgN19L/QPmg8j24A1sGF8mTZiDAxOM44vM4wv20aMgcFpx/Flh/Fl25AxMDjtOMDsMMBsGzIG9tp2HGB2GGC2jRkDo9OOI8wOI8y2MWNghNlxhNlhhFkZ7HjtOMLsMMJsGzMGhqcdR5gdRphtY8bAjteOI8wOI8y6CMNrpeMIs2SZ1a2zwr7TgpVWutTaBo3F66V3aLWVLLfetXFjYYj6Z7Q8WXG9a0PH4mXTO7DoekdWXe/a6LF45fQOrLvekYXXuzaALF48vQNLr3dk7fWujSGL10/vwOrrHVl+vWvDyMKg889oebICe9dGkoVx55/R8mQR9q4NJotXUu/AOuwdWYi9cyuxdzD8/EPqgARgt9gfWLEHETha8Hcr/nc4BOGaPwlBv+p/h2MQLfzTlX+/9H+HgxAt/tPVf7egj+dOGVr/pwDAE4A7HMWIAVAI4CnAHQ5jxAEoCPAk4A7HMWIBFAZ4GnCHAxkBAUoEPBK4w5GMoAChAplb6M8wdgJcICNgIGOePOFABmwgI3Agc+v9WYYDGfCBjACCzK35ZwEGBRhBRiBB5tb9swCHApwgI6Agc2v/WYBFAVaQEViQufX/AFECuCAjvCBzDCAL8CzADDICDTLHAZroxA5AHBJwkDkWkGU4kAE7yAg8yLiPQxzIgB9kBCBkjglkGHBlgCFkBCJk3GNQHMmAI2QEJGSODWQYdGWAJWQEJmSODzThiR2AQCRAIXOMIMPAKwNMISNQIXOcIMPQKwNcISNgIXOsIGvB17g7AWghI2whc7ggYzgQAV7ICF/IHDJoM6+hAxCIhDFkDhs04QkbI8AMGeEMmUMHGQZhGUANGWENmcMHGYZhGcANGeENmfBQHgciQA4ZYQ6ZwwgZhmIZwA4Z4Q6ZQwkZBmMZQA8ZYQ+ZwwkZhmMZwA8Z4Q+ZQwoZBmQZQBAZYRCZwwoZhmQZwBAZ4RCZQwsZBmUZQBEZYRGZwwtNfOIUBxCJhEdkDjFkGJhlAElkhElkDjNkGJplAEtkhEtkDjU08YkdgEgkbCKTPkUERyLAExnhE5lDDhlmYBlAFBlhFJnDDhnmYBnAFBnhFJlDDxlmYRlAFRlhFZnjDxnmYRngFRkBFpljEBlmYhlgFhmBFpnjEBnmYhngFhkBF5ljERnGWxlgFxmBF5njERlGXBngFxkBGJljEhkmVRlgGBmBGJnjEhmmVRngGBkBGZnyCUs4EgHLyAjMyByfyCSORMAzMgI0MscoMoyuMsA0MgI1MscpMoyvMsA1MgI2MscqMkyhMsA2MgI3MscrMkyiMsA3MgI4MscsMkyjMsA4MgI5MsctMkykMsA5MgI6MscuMkylMsA6MgI7MscvmvjECWggEgnwyBzDyDCdygDzyAj0yBzHgGvpGaAeGcEemSMZGQZcGSAfGUEfmaMZGYZcGaAfGcEfmSMaGQZdGSAgGUEgmaMaGUZOGaAgGcEgmfFxiAMZoJCMsJDM4Y0M06MM4JCM8JDMMY4ME6QMMJGMQJHMcY4MU6QMcJGMgJHMsY4Mk6QMsJGMwJHM+PdmHMiAj2QEkGTGp3LiSASMJCOQJHPcI8NoKAOcJCOgJHPsAwOeDKCSjLCSzOGPDOOlDOCSjPCSzCGQpoGgNzZATDKCTDLr4zCQlQrikGCTzJGQpn1gByAOCTrJHA3JMG3KAD3JCD7JHBHB3RngJxkBKJljIhkGVhlgKBmBKJnjIhmGVhngKBkBKZn1ScW4HQCWkhGYkjk+kmF4lQGekhGgwhwgaZrX90L+YK0aOGCAqDBCVJgjJE3z+l6IH2RGElcBUmEEqTCHSDLMohhgKowwFXbn4xBnvwKowghUYQ6SZJhJMUBVGKEqzFGSDGMpBrAKI1iFOUySYS7FAFdhhKswx0kyDKYYACuMgBXmQEmGyRQDZIURssI8WcFoigGywghZYZ6sYDbFAFlhhKwwT1YwnGKArDBCVpgnK5hOMUBWGCErzIGSQA43ACuMgBXm91VgvMUAWWGErDAHShjGWwyQFUbICnOghGG8xQBZYYSsMAdKGMZbDJAVRsgKc6CEYbzFAFlhhKywLJypzABYYXS7RbffArcEtOOCbrnwey4w3mJo18Vo24XLx8J4i8GdFyQO/d4LjLcY2n1Bt1+wcGopQxsw6A4MvwUD4zGGNmHQXRh+GwbGYwxtxKA7MfxWjAy3BLQbg27H8PsxMB9jaEcG3ZLh92RgPsbQrgxCVpjfl4EDGYAVRsAK437vD3zdZACsMAJWGA/nBTLAVRjhKsxhEob5HANchRGuwhwmafoo/AlAHBKuwhwmwZN0BrAKI1iFOUrCMJ9jAKswglUY92GIWyLgKoxwFeY3bQSCAEQhwSqM+yjELRFgFUawCnOUhGG+xwBWYQSrMEdJWGADG8AqjGAV5vdwBDaxAazCCFZhIphByABUYQSqMMdIWGAfHIAqjEAV5hgJw3iQAajCCFRhjpGw0H44EIYEqjDHSFhgTxyAKoxAFeYYCQvsiwNQhRGowhwjYZgPMgBVGIEqzDEShvkgA1CFEajCpI9DHMgAqjACVZhjJAzzQQagCiNQhUm/JTKD3RGAKoxAFeZ3fGA+yABUYQSqMMdIGOaDDEAVRqAKc4yEYT7IAFRhBKowx0gY5oMMQBVGoApzjIRhPsgAVGEEqjDHSBjmgwxAFUagCnOMhGE+yABUYQSqMMdIGOaDDEAVRqAKc4yEYT7IAFRhBKowx0gY5oMMQBVGoApTfoMujkQAVRiBKswxEtbywfFeWcBUGGEqzCEShvEgA0yFEabCHCJhGA8ywFQYYSrMIRKG8SADTIURpsIcImEYDzLAVBhhKswhEobxIANMhRGmwhwiYS0eBBuWQRwSpML8xhFMBxlAKowgFeYICcN0kAGkwghSYY6QMEwHGUAqjCAVpv1mcdwjAqTCCFJhjpEwTAcZgCqMQBXmGAnDdJABqMIIVGGOkTBMBxmAKoxAFeYYCZN43zqIQ8JUmEMkDMNBBpgKI0yFhfeWMEBUGCEqzPgwxP0pICqMEBXmAAnDbJEBosIIUWEOkOA9FwwAFUaACnN8hGE2yQBQYQSoMOOPLcDtAAAVRoAKc3yEKdgfA57CCE9hDo8wjCYZ4CmM8BTm+AjDbJEBoMIIUGGOjzDMFhkAKowAFeYACcNskQGiwghRYQ6QMMwWGSAqjBAVZn0cBs5xAHFIiApzgIRhtsgAUWGEqDC/IwWzRQaYCiNMhTlEwjBbZICpMMJUmPVnaOAOGTAVRpgKc4iEYbbIAFNhhKkwh0gYZosMMBVGmAp3iIRhtsgBU+GEqXCHSBhmgxwwFU6YCr8Lr9xwgFQ4QSrcERIG2SIHRIUTosLvfBzCQOaAqHBCVPid3xkVOJQEHLJBiAp3gIRhtsgBUeGEqHAHSBiGgxwQFU6ICr/zB7rgA0oAUeGEqHAHSBiGgxwQFU6ICneAhGE4yAFR4YSo8Cy8b50DoMIJUOGZD0PcEABQ4QSo8A6o4IYAiAonRIVnfiEbH3oCiAonRIV7ooLhIgdEhROiwj1RwXCRA6LCCVHhnqhguMgBUeGEqHBPVDBc5ICocEJUeOZPF8KRDJAKJ0iFe6SC4SIHSIUTpMI9UsFwkQOkwglS4R6pYLjIAVLhBKlwj1QwXOQAqXCCVLhHKhgucsBUOGEq3DMVDAc5YCqcMBXuEAnHcJADpsIJU+EOkXAMBzlgKpwwFe4QCcdwkAOmwglT4Q6RcAwHOWAqnB511Z11hSMRnXZFj7vy511huMfRiVf0yCt/5hWGexydejU69sqde4XhHocnX5FI9GdfYTjH0elX9Pgrf/4VhnMcnYBFj8DyZ2DBvWscHYJFT8Hyx2BhNsfRQVj0JCxPVTCb4+gwLHoalj8OC+9d4+hALIJVuKMkHLMxDrAKJ1iFC3/wGg5EgFU4wSrcURKO2RYHWIUTrMIdJ+GYbXEAVjgBK9xxEo7ZFAdghROwwh0n4ZhNcQBWOAEr3HESjtkUB2CFE7DCHSfhmE1xAFY4ASvccRKO4RIHYIUTsMIdJ+EYLnEAVjgBK9xxEo7hEgdghROwwv3xWRgucQBWOAErXPpjAHEkArDCCVjhjpNwDJc4ACucgBXuOAnHcIkDsMIJWOGOk3AMlzgAK5yAFe44CQ+cwgjACidghTtOwgMnMQKwwglY4Y6T8MBpjACscAJWuOMknKMlJA64CidchXuugl9aAVbhBKtwR0nwSUQcUBVOqAp3kIQHDoUEVIUTqsKVP5ESNwRAVTihKlyFN9ZzAFU4gSrcQRIeOlwSRCGhKtxTlcBPgE6nJEGofBDihgigCidQhSsfhLghAqjCCVThygchbogAqnACVbhjJByzNQ6gCidQhTtIwjFb44CqcEJVuIMkgSgAUIUTqMIdI+GYzXEAVTiBKlz7w1HxkAKgCidQhTtGwjGc4wCqcAJVuD+dC8M5DqAKJ1CFO0bCMZzjAKpwAlW436kC90NzwFQ4YSrcMRIuEFPhgKlwwlS48WEIV+AAUuEEqXDjoxC3AwBVOIEq3PjpIZyjA6bCCVPhDpFwicuDICRIhTtEwjEa5ICpcMJUuPGn9OJmAJgKJ0yFO0TCJRzPAFLhBKlwh0g4JoMcMBVOmAp3iARiMQ6ICidEhTtAwjFY5ICocEJUuAMkHINFDogKJ0SFe6KChxMAVDgBKtzxkcCIDngKJzyFWx+DeDgCPIUTnsJtZEAGOIUTnMKtj0E8nAGcwglO4dbHIG7GAKdwglO4oyNcwWYIaAonNIU7OMIxmeSApnBCU7iDIziIAUvhhKUIh0Y4BpsCsBRBWIpwaITj40AFYCmCsBTh2AjHZFMAmCIITBEOjnBMNgWgKYLQFOHgCMdkUwCaIghNEXfBfVICsBRBWIq480eW43OdAUsRhKWIOx+E+GxnwFIEYSnizkchbAYCsBRBWIpwaIRjMCoASxGEpQiHRjgGowKwFEFYivAsBYNRAWCKIDBFODbCMRgVAKYIAlOEYyMcg1EBYIogMEX4c78wGBUApggCU4RjIxyDUQFgiiAwRTg2wjEYFQCmCAJTROYP0MeRCGCKIDBFODbCMdkUAKYIAlOE356CyaYAMEUQmCIcG+GYbAoAUwSBKcKxEY7JpgAwRRCYIhwb4QZNjARgKYKwFOFZCsw1EQClCIJShCMjHINRAVCKIChFODLCMRgVAKUIglKERykYbAqAUgRBKcKjFAw2BUApgqAU4VEKBpsCoBRBUIrwKAWDTQFQiiAoRXTbU9DMQgCSIghJEZ6ktFwTlAdRSECK8CAFY00BQIogIEV4kIKxpgAgRRCQIjxIwVhTAJAiCEgR/tgvfCCEACBFEJAiPEjBXFQAkiIISRGepGAuKgBJEYSkiG5/Cg5kQFIEISmiu1gEBzIgKYLeLeJJCuaiAl0vQu8X8ReMYC4q0BUj9I6R2CUj6JYRes2Iv2cEc1WBbhoZXTUSfk0R8LIREof+uhHMZQW6cITeOCLC64YC3TlCLx3x+1NgvpFA147Qe0ccFMH7vAS6eYRePeLvHsFcWaDbRwhEETK8V08AhiIIQxHSx6CAnwAwFEEYinBIRGAuLQBDEYShCOmDEPcEgKEIwlBE5DoSARCKIAhFSB+EuCcBCEUQhCIcERGYawuAUARBKMIREYG5tgAIRRCEIhwREXjTqQAIRRCEIvzeFJiQLwBCEQShCIdEBAbjAjAUQRiK8AwFg3EBIIogEEV4iIJHdcBQBGEowiERkcG5IUAogiAU4ZCIwFxdAIYiCEMRDonAG2YEICiCEBThiIjIcHl0+xKJQQdEBKbyAhAUQQiKUD4GcTMCBEUQgiIcEBGYygtAUAQhKEL7IMTNCBAUQQiK0B7kwZklACiCABSh/bIhbgWAoAhCUER3pwluBYCgCEJQhAMiAkN5AQiKIARFOCAiMJQXgKAIQlCEAyICQ3kBCIogBEU4ICIwlBeAoAhCUIQjIgJDeQEQiiAIRTgkIjCUF4ChCMJQhGMiAkN5ASCKIBBFOCYiOAxEwFAEYSjCMRGBmbwAEEUQiCIcFGleXL7n2Q93htYABCKhKMKIcHcKIIogEEU4JiLwhlEBIIogEEX4k77QHbUCMBRBGIowOtydAoQiCEIRjomIlumD8iAGCUMRDokIjPQFYCiCMBThkEjz2gUndoChCMJQhPUxiJsRgCiCQBThIQpG6gJQFEEoivC7UuBNrgJAFEEginBQpHlt+15mP2R3ZP0ZUBRBKIqwMjweAIgiCEQRjomIwP2TAKIIAlGEgyJCwEkNgCiCQBThmIjARF4AiCIIRBGOiojAbZIAowiCUaSjIgITeQkwiiQYRToqIjCRlwCjSIJRpKMiAhN5CTCKJBhFOirSvPmhOJQAo0iCUaSjIgJvl5UAo0iCUaTjIgLOziXgKJJwFOmwiAjcFQk4iiQcRTosIgL3RQKOIglHkQ6LiMC1j4CjSMJRpMMiInD1I+AoknAUmd2FRzQJOIokHEU6LCIC90cCjiIJR5EOiwiMxSXgKJJwFOmwSPPyiFbtJOAoknAU6bCIwFhaAo4iCUeRDosIjJUl4CiScBSZ+UjE96UCjiIJR5EOiwi8Y1YCjiIJR5EOiwjMlSXgKJJwFOmwiMBgWAKOIglHkQ6LNO+P3wv7g5HDkVkCjiIJR5EOiwgMhiXgKJJwFOm4iMBgWAKQIglIkQ6MCAyGJSApkpAU6cCIUChLSQKQIglIkY6LNG+QsCkAkCIJSJEsvHAoAUeRhKNI5uMQBzLgKJJwFOmwiMBgWAKOIglHkQ6LCAyGJeAoknAU6biIwGBYApAiCUiRPLxLTwKQIglIkY6LCAyWJQApkoAU6biIwGBZApAiCUiRjosIDJYlACmSgBTpuIjAYFkCkCIJSJGOiwgMliUAKZKAFOm4iMBgWQKQIglIkdxEBkYAUiQBKZL7QMRNAYAUSUCK9Le0mzs4wQIgRRKQIj1IMfB8IwlAiiQgRTowIgx6W5QApEgCUqQHKXjLrQQgRRKQIv1RX/BVRwKQIglIkR6kGLiMLwFIkQSkSH93OybTEpAUSUiK9Pe3G4U/AohDglKkv8Mdk2kJWIokLEV6loJf9yRgKZJe5e7vcjd4UEG3udPr3D1MwWhbohvd6ZXuHqbgPbsS3epOr3X3MAXv2ZXoZnd6tbuDIwLDbYludx9d7+4iEcNtCW94J5HoaQqG2xLd8k6vefc0BbNpiW56p1e9e5qC2bRE173T+94dHRGYTUt05TvBKVLFXlYATpEEp0iPU2wzv2kcCOoARCLBKVL5SISvnACnSIJTpL//HbNtCXiKJDxFOjwiMZuWgKdIwlOk5ymYLUtAVCQhKtLfnoIPGJcAqUiCVKQjJBLDXQmQiiRIRarY0AyQiiRIRXYnfaFVWAmIiiRERTpAIvGuZQmIiiRERTpCIjEdlgCpSIJUpEcqgUAGSEUSpCI9UsGBDIiKJERFeqISeFsDREUSoiK1j0PcmwCiIglRkQ6QSMynJSAqkhAVqX0coiQHCYCKJEBFOj4iMZ6WAKhIAlRk5JwvCXiKJDxF+rtTAi0R8BRJeIp0fERiPi4BUJEEqEjHRyTm2xIAFUmAiowBFQmAiiRARTpAIjEgl4CoSEJUpCcqgUAGREUSoiIdIpEZB9ncEiAVSZCK9EgFv/MDpCIJUpH+pC/8yg6QiiRIRTpCIjGhlwCpSIJUpA3n2khAVCQhKtL6KMSdISAqkhAV2REVHESAqEhCVKQjJBJDfgmQiiRIRVofhbgvAkhFEqQiHSKRGPJLwFQkYSrS+ijEnRFgKpIwFekYicRb7yWAKpJAFekYicSUXwKoIglUkY6RSEz5JYAqkkAV5RiJxJRfAaiiCFRRjpFITPkVgCqKQBXlGIlksm0LRgjiYByJikAV5RiJxJRfAaiiCFRRjpFIhnoTBZiKIkxFOUYiMeRXAKooAlWUYyQSQ34FoIoiUEU5RiLxznsFoIoiUEU5RiIx5VcAqigCVZSHKnjhRQGooghUUR6qYDSmAFRRBKoox0gk3vuvAFRRBKoox0gkzhNQAKooAlWUYyQSb75XAKooAlWUYyQSk3oFoIoiUEU5RiLx5nkFoIoiUEU5RiK5Ros/CkAVRaCKynwkogmiAkxFEaaiMh+IuCkApqIIU1EOkUgMyhVgKoowFeUQicR73xVgKoowFeUQicSkXAGmoghTUQ6RSEzKFWAqijAV5RCJxKRcAaaiCFNRjpFITMoVgCqKQBXlGInEpFwBqKIIVFEOkkh8sLQCVEURqqIcJJGYlCtAVRShKspBEol3nytAVRShKspBEolRuQJURRGqohwkkRiVK0BVFKEqylESiVG5AlhFEayiHCWRGJUrgFUUwSrKURKJSbcCWEURrKJ4+FRiBaiKIlRFeaqC15IVoCqKUBXlIInEqF0BqqIIVVEOkki8A10BqqIIVVExqqIAVVGEqijuAxG3JUBVFKEqylMVvHKiAFVRhKookUWGFUBVFKEqSvhAhMMKoCqKUBUlfBzixgyoiiJURTlKInGygAJYRRGsohwlkThZQAGsoghWUY6SSIXAkgJURRGqohwkkXgTuQJURRGqohwkkThXQAGqoghVUQ6SSJwroABVUYSqKAdJJM4VUICqKEJVlPSvzWjdQQGooghUUY6RSLyLXAGooghUUY6RSLyLXAGooghUUR6qBKbJAKooAlWU9HGIWwKAKopAFeUYicTZBgpAFUWginKMROJsAwWgiiJQRTlGInG2gQJQRRGoohwjCQwqgKkowlSUQyQSZxsowFQUYSrKM5VAlw6YiiJMRXmmgvdaKQBVFIEqykMVnO+gAFRRBKoof84XPBtHAaaiCFNRnqngfAkFmIoiTEUpH4e4MwBMRRGmovw2ldCPAOKQMBXlmUpgWARMRRGmohwjkThjQwGooghUUR6q4IwNBaCKIlBF6Ui6gwJQRRGoohwjkdqi9XQFoIoiUEX5G+nx5b0KUBVFqIryN9LjFX0FqIoiVEV5qoJPM1CAqihCVZTfpxIIJEBVFKEqylMVfByCAlhFEayiPFbBxyEogFUUwSrKYRKJs04U4CqKcBXlMInE5xkowFUU4SrKYZLATY8KcBVFuIryXAWnnSjAVRThKsphEokPRFCAqyjCVZTnKjjtRAGuoghXUcbzPTjLBVhFEayiIlhFAayiCFZRxq9nw4VQgFUUwSqqu5Ae1x9EIcEqymMVfCCEAlhFEayibCTZQQGuoghXUZ6rGIR4FcAqimAV5SiJhAdKKEBVFKEqylMVuPVUAaiiCFRRHqpY+JIAmIoiTEX5bSqB8QAwFUWYivJMBefsKMBUFGEqysZGZcBUFGEqyjMVnPSjAFNRhKkoz1Rw0o8CTEURpqI9U8FJPxowFU2YivZMBSf9aMBUNGEq2jMVfCCFBkxFE6aiPVPBB1JowFQ0YSraMRKFk3Y0gCqaQBXtGInCSTsaQBVNoIp2jEThpB0NoIomUEU7RqJwzo0GUEUTqKL9ThWcRagBVNEEqmjHSBTOmdEAqmgCVbRjJArnzGgAVTSBKtoxEoUzTjSAKppAFZ1FOLMGUEUTqKI9VIE9sgZMRROmoj1TgT2yBkhFE6SiMx+HuC0CpKIJUtGZj0PcFgFS0QSp6MzHIf4GQBgSpKIdIVE4Y0UDpKIJUtEeqWBCqwFS0QSpaI9U4KimAVHRhKhoT1TgqKYBUNEEqGi/SQWPahoAFU2AinZ8ROGcHQ2AiiZARftNKoFmAICKJkBFOz6icM6OBkBFE6CiHR9R+LYHDYCKJkBF+20qcBuyBjxFE56iHR4JHBSlAU/RhKdoFgtDwFM04Sna4RGFs3Y04Cma8BTt8IjCWTca8BRNeIp2eEThpBkNeIomPEXzSO6XBjxFE56i/TYVvGahAVDRBKhoLiO/AgAqmgAVzX0g4g4VABVNgIp2fEThvB8NgIomQEVz3yHiyQ0AKpoAFe34iMJ5PxoAFU2AinZ8ROG8Hw2AiiZARXuggpddNAAqmgAV7QCJwolDGhAVTYiKdoBE4cQhDYiKJkRFO0CicOKQBkRFE6KiHSBR+HgQDYiKJkRFO0KicOKQBkhFE6SiHSFR+HgQDZCKJkhFO0KicOaQBkhFE6SihY9EHMoAqWiCVLQjJApnDmmAVDRBKtohksD6nQZMRROmoh0iCazfacBUNGEq2iEShXOXNGAqmjAVLWODM2AqmjAVLSP5sBowFU2YivYbVTCl1oCpaMJUtEMkCic/acBUNGEq2iEShZOfNGAqmjAV7RiJwslPGkAVTaCKVj4ScXMGUEUTqKJV5Pw5DaCKJlBFO0aicPaUBlBFE6iilY9E3B8AqKIJVNEOkih8zokGVEUTqqIdJFE4fUoDqqIJVdEOkiicPqUBVdGEqmgHSRROn9KAqmhCVbSDJAqnT2lAVTShKtpBEoXTpzSgKppQFa0jq4gaUBVNqIp2kETh/CsNqIomVEXHtqpoQFU0oSraX0qPV9M1oCqaUBXtIEloggGoiiZURTtIEhoXAFXRhKpoHdkzpQFV0YSqaO0jEXcogKpoQlW0jiTeaEBVNKEqWke2kWpAVTShKtpTlcBkG1AVTaiK9qd/4XQBDaiKJlRFe6qCM3c0oCqaUBXtIInCmYAaUBVNqIp2kEThTEANqIomVEU7SqJwJqAGWEUTrKKN7xNxpwq4iiZcRTtOgvMNNOAqmnAV7TiJwpmEGoAVTcCK7o4Aw5EMwIomYEU7TtK8s6HuBHAVTbiKtpFNpBqAFU3AinagROFcSA3IiiZkRTtSonAupAZoRRO0oh0qUTgXUgO2oglb0Q6VKJwLqQFb0YStaH8GWGCaCdiKJmxFd/tVcHcC2IombEVbH4i4SwVsRRO2oh0qUTgZUgO2oglbMQ6VKJzLaABbMYStmLvIm7MBbMUQtmLufCTC7sQAtmIIWzF3kTUcA9iKIWzF+P0qEPMagFYMQSvG71cJfQXjQDQErRiPVnA2pQFoxRC0YhwpCUwODEArhqAV40hJYHJgAFoxBK0Yj1ZwPqcBaMUQtGJih4AZgFYMQSvGoxWcEGoAWjEErRh/Mz2Hq9oGoBVD0IpxqETh46cMYCuGsBXjDwHDB0MaAFcMgSvGwxWck2oAXDEErhgPV3BOqgFwxRC4Yvx+FdyWAFwxBK4YD1dwTqsBcMUQuGIyH4iwRzQArhgCV4yDJUrBGZoBdMUQumKYD0R4VokBeMUQvGJYJAfMALxiCF4xHq/gnFQD8IoheMU4WqJwTqoBeMUQvGL8IWCB1gzwiiF4xbBw6o0BdMUQumL8dpXQdwgCkeAV4/FKoEsFeMUQvGK6y1TQAQ8G0BVD6IrxdAWn9RpAVwyhK4ZnkT4d0BVD6IrxdAXnBRtAVwyhKyZGVwygK4bQFROjKwbQFUPoinGwRGn43m4AXTGErhhPV3BerwF0xRC6YjxdwXm5BtAVQ+iKiW1XMYCuGEJXjKcrOLHXALpiCF0xnq7gtFoD6IohdMU4WKI07hEBXTGErhi/XQX3BgCuGAJXjIcr+Bw0A+CKIXDFiMiStgFwxRC4YjxcwUmxBsAVQ+CK8XAl9B2CQCRwxYjIyAzYiiFsxXi2gpNqDWArhrAVIyIvzQawFUPYipGRbVMGsBVD2Irx21Xw+5oBbMUQtmJkbGQGbMUQtmJkJDvbALZiCFsxMpKdbQBbMYStGOkDEXfqgK0YwlaMjGRnG8BWDGErxrMVPDACtGIIWjEerRiUOGEAWTGErBhPVgw6P94AsGIIWDEerBh0DbQBXMUQrmKUz8yWsCUDrmIIVzGeqxi4emQAVzGEqxjPVfBpegZwFUO4ivFcBSaRGYBVDMEqxlGSjFlcARCEBKsYj1XwaXwGYBVDsIrxWAWfxmcAVjEEqxiPVSzDHwGEIcEqxmMVC5sBoCqGUBXjIInCebkGUBVDqIrRkU1TBlAVQ6iKcZBEWdiQAFQxBKoYx0gUzus1AKoYAlWMPwAMY14DoIohUMU4RqIsStA3gKkYwlSMQySBrgwgFUOQivFIBXdlgKgYQlSMNuGuCAAVQ4CK8ad/BboiAFQMASrG3EW6IgBUDAEqxvERhTOrDQAqhgAVY1ikLwNAxRCgYjxQwanZBgAVQ4CKMZHOEPAUQ3iKcXhE49RuA3iKITzFdPep4N4U8BRDeIoxOtKXAaBiCFAx/lZ6nFxuAFAxBKgYx0c0Ti43AKgYAlSMvQv3pgCoGAJUjOMjGienGwBUDAEqJnYAmAFAxRCgYhwf0Tg53QCgYghQMY6PaJycbgBQMQSoGOsDEffHAKgYAlSMByr40CIDgIohQMU4PqJxcrgBQMUQoGL8rSr4HgYDgIohQMX4q+lxdrkBQMUQoGLvIlcIWABULAEq1t+qgs+LtgCoWAJUrOMjGp8JaQFQsQSoWMdHNE5wtwCoWAJUrAMkGqd3W0BULCEq1l9Oj7OzLSAqlhAV6wCJxtnZFhAVS4iKdYBE49xmC4iKJUTFOkCicW6zBUTFEqJiHSDROLfZAqJiCVGxDpBonBhsAVGxhKhYB0h0hrYfWgBULAEq1vERjfOCLQAqlgAV6/iIxnnBFgAVS4CKdXxE47xgC4CKJUDFOj6icVqvBUDFEqBiHR/ROK3XAqBiCVCxDpBonNZrAVGxhKhYB0g0Tuu1gKhYQlSsAyQap/VaQFQsISrWARKN03otICqWEBXLIm8qFhAVS4iKdYBE47xgC4iKJUTFMh+JOJQBUbGEqFgHSDTOC7aAqFhCVKwDJBpn5VpAVCwhKpb5w9vh6pkFSMUSpGIdIdE4J9YCpGIJUrH+XpXA0AiQiiVIxTpEonFSrQVMxRKmYh0i0Tip1gKmYglTsQ6RaJxUawFTsYSpWIdINM6JtYCpWMJUrEMkGufEWsBULGEqlvtIxG0BMBVLmIrlPhJxWwBMxRKmYh0i0aKZJrIfJJfEAYhEwlQsj+TdWMBULGEq1t9QL9B7vwVIxRKkYh0h0Tgp1wKkYglSscIfNAIXki1AKpYgFesIicZZvRYgFUuQihWR9xULmIolTMU6RKJxWrAFTMUSpmIdItE4q9cCpmIJU7EOkWickGoBU7GEqVgR6xIBU7GEqVjHSLRA6y8WMBVLmIr1d9TjXEwLmIolTMUKH4i4MQOmYglTsQ6RaJyLaQFTsYSpWIdINM6ltICpWMJUrL9YBSf1WsBULGEq1iESjVMZLWAqljAVKyO52RYwFUuYinWIRONcSAuYiiVMxTpEonEupAVMxRKmYmXklAcLoIolUMV6qALXci2AKpZAFeuhClxJtQCqWAJVbAdVoD6AKpZAFesYSWAh0gKoYglUsSqyjmgBVLEEqlgPVfAimgVQxRKoYh0k0Tif1QKqYglVsSqSdGMBVbGEqljlwxB3qICqWEJVrIMkWsL+EEAVS6CKjZ0AZgFUsQSqWAdJNE5ntYCqWEJVrIMkGmejWkBVLKEq1lOVwCQXUBVLqIr1e1Vw+pgFWMUSrGI1j8yOAFaxBKtYR0kCGXAWYBVLsIrVvj9EK+IWYBVLsIp1mETjZFILuIolXMV6rhL6DkEgErBi/QFggSEBkBVLyIp1oCTA6S0gK5aQFetAicbprBaQFUvIijWxl2ZAViwhK9aBEi7RkroFYMUSsGIdJwnk01oAViwBK9ZEsr8sICuWkBXryQo84tUCsGIJWLHGxyEelgFYsQSsWH+vSmBQAWDFErBiPVjB+bgWgBVLwIqN7VSxAKxYAlasjSTdWEBWLCEr1oGSLEMHxlgAViwBK9ZxEo0zgi0AK5aAFevBCs4ItgCsWAJWrI0kf1kAViwBK9ZxklBLAGDFErBibexFBYAVS8CK9WAFH7RrAVixBKxYD1ZwaroFYMUSsGI9WMEn9VoAViwBK9nd3V2wNXcPhx76fzy5iGxW6Z6OfGTUh49H+MbUPR35YNSHC0mcX909Hfng1IebLuL84O7pyIegPlwHiTN8u6cjH5L6cJ0kPry3ezryoaiPyP6V7unIh6Y+IltYuqcjH4b6cEGKs327pyMfNEw9dsEJv91T6iOjcZpFxu7u6cgHjVNPX3Dab/d05IPGqQcwOPO3ezryQePUMxh8pm73dOSDxqnHMDh/t3s68kHj1JMYnIHbPR35oHHqr7jH/XD3dOSDxqnnMTiPtns68kHj1CMZnMTZPR35oHHqqQw+orZ7Sn0wGqeOs2h8Sm33dOSDxqlnM/ic2e7pyAeNU49n8FGz3dORDxqn/o4W/NrUPR35oHHqIQ0+sbZ7OvJB45T5OA20FwBq+n88+XDDPb7tuHs68kHjlHmAjehv93Dkgoap5zU4S7N7OvJBw9QjG5yo2T2lPjgNU09t8M3J3dORDxqmHtzgg1i7pyMfNExj+2G6pyMfNEz9lhj8StE9HfmgYeovccEnu3RPRz5omHqIg9NPu6cjHzRMeWTVsns68kHDlPthH0YpQDn9P5482PDUtns68kGj1OEZfEl895C6EDRIPdHBx+R2T0c+aJAKH6SBfhBQnf4fTz5cX4oPy+2ejnzQIPVoB2d1dk9HPmiQerqD8zK7pyMfNEg94BFoIap7OHJBY9SfSYYXw7qnIx80Rv3WGbwc1T0d+aBRKvwdG4G+FKCe/h87H47dBKfZgPb0/3jykbl6BPpjAHz6fzz5YM5HoD8GzKf/x5MP7nwE+mOAffp/PPmIvNh3T0c+aJg6lGNw2mb3dOSDhqmjOQZnbnZPRz5onEp/Jkqg6QME1P/jyYdxPgJNH2Cg/h9PPnycBpo+QEH9P3Y+HNwxOIOxe0p9KBqnKnKOXvd05IPGqYocpdc9Hfmgceooj8HJlN3TkQ8apyoapwAN9f948uHiFOdkdk9HPmicOtxjcFpm93Tkg8apCm9D7B6OXNAwddDH4OTO7unIBw1Tx30Mzu/sno580DCNnWvWPaU+NA1T7fM4YC5M93Tkg4apA0CYunUPRy5olGofpQi/dg9HLmiQOghkskAtUIxqGqPa35YQmJcCctT/48mH70vR2VDdw5ELGqIOBhmcONs9HfmgMRo766x7OvJBY1T7GMVzW8CQ+n/sXHiKFAovgJH6fzz5cCN+hidRACT1/3hy4QZ8hhhA93Dkgkao4ZHfFdCk/h9PLlyE4mzg7unIBw1Rh4gMTgjuno580BA1kR203dORDxqj/gg0nFfcPR35oDHqWJHBqcXd05EPGqMOFxmcXdw9HfmgQeqIkcEJxt1T6sPSIHXUyOAc4+7pyAeNUn8mGrwYoHs4ckGj1KEjgxONu6cjHzRMrQ/TwOwH8Kb+H08+ZKS1AOLU/+PJhetIccZy93Tkg0Zp7PKZ7unIB41SayK9ICBP/T+eXLggxbnT3dORDxKkmWNJgV4wQ/Qpo/Qpu8vCveD/X9m3bTeuI8n+y37uBwG89x+cb5jVaxYt0RZ3yaKGpOyqntX/PgBIyJEJyCf80u1dLEfxAiQyMyIzTY58Mpp8Mgf7/LuaHPdkNPdkApHU5mXc+9UEo9AY3zmkJsc9Gc09mUAktXkx9341wag0xrZG8xbM5Lgno7knE4ikNi/p3q8mGI3GCGs0r+reryYYrcbYFmnegpkc92Q092QCkdTmtd37VY2huScTiKQ2L+/eryYYepkGIulZLt3kuCejuScTiKQ23zl5v5pg6HUaiKQ2r9PeryYYep2a6rlrbHLUk9HUkwk8UpsXa+9XEwy9TDfqKV9buV9NMPQyDTzSk+61+9UEQy/TwCO1edn3fjXB0Mt0o56ysun9oobQzJPZRtgU2VPB5Igno4knE1ikNq8/368mGHqR2m2RPjEeOeLJaOLJ2G2RPjEeOeLJaOLJBBYpP897v5hA6EVqt0X6xP7keCejeSezdV3LSzRMjnYymnYygURq84r2/WqCodeo3QKnJ+srt0Q17WQCh9TmdfH7VY2haScTOKQ2L43fryYYepEW3x34OdbJaNbJBAqpzevj96sJhl6jgUJq8wr3/WqCoddooJDavMh9v5pg6EUaKKQ2r5HeryYYepHuHdny2XiTY52MZp1MIJHavFJ6v5pg6FUaSKQ237t3v5pg6GUaWKQ2r3fer2oMTTyZwCIV2Ylu+8UEQq/SQCK1edX0fjXB0Mu03Jbpkx2X452M5p1MIJHavHB4v5pg6GVafqOi368mGHqZbrzTE8LH5Igno4knE1ikNi8A3q8mGHqZ7sRTnrwyOeLJaOLJbCVGWTH3fjGB0Ks0kEhtvjHuflVjaN7JbLxTXou7X00w9DLdeKe8mna/mmDoZVp9x+GbHO9kNO9kqm+EzfvVBEMv0+qbuWH71QRDL9NAIj2TQ5oc72Q072Sq76R7Jsc7Gc07meo76Z7J8U5G805m453yMuH9aoKh12n9XULf5Hgno3knU3/TmX+/mmDodVpv6/TJyZDjnYzmnUy9lWfmM78mxzsZzTuZ+jtJlMnxTkbzTqb+pgPrfjXB0Ot0453y6uX9aoKh12m9mdMnR1SOeDKaeDIb8fRE+mtyxJPRxJPZiKcn0l+TI56MJp5MYJHaJ9JfkyOejCaezHfd3/arCYZep9+N1dmvJhh6nTbfrtMc9WQ09WSab9dpjnsymnsyzbfrNMc9Gc09mY17eiKnNjnyyWjyyTTfpUxNjnwymnwygUlqn0iyTY58Mpp8MtusnaffNrdONftkvhu3s1/VGJp9Mu13kn2To5+Mpp9Ma787o3L8k9H8k2mL786oHAFlNAFlNgLqibzc5Agoowko037rnuYIKKMJKBPYJJur1d2vJQh6lbbfZqNy9JPR9JNpv+nVtV9NMPQq3cqb2nzCIcc+Gc0+mY19eqLXNzn2yWj2yWzs0xOtvcmxT0azTyZwSe0Trb3J0U9G008mcElPpkvtVxMMvUgDl/REymhy7JPR7JPpvuPxTY5+Mpp+MoFLKopc9eF+MYHQi3Rjn/LtQferCYZepHvdU7Y7wX41wdCLNHBJZZkb171fTCDUIrUb+/SkiMLm6Cer6Sd7+E5qYnP8k9X8k934pyeFGDZHQFlNQNmNgHpSiGFzBJTVBJQNbFL7pIjC5ggoqwkouxFQT4oobI6AspqAshsB9aSIwuYIKKsJKBvYpKLO5l9sjn+ymn+yh+/UJjbHP1nNP9lAJmXLNPdrCYJepBv79KQaxObYJ6vZJ7uxT0+qQWyOfbKafbKBSirKbDLc5sgnq8knu5FPTwpKbI58spp8shv59KQYxObIJ6vJJ7uRT0+KQWyOfbKafbLmO7mJzbFPVrNPNlBJ7ZOCEptjn6xmn2ygkton1SA2xz5ZzT7ZjX16Ug1ic+yT1eyTDVxS+6QaxOboJ6vpJ7t3pMsfCzbHP1nNP9mNf3pSUWJz/JPV/JPd+KcnVRg2xz9ZzT/ZjX96Unhgc/yT1fyTDWxS+6TwwOYIKKsJKLsRUE8KD2yOgLKagLKBTmqfFB7YHANlNQNlNwbqSeGBzTFQVjNQNvBJ3RO1vs1RUFZTUDbwSd0Tpb3NUVBWU1A28EndE6W9zVFQVlNQNhBK3ROlvc1xUFZzUDYQSt0TlbzNcVBWc1A2EErdE5W8zXFQVnNQNhBK3ROVvM1xUFZzUDYQSt0TlbzNcVBWc1A2EErdE5W8zXFQVnNQdh8MlD+xcxSU1RSULbZl+mSp5ygoqykoG/ik7onA3eYoKKspKBsIpe6JON3mOKj4h//6x1/j9WOY1+H0/66n4fdf//yv//rrv4ffw/G+Dn/943//+u9x+2NbV/8I/9xf//zfv6yLAv/5v//5zz/iv+L/6x8P+HDN/3sRaPlzPUqwGsBcOMiA9S/LdHFgt2kZ13G6CkD3Gb8AK/sjwHV8F49a4N2Vzu/9Edh0mY79BfF8J+cHXsfiHY/T/bqGX0OssgCssiCx/Pvyv7UgVun8kQdWVRka66OXa6Ms4e2XLo6kgE6nl35dh/nPZ78ez8MsPoEFxKKkEYcP9wdZPIN4DYs3D4t4ZX4+5gPHT8D8AY58+RY/pNtc2+9WNbexHOSHW27vQ+ZZjTOLD2QvQCIBM1C2xT2//Wpp91stt/9v9v/u9kfwjvz2g93/hj/Owg/FIf5QH+IP9f5DZ3b4iF+W+6Uy/kuV3f+katmH8pZtXMRire3XM9Xkwro4GLGcWjCGpa14lNN97rXxMrioTEMar4uwMSU8Vbl/gKaIL9nEl0xjj9fbfXXbaTwqmwGrtiQt2eUy3dcncCXAsa/xMn0Op9fxMqx/bhLOC/q/3qRX7NOI1+m6rP311M/OLN1P7itJ6Ab3gu9vTSO7vT/+WyxBr9qFHXr4wYMvl2G4Sctm0bKRGyNAvd8v63i7DMtwGY56Ufq6BnyVNPCnA3Dg4isbXDX1vizLll0/7pC4uu8xvvdv6jAs8TAk4d5fRvffl/HtLPa0Hx3yZdo78mS9vl2kdUHL4EefbbaxJl0cD7dOEhCckTbaTT+JiAK8jX8v8sM2Dd4giXIbrid5xnS4gslDK8C4xeb/VCyQysBDVuy7v93G66t4WfBo5Na/+fV/nMebWAu2BiTbkcf8F9brPL17AyUx8TBlLfEXZupDd4hHvzPEy95ng650R24qhzsek5PN4mtstt8NbNgPMfc1I5YMmL2KXsbanYZPQm6o+e2eLF/4EOROWG7O4gZPQJ4LpTgXyPe0LOPbtX+Rn9Ggn2MacnkEqNzbNg1uUHJRLMt0HHWscGjwyCe/3Lr2zjc95TyIg0GPhHzOHe/X8Odlcie+QDQdbgA2XAuIycrw3dXhhKKfdh5fVPztG4l+nfPt7gn7pqE/gkyDQHzaio2cI5x8cQagfMnBdous+YyYH/3lLpdMZ/AWyU98P43Ttl6kKwKrhbyx+3qe5vHfwRI5H3G9y0DOwKb1WTcK86MfL37LhmSBigwxfrNscBEB391DyyV4QI+E3boR7ja5mGVY3X8J0KKAXVzU5GGLoMlCLIoWIUlzjJC3fj0ryA4hSdscIZf+3R2WSSDgwlFYjWwK4LewprjlyB33O2OVS7Gau8cB23FP+tIff71O86czgG/Dst5nFUx1eBp53oMFfZun+/V0nC7TLI+3Shxv3Kp56S/9VW3iqsJPwL3Bl34Z6vI0HN0GEVYLv4apue+5gQ3XFAxD+Zq9s5AG085sgcFsUbLfdItdZeiKDgr7HYdz/zHKD1iZFr0AzjJFoMu4KJcCs49k0jCCJWdEhQnDqiOX1qiimhrj8mZPO5XFntlqLGeUPOx5Wp1zIVY/WEz2ad2vek9R3iPuyob8BtNJ3EuFW7vuyMearn9Pd7EganjpNXeyvHjTIHOqDUa4BbnO7+NFRaSYrtgtoddY0GgqY4xJuYJ9RQ5nHa/LMCd+aoGZs6IhX5Z7V5dhFA9aYvKoJCP4COT+bHwdVb4YTRZp/gKcP28FEEYcMYtLBnvO8VtVAqqoxWnBfgGP43yqiz+IhBXEREroX8rjXe/vL/KlVS28tboh7U0Ak4csmtTQgGZbuQdyxcUnvQWG4SRvscNNvueAG8M9eASend/Ra2SMGerORmRuUX8h34Z+leYEEziGW9rHLb8s76/C++NswNH9/bmXhgnvhgRxropIzNfIm7YkG+NhztPkXvs4D8fVRR86z42e1IFkYx+oPuWj8MTeIAlZh/c26W3W4qoLKiYaavdFpQ8qQkr+9S3nfh7GdXiXsRC6Zx0ZSTq0j16FVLAw6Ad0INncJ1KTFb3tPdz7dF+GQHkqRMyN0cv/trhg9JcPcKVLi9G3JbkKh6Zzgc7Fg7d2YJdYwLESCPflgd2YNx/gJBRChdF7xW4k9x/D7Cz5cR4GeWg1aM4t+5Rnt/yHwPfL7Cm8sYLHmvujuz25JFpkPUny4Hh25kd6CkbsRhJlOP7qj84dWsaX8TKuwhO1aKqLn0Cm9triCitIii5gBbbzfbqO3tRe3yQoZjpIryGA+tROkhDvMMlhyQPTo72Px3m6naerTNZ3mOEgc0UbnrcdOYcEaU7Stnm86+Q9y+2JpeN7QCmH5dzBALltL3cATvNJfZUCs76FZe/TefnuBgOEyC8KLoH9KA5slru/7AoEYr+GP5JneUyBy0Au43E+XhTJDAs39DqicJy3JyUgaNGKQ+RuSQlNgDu6FTHJmyvRgSkbclF4sHV2h7vzFN6TvVVhvqRmzeVl9NYpaJrUGquQAa/Zc+YyLZqKaQshyDHsnU2LYrthI/mZvnuk0Jj4UxvjXhM5dmOiCCQUo9D/bvaToSqOdXs8WLCu4kk6EfSQxP1xunidwls/v6hDvESesWRPN3e1v54SDYnFZWRJysZdDbLEVJLSgKGi7+z66kN1mfSsBXFfkovIQ73pYxyzXOSBFnCSgB9TUexH9EC7CCqekEoYh3wKqdASsMuwZs9e5OIsyVlIYOceyOO3RB0ryVkIyJzorkTWnGQtMhsWrAW9WJZ1vvt4UyacUFvW7vakikm2qmj3H6I4parjnzz+cswR1PEv11GTVtc7bVE3u0Wru0P8Yb/UxGxSEyWFTRE1bg8ZYnOIP+z/RNPuyZQ2nlptvOfW7indNuK08cbasow/xF+v9htro6Vt4+N0dv+TrnyoIPd77qKk08+F3H+IaqCujBbbPGx3vJEwomP/qXr8vfrxU3zM0O842v3HWfDFAR3ib5iyij9Vj1OhfpwUj9PDNF8Cjfgb9hD/DV/SxK6hu9JYoGKZPIMmF2Bd1y8uSeYEMPlhWSd6CjL38/p+cX88riqjYhq0ZWTS8jjdRDBjZAaU9NwcSBKW1pjkbSrWsNz+zF7W5n3xo+Kl4MbYI22+DvPcn0bJd7eFkH6RGeM0uC0wrVA9dmjcR9F0dCTNdLzdk38DVWXs+p0HzZ6hLDAagLiRos0yD/VzFN/a+HeLdt9DRbfv/5JNooR7eZ9OspzAYEbRsI5YwPIHeE4xLjwCNsbdEKd57VftGBToqhYNefw8AP1vniQehntsLjbgLT4AOcu9hamQn0D5nKK8rRJvi/2q0+02nLTtqFH71VTkqX+f50HtK1RmWjbc3nD6ZfF6eR3AYxxUVOTH3BDd/y3ugzqnWO59i3ufNOAbYpKSEiKFH0FtGvfePfZ0n5XCAMWVFZtf2GAv/R/FRxjM0ljWU97Q3of1PJ3kF0Z9GmvNd7TpFPg/JfSAA5o8aja467B+TrPI/5eoXiqrH62/vUwg/0UaIZr50W1uaKN6i3j+sKfDhqcLxhrUo3RsyLJhZeXyWBVB8urHu4tO3mWeHL5Ec+C8Ef/yX0YlYsTiuo7cY6f+j7QiyKaVpLT1NLzcRU4G888kwvGXNj9NI9guUj/kkC7O/odckUpiF5jNKshCutPw2t8v6/D6OhzXjFARE2Ts2wqIULojTRrmSH4CiNU7cktiXPgTRO0vtJjACZMlfgC2Dr+FtW3RswyTCDiwy7AOqqrKYCWoIdM3G1KSKxEuOJmpPw3Lr3W6pYUvB5TMkB6yA1vnSeqAcOHWhweRvzuqjY0/PCRQMcXYxEizrWJ4G+PW7pFyPMRwPbSn33+qHuHoI6h9SK1C/zLuWRJJqkUFkCWP7G1R5+QiFr0eS+9AD5e4rxZfs6U3X6IhspiCteyWG/vLJMkTVMKUpIt4GpO8doXMcN3FjIwlP+EGmOw4tAQNuXcdVL7WoENfhHzv43JzLlz4NZEgwPval2ssSG1IxYTDXrWY1aJh8B0Xtm0V82Mt/w4C9Ovoy+VEZIFRSkMGT6epf121Ig49O1K963Bk5Sw61iUp6nJ/IB0StH6kOzINH8MsT230KEuSHztN7/0oaSesG6zIWPc0zcP/3AepiDXI+xmyePU03d0uCjTW6FUJHzJZgPoZ9iQMiJfhdQ2oAk2crOyj3l2odZFvXlRhsDifZ1WqVjSYmSYzUae5f3sbr285o1+hga0PXCLktEryFt2Pjj3o71utm9I0N3g3u2Wo2YWRqTT3Qw4hUHkkmsma8+Fv56pufQeka4NeEnny7lKofr1No8xgYKETGT8+wDKFUxUWbtdk6m0HTMXKFWrpazKM2dGS/GSFgVVNWtQd7LSXcaovXDaYuCDF1Dvkr0GGbBWu5Jq01cP7KL1xLNEml1lSzFihQqOO9ElDyoU2vD1aeJ1mZ3jlSVBVuNHYlxaKP3JwRsSXZOX8BjfnlcsiOiJNSgT021Um9JpG4JEU8ANPLeJGSN4OZHZrR5tV6qPB5evA2EeVBBFmn8NUKw5E+02YhmkK7pQKKK9XiQOLt6G/3sc4T9fwZ7i08F0/+L+CXGL/c+9lzFTjymrrPUZrY5DXkdVQ/jtKChs8Wg5hWV2Quw6n2zy96aY7bSdlh+T+dJ7Q34vDcpteoonTiv0eicrW9weHVUYmBwLO2osWHqjNJAOJDSZpf4JpSHLV/x6Of6u33Yj3Qx5xv138oaqBBQ75en7L06PG4Mh5VjSI3oJIp5KP5FXyN+cAqygIt0xJOjse6r6O8vUIpTC3ph3ORVo6UbtD2t5X99sv3vKGYzEENPLcR4KhqrmFFECTqBlDRrLmaQOalZhFFN2yL90DLcM89pe0gKfAM78gd8sGuY6rujksR92tcllzhmWDvEtyAoNkklb0OFvKKP0KJQbu7Er7glM3V6KHyZkrj+b+4O4LMjK3J5pXkQyUhNTZ1lL0qSIDXw85D2/OkG2RU3ZrYLEGSc143FxJYHVA3fEP1svGGcnnxf1BRuavo6Sz24PgRehtNr9/9rNPryw63GxFUSZJsr2qIwBprLbljoDXS/+mCiAE608uiMsk/Zoa1fFtFNm2bRStkAXfr+4PlC8hiqZIri7ADKdcuxbRTuknYJmlZQQTFZvykVmI10neWStokMODKjCkq/86TV7epKJDNJdk1sYFbsOzPgVoj8IoWQpwTqwuHqNlFDUeoqywqx/P/qW8I9/q7EzT7baV4UoVCRZZscsx0wWqQDaliGLzgqxG8IiJK4D1CA3rVTggbdtrlNM3rA32QEoBIPpn0SjudNDFKFgWVRT8J1z+vL9MsloUxXUNeyQ4qPt1XH2pqLScHVpO/o3fZ3lTGE83pLxhx5FmTvRXMCRR7pC8cEXmyjFzRobmrzI8OYjyGPKj3S+XZJ83iNSSNVNvg0yiiHNltwZRL2wj+1qSlJ8D7y+Xc++tw+yLZZbjeZA3XaCItiy4b+pwXzaBqYrQGyNCWG7ZOrSoz0nqKC3qXy1ZSeUA9yTf/ujygZH0JDfpmxdfJXlRU4ssDLf6HFTgZ157VdaBYXLDfwh3Uz6D9i5TCQYjB0M6Sxua6qom+rxy1tHhRI9cNXnF+IgsQ/Jgu1hNPyPydoY8kRxcciBhBN7wK8IrVCUO2mwyF+dw5uHiwoyPJ/3MUX1AsiAOMxcZoC9IepaZsn5RssXKK57U9Atnl8wMeV/tplhgLFUlYzzpSaARbL8aWXN3dO4XVQ2Fz0V2fHUgiToWg4GC7D94HvrTZZTFwTXmcRoaSLYqQ/l7TXpt5/GkAnzsHhmrcepYjVM/anjaRzEK2enh/N4f30+V+AzYGdSwd+xwlnNvJBB6K6SfuQP5LSugUKVMunU7lO9vJqAwgCKdsfP0/mgloipWcM2SjtTZ+WLamFbYZbAiRSYRSNX/YftDUk+Rttsy2JvK0Dd0l9LoApP8JakUlU0IUVFA/vqTbrol8rElefA5tCedMAXPTspfHFq2ESH6rxV5lJ6XvaNYWqJRIgdRkRkMwJv1w1YHISpgbzDtMVFhrFfR3yDtIVNhIqQiFa8OKO0WUGG2p6ZffpL2qHCt1+z5teQYrQoZ8Jo1Ug+o8P8ye4dCCTIj/oWXWocKE3k12fblvOhsVoUNH2qyq995Se+nxtRrQyqZIlBSIVbjIm3Iei6Htq43v3c0DY63VrArPlPSiDdF9l46L7GSO1O2VmOSvyELpc+Lj1Fe+tmHKRINqUayrM6hjacxNa41NhVtSAnIednraf5/FeJ1hekC0qd/oN9U+qrGk7KlD4IdzVdEnPu0sU+NUVpLFo04VGgjI+HAq2vpVTgd5+nFr+kMIPr+tNV0gKmkoEaPvSV7kJ+XJ9WYNbYWbMmUj0PTOroadQUtmUM5L2kWEQtgWX9sSXM6DZ7BLX3ibQSuDrob1EZ2pOTcgZ17n73NeAgNJv07sjW4A1SjXRr0qjoycHcwusi9wYihY4OPxa2CbbJJCJdltIyyVDJpBYDaXDbYh7ajLdwDL1HNNVhr05GEvANcnQV692VeqRVuhKD6QAqNA6aykQ0e9OZA259Vp1FKkQEnpUweZ5GSQNGb+0CmDc9eZSWNTXsQD0Yfy6EN02Vvt7Jo4reV3XjZIHy5j8morVYU+B7oU/4+poUvrZAkHegz/j7mtUAtNlo0B7IXr8fzNWs3T0mpyjXx2mh/8j6meb+2ECQmyYqelw/nzcihJCKQNmSzJgf0bD5dKzpYG7IB/nn5HF7c8ftLEietaIZg6FDxAeZ8rWtm+lUjhFX0qffpVkrukRvxMch+Zx4u+ayiT4khq1+8Zy9T6Ljr2XXrQHLy5AJtY0kOwMjHGgZdH0POqhi9uzzNmsGuURvXkCE/YOm0bI0OQkP2elLKKaHLiHMS203xFOh/FnXI9PEuMUVfxfqxKqa164cCIbZnamKxWRP/TtM9Gpzsl9oqaoFjrVsX5zJ2Eadr97/cxc5N3UPbcPjSNjy6GZn6q+fQoyyUlORsj77+yZRP1ZgZbUgZ2fh2nebhWSNdtKE1GZVnptShY1M+3gfptAY8z6ZnckjIktZkdjLgJW6r2HgHMvs+Xo+X+2lYboM7tCf/v3I9olAwissrchSVA8klrNtW9PsgXbpktAYQLDRAaDn5MSTl5iKFfviiMEgVXijX9x2Ar4NUS5SoUK1Iba/qaSIB8VCrSMnL1hr3vg7KkqGtIbVbASotHysrXCek2ioMWVhz0jdkTmuy9sOhKcqqxqYobaxUb8nz1uH5AW+6jKk7iG7m9BdYvJzjZbz2irwRe4E1eFGEkCmhL9FtL0ka9AGoWBxUV8UmcyXpnwXM+S6940bwxgeyM2eAWlROo8EP0ZL+T668tj2I6IRMsow3OdIFEzWG9PrHJXQikTsJ134Z+441JFnvEB9j3YY1WbwlhpwVmdkYl23Z7mtYGhGD9Srs0Kpx8R3O3xIJHnZgIbM347L19ZKzLZDKqknHf1zy7CoOJTJk9cq47PWK4uXj+VyVsXdm3Fd1bD/XkE0Hx0W7ywbHEBgyweFgpiAblveKsvby4eGRLIvDvF8uudb6ItIjC6XG5a1fXTSm8znYZqIjNXvjch5PJ9XyG2ealfQjJi2RS4yyK1KO6HHuskl0hUq8ij2uFj+ca7iql2RQM2/ol3SZet2uve1kY0z2212mz9v0OczvasxagZxUUbKL9X28ju/O85VyJFGta8i89LhMx+D8SuOBq6FmXbZluibSHRxU0pB10w7oplLuGMB09DmwNXySyxPtDxseLLdeG4cax9K2rHsWOrLoLYzucUfmBcfFWfxTMitX5PHIDIaDul/1lilRf1/GcLg1jwA5hvoHssp8XJbz9Kk70+O/UrPe9xJmx9/mEOeq/prY96IgM3IOcO2vJ63uE8Xlhl66y593twl+yc8iGpWzu+ljnNe7IsRRE9aQ3IJHWkbdiQCrGGoTW1bHE7lpH8cd/a98zmPibBnsPmUK7gv/3X/0mVnmGPVZslfYF1R+RDgWeJMO6xdkMskcs5GWPGckXP4uUUNLhkd/L+6PFl1yIvhd7v4SgQeKjckgN46nlocyBlZkWj8CfTPkCb8o2dZkl6BLXQ1G3yTLuOOoIdzYBJ9MvQWgtN2FCK8OJOcWsHSrC+EQHUg3xiFto+5OgzvFRD5A3tjP0LLdnuT90YC6C4dILBzINiu+hmCdp18y5SF5yp8BiZsSXd9JMfMXUq+NTidrXTk4VX5folS1Yu/JgXQSRRRUx/aIB7Ln4K/xquaDYoMC0p29uJB6SOraa6x2bsiXdOnvfszgnBS5ov6LjIW3VspqOjpaKjJQyjczE2Qw97Ivznm6SH8A0wVfZAe5ZwJeOswYqwBr0ttOvSfcMKRCwIN4D3EcpEXoDqIFCykU1yOfjRgzGfuFFmTrlC1GdbGSVHKiv1mTYYCHmgffnFxl0IxoREvW8viA18+VkC9MRLzsendIy21Ssm9sYFaSPJlHUmWc3UF2+eeOB6+/VH4V1juyY+EDjA+9wy8iGmpV2WKggKa7cBfo75VkaLkhTf3L4hwHNfgBm8Z0rIHIDR5CoH0p+D5+MWYgGbHguCVpsQJXbEHqd5QuBt8b+fvTr/utP510qyaLiRnLGp2Aln9zuNRIkaaDk+2VaqHlINvvehQ1O1ZMRuQs4Ht/PI/XQS96QRlyG/q9f7s+lLFvw+KnmSoTLZhRMovx3o9u+edlHbgsyOhbN0ctkJEoyH4EHiRTyFiILjYs1K/BOYFJQYEcQMetCMT6HNezjn0kPcUZMo/5JT4QS+QgtWA0nDMR0+XyeR6GSwZUbAV2DV/vr/3RLzilQkf5PSnW0bW8+CEsqWB49wKr8foWh9pLcwjr7WdwepOiuILeTb9DglmSqpgSJHVISU2jmGREYmx1DsKeIsljybz5jjN9XlVFPW5t8uu740KXhWCP7ubhQB/YDb4hvkwnKSbGitOO1NBvo1ZUtIFHN+mJv4+n096SWW4+2VaGxRrlF8TwhxRjet6jd/t3/HcymrQUckKSPYw8ihTmCG0DGeoHpPv7tGS6RyF5SqZadjgv0dEKpwqbmNTsoTtePRsuvUwk/EiK5330HTKnV+leooCePYMC0LJKD6dB9rtjj55fepQSxhmG5Cc0M9dgnrMlOX0PovL12HqVzFnHdhFJ769W6O9YLFnEi8qYhrUD20BxsQrR2lVk4BscBGkEMAdMttEJKNmm5yiUrdmd5tFyLrsRUSZ7ok86DEdfKgpX2zhSsyXnM3rYdfLJn3N/eZWHMibJSDHvBhca4KR46JySWYhUVYfkaEXaKO22lNhkqbJxJmscsVLF4Z5NHMTSRLFud3hofXeasiPr5v0/J90wrH8s4rjEmqxj8r8oj2Hk1S3ZmDAznMziUrdkWcqOk+vgWAu2g0ST8tEG3cOO9PM9yOoW4psu5hEpTVLAd/XK1os6LmscHNGSFdxYvJk0J0ZFA5mmCHjCr7MYhFuSX4IKUNX9Gp+R1BNOR+lRY3LBkkrC6fpyX1dVcSK0YocvHpnkhaZr4nC2pVBMkZm66ZoZFNWWQiRDlvNOV90JpsLvV39pw8gu3A5wUiUjbSn0BmRvZ3cyXz/copfqHRQi12QZr59i3p+8flvGNd1BzPsiA6Tpeu0/xjfFznaiMasl5QAPLN/KdjiO2r/uhLVgk3XTNVUHtULIybK10zXUgKavrkItXE3GOL4O8aJkvhVuzprd4DuQrggT3vGBVHc4sLNMY1V4xtexlsawY1Oma2DpcutNNOgic6XTrT+qwv0WSU3DNm7XyrMCt2XRxMnnJKPi0TIT7Ut0C0vW+jssxYQUSP2VP7gnh+Mzf2nf1QLzWCUZO3nEbFGjERoqUuk6zadhjg18lawfXxuZufZ+rszl1kiZtyRpMS05SRL6TZYsesvnCMQQ15/h3PpZUcuYWuECl80WZqt38Bkr9t7UAFxVvoPRAUnBuv3tFpd0e7DQviWjDE/2aFGvGPt0+JrhSNa1uPfvSwLkzkTrWJIVVA7I/ye+KhTqVORJfvM9YWQWEVPAHf1Yyzoksi2LaSNL5kUSGRqmXDt6Bazn12nOJsvF2NqfoOUKZFGUSjoTAW2e3l+m6dd7L2M1I4rhyZIOD7g8e1pxIv0ILvu4YPHJI8TD5blmI2bWkon5DS7/7jDVTK9/lWaqsUiijZmE7rHRD1+1rGSG/TY4o3ZdFQVQYDKmYO92mENJZuKolSgUq8hcwc13mb26P9Eqmga9oY5shOvRxtAUQ54vyKgWZKJNNy0XUoLtd8o4erUqvz7NIX4aMuOpu0JZzOBYckDg7dIfh/N0OakOdZiSqkkC/qbEkg1GZ13zmCLMfhMtRiowFVuw5k+1IaowMqvIxnS5hr8lSi6rcn+67hCriQ9fD0ymw2+Tni6Kfn33UKGQO9eX4chNK+g/cjF7lM21kVhoS8mA7zYPr8PsPN6LC4XuvqZdOobCmSPXyFYbEeokJKmM91fR9/cxTlIC2aCl60j+/TaP76rytxAnN5nH3HGyXcgtZucs6ds7wOt6HofZt+9UojzY7+RT3tVqFRIZzvykgx1FgpY8pOZ+XBS1KcSPpM537t/7d60gl0PFSZzPzDQbrDMju5Bip74E0WJ3E0vm6QXiNOf0YFh4Y8kJYHnYWy/pSovyE0uaXgWd62RskXu0ZKsexA0b7Cojeou9SSzZeApBvV8StIoSFdV2JJvoC+Ckr4iEHWl8PYgPU8XdtGImB/1BEu2sxf1WkMJLD5S0XrFY+lGQHPu8t1KX9SgYehkylbgjKdccc6Wkxt8DzeurfDSUJ5Gcv8dJm9tZ9D0KkoLyUCqtZtEqFeTp5nH+JPVIbS34BlI4OA/H8TYOqotPg/UVHTmxzkFNb9fx30m7F4sZCksS0b43gPNStPYGjzi2+brzepw1PB/PUzJODmd/1GQrinnw9IXwRDHuLh/tbCwZ4/pmSh9Df3ExwGX88BlJabFQuUAfXDvkbbjqJJRFrsCSM442wJd+dYb6T6ZdW4F55oJ+kx40O78Z77GjTxQPl2twgyd1TSYWBVp+TDp2pqzJ9OcOGxSxmdcohjSRHUM2yEw/fyFvJtX9G9jFZ+RyLxKdQ5Id3RDTjvXYhpCUf2xQT9skGsynsar1DTP3LXBF72xMFWPAWIjwIKP2NMI+atlPoDrEH3ZlSGH2Xypib6Qi9nIr4nz2MqYjythErorFDxVJamyljlLNJYjVA72sQm5iXwbSbiJNXrNe+dZ/rj8efffTtP11cRBCZNZ2BtB06kCBoqqCjGZ3tK2B1yZF011zcE8V9AEUYHParwI/TUHWPO147+Nxnm7nSfbBKDC/UpCC7h0R1ShSwonEd0FKu3fQrQDHewezPooKZGALkvCffa8lcVi0gmcm9Qyz7+iXiHsr0bmV/h7LdPlQIRGW4UQytyJL0XbApb+M/aIGlgud34FMVXpAn0LS9IgVIjEW6n5R7iI6eF37KMclySiP+K7S6CiJtbsF7JqH1J3NS7y9yBwLmi1yplAQL2aU6bKJLgf1rvXDSLCwjICe811iDFGx4dHk44fjUQgt6g7b6JM1ExtS1lnAlivs6kK0PgybTbr0VyiUqNnt7oH1sGXMZ3dk8b9iwBsMTjvWYNyV8kMQY5GHYIt7HFpSq18gf1CSgrhMd55WaGQOZDPCHQiGMqlRiXhvFOLSv98u7ohflXAXlz7pgS+91yQnvY/xOzZkBnbRhb419qdoY7fftt0NV0fmnf3wo6ihlbIUHGdF3+SkaFhM1xVkc5ZMGa2o9qr2I86w3Rg3wGzw14ojjpR5bUV8W1PBZDQkJv1Ije+G51axi8rXXk74w/KImoygJZ4arYQGjexAB0WL8mCSaSAOKwnOCsy+FmSTvg1mub/oDFAlYj2Sflycx3g9uVDh6oKQ26TuD1vQleT5uwyDVPvWoryMzHNlRJM4uKcmw6sNZjjNWuyIa+tHtxSw3Dtbk3AN+1nVJL+/Yb7v02lf/uikf4muckWmnDWo9kdLIXkns8/LINu51Ngcqy0eLHD9+ImkPjyw/xu9wkcOoSGFSR5Lp/8brK3oSAnkEjJ6Wk4sS5/pHeb2159l+C2fDiUspAu/KN+vRvejpbenixeviueuRBaGXWV+/pE8q4TSir0fD3O9v7/IxFAjtNsH1u1Ix8Qh1drSpnqrqcl0vLWoCbD0ctrwXidVqYz2n0zA7lhJHYvQlLPvPpmQUyAzVZJZXJUqKDF9Uz6yebHTfvMYs3Ag1S0OP4rT8kOpMQ1Aes8eE5Nk7kDVMV+FEUPNekhhxv30+Wi87PU9erId1tQ09Br6SpAnnZlK1EBXrPM1rPtkUnlz2FyLjRwcVIjhr4pob3C7dObx5cnMo8cNJUnJVNCmE8aYzD0+8NJpGJ2YNEEmHR1etnQVVSL1Y4rJoxtnlCq2UUfVxvZqrbXxhz2caas4/ztq57o4saRr2vg+H4IsUz2y5S29e7/pv4hiBtpVWHM0IMrEa36JhqxQ7iXXmPpo2ADBA075guO2FiVbZHGhR7zPXumtZlyI/YneUkXmi7+Qtf5eQqNCj8waO+jT8NrfL+vw+ursVGYMM6bxKjJr/AV77r3QWVE9WO7BG5YdcXu7mftEy8cfKDvq/mYzsDjkhJSNe9ho9jccYVex1y8ppfaI+5/N0yS9P5TcNqQ62eF9T7ai3eJt9I4Zhu/tA2nkEV1hHFPzxnrwbSXye1VUg5FpVIf4OqsQq8JoqObtfphk6fNvj+EUMlsv0itk2tPB+klf0so1aOXofZiVU9ao82tITZUDi3169aAMFI5bUuuzwUnXFeOPlo5y160Np3AF0fVk+/l7JP1gSNmQyiMH897/9h1/dI+XGhmghhRpeTgXwsu1gM2ayaLugBOaEeX3kRD7kM0CAqZvSiTfPb40PnRIWrVgWWBHpucdjs6d1NjVsyEpG4/zrImB2NFsXnhYQ9Fo7tU3ggYl1RnL1upDlkA2GFB0pAjFId36ZfmcZEVYjY0bG1Lf4bFUCUKN4vSGpN0CjlL0lyiZL2t6XWX06Q3GNh3ZJMlBpUOBxbc7kF2lHNI8XMK0tnwci6kFfoEF7kGePmJM6IFUhgcozxdkgiPREZwk4Dye7naFuuv6BzhucZ2GrWJ3mtWzinsj9b0B07vSqowJE/uWTjqt62Xx9YK3X8fFGSyxC7CNHJ0ydCHq5Fzem7T+CEUqPAPUzbcakp8BRXV8OOIcvOMvP6f8NqisGOq4LL9Hv/MYUQXHhzUhNeJzLk/8MjFh9sD7Gl+DeXOhKCoKG5ZPOPdGOB2YE6ZP4nNvXcQvYNAzZk+Vc1/JhWvQJ2MHDfsx9oMnHVSHWlSukLJVD6WFTKgwLchioOU8XFQpN2YnWcf87AzQUbV8LzABUZDFEw7pfjkNvhP94KzPx5ASFphG79jNqdp5iBZCe5bIxnm4dZyiW0dCuWkfqp+H2vIQ22OZQ/cgdQ6P1jg/uLFNNSvrFsQJxSZvdAtTpIirWPVbRzKqiamw9qsHADnFZbn2N3fnUgGHAXzH0i1eXCMXDXItbIouHFWxoFB8ZyNOejbxf3OBofRuK9GBl7W3vk2L0rJUgu5lE0e+ubxUYWCoWrJc4m1aLz4NLdktNBts1LT20p01uNZs7EhXN0Vca4/cbszkHmICN3ata6vHhjo8tluUILtv95XCfdSvk5UI4W43380Lb5TaHauWWF7aHZ9qSgbW9ZRfWWryfAl4aYlPjWagZZMvqs2oQWWHjZnwqt53f9U+PlYZP1bMyEdj1x7iN4pK8PYryd49vtoj3V4/zGDVPr4VuWfc3fcn95FWPyZRvg0MWPl38TJqtRxW87Jb2buJ6YTETkS9NN/pwPLS7gobllas+XNhU//uDk3ZCB4VAgUp3E+XYIHC5pLNeSYDhdpK9BdlE9EB53M8SYVGW8miEtJLXf8oobWYnXpgk4f3l5DbVPlMbDnDBh/3l/NetCiWOdYgNKwLfn/5W09LxqRyR7abzfC8JdqPis1U3N91dqHGXFpLFu4s9+us6rotJsAsS5Tcr4qGt6JRNdmoZrnffCLnWfcCXAU2+owl+6iZUYqY8mBbZix/FhdiyBWFXAhLUwaYflnGt6tK/4qUArttAlzao0F0/mdpzw3L+47yEEYvrfjRjTkbk9WPC4kDhbeqEn2DsT+r71vDYK+8RyvyOSQLu/aLOhxQ7U22JvEgL/dRt4kpsE6y6KJzxtLh7uXfLopXr3FVNKRT5oGm2Rmd/FBvFHwb0hquviPQVRc5i2kchx9CjdPVndaLKgJQU/J+DJk6pI2clEcSqlo0W2P3mTYKNNqv/pdkRy6Pe/MZQBl6oMi6JH1lPxb8vb8kWowCj4WCZJH8MCq1mHFOAJm4Tibwlbjny1hYWZUxnRA95ebRYbN6eMyPWcMsRxT+dZlVRZqvIfm5AFNIGOTlyMYAAUaOFq5EmRJZkL5ObpeoBAP6WKRUMS2yKNCAFvTdvL1dhm90QBj9sm8qYL7eL5e0rqEVw08tmbVfp6tzTmTvQcwTdOTcRZ9dVyNoOgxMDOt1ZXPrKMMnXfd18sPN1YNhzRM52sHhpAGOEQODyM0y3WUtgEEZtSFHcTsUFwTO2m/H86UlG32t0+egtwvmScl+oc8ZDDw+LesKefpCn+2tERQDmciPUIkeF4uRSEFDwPJuvO4NWWKGoSLd9jU7ehrvi6xcWX+vW4Gy2C5Y9FyRGmj9XBUW0FWxgrUmc30eTYsHKvyIVRvnqT/EzO0jcbSffa15pPvipdhGvn30ozyQOqVE3G0x+1iQmoj7KFcSJlTJdgL3UQ0CwY9l47FPVrfdx8/hxY9wlQeB6A9OptXvSQf/ErO8FalFctbJe5aXy4tzM5U7jfdlSZrI4eniVyxVJPfJ/ZofZCXGpJJpE9UKqRWTuFmC24EkI/sKlASUJBnkgAJNrmyJQWLPkEM4HFbSKduIYV9kL/z7IurXS6zyKclI5b4Ms4tj5SvqBDfDZmA81C5OVfW8+MJJ99+BLad1Pi3z62UrW5snsSAaTMB0JFvjUT3fsC5PUVHCReZC72nuBEW4JekQ35XNatCx68iAJy2wQHNQRdKm+6JNyVcXgH3zwJz8tsHYrCObSz4ED0rnIAbckyHSR0griBAJDUZb79FcS2bbc53xMZDgvuiHM/WTDLhE+S3p0n6M83p3cXXgUv1vS/8PZW+WzEQKSNWzH48PMin2MS7jy2WY1ZyECk/dmnS9d6zc2AXMC5fN7tGUZI5s6wslnQLcGja2CG4eAT8pvdyQpT3H5l+GbHD74dsfSaWlUNYYMrZTXTuwYDNyvB1ZbPbZj+v9uo5SiIKpp5KMXB9Iw+9RFaeKtCm5Sjzc51knELB6qSQjz89+lvotWBMkQGgOFhyNxP8tUZdXkh7CjhiU8B+qQymeLAXZuSPjvRZYhVbGbmSGHQvwOQy/FMuOeGRMm9CHFe7Imn1b4+soXzkmCtn1NOrx2AXW1ZWRXS/JAHvD69ekPU2J1GZJtoHf0F6Gc/8xahUp5uPZ1+7RcpwKFtGwL99jeS/7oqh8sDqk2dosvvcxbjf5ytCBJOVzO9p0TVN4JaYrS7KH8oaX5JNbIVpkB034mUf9rIaqYqTs4kn2Mdfzae6lyUcXqiUTeR5ouDq/YLrqZdG2Yq4ZqT737Wl8P5Mc5dPgoWQOZA3Y5zyq5K4YtkzqMwNK2moZzSr77j1S2msZ+Tv2XXmkTLNl5E3IBEOAmoLkQM3KQC6QDEkCmO6TjHaxYE9/D5RplIyxeMEe2B5Ld0pGb78gjx9Z5YhZijYK2Voyr/fbh0VvauiYmBZJ9n0JQHqyhhHDIknSNSBt7UslFm49ktYPWIt+PLR8pD8pZSeY2GujHq0l9cj/znjLoiSMsSr/+sdft/E2BKHPP//rX//5z/8Br3eLSw=="; \ No newline at end of file +window.searchData = "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"; \ No newline at end of file diff --git a/docs/ts/html/classes/HSWindow.html b/docs/ts/html/classes/HSWindow.html index f2138ab51..529f4bb1d 100644 --- a/docs/ts/html/classes/HSWindow.html +++ b/docs/ts/html/classes/HSWindow.html @@ -20,6 +20,7 @@ focus minimize raise +snapshot toggleFullscreen unminimize

Constructors

Properties

application: HSApplication | null

The application that owns this window

@@ -47,8 +48,12 @@

Returns boolean

true if successful

  • Raise this window to the front

    Returns boolean

    true if successful

    +
  • Capture the current on-screen contents of this window as an image. +Requires Screen Recording permission.

    +

    Parameters

    • OptionalkeepTransparency: boolean

      Whether to preserve the window's alpha channel. If false (the default), transparent regions are filled with an opaque black background.

      +

    Returns Promise<HSImage>

    Resolves with the captured image, or rejects if the capture fails (e.g. permission denied, or the window could no longer be located).

  • Toggle fullscreen mode

    Returns boolean

    true if successful

  • Unminimize this window

    Returns boolean

    true if successful

    -
+
diff --git a/docs/ts/html/functions/hs.window.snapshotForID.html b/docs/ts/html/functions/hs.window.snapshotForID.html new file mode 100644 index 000000000..9f6dd6d5f --- /dev/null +++ b/docs/ts/html/functions/hs.window.snapshotForID.html @@ -0,0 +1,6 @@ +snapshotForID | hammerspoon2-docs
hammerspoon2-docs
    Preparing search index...

    Function snapshotForID

    • Capture the current on-screen contents of the window with the given ID. +Requires Screen Recording permission.

      +

      Parameters

      • id: number

        The window's underlying ID (see the id property on hs.window objects).

        +
      • OptionalkeepTransparency: boolean

        Whether to preserve the window's alpha channel. If false (the default), transparent regions are filled with an opaque black background.

        +

      Returns Promise<HSImage>

      Resolves with the captured image, or rejects if no window with that ID can be found, or the capture fails.

      +
    diff --git a/docs/ts/html/modules/hs.window.html b/docs/ts/html/modules/hs.window.html index 30a86d70c..619413de3 100644 --- a/docs/ts/html/modules/hs.window.html +++ b/docs/ts/html/modules/hs.window.html @@ -1,2 +1,2 @@ window | hammerspoon2-docs
    hammerspoon2-docs
      Preparing search index...
      +

      Functions

      allWindows
      currentWindows
      findByTitle
      focusedWindow
      maximize
      moveToLeftHalf
      moveToRightHalf
      orderedWindows
      snapshotForID
      visibleWindows
      windowAtPoint
      windowsForApp
      windowsOnScreen