Add systemd --user backend for Atlas on Linux - #1743
Open
schmetti-dev wants to merge 1 commit into
Open
Conversation
Atlas's launchd collector and its com.lifeos.atlas background service had no Linux equivalent - the asset graph simply couldn't discover background services or schedule its own tick on Linux, mirroring the gap PR danielmiessler#1692 fixed for WorkSweep. - collectors/Systemd.ts: reads ~/.config/systemd/user/com.{lifeos,pai}.*.{service,timer} unit files directly (no subprocess - OnUnitActiveSec/OnBootSec/Persistent are plain text in the .timer file), registered alongside launchd in Atlas.ts. Same asset/edge shape as the launchd collector (service + RUNS_ON), so blast/owns/exposed queries work identically regardless of platform. - InstallAtlas.ts + com.lifeos.atlas.{plist,service,timer}.template: Atlas had no installer for its own tick service at all (macOS or Linux) - this adds both backends, mirroring InstallWorkSweep.ts's pattern (bun+gh PATH detection so the github collector resolves gh from the unit's restricted PATH, `loginctl enable-linger` via `id -un` so the Linux timer survives logout). - AtlasEventCapture.hook.ts: added the systemd-equivalent Bash/file matchers (systemctl --user commands, unit-file edits under ~/.config/systemd/user/) alongside the existing launchctl ones. - Launchd.ts: plutil is only called if AGENTS_DIR exists, but a directory existing doesn't imply the platform's own tool does (found testing this PR: a Linux box can have stray com.lifeos.*.plist files under ~/Library/LaunchAgents with no plutil to read them). Wrapped the spawn in try/catch, degrading to null the same way Github.ts already treats a missing `gh` - absent tool is a normal state, not a fault this collector should throw on. Verified end to end on a real Linux host: full atlas sync picks up the systemd collector's services correctly, `atlas tick` and the installed timer both confirmed working via `systemctl --user list-timers`, IntegrityCheck-equivalent manual review found no regressions on the darwin path (only new `if (IS_LINUX)`-shaped branches were added, same invariant danielmiessler#1692 documented).
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Atlas's
launchdcollector and itscom.lifeos.atlasbackground tick service had no Linux equivalent — the asset graph couldn't discover background services or schedule its own reconciliation on Linux at all. Same shape as #1692 (WorkSweep's systemd port): the gap is in the platform-specific scheduling/discovery layer, not the core logic.collectors/Systemd.ts(new) — reads~/.config/systemd/user/com.{lifeos,pai}.*.{service,timer}unit files directly (plain-text parse, no subprocess —OnUnitActiveSec/OnBootSec/Persistentare just INI keys in the.timerfile). Registered alongsidelaunchdinAtlas.ts. Produces the identical asset/edge shape (service+RUNS_ON) soblast/owns/exposedqueries work the same regardless of platform.InstallAtlas.ts+com.lifeos.atlas.{plist,service,timer}.template(new) — Atlas had no installer for its own tick service on either platform. Added both backends, mirroringInstallWorkSweep.ts's pattern: bun+gh PATH detection (so thegithubcollector'sghcalls resolve inside the unit's restricted PATH) andloginctl enable-lingerviaid -unso the Linux timer survives logout.AtlasEventCapture.hook.ts— added the systemd-equivalent Bash/file matchers (systemctl --usercommands, unit-file edits under~/.config/systemd/user/) alongside the existing launchctl ones.Launchd.ts— small robustness fix found while testing this on a real Linux box:plutilis only called ifAGENTS_DIRexists, but a directory existing doesn't imply the platform's own tool does (a Linux machine can have straycom.lifeos.*.plistfiles under~/Library/LaunchAgents— e.g. left over from cross-platform experimentation — with noplutilbinary to read them). Wrapped the spawn in try/catch, degrading tonullthe same wayGithub.tsalready treats a missinggh— absent tool is a normal state, not a fault this collector should throw on.AtlasSystem.md— documented the new collector and the cross-platform installer.Testing evidence
Verified end-to-end on a real Linux host (Ubuntu, systemd):
Also confirmed the
Launchd.tsfix: before the try/catch,atlas syncthrewExecutable not found in $PATH: "plutil"on a Linux box with 2 straycom.lifeos.*.plistfiles under~/Library/LaunchAgents; after the fix it degrades cleanly (complete: false) instead of aborting the whole sync run.The macOS/launchd path is unchanged — only new
if (IS_LINUX)-shaped branches were added (same invariant #1692 documented), andLaunchd.ts's fix only changes behavior on the ENOENT path, which never fires whenplutilis actually present.🤖 Generated with Claude Code