# Services **Service APIs are version-sensitive and can mutate the user's session.** Start from the installed-version type index, not from a remembered recipe. Inspect local `*.qmltypes` files when the installed module and web docs may differ. ## PipeWire The retained default-sink shape is: ```qml import QtQuick import Quickshell import Quickshell.Services.Pipewire PanelWindow { id: root anchors { top: true; left: true; right: true } implicitHeight: 30 readonly property var sinkAudio: Pipewire.defaultAudioSink ? Pipewire.defaultAudioSink.audio : null PwObjectTracker { objects: [Pipewire.defaultAudioSink] } Text { anchors.centerIn: parent text: `${Math.floor((root.sinkAudio ? root.sinkAudio.volume : 0) * 100)}%` } } ``` For a slider, keep the service-to-control binding declarative and write only user movement: ```qml Slider { value: root.sinkAudio ? root.sinkAudio.volume : 0 onMoved: if (root.sinkAudio) root.sinkAudio.volume = value } ``` Verify the tracker and node properties against the installed PipeWire module before extending this shape. ## Notifications Creating `NotificationServer` attempts to become the session notification daemon. Do not run it alongside the user's real notification daemon during tests. Capability properties advertise behavior to clients. Set `actionsSupported`, `persistenceSupported`, `inlineReplySupported`, markup, hyperlinks, images, or action icons to true only when the UI implements that behavior. Receiving a property from `Notification` does not mean the daemon implements its presentation or interaction. A received notification must be marked `tracked` in `onNotification` if it should remain in `trackedNotifications`. `Notification.expireTimeout` is expressed in seconds in the installed-version docs checked for this skill. Use `expire()` for timeout expiry and `dismiss()` for an explicit user dismissal because they report different close reasons. Re-check these semantics for the installed version. The bundled notification example intentionally renders only plain summary and body text. It does not advertise actions, persistence, inline reply, markup, hyperlinks, or images. ## PAM Never send the PAM prompt text back as the response. The prompt is display state. The response comes from the user's input and may be sent only while `responseRequired` is true. Honor `responseVisible` when deciding whether user input may be shown. Do not use an abbreviated PAM recipe for a lockscreen. Read the complete installed-version `PamContext` page and official lockscreen example. Do not run live PAM or lockscreen checks during routine skill validation. ## greetd and Polkit These components participate in authentication and session authorization. Do not guess method names, lifecycle order, or response objects. Use the installed-version type pages and official examples. Test only in an isolated environment with a recovery path. ## MPRIS, system tray, UPower, Bluetooth, and networking Look up the installed module name and exported types before importing them. Module names and singleton shapes are not uniform across these services. If the installed API cannot support a requested feature, report the blocker. Do not silently delete requested behavior or add guessed adapters and compatibility branches. ## Runtime isolation A nested compositor alone does not isolate D-Bus or per-user services. For service tests, isolate the runtime directory, session bus, and relevant service daemons as well. Static `qmllint` and offscreen loading do not validate service ownership, events, or interaction.