Add Plugin Library panel (SUPER+SHIFT+I), registry.json with 10 plugins, browse+install UI

swadhinbiswas committed 2 months ago
3f06578
1 parent 4735209
commit 3f06578
4 files changed
+442 -0
▼bin/omarchy-plugins
+87-0
1
+#!/bin/bash
2
+# omarchy-plugins — browse and install plugins from the de-omarchy registry
3
+# Usage: omarchy-plugins [list|install|search|info] [plugin-name]
4
+set -euo pipefail
5
+
6
+REGISTRY="${OMARCHY_PATH:-/usr/share/de-omarchy}/registry.json"
7
+PLUGIN_DIR="$HOME/.config/omarchy/plugins"
8
+
9
+ACTION="${1:-list}"
10
+QUERY="${2:-}"
11
+
12
+log() { printf '\033[1;36m==>\033[0m %s\n' "$*"; }
13
+err() { printf '\033[1;31mERR:\033[0m %s\n' "$*" >&2; exit 1; }
14
+
15
+[[ -f "$REGISTRY" ]] || err "Registry not found at $REGISTRY"
16
+
17
+list_plugins() {
18
+ python3 -c "
19
+import json, sys
20
+with open('$REGISTRY') as f: r = json.load(f)
21
+for p in r.get('plugins', []):
22
+ installed = '$PLUGIN_DIR/' + p['id'].split('.')[-1]
23
+ import os
24
+ status = 'installed' if os.path.isdir(installed) else 'available'
25
+ print(f\" {p['id']:40s} {p['category']:12s} {p['status']:8s} [{status}]\")
26
+"
27
+}
28
+
29
+search_plugins() {
30
+ python3 -c "
31
+import json, sys
32
+with open('$REGISTRY') as f: r = json.load(f)
33
+q = '$QUERY'.lower()
34
+for p in r.get('plugins', []):
35
+ searchable = (p['name'] + ' ' + p['description'] + ' ' + ' '.join(p.get('tags', []))).lower()
36
+ if q in searchable:
37
+ print(f\" {p['id']:40s} {p['name']}\")
38
+ print(f\" {p['description']}\")
39
+ print()
40
+"
41
+}
42
+
43
+show_info() {
44
+ python3 -c "
45
+import json
46
+with open('$REGISTRY') as f: r = json.load(f)
47
+for p in r.get('plugins', []):
48
+ if p['id'] == '$QUERY' or p['name'].lower() == '$QUERY'.lower():
49
+ print(f\"Name: {p['name']}\")
50
+ print(f\"ID: {p['id']}\")
51
+ print(f\"Description: {p['description']}\")
52
+ print(f\"Author: {p['author']}\")
53
+ print(f\"Category: {p['category']}\")
54
+ print(f\"Tags: {', '.join(p.get('tags', []))}\")
55
+ print(f\"Status: {p['status']}\")
56
+ print(f\"Kind: {p['kind']}\")
57
+ print(f\"Install: {p['installCommand']}\")
58
+ exit(0)
59
+print('Plugin not found: $QUERY')
60
+"
61
+}
62
+
63
+install_plugin() {
64
+ local cmd
65
+ cmd=$(python3 -c "
66
+import json
67
+with open('$REGISTRY') as f: r = json.load(f)
68
+for p in r.get('plugins', []):
69
+ if p['id'] == '$QUERY' or p['name'].lower() == '$QUERY'.lower():
70
+ print(p['installCommand'])
71
+ exit(0)
72
+print('NOT_FOUND')
73
+")
74
+ [[ "$cmd" == "NOT_FOUND" ]] && err "Plugin not found: $QUERY"
75
+ log "Installing: $QUERY"
76
+ mkdir -p "$PLUGIN_DIR"
77
+ eval "$cmd"
78
+ log "Done. Restart the shell to load: pkill -x quickshell"
79
+}
80
+
81
+case "$ACTION" in
82
+ list) list_plugins ;;
83
+ search) [[ -z $QUERY ]] && err "Usage: omarchy-plugins search <query>"; search_plugins ;;
84
+ info) [[ -z $QUERY ]] && err "Usage: omarchy-plugins info <plugin-id>"; show_info ;;
85
+ install) [[ -z $QUERY ]] && err "Usage: omarchy-plugins install <plugin-id>"; install_plugin ;;
86
+ *) echo "Usage: omarchy-plugins [list|install|search|info] [plugin-name]" ;;
87
+esac
0
88
▼registry.json
+116-0
1
+{
2
+ "name": "de-omarchy plugins",
3
+ "version": "1.0.0",
4
+ "plugins": [
5
+ {
6
+ "id": "deomarchy.sysmon",
7
+ "name": "System Monitor",
8
+ "description": "CPU, RAM, disk, GPU temp, network in bar",
9
+ "author": "de-omarchy",
10
+ "category": "System",
11
+ "tags": ["monitoring", "bar-widget"],
12
+ "kind": "bar-widget",
13
+ "status": "stable",
14
+ "installCommand": "cp -r shell/plugins/sysmon ~/.config/omarchy/plugins/"
15
+ },
16
+ {
17
+ "id": "deomarchy.docker-status",
18
+ "name": "Docker Status",
19
+ "description": "Running container count, click to open lazydocker",
20
+ "author": "de-omarchy",
21
+ "category": "System",
22
+ "tags": ["docker", "containers", "bar-widget"],
23
+ "kind": "bar-widget",
24
+ "status": "stable",
25
+ "installCommand": "cp -r shell/plugins/docker-status ~/.config/omarchy/plugins/"
26
+ },
27
+ {
28
+ "id": "deomarchy.power-profile",
29
+ "name": "Power Profile",
30
+ "description": "Toggle performance/balanced/powersave",
31
+ "author": "de-omarchy",
32
+ "category": "System",
33
+ "tags": ["power", "battery", "bar-widget"],
34
+ "kind": "bar-widget",
35
+ "status": "stable",
36
+ "installCommand": "cp -r shell/plugins/power-profile ~/.config/omarchy/plugins/"
37
+ },
38
+ {
39
+ "id": "deomarchy.wallpaper-manager",
40
+ "name": "Wallpaper Manager",
41
+ "description": "Per-monitor wallpaper selection from theme backgrounds",
42
+ "author": "de-omarchy",
43
+ "category": "Desktop",
44
+ "tags": ["wallpaper", "panel"],
45
+ "kind": "panel",
46
+ "status": "stable",
47
+ "installCommand": "cp -r shell/plugins/wallpaper-manager ~/.config/omarchy/plugins/"
48
+ },
49
+ {
50
+ "id": "deomarchy.system-overview",
51
+ "name": "System Overview",
52
+ "description": "Full system stats panel (CPU/RAM/disk/GPU/network/uptime)",
53
+ "author": "de-omarchy",
54
+ "category": "System",
55
+ "tags": ["monitoring", "panel"],
56
+ "kind": "panel",
57
+ "status": "stable",
58
+ "installCommand": "cp -r shell/plugins/system-overview ~/.config/omarchy/plugins/"
59
+ },
60
+ {
61
+ "id": "deomarchy.monitor-manager",
62
+ "name": "Monitor Manager",
63
+ "description": "Visual multi-monitor arrangement (drag, rotate, scale)",
64
+ "author": "de-omarchy",
65
+ "category": "Desktop",
66
+ "tags": ["monitor", "display", "panel"],
67
+ "kind": "panel",
68
+ "status": "stable",
69
+ "installCommand": "cp -r monitor-manager ~/.config/omarchy/plugins/ && ln -sf ~/.config/omarchy/plugins/monitor-manager/shell.qml ~/.config/omarchy/plugins/monitor-manager/main.qml"
70
+ },
71
+ {
72
+ "id": "lacuna.shell-suite",
73
+ "name": "Lacuna",
74
+ "description": "Complete visual shell with custom bar, sidebar, system controls",
75
+ "author": "OldJobobo",
76
+ "category": "Desktop",
77
+ "tags": ["bar", "quickshell", "suite"],
78
+ "kind": "suite",
79
+ "status": "beta",
80
+ "installCommand": "git clone https://github.com/OldJobobo/lacuna-omarchy-plugins.git \"$HOME/lacuna\" && cd \"$HOME/lacuna\" && ./scripts/lacuna"
81
+ },
82
+ {
83
+ "id": "omarchy.omni",
84
+ "name": "Omni",
85
+ "description": "AI-powered launcher and productivity tools",
86
+ "author": "bjarneo",
87
+ "category": "Productivity",
88
+ "tags": ["launcher", "ai"],
89
+ "kind": "plugin",
90
+ "status": "stable",
91
+ "installCommand": "git clone https://github.com/bjarneo/omarchy-shell-plugins.git \"$HOME/omarchy-plugins\" && cd \"$HOME/omarchy-plugins\" && ./install.sh omni"
92
+ },
93
+ {
94
+ "id": "omarchy.quickapps-hud",
95
+ "name": "QuickApps HUD",
96
+ "description": "Quick application launcher with HUD overlay",
97
+ "author": "bjarneo",
98
+ "category": "Desktop",
99
+ "tags": ["launcher", "quickshell"],
100
+ "kind": "plugin",
101
+ "status": "stable",
102
+ "installCommand": "git clone https://github.com/bjarneo/omarchy-shell-plugins.git \"$HOME/omarchy-plugins\" && cd \"$HOME/omarchy-plugins\" && ./install.sh quickapps-hud"
103
+ },
104
+ {
105
+ "id": "omarchy.overview",
106
+ "name": "System Overview",
107
+ "description": "System resource monitor with process list",
108
+ "author": "AyushKr2003",
109
+ "category": "System",
110
+ "tags": ["monitoring", "system"],
111
+ "kind": "plugin",
112
+ "status": "stable",
113
+ "installCommand": "git clone https://github.com/AyushKr2003/omarchy-overview.git \"$HOME/omarchy-overview\" && cd \"$HOME/omarchy-overview\" && ./install.sh"
114
+ }
115
+ ]
116
+}
0
117
▼shell/plugins/plugin-library/Panel.qml
+226-0
1
+import QtQuick
2
+import Quickshell
3
+import Quickshell.Io
4
+import qs.Commons
5
+import qs.Ui
6
+
7
+Panel {
8
+ id: root
9
+ moduleName: "deomarchy.plugin-library"
10
+
11
+ property var plugins: []
12
+ property int selectedIndex: -1
13
+ property string statusText: ""
14
+ property bool installing: false
15
+
16
+ implicitWidth: 520
17
+ implicitHeight: 600
18
+
19
+ Component.onCompleted: loadRegistry()
20
+
21
+ function loadRegistry() {
22
+ var path = Quickshell.env("HOME") + "/.config/omarchy/plugins/registry.json"
23
+ var fallback = (Quickshell.env("OMARCHY_PATH") || "/usr/share/de-omarchy") + "/registry.json"
24
+ registryProc.command = ["bash", "-c", "cat " + path + " 2>/dev/null || cat " + fallback + " 2>/dev/null || echo '{\"plugins\":[]}'"]
25
+ registryProc.running = true
26
+ }
27
+
28
+ Process {
29
+ id: registryProc
30
+ running: false
31
+ stdout: SplitParser {
32
+ onRead: function(line) {
33
+ try {
34
+ var data = JSON.parse(String(line).trim())
35
+ if (data && data.plugins) root.plugins = data.plugins
36
+ } catch(e) {}
37
+ }
38
+ }
39
+ }
40
+
41
+ Process {
42
+ id: installProc
43
+ running: false
44
+ onRunningChanged: {
45
+ if (!running) {
46
+ root.installing = false
47
+ root.statusText = root.installExitCode === 0 ? "Installed!" : "Install failed"
48
+ timer.restart()
49
+ }
50
+ }
51
+ property int installExitCode: 0
52
+ onExited: function(code) { installExitCode = code }
53
+ }
54
+
55
+ Timer {
56
+ id: timer
57
+ interval: 3000
58
+ onTriggered: root.statusText = ""
59
+ }
60
+
61
+ function installPlugin(plugin) {
62
+ if (root.installing) return
63
+ root.installing = true
64
+ root.statusText = "Installing " + plugin.name + "..."
65
+ var pluginDir = Quickshell.env("HOME") + "/.config/omarchy/plugins"
66
+ installProc.command = ["bash", "-c", "mkdir -p " + pluginDir + " && " + plugin.installCommand]
67
+ installProc.running = true
68
+ }
69
+
70
+ Column {
71
+ anchors.fill: parent
72
+ anchors.margins: 16
73
+ spacing: 12
74
+
75
+ Row {
76
+ width: parent.width
77
+ spacing: 12
78
+
79
+ Text {
80
+ text: "Plugin Library"
81
+ color: Color.foreground
82
+ font.family: root.bar ? root.bar.fontFamily : Style.font.family
83
+ font.pixelSize: 20
84
+ font.bold: true
85
+ anchors.verticalCenter: parent.verticalCenter
86
+ }
87
+
88
+ Item { width: 1; height: 1 }
89
+
90
+ Rectangle {
91
+ width: statusText.length > 0 ? statusLabel.implicitWidth + 20 : 0
92
+ height: 24
93
+ radius: 12
94
+ color: installing ? Qt.rgba(0.2, 0.5, 0.9, 0.3) : Qt.rgba(0.2, 0.8, 0.3, 0.3)
95
+ visible: statusText.length > 0
96
+ anchors.verticalCenter: parent.verticalCenter
97
+
98
+ Text {
99
+ id: statusLabel
100
+ anchors.centerIn: parent
101
+ text: root.statusText
102
+ color: Color.foreground
103
+ font.family: root.bar ? root.bar.fontFamily : Style.font.family
104
+ font.pixelSize: 11
105
+ }
106
+ }
107
+ }
108
+
109
+ Text {
110
+ text: plugins.length + " plugins available"
111
+ color: Color.subtext
112
+ font.family: root.bar ? root.bar.fontFamily : Style.font.family
113
+ font.pixelSize: 12
114
+ }
115
+
116
+ ListView {
117
+ id: listView
118
+ width: parent.width
119
+ height: parent.height - 80
120
+ clip: true
121
+ spacing: 8
122
+ model: root.plugins
123
+
124
+ delegate: Rectangle {
125
+ required property var modelData
126
+ required property int index
127
+ width: listView.width
128
+ height: 90
129
+ radius: 8
130
+ color: index === root.selected ? Qt.rgba(Color.accent.r, Color.accent.g, Color.accent.b, 0.15) : Qt.rgba(1, 1, 1, 0.05)
131
+ border.color: index === root.selected ? Color.accent : Qt.rgba(1, 1, 1, 0.1)
132
+ border.width: index === root.selected ? 1 : 0
133
+
134
+ Column {
135
+ anchors.fill: parent
136
+ anchors.margins: 10
137
+ spacing: 4
138
+
139
+ Row {
140
+ width: parent.width
141
+ spacing: 8
142
+
143
+ Rectangle {
144
+ width: 36; height: 36; radius: 8
145
+ color: Qt.rgba(0.4, 0.5, 0.9, 0.2)
146
+ Text {
147
+ anchors.centerIn: parent
148
+ text: modelData.name ? modelData.name.charAt(0) : "?"
149
+ color: Color.foreground
150
+ font.family: root.bar ? root.bar.fontFamily : Style.font.family
151
+ font.pixelSize: 16
152
+ font.bold: true
153
+ }
154
+ }
155
+
156
+ Column {
157
+ width: parent.width - 120
158
+ spacing: 2
159
+
160
+ Text {
161
+ text: modelData.name || "Unknown"
162
+ color: Color.foreground
163
+ font.family: root.bar ? root.bar.fontFamily : Style.font.family
164
+ font.pixelSize: 13
165
+ font.bold: true
166
+ elide: Text.ElideRight
167
+ }
168
+
169
+ Text {
170
+ text: modelData.description || ""
171
+ color: Color.subtext
172
+ font.family: root.bar ? root.bar.fontFamily : Style.font.family
173
+ font.pixelSize: 11
174
+ elide: Text.ElideRight
175
+ width: parent.width
176
+ }
177
+
178
+ Row {
179
+ spacing: 6
180
+ Text {
181
+ text: modelData.author || ""
182
+ color: Color.subtext
183
+ font.family: root.bar ? root.bar.fontFamily : Style.font.family
184
+ font.pixelSize: 10
185
+ }
186
+ Text {
187
+ text: (modelData.tags || []).join(", ")
188
+ color: Color.subtext
189
+ font.family: root.bar ? root.bar.fontFamily : Style.font.family
190
+ font.pixelSize: 10
191
+ }
192
+ }
193
+ }
194
+
195
+ Rectangle {
196
+ width: 60; height: 28; radius: 6
197
+ color: root.installing ? Qt.rgba(1,1,1,0.05) : Qt.rgba(0.3, 0.7, 0.3, 0.3)
198
+ anchors.verticalCenter: parent.verticalCenter
199
+
200
+ Text {
201
+ anchors.centerIn: parent
202
+ text: root.installing ? "..." : "Install"
203
+ color: root.installing ? Color.subtext : Color.foreground
204
+ font.family: root.bar ? root.bar.fontFamily : Style.font.family
205
+ font.pixelSize: 11
206
+ font.bold: true
207
+ }
208
+
209
+ MouseArea {
210
+ anchors.fill: parent
211
+ cursorShape: Qt.PointingHandCursor
212
+ enabled: !root.installing
213
+ onClicked: root.installPlugin(modelData)
214
+ }
215
+ }
216
+ }
217
+ }
218
+
219
+ MouseArea {
220
+ anchors.fill: parent
221
+ onClicked: root.selectedIndex = index
222
+ }
223
+ }
224
+ }
225
+ }
226
+}
0
227
▼shell/plugins/plugin-library/manifest.json
+13-0
1
+{
2
+ "schemaVersion": 1,
3
+ "id": "deomarchy.plugin-library",
4
+ "name": "Plugin Library",
5
+ "version": "1.0.0",
6
+ "author": "de-omarchy",
7
+ "description": "Browse and install plugins from the de-omarchy registry",
8
+ "kinds": ["panel"],
9
+ "entryPoints": {
10
+ "panel": "Panel.qml"
11
+ },
12
+ "keepLoaded": false
13
+}
0
14