Permissions reference
Every permission a widget can request, what the user is told it means at install time, and which methods and events it unlocks.
Everything is denied by default. A widget declares what it needs in the
manifest's permissions object, and the user consents at install time,
permission by permission. Three rules shape the system:
- Consent can only narrow. What the user granted is intersected with the manifest; nothing can escalate past what the manifest declared, and the user may grant less.
- Updates re-prompt only for additions. An update that adds a permission asks again; removals apply silently.
- Ask for what you use. Every grant is shown to the user in plain language (the wording below). A widget requesting more than it visibly needs reads as suspicious in review and to users.
The permissions
The wording in the second column is exactly what the marketplace shows the user at install time.
| Permission | Shown to the user as | Unlocks |
|---|---|---|
time | Reads the current time from the dashboard's clock | dd.time, the time.tick event |
storage | Saves its own data inside the dashboard | dd.storage |
files | Reads files or folders you explicitly pick for it | dd.files.read of user-set filePath settings |
desktop | Integrates with your desktop (icons, wallpaper area) | dd.desktop, desktop.changed, dd.dialogs.pickDesktopItems |
system | Reads system stats like CPU, memory and battery | dd.system.status / onVitals, the system.vitals stream |
systemControls | Changes system settings such as volume, sound devices, Wi-Fi, Bluetooth and brightness | the dd.system write surface: volume, mute, the microphone, the radio switch, Wi-Fi, openSettings, the audio device list and switch, the per-app mixer, the paired Bluetooth list and connect, display brightness. Useless without system |
media | Sees what music or video is playing | dd.media.status / onNowPlaying, the media.nowPlaying stream |
mediaControls | Controls media playback | the dd.media transport verbs. Useless without media |
audio | Reads audio levels (for visualizations) | the audio.spectrum stream. Loudness bands only, never raw audio |
control | Controls other widgets you grant it access to | dd.widgets over user-approved targets, widgets.changed |
peers | Talks to other widgets of the same type | dd.peers drag and drop |
systemApps | Opens system apps you pick for it | dd.apps, catalog keys only |
claudeUsage | Reads your local Claude Code usage summary | dd.claudeUsage.status, aggregated only |
notifications | Shows you reminders, even when the widget is hidden | dd.notify.sync |
power | Shuts down, restarts (also into advanced startup), sleeps, locks or signs out of this PC | dd.power |
folders | Lists and opens items in folders you pick for it | dd.folders, folders.changed, dd.dialogs.pickFolderItems |
games | Sees the games installed on this PC and can start them | dd.games, opaque ids and local cover art |
taskbar | Reads your taskbar: open windows, pinned apps, the notification area and how many notifications you have | the bar-only surface (kind: "bar" widgets): dd.windows, dd.pins, dd.bar.strip (with its one write, a reorder on the user's drag), dd.bar.flyout, dd.systray, dd.notificationCenter (0.4.2+: a count and open and close; the notifications stay in a host-drawn window), dd.bar.openStartMenu, dd.bar.openQuickSettings and dd.bar.openNotifications |
launchers | Opens the files, folders and apps you drop on it | dd.launchers, the launchers.drag, launchers.drop and launchers.changed events. Grid widgets only: the drop gesture is the consent, and the widget only ever sees opaque ids |
clipboard | Sees all text and pictures you copy, which can include passwords, and can put them back when you click it | dd.clipboard, the clipboard.changed event. Grid widgets only, and a manifest cannot combine it with http, links or feeds |
clipboardWrite | Puts text or pictures on your clipboard when you click it | dd.clipboard.writeText and dd.clipboard.writeImage, from a click only. Grid widgets only |
feeds | Reads news feeds from web addresses you enter in its settings and opens their articles when you click them | dd.feeds.fetch, the address the user typed into a url setting. The host fetches and parses the feed; only titles, links and dates reach the widget. dd.feeds.open (0.3.11+) opens those links from a click, no links grant needed |
The scoped grants
http and links are objects, not booleans, and their scope is part of the
consent.
http
"permissions": { "http": { "hosts": ["api.open-meteo.com"], "rateLimit": 60 } }hosts: exact hostnames the widget may fetch through dd.http.fetch. Shown to the user as: "Talks to the internet, only to:" followed by the list. No wildcards; every hop of a redirect is re-checked.rateLimit: requests per minute, optional. Omitted means the host default of 30; values are clamped to 120. Never shown at install.
links
"permissions": { "links": { "prefixes": ["steam://run/"] } }prefixes: URL prefixes dd.links.open may launch, each a fullscheme://...string. Shown to the user as: "Can open these link types on your PC:" followed by the list. Empty means no access, and dangerous schemes are refused at call time no matter what a manifest declares.
Read and control pairs
Two capabilities are split so that reading never implies acting:
systemreads vitals;systemControlschanges volume, the microphone, the radios, Wi-Fi, the sound device, per-app volume, Bluetooth connections and brightness, and opens settings panels. The lists that name your apps, devices and displays aresystemControlsreads too. Controls withoutsystemare useless.mediareads now-playing;mediaControlsdrives playback.
power is deliberately its own permission rather than part of
systemControls: granting a volume slider is not granting the ability to
turn the machine off.
Version floors
Some permissions did not exist in the earliest app releases, and others
gained methods later. You do not declare anything for this: the store
stamps every new version's minAppVersion from the release that last
changed each permission it requests (see
the feature floor).
The entries above the oldest supported app, today:
| Permission | Last changed in |
|---|---|
audio | 0.3.0 |
games | 0.3.2 |
desktop, folders, links, power, systemApps | 0.3.7 |
launchers | 0.3.9 |
feeds | 0.3.11 |
system, systemControls, taskbar (bar widgets) | 0.4.2 |
clipboard, clipboardWrite | 0.5.2 |
Consent-bearing settings
Four setting types are part of the permission story:
filePath (which file or folder), secretRef (which credential),
instances (which other widgets), and url (which web address a feed
comes from). Their manifest defaults are always
ignored; only what the user actively picked counts. See
the manifest reference. Bar widgets
cannot declare these fields at all: the manifest refuses them, see
Bar.
One API rides this model with no grant of its own:
dd.image.load returns
the image the user picked in a filePath setting as a data: URL. The
picked file IS the consent; the method can read nothing else, and only
sniffed image bytes with an 8 MB cap ever cross the bridge.
For the containment model behind all of this, see How the sandbox works.