Introduction

DockMaster Pro is a powerful, customizable multi-row Dock replacement for macOS. It replaces the native macOS Dock with a feature-rich overlay that supports multiple rows, sections, workspaces, themes, and much more.

Built with Swift and SwiftUI, DockMaster Pro is designed to be fast, lightweight, and beautiful.

Installation

  1. Download the latest version from the Releases page.
  2. Choose the appropriate architecture: Universal (recommended), Apple Silicon, or Intel.
  3. Unzip the downloaded file.
  4. Drag DockMaster Pro.app to your Applications folder.
  5. Open the app from Applications. If Gatekeeper blocks it, right-click and select Open.

System Requirements

Permissions

DockMaster Pro requires the following permissions to function properly:

Grant these permissions in System Settings > Privacy & Security > Accessibility.

Quick Start

  1. Launch DockMaster Pro from Applications.
  2. Grant Accessibility permission when prompted.
  3. The app will automatically replace your native Dock with the DockMaster overlay.
  4. Click the menu bar icon to access settings and workspace switcher.
  5. Right-click on any dock icon to access context menu options.

Dock Layout

Customize the dock appearance from Settings:

Sections

Organize your apps into logical groups:

Workspaces

Create multiple workspaces, each with its own dock layout:

Themes

Customize the dock appearance with themes:

Press Option + Space to open the search panel:

Animations

Choose from a rich set of animations:

Animations respect the macOS Reduce Motion accessibility setting.

Plugin Development

DockMaster Pro supports a powerful plugin system that allows developers to extend the application's functionality. Plugins can add new widgets, search providers, menu items, themes, and more.

Overview

The plugin system is designed with the following principles:

Plugin Types

DockMaster Pro supports the following plugin types:

Type Protocol Description
Widget WidgetPlugin Add custom metrics to the status widget (weather, CPU stats, etc.)
Search SearchPlugin Extend Quick Search with custom search providers
Menu MenuPlugin Add custom items to dock icon context menus
Theme ThemePlugin Provide custom themes and icon packs
Shortcut ShortcutPlugin Register custom keyboard shortcuts
Notification NotificationPlugin Create custom notification rules
DataSource DataSourcePlugin Provide external data feeds
Layout LayoutPlugin Implement custom dock layout algorithms

Plugin Structure

Every plugin must implement the base DockMasterPlugin protocol and one or more type-specific protocols:

import SwiftUI

class MyPlugin: WidgetPlugin, PluginLocalizable {
    // Required: Plugin metadata
    let metadata = PluginMetadata(
        id: "com.example.myplugin",
        name: "My Plugin",
        nameLocalized: [
            "en": "My Plugin",
            "zh-Hans": "我的插件",
            "zh-Hant": "我的外掛",
            "ja": "マイプラグイン"
        ],
        version: "1.0.0",
        buildNumber: "1",
        author: "Your Name",
        description: "A sample plugin",
        descriptionLocalized: [
            "en": "A sample plugin",
            "zh-Hans": "一个示例插件",
            "zh-Hant": "一個範例外掛",
            "ja": "サンプルプラグイン"
        ],
        type: .widget,
        icon: "star"
    )

    // Required: Plugin context (injected by system)
    var context: PluginContext?

    // Required: Plugin state
    private(set) var state: PluginState = .installed

    // MARK: - PluginLocalizable

    let localizedStrings: [String: [String: String]] = [
        "my.label": [
            "en": "Label",
            "zh-Hans": "标签",
            "zh-Hant": "標籤",
            "ja": "ラベル"
        ],
        "my.description": [
            "en": "Description",
            "zh-Hans": "描述",
            "zh-Hant": "描述",
            "ja": "説明"
        ]
    ]

    // MARK: - Lifecycle

    func activate() async throws {
        state = .active
        // Initialize your plugin here
    }

    func deactivate() async {
        state = .installed
        // Clean up resources here
    }

    // MARK: - WidgetPlugin

    var widgetItems: [PluginWidgetItem] {
        [
            PluginWidgetItem(
                id: "my-item",
                name: localized("my.label"),
                icon: "star.fill",
                value: "42",
                detail: localized("my.description")
            )
        ]
    }

    func updateData() async {
        // Refresh your data here
    }

    // Optional: Configuration view
    var configurationView: AnyView? {
        AnyView(MyPluginConfigView(plugin: self))
    }
}

Internationalization

Plugins should support multiple languages using the PluginLocalizable protocol. This allows your plugin to be used by users worldwide.

Metadata Localization

Provide localized names and descriptions in the PluginMetadata:

let metadata = PluginMetadata(
    id: "com.example.plugin",
    name: "Default Name",  // Fallback language
    nameLocalized: [
        "en": "Weather",
        "zh-Hans": "天气",
        "zh-Hant": "天氣",
        "ja": "天気"
    ],
    description: "Default description",
    descriptionLocalized: [
        "en": "Display weather in Dock",
        "zh-Hans": "在 Dock 显示天气",
        "zh-Hant": "在 Dock 顯示天氣",
        "ja": "Dockに天気を表示"
    ],
    // ...
)

UI String Localization

Implement PluginLocalizable for UI strings:

class MyPlugin: WidgetPlugin, PluginLocalizable {
    let localizedStrings: [String: [String: String]] = [
        "settings.city": [
            "en": "City",
            "zh-Hans": "城市",
            "zh-Hant": "城市",
            "ja": "都市"
        ],
        "settings.placeholder": [
            "en": "Enter city name",
            "zh-Hans": "输入城市名称",
            "zh-Hant": "輸入城市名稱",
            "ja": "都市名を入力"
        ]
    ]

    // Use localized strings
    var widgetItems: [PluginWidgetItem] {
        [PluginWidgetItem(
            id: "weather",
            name: localized("settings.city"),
            icon: "cloud.sun",
            value: "22°C"
        )]
    }
}

Supported Languages

Plugin Permissions

Declare required permissions in your plugin metadata:

let metadata = PluginMetadata(
    id: "com.example.plugin",
    name: "My Plugin",
    version: "1.0.0",
    buildNumber: "1",
    author: "Your Name",
    description: "Description",
    type: .widget,
    permissions: [.network, .filesystem]
)

Available permissions:

Plugin API Reference

PluginContext

The PluginContext provides access to app functionality:

protocol PluginContext {
    // App info
    var appVersion: String { get }
    var appName: String { get }

    // Localization
    var currentLanguage: String { get }
    func localizedString(_ key: String, _ args: CVarArg...) -> String

    // Data access
    func getSections() -> [DockSection]
    func getPinnedItems() -> [DockPinnedItem]
    func getRecentItems() -> [DockItem]
    func getWorkspaces() -> [Workspace]
    func getCurrentWorkspace() -> Workspace?
    func getActiveTheme() -> Theme

    // System metrics
    func getSystemMetrics() async -> SystemMetricsSnapshot

    // Actions
    func launchApp(bundleIdentifier: String)
    func showNotification(title: String, message: String)
    func openSettings()
}

PluginWidgetItem

Represents a widget item displayed in the status widget:

struct PluginWidgetItem {
    let id: String           // Unique identifier
    let name: String         // Display name (should be localized)
    let icon: String         // SF Symbol name
    let value: String        // Primary value to display
    let detail: String?      // Optional detail text
}

Complete Example: Weather Plugin

Here's a complete example of a weather plugin:

import SwiftUI
import Foundation

class WeatherPlugin: WidgetPlugin, PluginLocalizable {
    let metadata: PluginMetadata
    var context: PluginContext?
    private(set) var state: PluginState = .installed

    // MARK: - Localization

    let localizedStrings: [String: [String: String]] = [
        "weather.temp": [
            "en": "Temperature",
            "zh-Hans": "温度",
            "zh-Hant": "溫度",
            "ja": "温度"
        ],
        "weather.humidity": [
            "en": "Humidity",
            "zh-Hans": "湿度",
            "zh-Hant": "濕度",
            "ja": "湿度"
        ],
        "settings.city": [
            "en": "City",
            "zh-Hans": "城市",
            "zh-Hant": "城市",
            "ja": "都市"
        ]
    ]

    // MARK: - Init

    init() {
        self.metadata = PluginMetadata(
            id: "com.example.weather",
            name: "Weather",
            nameLocalized: [
                "en": "Weather",
                "zh-Hans": "天气",
                "zh-Hant": "天氣",
                "ja": "天気"
            ],
            version: "1.0.0",
            buildNumber: "1",
            author: "Example",
            description: "Display weather in Dock",
            descriptionLocalized: [
                "en": "Display weather in Dock",
                "zh-Hans": "在 Dock 显示天气",
                "zh-Hant": "在 Dock 顯示天氣",
                "ja": "Dockに天気を表示"
            ],
            type: .widget,
            icon: "cloud.sun",
            permissions: [.network]
        )
    }

    // MARK: - Lifecycle

    func activate() async throws {
        state = .active
        await fetchWeather()
    }

    func deactivate() async {
        state = .installed
    }

    // MARK: - WidgetPlugin

    var widgetItems: [PluginWidgetItem] {
        [
            PluginWidgetItem(
                id: "weather-temp",
                name: localized("weather.temp"),
                icon: "thermometer",
                value: "22°C",
                detail: "Sunny"
            ),
            PluginWidgetItem(
                id: "weather-humidity",
                name: localized("weather.humidity"),
                icon: "humidity",
                value: "65%"
            )
        ]
    }

    func updateData() async {
        await fetchWeather()
    }

    // MARK: - Private

    private func fetchWeather() async {
        // Fetch weather data from API
    }
}

Best Practices

Troubleshooting

App doesn't open

DockMaster Pro is a menu bar app (LSUIElement). It won't show a window on launch. Look for the icon in the menu bar at the top of your screen.

Gatekeeper blocks the app

Right-click the app and select Open from the context menu. Alternatively, go to System Settings > Privacy & Security and click Open Anyway.

Dock doesn't appear

Make sure you've granted Accessibility permission. Go to System Settings > Privacy & Security > Accessibility and ensure DockMaster Pro is enabled.

App crashes on launch

Check the Console app for crash logs. Search for "DockMasterPro" to find relevant entries. Common causes include corrupted preferences — try deleting ~/Library/Application Support/DockMasterPro/ and restarting.

Download DockMaster Pro

Choose your architecture and get started.