app.websocket - WebSocket API

WebSocket client for real-time bidirectional communication.

Requires: macOS 10.15+ (returns an error on older systems) Permission: Requires websocket declared in the manifest (L1 standard)

Methods

app.websocket.connect(url, config?)

Connects to a WebSocket server.

Parameters:

  • url (string) - WebSocket URL (ws:// or wss://)
  • config (table, optional):
    • headers (table, optional) - Custom request headers
    • onMessage (function, optional) - Message callback function(id, data, type)
      • id (string) - Connection ID
      • data (string) - Message content (base64-encoded for binary type)
      • type (string) - "text" or "binary"
    • onClose (function, optional) - Close callback function(id, code, reason)
    • onError (function, optional) - Error callback function(id, message)

Returns: string, error - Connection ID

local id, err = app.websocket.connect("wss://echo.websocket.org", {
    headers = {
        ["Authorization"] = "Bearer token123"
    },
    onMessage = function(id, data, type)
        app.log.info("Received message: " .. data)
    end,
    onClose = function(id, code, reason)
        app.log.info("Connection closed: " .. code)
    end,
    onError = function(id, msg)
        app.log.error("WebSocket error: " .. msg)
    end
})

app.websocket.send(id, data, options?)

Sends a message.

Parameters:

  • id (string) - Connection ID
  • data (string) - Data to send (must be base64-encoded for binary type)
  • options (table, optional):
    • type (string, optional) - "text" (default) or "binary"

Returns: boolean, error

-- Send text
local ok, err = app.websocket.send(id, "Hello, Server!")

-- Send JSON
local ok, err = app.websocket.send(id, app.json.stringify({
    action = "subscribe",
    channel = "updates"
}))

-- Send binary data (base64-encoded)
local ok, err = app.websocket.send(id, base64Data, {type = "binary"})

app.websocket.close(id, options?)

Closes a connection.

Parameters:

  • id (string) - Connection ID
  • options (table, optional):
    • code (number, optional) - Close status code (default 1000)
    • reason (string, optional) - Close reason

Returns: boolean, error

local ok, err = app.websocket.close(id)

-- Specify close code and reason
local ok, err = app.websocket.close(id, {code = 1001, reason = "Going away"})

app.websocket.closeAll()

Closes all connections.

Returns: boolean

app.websocket.closeAll()

app.websocket.list()

Lists all active connections.

Returns: array - Array of connection info

local connections = app.websocket.list()
for _, conn in ipairs(connections) do
    app.log.info(string.format("ID: %s, URL: %s, State: %s",
        conn.id, conn.url, conn.state))
end

Connection states (state): "connecting" | "open" | "closing" | "closed"

Examples

Real-time chat

function MyPlugin:handleChat(context)
    local ws, err = app.websocket.connect("wss://chat.example.com/ws", {
        onMessage = function(id, data, type)
            local msg = app.json.parse(data)
            if msg and msg.text then
                app.notification.show("New Message", msg.text)
            end
        end,
        onError = function(id, msg)
            app.notification.show("Connection Error", msg)
        end
    })

    if not ws then
        app.dialog.alert({title = "Error", message = err})
        return
    end

    -- Send a message
    app.websocket.send(ws, app.json.stringify({
        type = "message",
        text = "Hello from iRightMenu!"
    }))
end

File change monitoring

function MyPlugin:init()
    self.wsId = nil
end

function MyPlugin:handleStartWatch(context)
    if self.wsId then
        app.websocket.close(self.wsId)
    end

    self.wsId = app.websocket.connect("ws://localhost:8080/watch", {
        onMessage = function(id, data)
            local event = app.json.parse(data)
            if event and event.type == "change" then
                app.notification.show("File Changed", event.path)
            end
        end,
        onClose = function(id, code, reason)
            self.wsId = nil
            app.log.info("Monitoring stopped")
        end
    })
end

function MyPlugin:cleanup()
    if self.wsId then
        app.websocket.close(self.wsId)
    end
end

Notes

  1. macOS version: Requires macOS 10.15+; all methods return an error on older versions
  2. Connection limit: Each plugin can have up to 10 concurrent connections
  3. Binary data: Binary data is sent and received using base64 encoding
  4. Resource cleanup: All connections are automatically closed when the plugin is unloaded; you can also manually call closeAll()
Developer Documentation
User Guide
Getting Started Script Menus FAQ
Script Development
Development Guide
Plugin Development
Quick Start Development Guide Example Plugins
API Reference
Overview API Query Plugin Info Logging Finder Context Plugin Settings Internationalization
UI & Interaction
Dialog Progress Notification Chooser WebView Status Bar Dock
Files & Paths
File Operations Path Utilities Finder Actions Trash Extended Attributes Metadata File Watcher
Data Formats
JSON Plist CSV XML PDF Image
Text & Encoding
String Regex Date & Time Color Crypto
System
Shell Commands Process Application System Info AppleScript Shortcuts
System Info
Network Power/Battery Screen/Appearance Audio Bluetooth Location
Network
HTTP WebSocket URL
Input & Clipboard
Keyboard Mouse Hotkey Clipboard Window
Storage
SQLite Keychain UserDefaults
Media
OCR QR Code
Utilities
Archive UTI Share Timer Wake Lock Thread