---
title: "DropletHost, DroppyKit"
description: "Everything the host offers a droplet."
canonical: "https://getdroppy.app/docs/droppykit/api/droplet-host"
last-updated: "2026-09-09"
---

# DropletHost

Everything the host offers a droplet.

`@MainActor struct DropletHost`

A droplet receives one of these in [`activate(host:)`](https://getdroppy.app/docs/droppykit/api/droplet#activate-host) and should store it. There is no global accessor and no singleton: if you did not keep the host, you cannot reach the host, which is deliberate. It keeps a droplet's dependencies visible in its own source and lets the harness hand you a different implementation without changing a line of droplet code.

## Capabilities

Services are present whether or not the droplet is allowed to use them, but the *effect* is gated: a call the droplet lacks the capability for returns `false`, `nil`, or does nothing, and the host logs the refusal. Check `isGranted(_:)` when you want to hide UI for something you cannot do, rather than offering a button that will quietly fail.

Declare the capabilities you need in `droplet.json`; the store shows them to the user before they install.

```
final class WorldClockDroplet: Droplet, ShelfWidgetProviding {
    static let id: DropletID = "worldclock"
    private var host: DropletHost?

    func activate(host: DropletHost) throws {
        self.host = host
        let zone = host.preferences.value(forKey: "zone", default: "UTC")
        host.log.info("activated for \(zone)")
    }

    func deactivate() { host = nil }
}
```

## Initializers

### init(grantedCapabilities:preferences:environment:log:installState:hud:shelf:liveActivity:notchSurface:shortcuts:workspace:feedback:permissions:)

`@MainActor init(grantedCapabilities: Set<DropletPermission>, preferences: any DropletPreferencesService, environment: any DropletEnvironmentService, log: any DropletLogService, installState: any DropletInstallStateService, hud: any DropletHUDService, shelf: any DropletShelfService, liveActivity: any DropletLiveActivityService, notchSurface: any DropletNotchSurfaceService, shortcuts: any DropletShortcutsService, workspace: any DropletWorkspaceService, feedback: any DropletFeedbackService, permissions: any DropletPermissionsService)`

Creates a host. Implemented by Droppy and by `DroppyKitHarness`; droplets never call this.

### init(grantedCapabilities:preferences:environment:log:installState:hud:shelf:liveActivity:notchSurface:shortcuts:workspace:feedback:permissions:launcher:)

`@MainActor init(grantedCapabilities: Set<DropletPermission>, preferences: any DropletPreferencesService, environment: any DropletEnvironmentService, log: any DropletLogService, installState: any DropletInstallStateService, hud: any DropletHUDService, shelf: any DropletShelfService, liveActivity: any DropletLiveActivityService, notchSurface: any DropletNotchSurfaceService, shortcuts: any DropletShortcutsService, workspace: any DropletWorkspaceService, feedback: any DropletFeedbackService, permissions: any DropletPermissionsService, launcher: any DropletLauncherService)`

Creates a host that offers a launcher bridge. Implemented by Droppy; droplets never call this. A second initializer rather than a defaulted parameter, so the 1.0 initializer keeps its symbol.

## Properties

### environment

`@MainActor let environment: any DropletEnvironmentService`

Read-only facts about the host and the machine.

### feedback

`@MainActor let feedback: any DropletFeedbackService`

Droppy's own sound and haptic cues.

### grantedCapabilities

`@MainActor let grantedCapabilities: Set<DropletPermission>`

The capabilities the user granted this droplet at install time.

### hud

`@MainActor let hud: any DropletHUDService`

Transient HUDs on the notch surface. Requires `hud`.

### installState

`@MainActor let installState: any DropletInstallStateService`

Which of this droplet's pieces the user has switched on.

### launcher

`@MainActor let launcher: any DropletLauncherService`

Droppy's commands, settings, droplets and content, for a droplet that draws a launcher. Requires `launcher`. Since 1.12.0: a host older than that has no such property, so declare `minAPI` 1.12.0 to read it.

### liveActivity

`@MainActor let liveActivity: any DropletLiveActivityService`

The seat this droplet's live activity currently holds.

### log

`@MainActor let log: any DropletLogService`

Droppy's own log stream, tagged with your droplet id.

### notchSurface

`@MainActor let notchSurface: any DropletNotchSurfaceService`

Expanded (takeover) surfaces. Requires `expanded-surface`.

### permissions

`@MainActor let permissions: any DropletPermissionsService`

Checking and requesting macOS permissions.

### preferences

`@MainActor let preferences: any DropletPreferencesService`

Persistent, droplet-scoped settings.

### shelf

`@MainActor let shelf: any DropletShelfService`

Opening, closing, and re-measuring the shelf. Requires `shelf-read` to observe and `shelf-write` to act.

### shortcuts

`@MainActor let shortcuts: any DropletShortcutsService`

Global keyboard shortcuts. Requires `global-shortcuts`.

### workspace

`@MainActor let workspace: any DropletWorkspaceService`

Opening URLs and files, and writing the pasteboard.

## Methods

### isGranted(_:)

`@MainActor func isGranted(_ capability: DropletPermission) -> Bool`

Whether the user granted a capability.

Use it to hide affordances you cannot honour, not as a substitute for handling a refusal: capabilities can be revoked while the droplet runs.
