Quick start

Write an add-on in Swift with LedgeKit, package it as a .ledgeaddon folder, and load it into your own Ledge.

What you need

  • macOS 14 Sonoma or later
  • Swift 6, from Xcode or the Swift toolchain
  • Ledge, to load and try your add-on

LedgeKit is public, so you don't need a GitHub account to use it. To check your toolchain, clone it and run its tests:

git clone https://github.com/Ammyy9908/LedgeKit.git
cd LedgeKit
swift test

1. Lay out the package

An add-on is an ordinary Swift package with a manifest and an icon beside it:

my-addon/
├── Package.swift
├── addon.json
├── Assets/
│   └── Icon.png
├── Sources/
│   └── MyAddOn/
│       └── main.swift
├── Tests/
└── README.md

2. Depend on LedgeKit

Pin the released SDK to an exact version, so the build is the same on every machine:

Package.swift
// swift-tools-version: 6.0
import PackageDescription

let package = Package(
    name: "MyAddOn",
    platforms: [.macOS(.v14)],
    dependencies: [
        .package(url: "https://github.com/Ammyy9908/LedgeKit.git", exact: "0.1.0")
    ],
    targets: [
        .executableTarget(name: "MyAddOn", dependencies: ["LedgeKit"])
    ]
)

While you work on LedgeKit itself, you can point at a checkout instead with .package(path: "../LedgeKit").

3. Write the worker

AddOnWorker.run reads Ledge's request, calls your handler and writes the response. Your code only answers the request:

Sources/MyAddOn/main.swift
import LedgeKit

@main
struct MyAddOn {
    static func main() async {
        await AddOnWorker.run { request in
            // Check the operation and inputs before doing anything.
            guard ["read", "write"].contains(request.operation) else {
                return AddOnResponse(value: nil, error: "Unsupported operation.")
            }
            return AddOnResponse(value: request.liked ?? false)
        }
    }
}

The worker covers the request, the response and the limits Ledge enforces.

4. Describe it in addon.json

addon.json
{
  "id": "my-addon",
  "version": "1.0.0",
  "protocolVersion": 1,
  "name": "My Add-on",
  "summary": "One line for the Store",
  "description": "A sentence or two about what it does.",
  "author": "Your name",
  "capabilities": ["spotify-library"],
  "executable": "MyAddOn",
  "icon": "Assets/Icon.png"
}

Check it with the ledgekit CLI. Every field is described in addon.json.

5. Build and package

Build a release binary, then copy it into a folder with the manifest and icon. The executable's file name must match executable in the manifest.

swift test
swift build -c release
bin="$(swift build -c release --show-bin-path)"

mkdir -p MyAddOn.ledgeaddon/Assets
cp "$bin/MyAddOn" MyAddOn.ledgeaddon/
cp addon.json MyAddOn.ledgeaddon/
cp Assets/Icon.png MyAddOn.ledgeaddon/Assets/
codesign --force --sign - MyAddOn.ledgeaddon/MyAddOn

6. Load it into Ledge

In Ledge, open Settings → Add-on Store, choose Load Add-on… and pick MyAddOn.ledgeaddon. Ledge checks the package and asks you to trust it.

For a complete add-on to copy from, read Spotify Likes in LedgeAddOns. It has tests that run without a Spotify account, and a script that builds the package.