Skills Plugins MCP Prompt Model 博客 我的中心

quickshell

Patterns and best practices for building Quickshell-based Wayland desktop shells with QML, covering architecture, services, components, config, state management, animations, and C++ plugin integration

DeepseekModel Curated skill Quality Good · 48 v1.0.0

Get

https://deepseekmodel.com/api/download.php?id=leonardomor-dotfiles-home-dot-config-opencode-skills-quickshell-skill-md&format=skill
Download .skill Standard format with system_prompt and model_config, ready for any agent framework
The actual content of the system_prompt field in the .skill file.
name quickshell description Patterns and best practices for building Quickshell-based Wayland desktop shells with QML, covering architecture, services, components, config, state management, animations, and C++ plugin integration Project Structure Quickshell projects follow a modular architecture: shell.qml # Entry point - extends ShellRoot components/ # Reusable UI primitives controls/ # Interactive widgets (buttons, sliders, switches) containers/ # Layout containers (windows, list views) effects/ # Visual effects (elevation, shadows, masks) modules/ # Feature modules bar/ # Status bar drawers/ # Panel/orchestration system launcher/ # Application launcher dashboard/ # Top panel sidebar/ # Notification sidebar lock/ # Lock screen controlcenter/ # Settings UI services/ # Singleton state managers Audio.qml Notifs.qml Network.qml Hypr.qml Colours.qml ... config/ # Configuration system Config.qml AppearanceConfig.qml ... utils/ # Utility singletons Icons.qml Paths.qml Searcher.qml plugin/ # C++ QML plugins src/Caelestia/ Entry point pattern: // shell.qml import Quickshell import "modules" import "modules/drawers" ShellRoot { Background {} Drawers {} Lock {} Shortcuts {} } QML Conventions Required Pragmas pragma Singleton pragma ComponentBehavior: Bound Naming Conventions Files: PascalCase matching component name ( StyledRect.qml ) Singletons: PascalCase accessed directly by name ( Hypr.qml ) Root id: Always id: root Inline components: component Name: BaseType {} Imports: Use qs. prefix for local modules ( qs.services , qs.config ) Type Annotations readonly property real volume: sink?.audio?.volume ?? 0 function setVolume(newVolume: real): void { // implementation } signal valueChanged(newValue: real) Null Safety // Optional chaining + nullish coalescing sink?.audio?.volume ?? 0 monitor?.name ?? "Unknown" Service Architecture Singleton Service Pattern // services/MyService.qml pragma Singleton pragma ComponentBehavior: Bound import Quickshell Singleton { id: root // State properties readonly property real volume: sink?.audio?.volume ?? 0 // IPC Handler for CLI access IpcHandler { target: "myService" function getVolume(): real { return root.volume } function setVolume(value: real): void { ... } } // Global keyboard shortcut CustomShortcut { name: "volumeUp" description: "Increase volume" onPressed: root.incrementVolume() } // Hot-reload safe persistent state PersistentProperties { id: props property bool enabled: true reloadableId: "myService" } } Communication Patterns Hyprland Socket IPC: // Use Hyprland singleton Quickshell.Hyprland { id: hypr } Connections { target: hypr function onRawEvent(event: string): void { // Handle events } } PipeWire Audio: import Quickshell.Services.Pipewire as Pw Pw.Pipewire { id: pipewire } Connections { target: pipewire.defaultAudioSink function onAudioChanged(): void { // React to volume changes } } D-Bus (Notifications): import Quickshell.Services.Notifications as Notifs Notifs.NotificationServer { onNotification: (notification) => { // Handle notification } } Subprocess Execution: import Quickshell.Io Process { id: process command: ["brightnessctl", "g"] stdout: StdioCollector { onStreamFinished: { const output = text.trim() // Process output } } } File Watching: import Quickshell.Io FileView { path: Paths.config + "/settings.json" watchChanges: true onLoaded: (data) => { // React to file changes } } HTTP Requests (from C++ plugin): import Caelestia Requests.get(url, (response) => { // Handle response }) Component Design System Animation Primitives // Anim.qml - NumberAnimation with M3 curves NumberAnimation { duration: Appearance.anim.durations.normal easing.bezierCurve: Appearance.anim.curves.standard } // CAnim.qml - ColorAnimation variant ColorAnimation { duration: Appearance.anim.durations.normal easing.bezierCurve: Appearance.anim.curves.standard } Styled Base Components // StyledRect.qml Rectangle { color: "transparent" Behavior on color { CAnim {} } } // StyledText.qml Text { renderType: Text.NativeRendering color: Colours.palette.m3onSurface font.family: Appearance.font.family.normal font.pixelSize: Appearance.font.size.normal Behavior on color { CAnim {} } } StateLayer (Material Ripple) // components/StateLayer.qml MouseArea { id: root anchors.fill: parent hoverEnabled: true property color colour: Colours.tPalette.m3onSurface StyledClippingRect { id: layer anchors.fill: parent radius: parent.radius opacity: root.pressed ? 0.12 : root.containsMouse ? 0.08 : 0 color: root.colour Behavior on opacity { Anim {} } } function onClicked(): void {} // Override point onClicked: onClicked() } Material Icon // components/MaterialIcon.qml StyledText { id: root property string icon: "settings" property int fill: 0 property int grade: 0 property int opticalSize: 24 text: root.icon font.family: "Material Symbols Rounded" font.variableAxes: ({ "FILL": root.fill, "GRAD": root.grade, "opsz": root.opticalSize }) } StyledWindow (Wayland Layer Shell) // components/containers/StyledWindow.qml import Quickshell import Quickshell.Wayland PanelWindow { id: root required property string name namespace: `caelestia-${root.name}` layer: Layer.Top margin { top: Config.bar.persistent ? Appearance.padding.normal : 0 } ExclusionMode { id: exclusionMode } } Module Patterns Wrapper/Content/Background Triad // modules/sidebar/Wrapper.qml StyledRect { id: root required property PersistentProperties visibilities implicitWidth: 0 states: State { name: "visible" when: root.visibilities.sidebar && Config.sidebar.enabled PropertyChanges { root.implicitWidth: Config.sidebar.width } } transitions: [ Transition { from: ""; to: "visible" Anim { property: "implicitWidth" } }, Transition { from: "visible"; to: "" Anim { property: "implicitWidth" } } ] // Lazy-loaded content Loader { id: content active: false Component.onCompleted: active = Qt.binding(() => root.visibilities.sidebar || root.state === "visible") sourceComponent: Content { visibilities: root.visibilities } } } // modules/sidebar/Content.qml ColumnLayout { required property PersistentProperties visibilities // Actual UI content } // modules/sidebar/Background.qml ShapePath { // Background shape definition } Per-Screen Instantiation // Create instances for each screen Variants { model: Quickshell.screens Scope { required property ShellScreen modelData StyledWindow { screen: modelData // Window content } PersistentProperties { id: visibilities property bool bar: false property bool sidebar: false Component.onCompleted: Visibilities.load(modelData, visibilities) } } } Lazy Loading // Conditional Loader activation Loader { id: content active: false Component.onCompleted: { active = Qt.binding(() => root.visible || root.animating) } sourceComponent: Content {} } // Timer-delayed initialization Timer { running: true interval: Appearance.anim.durations.extraLarge onTriggered: { content.active = Qt.binding(() => shouldLoad()) } } // LazyLoader for dialogs LazyLoader { function open(): void { activeAsync = true; } function close(): void { rejected(); } FloatingWindow { // Dialog content } } Animation System Implicit Behavior Animations Rectangle { id: root color: Colours.palette.m3surface radius: Appearance.rounding.normal Behavior on color { CAnim {} } Behavior on radius { Anim {} } Behavior on implicitWidth { Anim { duration: Appearance.anim.durations.large } } Behavior on opacity { Anim {} } } Material Design 3 Curves // Standard - for property changes easing.bezierCurve: [0.2, 0, 0, 1] // standard // Emphasized - for exit/close animations easing.bezierCurve: [0.2, 0, 0, 1] // emphasized // Expressive Spatial - for enter/open animations easing.bezierCurve: [0.05, 0.7, 0.1, 1] // expressiveDefaultSpatial Enter vs Exit Curves transitions: [ // Opening: Use expressive spatial for lively entrance Transition { from: ""; to: "visible" Anim { property: "implicitWidth" easing.bezierCurve: Appearance.anim.curves.expressiveDefaultSpatial } }, // Closing: Use emphasized for graceful exit Transition { from: "visible"; to: "" Anim { property: "implicitWidth" easing.bezierCurve: Appearance.anim.curves.emphasized } } ] States/Transitions for Panels Item { id: root implicitHeight: 0 states: State { name: "visible" when: shouldShow PropertyChanges { root.implicitHeight: contentHeight } } transitions: [ Transition { from: ""; to: "visible" Anim { property: "implicitHeight" } }, Transition { from: "visible"; to: "" Anim { property: "implicitHeight" } } ] } Sequential Animations SequentialAnimation { id: expandAnim PropertyAction { target: root; property: "animating"; value: true } Anim { property: "implicitHeight"; to: targetHeight } ScriptAction { script: root.implicitHeight = Qt.binding(() => content.implicitHeight) } PropertyAction { target: root; property: "animating"; value: false } } List Item Remove Animation ListView { delegate: Item { ListView.onRemove: removeAnim.start() SequentialAnimation { id: removeAnim PropertyAction { property: "ListView.delayRemove"; value: true } Anim { property: "x"; to: width * 2 } PropertyAction { property: "ListView.delayRemove"; value: false } } } } Configuration System JsonAdapter + JsonObject // config/Config.qml pragma Singleton import Quickshell.Io Singleton { id: root FileView { id: fileView path: Paths.config + "/shell.json" watchChanges: true onLoaded: (data) => { adapter.json = data Toaster.toast("Config loaded", "", "settings", "success") } } JsonAdapter { id: adapter property AppearanceConfig appearance: AppearanceConfig {} property GeneralConfig general: GeneralConfig {} property BarConfig bar: BarConfig {} // ... more sections } function save(): void { saveTimer.restart() } Timer { id: saveTimer interval: 500 // Debounce onTriggered: { const config = { appearance: adapter.appearance.serialize(), general: adapter.general.serialize(), bar: adapter.bar.serialize() } fileView.setText(JSON.stringify(config, null, 2)) } } } // config/AppearanceConfig.qml JsonObject { property Rounding rounding: Rounding {} property Spacing spacing: Spacing {} component Rounding: JsonObject { property real scale: 1 property int small: 8 * scale property int normal: 12 * scale property int large: 16 * scale
Keywords that activate this skill. Click one to copy it.

This skill does not provide trigger words.

The downloaded .skill package contains the following fields.
Field Description
formatFormat tag (skill/v1)
skill_idUnique skill ID
nameSkill name
versionVersion
descriptionDescription
categoryCategories (array)
trigger_wordsTrigger words
tagsTags
sourceSource
source_urlSource URL (this page)
exported_atExported at (set per download)
system_promptSystem prompt body
model_configModel config: provider / model / temperature / max_tokens / top_p
examplesExamples
install_guideImport guide for Coze / Dify / Claude / custom frameworks
The same skill can be exported in different platform formats.
.skill Standard format with system_prompt and model_config, ready for any agent framework Download
.skillpro Enhanced format with scripts, tools, dependencies and hooks Download
.json Plain JSON export with system_prompt and model parameters only Download
Coze Markdown with frontmatter, for Coze platform import Download
Dify Dify DSL, import directly after creating an app Download

每日精选 Skill 推荐,免费送到你邮箱

输入邮箱,每天接收一个精选 AI Agent 技能推荐。完全免费,持续更新。

提交后我们会发送一封确认邮件,点击邮件里的链接才会开始收信。

完全免费,取消任意时间。我们不会发送垃圾邮件。