Swiftpack.co - emorydunn/StreamDeckPlugin as Swift Package

Swiftpack.co is a collection of thousands of indexed Swift packages. Search packages.
See all packages published by emorydunn.
emorydunn/StreamDeckPlugin 0.3.0
A library for creating Stream Deck plugins in Swift.
⭐️ 22
🕓 13 weeks ago
.package(url: "https://github.com/emorydunn/StreamDeckPlugin.git", from: "0.3.0")


Swift Documentation badge

A library for creating Stream Deck plugins in Swift.


Your plugin should conform to PluginDelegate, which handles event routing to you actions and lets you interact with the Stream Deck application.

import StreamDeck

class CounterPlugin: PluginDelegate {

    // Skipping manifest for brevity

    var counter: Int = 0

    func keyDown(action: String, context: String, device: String, payload: KeyEvent) {
        counter += 1
        setTitle(in: context, to: "\(counter)")


By using the @main attribute your plugin will be automatically initialized.

Responding to Events

When the plugin receives a message from the application the event is parsed and routed. Events are first sent to the relevant Action and then to the PluginDelegate. Global events, like applicationDidLaunch and didReceiveGlobalSettings, are sent only to the delegate.

With Methods

When events are received by your plugin they are parsed and the corresponding method is called. See the Events Received page for more details. Each event has a default implementation that does nothing, so your plugin only needs to include any events you care about.

Each method is called with the top-level properties along with an event specific payload. For instance, to the keyDown event provides a payload that includes the actions settings, coordinates, etc.

With Actions

A more powerful way to respond to events is with Actions. By creating an object that conforms to Action you can move the logic out of the plugin. For a plugin with many actions this is the preferred way to handle events. The StreamDeckPlugin creates a new instance of your action when willAppear is called and releases it when willDisappear is called.

The Environment

In order to pass variables between instances you can use @Environment property wrapper. Firstly you need to declare your EnvironmentKey:

struct PluginCount: EnvironmentKey {
    static let defaultValue: Int = 0

Then when you need to access that value in an action you decorate the variable:

class IncrementAction: Action {
    @Environment(PluginCount.self) var count: Int

Sending Events

In addition to receiving events from the application your plugin can send events. Most of the commands require a context object to specify the instance on the Stream Deck.

Exporting Your Plugin

Your plugin executable ships with an automatic way to generate the plugin's manifest.json file in a type-safe manor. Each Action also has its own manifest properties as well.

class CounterPlugin: PluginDelegate {

    // MARK: Manifest
    static var name: String = "Counter"

    static var description: String = "Count things. On your Stream Deck!"

    static var category: String? = "Counting Actions"

    static var categoryIcon: String? = nil

    static var author: String = "Emory Dunn"

    static var icon: String = "counter"

    static var url: URL? = nil

    static var version: String = "0.2"

    static var os: [PluginOS] = [.mac(minimumVersion: "10.15")]

    static var applicationsToMonitor: ApplicationsToMonitor? = nil

    static var software: PluginSoftware = .minimumVersion("4.1")

    static var sdkVersion: Int = 2

    static var codePath: String = CounterPlugin.executableName

    static var codePathMac: String? = nil

    static var codePathWin: String? = nil

    static var actions: [Action.Type] = [


class IncrementAction: Action {

    static var name: String = "Increment"

    static var uuid: String = "counter.increment"

    static var icon: String = "Icons/plus"

    static var states: [PluginActionState] = []

    static var propertyInspectorPath: String?

    static var supportedInMultiActions: Bool?

    static var tooltip: String?

    static var visibleInActionsList: Bool?

Using the export command you can generate the manifest file and copy the actual executable to the Plugins directory:

counter-plugin export --copy-executable --generate-manifest

You can also specify the output directory, manifest name, executable name, or preview the manifest. Check export -h for all of the options.

Adding StreamDeck as a Dependency

To use the StreamDeck library in a SwiftPM project, add the following line to the dependencies in your Package.swift file:

.package(name: "StreamDeck", url: "https://github.com/emorydunn/StreamDeckPlugin.git", .branch("main"))

Finally, include "StreamDeck" as a dependency for your executable target:

let package = Package(
    // name, products, etc.
    platforms: [.macOS(.v10_15)],
    dependencies: [
        .package(name: "StreamDeck", url: "https://github.com/emorydunn/StreamDeckPlugin.git", .branch("main")),
        // other dependencies
    targets: [
        .executableTarget(name: "<command-line-tool>", dependencies: [
        // other targets


Stars: 22
Last commit: 4 weeks ago
jonrohan Something's broken? Yell at me @ptrpavlik. Praise and feedback (and money) is also welcome.

Release Notes

Settings and Stream Deck +
13 weeks ago

This release introduces the new Settings API as well as support for the rotary encoders on the Stream Deck +.


Actions can now have strongly-typed settings which are automatically decoded when receiving an action from the Stream Deck. This means actions no longer need to manually parse the payload dictionary (and optional values) and allows for settings to be any Codable type instead of just strings.

Stream Deck +

Rotary encoders and screen layouts are fully supported so actions can run on the Stream Deck +.

Actions can now conform to one of several helper protocols which provide default values for key actions, both with and without states, and rotary encoder actions.

What's Changed

New Contributors

Full Changelog: https://github.com/emorydunn/StreamDeckPlugin/compare/0.2.0...0.3.0

Swiftpack is being maintained by Petr Pavlik | @ptrpavlik | @swiftpackco | API | Analytics