The plugin you didn't know you need till you have it. Restores window positions and running apps after reboot or shutdown on Omarchy (Hyprland).
Snapshots live in a SQLite DB at: ${XDG_STATE_HOME:-$HOME/.local/state}/omarchy/session.db.
The plugin is published as an Omarchy bar widget with manifest id
mrpbennett.sesh (kind bar-widget). Use the Omarchy plugin manager instead of
running install.sh by hand.
omarchy plugin add https://github.com/mrpbennett/omarchy-sesh.git --enableWhat happens:
- Omarchy clones the repository into a staging directory.
- It validates the folder against the Omarchy plugin manifest schema
(
omarchy plugin validate); invalid plugins are refused. - It reads the manifest id (
mrpbennett.sesh) and moves the checkout to~/.config/omarchy/plugins/mrpbennett.sesh/. - It rescans shell plugins and, because the manifest declares a bar widget,
asks which bar section to place it in (default
right). - It enables the widget with
omarchy plugin enable mrpbennett.sesh --section <section>.
Verify placement with:
omarchy plugin listTo update a git-managed plugin:
omarchy plugin update mrpbennett.seshTo remove it, see Uninstall.
The bar widget is a button showing a session icon. Opening its panel on a fresh
install runs the plugin's installation check: it verifies the CLI binary, the
two systemd user units, and the version marker. If any are missing, it runs the
bundled install.sh automatically, which deploys (user-level, no sudo):
~/.local/bin/omarchy-sesh~/.config/systemd/user/omarchy-sesh.serviceandomarchy-sesh-autosave.service- marker-delimited pre-shutdown save actions in
~/.config/omarchy/extensions/omarchy-menu.jsonc, preserving any user-customized logout, reboot, and shutdown actions
After installation the widget shows three actions:
- Active — enables periodic autosave (default interval 60s).
- Manual — disables autosave and saves the current session immediately.
- Restore — opens a picker of named sessions to relaunch.
On a fresh install autosave defaults to manual mode. Selecting Active
captures the current desktop once and enables the periodic saver. A restore then
runs at the next graphical login via omarchy-sesh.service; the autosave
service is ordered after it and waits one interval before its first capture.
Saves before logout, reboot, or shutdown happen synchronously so the reboot
snapshot is never superseded by a periodic capture during teardown.
See How it works for the full save/restore behavior and
install.sh/Service.qml for the installation and first-open wiring.
omarchy-sesh save [--label manual|logout] [--name NAME] # snapshot current windows
omarchy-sesh restore [--name NAME] [--dry-run] # restore latest or named snapshot
omarchy-sesh autosave [--interval 60] # periodic save (crash cover)
omarchy-sesh status # list saved sessions
omarchy-sesh list # list named sessions
omarchy-sesh delete --name NAME # delete a named session
omarchy-sesh mode [active|manual] # query or change autosave mode
omarchy-sesh acceptance [--expect-power-save|--expect-restore-failure] # read-only live acceptance evidenceConfig (optional): ${XDG_CONFIG_HOME:-$HOME/.config}/omarchy/sesh/config.json
{
"exclude_classes": ["polkit-gnome-authentication-agent-1"],
"autosave_seconds": 60,
"restore_timeout_seconds": 20,
"snapshot_retention": 5,
"monitor_fallback": "focused"
}exclude_classes must be an array of non-empty strings. Autosave and retention
must be positive integers, and the restore timeout must be at least 2 seconds so
a launch group can retry at least once. monitor_fallback accepts "focused",
"lowest", or a connector-shaped name such as "DP-2"; any other string is
rejected rather than treated as an unknown monitor. Each retention slot applies
separately to complete and diagnostic snapshots.
Unknown settings, invalid JSON, and invalid values are reported the same way
everywhere but acted on differently, because a bad config must never cost you a
session. restore fails closed: it reports the error, exits 2, and changes
nothing, and its service does not restart-loop. save and autosave log the
error and continue with the built-in defaults, so a typo cannot skip the logout
snapshot or silently stop periodic saves. A file that cannot be read at all is
treated as transient: every command logs it and continues with the defaults.
hyprctl— queried (-j) for clients, monitors, and workspaces, and invoked to relaunch/place windows during restore.bash— runsinstall.sh/uninstall.sh.python3(stdlib only:sqlite3,json,shlex) — implements theomarchy-seshCLI./proc/<pid>/{cmdline,cwd}— read directly to capture each window's launch command and working directory.- systemd user units (
omarchy-sesh.service,omarchy-sesh-autosave.service) — installed to drive restore-on-login and periodic autosave.
No network calls and no non-stdlib QML imports. See Requirements for version constraints.
Save (omarchy-sesh save) queries clients, monitors, and workspaces through
hyprctl -j, filters out unmapped windows and excluded classes, and reads each
remaining window's real command line and cwd from /proc/<pid>/{cmdline,cwd}.
Position, size, workspace, monitor connector and description, and
floating/fullscreen/pinned state are captured alongside the launch command and
written as one sessions row plus window and workspace-layout rows in the
SQLite DB. Complete Hyprland group membership and member order are translated
from live addresses to snapshot-local metadata. Windows sharing a saved PID are
kept as one launch group. By default, the latest five complete and five
diagnostic snapshots are retained; retention is configurable.
Complete command lines can contain credentials supplied as arguments. The
state and log directories are therefore owner-only (0700), and runtime state
files, including the SQLite database and sidecars, are owner-only (0600). The
installer and CLI repair older permissive modes automatically. Restore failure
logs omit launch commands; restore --dry-run intentionally prints them to the
calling terminal for inspection.
Named save (omarchy-sesh save --name NAME) captures the same state as a
manual save and assigns it a unique name. Named sessions are independent from
the automatic boot snapshot: they are retained until explicitly deleted and
are restored only with omarchy-sesh restore --name NAME. omarchy-sesh list
shows named sessions and omarchy-sesh delete --name NAME removes a name and
its saved window state. Saving an existing name fails; delete it before using
that name again. Names may contain internal spaces but cannot be empty, padded
with whitespace, contain control characters, or exceed 128 characters.
The panel's Restore action lists these named sessions; create them from the
CLI until a named-save panel action is added.
Restore (omarchy-sesh restore) loads the most recent complete session;
a healthy empty session intentionally restores nothing. An advisory lock
serializes restore and save operations. Existing windows are consumed
one-to-one using class, title, and workspace, and class multiplicities prevent
false already-restored matches. All missing saved PID groups launch immediately
via Hyprland's Lua dispatch API, then windows are matched and placed as they
appear during one shared bounded polling window. If a process does not recreate
all of its saved windows, its command is retried independently. Chromium app-mode
windows are restored individually through
Omarchy's web-app launcher because Chromium does not reopen them from the base
browser command. After matching, eligible nested dwindle workspaces are rebuilt
in one fast Lua evaluation: one seed remains on the target workspace while the
other leaves pass through a temporary staging workspace. Focus, insertion
direction, and split ratios recreate the saved geometry, which is then verified.
Eligible two-window dwindle workspaces set their saved split ratio directly and
also verify both resulting rectangles, so a 30/70 split is not silently accepted
as Hyprland's default 50/50 split.
Each saved workspace returns to the same connected monitor; renamed or rewired
outputs are identified by monitor description. Workspaces from disconnected
displays use the configured fallback: the focused monitor then the lowest
monitor ID by default, the lowest monitor directly, or a preferred connector.
An unavailable preferred connector safely returns to the default policy.
Floating windows temporarily leave pinned/fullscreen state when necessary,
resize before moving, and then return to their saved state. Restore verifies
their final compositor geometry after a short settling interval and reapplies
one mismatched placement pass.
--dry-run prints the launch plan without executing it.
On Hyprland 0.56 or newer, complete and uniquely matched window groups are re-formed in saved member order after placement. Partial or ambiguous groups, unrelated existing groups, and groups containing fullscreen or pinned windows are left unchanged. Hyprland does not expose the saved active tab or lock/deny state; reconstructed groups select their first saved member. Hyprland 0.55 continues to restore the windows without grouping them.
Autosave (omarchy-sesh autosave) waits one interval before its first
capture, then saves periodically (default 60s, configurable). It remains gated
until restore succeeds, so a partial login cannot replace the reboot snapshot,
and refreshes the active Hyprland instance before every capture. Explicitly
selecting Active mode captures the current desktop first when no successful
restore marker exists. A synchronous logout, reboot, or shutdown save closes
the gate before capture so a periodic save cannot supersede it during teardown.
Exact dwindle tree replay, including two-window ratios, requires a schema-v5
snapshot, dwindle:use_active_for_splits = true, dwindle:preserve_split = true,
dwindle:permanent_direction_override = false, every saved tiled window to be
present and uniquely identified, no unrelated tiled occupants, unchanged
workspace dimensions, and geometry with one unambiguous recursive split. Apps
continue to launch in parallel. Replay runs independently per workspace and
restores the focused window or empty workspace afterward; because Hyprland
layout messages act on the focused workspace, a very brief workspace change may
still be visible during login.
Ineligible workspaces retain the guarded two-window and compatible-slot
fallback without moving unrelated windows. Hyprland's stableId is only a live
compositor window-object selector and resets with Hyprland, so ambiguous
same-class windows still depend on title and workspace metadata. See
docs/session-restore-spec.md for the full design rationale and limitations.
When a disconnected display falls back to a monitor with different dimensions,
saved floating coordinates may require manual adjustment.
- Hyprland >= 0.55 (uses the Lua dispatch API)
- python3 (stdlib only — sqlite3, json, shlex)
Exact dwindle tree replay requires Hyprland >= 0.56 with the three dwindle options listed above. Ordinary restore remains available when those conditions are not met.
Omarchy does not run lifecycle hooks when removing plugins. For a plugin installation, uninstall the session services before removing the checkout:
${XDG_CONFIG_HOME:-$HOME/.config}/omarchy/plugins/mrpbennett.sesh/uninstall.sh
omarchy plugin remove mrpbennett.seshFor a direct repository installation, run:
./uninstall.shRemoves every trace: the binary, both systemd user units and their enablement, legacy Hyprland hook, marker-delimited power-menu overrides, session DB, lock, and logs. User-authored configuration is preserved. Idempotent and safe to rerun.
See docs/future-improvements.md for the full roadmap, including live reboot
acceptance, stable window identity, window groups, configuration, and upgrade
coverage.
omarchy-sesh acceptance only reads systemd, Hyprland, and saved session state;
it never saves, restores, changes mode, or powers off. Follow
docs/live-acceptance.md for the controlled reboot, power-menu, and
failure-recovery procedures.
MIT — see LICENSE.