Promote shell to its own top-level directory

This commit is contained in:
David Heinemeier Hansson
2026-05-18 14:56:59 +02:00
parent d782705878
commit 0fe985b45d
83 changed files with 50 additions and 28 deletions
+3 -3
View File
@@ -107,7 +107,7 @@ When testing layer-shell UI, capture the reference and candidate states as separ
# Omarchy shell
The Quickshell desktop runs as a single long-running process out of
`default/quickshell/omarchy-shell/`. The `omarchy-shell.service` user unit
`shell/`. The `omarchy-shell.service` user unit
keeps it running for the graphical session; do not start additional
standalone `quickshell -p` instances for individual components.
@@ -116,7 +116,7 @@ Run `omarchy-restart-shell` after making changes to QML files.
Plugin contract:
- Each plugin lives in its own directory under
`default/quickshell/omarchy-shell/plugins/<id>/` (first-party) or
`shell/plugins/<id>/` (first-party) or
`~/.config/omarchy/plugins/<id>/` (third-party).
- Every plugin ships a `manifest.json` declaring `id`, `kinds`,
`activation`, and `entryPoints`. The full schema is in
@@ -137,7 +137,7 @@ IPC:
plugins can register additional IPC targets (the bar registers `bar`,
the background switcher registers `image-selector`).
Widget files in `plugins/bar/widgets/` contain Nerd Font glyphs as raw
Widget files in `shell/plugins/bar/widgets/` contain Nerd Font glyphs as raw
unicode characters. The `Write` and `Edit` tools strip multi-byte
codepoints in some positions — do **not** rewrite widget files wholesale
through those tools. For glyph fixes, use the targeted `Edit` tool with
+1 -1
View File
@@ -30,7 +30,7 @@ if [[ -z ${OMARCHY_PATH:-} ]]; then
exit 1
fi
SHELL_QML="$OMARCHY_PATH/default/quickshell/omarchy-shell/shell.qml"
SHELL_QML="$OMARCHY_PATH/shell/shell.qml"
perl -MCwd=abs_path -MEncode=encode,decode -MSocket -MIO::Handle \
-e '
+1 -1
View File
@@ -7,7 +7,7 @@
set -e
CONFIG_FILE="$HOME/.config/omarchy/shell.json"
DEFAULTS_FILE="$OMARCHY_PATH/default/quickshell/omarchy-shell/shell-defaults.json"
DEFAULTS_FILE="$OMARCHY_PATH/shell/shell-defaults.json"
position=$1
if [[ ! $position =~ ^(top|bottom|left|right)$ ]]; then
+1 -1
View File
@@ -8,7 +8,7 @@ StartLimitBurst=5
[Service]
Type=exec
Environment=OMARCHY_PATH=%h/.local/share/omarchy
ExecStart=/usr/bin/quickshell -p %h/.local/share/omarchy/default/quickshell/omarchy-shell
ExecStart=/usr/bin/quickshell -p %h/.local/share/omarchy/shell
Restart=always
RestartSec=2
Slice=session-graphical.slice
+4 -3
View File
@@ -51,13 +51,14 @@ This directory contains Omarchy's source files managed by git. Any changes will
├── config/ # Default config templates
├── themes/ # Stock themes
├── default/ # System defaults
├── shell/ # Omarchy shell source and defaults
├── migrations/ # Update migrations
└── install/ # Installation scripts
```
**Reading `~/.local/share/omarchy/` is SAFE and useful** - do it freely to:
- Understand how omarchy commands work: `omarchy theme set --help` or `cat $(which omarchy-theme-set)`
- See default configs before customizing: `cat ~/.local/share/omarchy/default/quickshell/omarchy-shell/shell-defaults.json`
- See default configs before customizing: `cat ~/.local/share/omarchy/shell/shell-defaults.json`
- Check stock theme files to copy for customization
- Reference default hyprland settings: `cat ~/.local/share/omarchy/default/hypr/*`
@@ -154,7 +155,7 @@ inside a single long-running Quickshell process (`omarchy-shell`).
```
~/.config/omarchy/shell.json # User overrides: bar.position, bar.layout, plugins[]
~/.local/share/omarchy/default/quickshell/omarchy-shell/shell-defaults.json # Canonical defaults
~/.local/share/omarchy/shell/shell-defaults.json # Canonical defaults
```
The shell hot-reloads `shell.json` on save — no restart needed for layout
@@ -375,7 +376,7 @@ omarchy reminder clear
## Out of Scope
This skill intentionally does not cover Omarchy source development. Do not use this skill for:
- Editing files in `~/.local/share/omarchy/` (`bin/`, `config/`, `default/`, `themes/`, `migrations/`, etc.)
- Editing files in `~/.local/share/omarchy/` (`bin/`, `config/`, `default/`, `shell/`, `themes/`, `migrations/`, etc.)
- Creating or editing migrations
- Running `omarchy dev ...` commands
+1 -1
View File
@@ -36,7 +36,7 @@ first call.
(loaded by `shell summon`, unloaded by `shell hide`). On-demand
plugins can set `keepLoaded: true` to survive between summons.
Full schema: `services/PluginRegistry.qml`.
Full schema: [`shell/services/PluginRegistry.qml`](../shell/services/PluginRegistry.qml).
## Installing a third-party plugin
+2 -1
View File
@@ -10,7 +10,8 @@ for file in ~/.config/hypr/bindings.lua ~/.config/hypr/bindings/*.lua; do
done
if ! systemctl --user is-active --quiet omarchy-shell.service && omarchy-cmd-present quickshell; then
quickshell kill -p "$OMARCHY_PATH/default/quickshell/omarchy-shell" >/dev/null 2>&1 || true
quickshell kill -p "$OMARCHY_PATH/shell" >/dev/null 2>&1 || true
quickshell kill -p "$OMARCHY_PATH/default/quickshell"/omarchy-shell >/dev/null 2>&1 || true
fi
systemctl --user enable --now omarchy-shell.service || true
+13
View File
@@ -0,0 +1,13 @@
echo "Move omarchy-shell to the top-level shell directory"
mkdir -p ~/.config/systemd/user
cp "$OMARCHY_PATH/config/systemd/user/omarchy-shell.service" ~/.config/systemd/user/omarchy-shell.service
systemctl --user daemon-reload
if omarchy-cmd-present quickshell; then
quickshell kill -p "$OMARCHY_PATH/default/quickshell"/omarchy-shell >/dev/null 2>&1 || true
fi
if systemctl --user is-enabled --quiet omarchy-shell.service || systemctl --user is-active --quiet omarchy-shell.service; then
systemctl --user restart omarchy-shell.service || true
fi
@@ -14,10 +14,10 @@ Hosting everything inside one shell means:
- third-party plugins can be loaded from disk without changing any source
code in Omarchy itself
The runtime layout in this branch:
The runtime layout:
```
default/quickshell/omarchy-shell/
shell/
shell.qml entry point (ShellRoot)
shell-defaults.json canonical out-of-the-box config
services/
@@ -94,7 +94,7 @@ The full schema lives in `services/PluginRegistry.qml`.
3. Enable the plugin with `omarchy-shell shell setPluginEnabled <id> true`.
4. If it's a `bar-widget`, add it to a layout section from the bar editor.
First-party plugins under `default/quickshell/omarchy-shell/plugins/`
First-party plugins under `shell/plugins/`
are discovered the same way and cannot be disabled.
## IPC contract
@@ -118,14 +118,14 @@ running a separate Quickshell instance.
Direct invocation:
```
quickshell ipc -p $OMARCHY_PATH/default/quickshell/omarchy-shell call shell ping
quickshell ipc -p $OMARCHY_PATH/shell call shell ping
```
The `omarchy-shell.service` user unit starts the shell for the graphical
session and restarts it if it exits. Use `omarchy-restart-shell` to reload
the long-running shell process.
A convenience wrapper, [`omarchy-shell`](../../../bin/omarchy-shell),
A convenience wrapper, [`omarchy-shell`](../bin/omarchy-shell),
forwards IPC calls to the running service. It does not start the shell; the
systemd unit owns the shell lifecycle.
@@ -577,7 +577,7 @@ Item {
Process {
id: screenRecordingProc
command: ["bash", "-lc", root.commandWithOmarchyPath(root.shellQuote(root.omarchyPath + "/default/quickshell/omarchy-shell/scripts/indicators/screen-recording.sh"))]
command: ["bash", "-lc", root.commandWithOmarchyPath(root.shellQuote(root.omarchyPath + "/shell/scripts/indicators/screen-recording.sh"))]
stdout: StdioCollector {
waitForEnd: true
onStreamFinished: root.updateIndicator("screenRecording", text)
@@ -586,7 +586,7 @@ Item {
Process {
id: notificationSilencingProc
command: ["bash", "-lc", root.commandWithOmarchyPath(root.shellQuote(root.omarchyPath + "/default/quickshell/omarchy-shell/scripts/indicators/notification-silencing.sh"))]
command: ["bash", "-lc", root.commandWithOmarchyPath(root.shellQuote(root.omarchyPath + "/shell/scripts/indicators/notification-silencing.sh"))]
stdout: StdioCollector {
waitForEnd: true
onStreamFinished: root.updateIndicator("notifications", text)
@@ -548,7 +548,7 @@ Item {
// Poll the weather pill text/class every minute. Local to this widget.
Process {
id: weatherProc
command: ["bash", "-lc", root.bar ? root.bar.commandWithOmarchyPath(root.bar.shellQuote(root.bar.omarchyPath + "/default/quickshell/omarchy-shell/scripts/weather.sh")) : ""]
command: ["bash", "-lc", root.bar ? root.bar.commandWithOmarchyPath(root.bar.shellQuote(root.bar.omarchyPath + "/shell/scripts/weather.sh")) : ""]
stdout: StdioCollector {
waitForEnd: true
onStreamFinished: root.updateWeather(text)
@@ -152,7 +152,7 @@ Item {
}
FileView {
path: root.omarchyPath + "/default/quickshell/omarchy-shell/plugins/emoji-picker/emojis.json"
path: root.omarchyPath + "/shell/plugins/emoji-picker/emojis.json"
onLoaded: root.loadEmojis(text())
}
PanelWindow {
@@ -61,7 +61,7 @@ Item {
function scriptPath(name) {
var base = omarchyPath || Quickshell.env("OMARCHY_PATH") || (Quickshell.env("HOME") + "/.local/share/omarchy")
return base + "/default/quickshell/omarchy-shell/scripts/" + name
return base + "/shell/scripts/" + name
}
function focusPicker() {
@@ -37,13 +37,16 @@ Item {
var env = Quickshell.env("OMARCHY_PATH")
if (env) return env
var dir = String(Quickshell.shellDir || "")
if (dir.indexOf("/default/quickshell/omarchy-shell") !== -1)
return dir.substring(0, dir.indexOf("/default/quickshell/omarchy-shell"))
while (dir.length > 1 && dir.charAt(dir.length - 1) === "/")
dir = dir.substring(0, dir.length - 1)
var suffix = "/shell"
if (dir.length > suffix.length && dir.substring(dir.length - suffix.length) === suffix)
return dir.substring(0, dir.length - suffix.length)
return Quickshell.env("HOME") + "/.local/share/omarchy"
}
readonly property string home: Quickshell.env("HOME")
readonly property string userConfigPath: home + "/.config/omarchy/shell.json"
readonly property string defaultsPath: omarchyPath + "/default/quickshell/omarchy-shell/shell-defaults.json"
readonly property string defaultsPath: omarchyPath + "/shell/shell-defaults.json"
// ---------------- theme --------------------------------------------------
// Bar settings deliberately isn't a themable surface in shell.toml it
@@ -26,13 +26,17 @@ ShellRoot {
var env = Quickshell.env("OMARCHY_PATH")
if (env) return env
var dir = String(Quickshell.shellDir || "")
if (dir.indexOf("/default/quickshell/omarchy-shell") !== -1)
return dir.substring(0, dir.indexOf("/default/quickshell/omarchy-shell"))
while (dir.length > 1 && dir.charAt(dir.length - 1) === "/")
dir = dir.substring(0, dir.length - 1)
var suffix = "/shell"
if (dir.length > suffix.length && dir.substring(dir.length - suffix.length) === suffix)
return dir.substring(0, dir.length - suffix.length)
return home + "/.local/share/omarchy"
}
property string omarchyPath: deriveOmarchyPath()
readonly property string firstPartyPluginsDir: omarchyPath + "/default/quickshell/omarchy-shell/plugins"
readonly property string defaultsPath: omarchyPath + "/default/quickshell/omarchy-shell/shell-defaults.json"
readonly property string shellPath: omarchyPath + "/shell"
readonly property string firstPartyPluginsDir: shellPath + "/plugins"
readonly property string defaultsPath: shellPath + "/shell-defaults.json"
readonly property string userConfigPath: home + "/.config/omarchy/shell.json"
// Bundled fallback so the shell can start even when shell-defaults.json is