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 # Omarchy shell
The Quickshell desktop runs as a single long-running process out of 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 keeps it running for the graphical session; do not start additional
standalone `quickshell -p` instances for individual components. standalone `quickshell -p` instances for individual components.
@@ -116,7 +116,7 @@ Run `omarchy-restart-shell` after making changes to QML files.
Plugin contract: Plugin contract:
- Each plugin lives in its own directory under - 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). `~/.config/omarchy/plugins/<id>/` (third-party).
- Every plugin ships a `manifest.json` declaring `id`, `kinds`, - Every plugin ships a `manifest.json` declaring `id`, `kinds`,
`activation`, and `entryPoints`. The full schema is in `activation`, and `entryPoints`. The full schema is in
@@ -137,7 +137,7 @@ IPC:
plugins can register additional IPC targets (the bar registers `bar`, plugins can register additional IPC targets (the bar registers `bar`,
the background switcher registers `image-selector`). 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 unicode characters. The `Write` and `Edit` tools strip multi-byte
codepoints in some positions — do **not** rewrite widget files wholesale codepoints in some positions — do **not** rewrite widget files wholesale
through those tools. For glyph fixes, use the targeted `Edit` tool with 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 exit 1
fi 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 \ perl -MCwd=abs_path -MEncode=encode,decode -MSocket -MIO::Handle \
-e ' -e '
+1 -1
View File
@@ -7,7 +7,7 @@
set -e set -e
CONFIG_FILE="$HOME/.config/omarchy/shell.json" 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 position=$1
if [[ ! $position =~ ^(top|bottom|left|right)$ ]]; then if [[ ! $position =~ ^(top|bottom|left|right)$ ]]; then
+1 -1
View File
@@ -8,7 +8,7 @@ StartLimitBurst=5
[Service] [Service]
Type=exec Type=exec
Environment=OMARCHY_PATH=%h/.local/share/omarchy 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 Restart=always
RestartSec=2 RestartSec=2
Slice=session-graphical.slice 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 ├── config/ # Default config templates
├── themes/ # Stock themes ├── themes/ # Stock themes
├── default/ # System defaults ├── default/ # System defaults
├── shell/ # Omarchy shell source and defaults
├── migrations/ # Update migrations ├── migrations/ # Update migrations
└── install/ # Installation scripts └── install/ # Installation scripts
``` ```
**Reading `~/.local/share/omarchy/` is SAFE and useful** - do it freely to: **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)` - 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 - Check stock theme files to copy for customization
- Reference default hyprland settings: `cat ~/.local/share/omarchy/default/hypr/*` - 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[] ~/.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 The shell hot-reloads `shell.json` on save — no restart needed for layout
@@ -375,7 +376,7 @@ omarchy reminder clear
## Out of Scope ## Out of Scope
This skill intentionally does not cover Omarchy source development. Do not use this skill for: 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 - Creating or editing migrations
- Running `omarchy dev ...` commands - Running `omarchy dev ...` commands
+1 -1
View File
@@ -36,7 +36,7 @@ first call.
(loaded by `shell summon`, unloaded by `shell hide`). On-demand (loaded by `shell summon`, unloaded by `shell hide`). On-demand
plugins can set `keepLoaded: true` to survive between summons. 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 ## 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 done
if ! systemctl --user is-active --quiet omarchy-shell.service && omarchy-cmd-present quickshell; then 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 fi
systemctl --user enable --now omarchy-shell.service || true 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 - third-party plugins can be loaded from disk without changing any source
code in Omarchy itself code in Omarchy itself
The runtime layout in this branch: The runtime layout:
``` ```
default/quickshell/omarchy-shell/ shell/
shell.qml entry point (ShellRoot) shell.qml entry point (ShellRoot)
shell-defaults.json canonical out-of-the-box config shell-defaults.json canonical out-of-the-box config
services/ services/
@@ -94,7 +94,7 @@ The full schema lives in `services/PluginRegistry.qml`.
3. Enable the plugin with `omarchy-shell shell setPluginEnabled <id> true`. 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. 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. are discovered the same way and cannot be disabled.
## IPC contract ## IPC contract
@@ -118,14 +118,14 @@ running a separate Quickshell instance.
Direct invocation: 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 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 session and restarts it if it exits. Use `omarchy-restart-shell` to reload
the long-running shell process. 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 forwards IPC calls to the running service. It does not start the shell; the
systemd unit owns the shell lifecycle. systemd unit owns the shell lifecycle.
@@ -577,7 +577,7 @@ Item {
Process { Process {
id: screenRecordingProc 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 { stdout: StdioCollector {
waitForEnd: true waitForEnd: true
onStreamFinished: root.updateIndicator("screenRecording", text) onStreamFinished: root.updateIndicator("screenRecording", text)
@@ -586,7 +586,7 @@ Item {
Process { Process {
id: notificationSilencingProc 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 { stdout: StdioCollector {
waitForEnd: true waitForEnd: true
onStreamFinished: root.updateIndicator("notifications", text) onStreamFinished: root.updateIndicator("notifications", text)
@@ -548,7 +548,7 @@ Item {
// Poll the weather pill text/class every minute. Local to this widget. // Poll the weather pill text/class every minute. Local to this widget.
Process { Process {
id: weatherProc 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 { stdout: StdioCollector {
waitForEnd: true waitForEnd: true
onStreamFinished: root.updateWeather(text) onStreamFinished: root.updateWeather(text)
@@ -152,7 +152,7 @@ Item {
} }
FileView { 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()) onLoaded: root.loadEmojis(text())
} }
PanelWindow { PanelWindow {
@@ -61,7 +61,7 @@ Item {
function scriptPath(name) { function scriptPath(name) {
var base = omarchyPath || Quickshell.env("OMARCHY_PATH") || (Quickshell.env("HOME") + "/.local/share/omarchy") 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() { function focusPicker() {
@@ -37,13 +37,16 @@ Item {
var env = Quickshell.env("OMARCHY_PATH") var env = Quickshell.env("OMARCHY_PATH")
if (env) return env if (env) return env
var dir = String(Quickshell.shellDir || "") var dir = String(Quickshell.shellDir || "")
if (dir.indexOf("/default/quickshell/omarchy-shell") !== -1) while (dir.length > 1 && dir.charAt(dir.length - 1) === "/")
return dir.substring(0, dir.indexOf("/default/quickshell/omarchy-shell")) 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" return Quickshell.env("HOME") + "/.local/share/omarchy"
} }
readonly property string home: Quickshell.env("HOME") readonly property string home: Quickshell.env("HOME")
readonly property string userConfigPath: home + "/.config/omarchy/shell.json" 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 -------------------------------------------------- // ---------------- theme --------------------------------------------------
// Bar settings deliberately isn't a themable surface in shell.toml it // Bar settings deliberately isn't a themable surface in shell.toml it
@@ -26,13 +26,17 @@ ShellRoot {
var env = Quickshell.env("OMARCHY_PATH") var env = Quickshell.env("OMARCHY_PATH")
if (env) return env if (env) return env
var dir = String(Quickshell.shellDir || "") var dir = String(Quickshell.shellDir || "")
if (dir.indexOf("/default/quickshell/omarchy-shell") !== -1) while (dir.length > 1 && dir.charAt(dir.length - 1) === "/")
return dir.substring(0, dir.indexOf("/default/quickshell/omarchy-shell")) 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" return home + "/.local/share/omarchy"
} }
property string omarchyPath: deriveOmarchyPath() property string omarchyPath: deriveOmarchyPath()
readonly property string firstPartyPluginsDir: omarchyPath + "/default/quickshell/omarchy-shell/plugins" readonly property string shellPath: omarchyPath + "/shell"
readonly property string defaultsPath: omarchyPath + "/default/quickshell/omarchy-shell/shell-defaults.json" readonly property string firstPartyPluginsDir: shellPath + "/plugins"
readonly property string defaultsPath: shellPath + "/shell-defaults.json"
readonly property string userConfigPath: home + "/.config/omarchy/shell.json" readonly property string userConfigPath: home + "/.config/omarchy/shell.json"
// Bundled fallback so the shell can start even when shell-defaults.json is // Bundled fallback so the shell can start even when shell-defaults.json is