How Omarchy Manages User Services like bt-agent and omarchy-sleep-lock
Omarchy manages user services such as bt-agent and omarchy-sleep-lock through systemd user units that are automatically enabled during first-run setup and maintained via version-specific migration scripts.
Omarchy, Basecamp's opinionated Linux desktop environment, delegates background helper management to systemd user-level units rather than system-wide services. This architecture ensures that utilities like the Bluetooth pairing agent and session lock handler start only when a graphical session is active and run with user privileges instead of root.
User-Level Systemd Unit Definitions
Both services are defined as user-level systemd units located in default/systemd/user/, allowing them to integrate with the graphical session lifecycle.
Bluetooth Pairing Agent Service
The bt-agent.service provides automatic Bluetooth pairing acceptance without requiring manual PIN entry. Defined in default/systemd/user/bt-agent.service, the unit includes hardware and dependency guards:
[Unit]
Description=Bluetooth pairing agent (auto-accept)
ConditionPathIsDirectory=/sys/class/bluetooth
ExecCondition=/usr/bin/systemctl is-active --quiet bluetooth.service
After=dbus.socket
Requires=dbus.socket
[Service]
Type=simple
ExecStart=/usr/bin/bt-agent -c NoInputNoOutput
Restart=on-failure
RestartSec=2
[Install]
WantedBy=graphical-session.target
The ConditionPathIsDirectory directive ensures the service skips activation on machines lacking Bluetooth hardware, while ExecCondition verifies the system Bluetooth daemon is active before launching.
Session Sleep Lock Service
The omarchy-sleep-lock.service secures the session before system suspension. Located at default/systemd/user/omarchy-sleep-lock.service, it invokes the omarchy-system-sleep-monitor helper:
[Unit]
Description=Lock Omarchy before suspend
After=dbus.socket wayland-session-waitenv.service
Requires=dbus.socket
PartOf=graphical-session.target
ConditionEnvironment=OMARCHY_PATH
ConditionEnvironment=WAYLAND_DISPLAY
[Service]
Type=simple
ExecStart=/usr/bin/omarchy-system-sleep-monitor
Restart=always
RestartSec=2
[Install]
WantedBy=graphical-session.target
The ConditionEnvironment checks ensure the service only runs within a proper Omarchy Wayland session, preventing activation in incompatible environments.
First-Run Installation and Enablement
During initial setup, the script install/user/first-run/enable-user-units.sh iterates over a hard-coded list of services including bt-agent.service and omarchy-sleep-lock.service. It calls the helper function enable_user_unit defined in install/lib.sh, which executes:
systemctl --user enable --now "$1"
This command installs the units into $HOME/.config/systemd/user/ and immediately starts them. Because both units specify WantedBy=graphical-session.target, they automatically activate when the user logs into the graphical session and terminate upon logout.
Upgrade Handling and Migration Scripts
Omarchy preserves service continuity across updates through targeted migration scripts. When the repository layout changes, the upgrade script bin/omarchy-upgrade-to-quattro retires obsolete unit copies and re-invokes enable_user_unit to install current versions.
For the sleep-lock service specifically, migrations/1785608166.sh performs health checks on existing user configurations. It attempts to reset failed states, restart the service, and verify it reaches active status. If the unit remains unhealthy, the script logs actionable errors and attempts clean termination, ensuring the user environment stays synchronized with the repository.
Runtime Conditions and Dependencies
The Bluetooth agent employs conditional activation to avoid unnecessary resource consumption. The ConditionPathIsDirectory=/sys/class/bluetooth check gates startup on hardware presence, while ExecCondition validates the system bluetooth.service is running. These conditions prevent restart loops on Bluetooth-less systems, as validated by test/shell.d/bluetooth-test.sh.
The sleep-lock service exposes its state through standard systemd interfaces. Omarchy shell scripts query this status programmatically; for example, omarchy-debug-idle uses systemctl --user status omarchy-sleep-lock.service to verify lock readiness before suspending.
Testing and Validation
Omarchy ships a comprehensive test suite in test/shell.d/ that guards against regressions:
systemd-test.shvalidates that both units appear in the enabled user units list and that stale copies are properly reset during upgrades.bluetooth-test.shconfirmsbt-agent.servicecorrectly skips activation when Bluetooth hardware is absent.sleep-lock-test.shandsleep-lock-environment-migration-test.shverify the service respects environment variables (OMARCHY_PATH,WAYLAND_DISPLAY) and handles start/stop transitions cleanly.
These tests run under ./test/shell and assert the integrity of the user service management pipeline.
Manual Service Management
While Omarchy automates enablement, you can interact with these services directly using systemctl --user:
Enable and start the Bluetooth agent manually:
systemctl --user enable --now bt-agent.service
systemctl --user status bt-agent.service
Verify the sleep-lock service state:
systemctl --user show --property=ActiveState --value omarchy-sleep-lock.service
If the service is inactive, start it with:
systemctl --user enable --now omarchy-sleep-lock.service
Summary
- Omarchy defines user services in
default/systemd/user/as systemd user units tied tographical-session.target. bt-agent.serviceauto-accepts Bluetooth pairings only when hardware is present and the system Bluetooth service is active.omarchy-sleep-lock.servicelocks the session before suspend, requiringOMARCHY_PATHandWAYLAND_DISPLAYenvironment variables.- First-run installation occurs via
install/user/first-run/enable-user-units.sh, which enables and starts units immediately. - Migration scripts like
migrations/1785608166.shandbin/omarchy-upgrade-to-quattrohandle upgrades by retiring old units and re-enabling current versions. - Comprehensive tests in
test/shell.d/validate enablement, conditional logic, and migration behavior.
Frequently Asked Questions
What triggers bt-agent to start?
The bt-agent.service unit starts automatically when you log into a graphical session, provided the machine has Bluetooth hardware (/sys/class/bluetooth exists) and the system bluetooth.service is active. These checks prevent the service from attempting to start on incompatible systems or when Bluetooth is disabled.
How does Omarchy ensure services survive upgrades?
When upgrading to a new version, the script bin/omarchy-upgrade-to-quattro removes obsolete unit files and re-runs enable_user_unit for each service. Additionally, migration scripts like migrations/1785608166.sh verify service health, reset failed states, and ensure the units are active after the upgrade completes.
Can I disable omarchy-sleep-lock if I don't want automatic locking?
Yes. You can disable the service for your user without affecting system functionality by running systemctl --user disable omarchy-sleep-lock.service. However, this will prevent Omarchy from automatically locking your session before suspend, which may have security implications.
Where are the user service files actually stored?
Omarchy keeps source unit files in default/systemd/user/ within the repository. When enabled, systemd creates symlinks in your home directory under $HOME/.config/systemd/user/, which is the standard location for user-level systemd configurations.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →