Skip to content

feat(linux): add systemd --user discovery to Services.ts status/doc - #1705

Open
takanorinishida wants to merge 1 commit into
danielmiessler:mainfrom
takanorinishida:feature/linux/services-status
Open

feat(linux): add systemd --user discovery to Services.ts status/doc#1705
takanorinishida wants to merge 1 commit into
danielmiessler:mainfrom
takanorinishida:feature/linux/services-status

Conversation

@takanorinishida

Copy link
Copy Markdown

What's broken

Services.ts's own doc comment says status "reports reality, not a hand-maintained guess" — but loadedLabels()/findPlist()/cadenceOf() only ever look at launchctl/~/Library/LaunchAgents, so on Linux every one of the 16 registered services reports "✗ missing" regardless of what's actually installed. After the systemd backends for WorkSweep (#1692) and DerivedSync/CommitmentSweep/UsageAggregator/CodexUpdate (#1704) land, that's no longer true — but Services.ts has no way to know it.

Fix

Adds a process.platform branch to the three discovery functions:

  • loadedLabels(): darwin parses launchctl list; linux parses systemctl --user list-units --all --type=service,timer,path, stripping the .service/.timer/.path suffix so a label counts as loaded from any of its unit files (same "loaded, not necessarily running" semantics launchctl list already had).
  • findPlist(): darwin looks for an installed plist then a template in TOOLS/PULSE; linux looks for an installed unit (preferring .timer or .path over .service, since that's where the schedule lives) then a template, falling back to a bare .service for persistent daemons with no timer pairing (pulse — the systemd analog of a RunAtLoad-only launchd job) or a bare non-.template unit (pulse's own manage.sh keeps its systemd source that way, mirroring the plist side's existing dual lookup).
  • cadenceOf(): darwin parses StartInterval/StartCalendarInterval/WatchPaths/RunAtLoad from XML; linux parses PathModified/OnCalendar/OnUnitActiveSec/Type=simple from the ini-style unit file.

install/uninstall need no branch — they just run each service's install: command, which is itself platform-dispatching inside the Install*.ts script; Services.ts never had to know how a service installs itself, only how to tell whether it did.

Services with no Linux port yet (com.lifeos.pulse-menubar, com.lifeos.deriver — both launchd-only by design, deriver explicitly per its own manage-deriver.sh: "Linux/systemd analog is intentionally not implemented") correctly continue to report "✗ missing" on Linux. That's fact, not a regression.

Why this doesn't change macOS behavior

Every deletion in this diff is a function signature line whose body moved unchanged into a renamed *Darwin variant, with the original name now the platform-dispatching wrapper — same pattern used across InstallWorkSweep.ts and the four Install*.ts scripts this depends on.

Verification

Tested on Ubuntu 24.04 / systemd 255 with all 6 currently-installed systemd services live (pulse, derivedsync, worksweep, commitmentsweep, usage-aggregator, codexupdate):

bun Services.ts status
  ● running    at load         Pulse (dashboard server)
  ● running    on file-change  Derived-file sync
  ● running    every 1h        Work sweep
  ● running    daily/scheduled Commitment sweep
  ● running    daily/scheduled Codex update
  ● running    daily/scheduled Usage aggregator

Every cadence string matches the actual installed unit content (OnUnitActiveSec=60min → "every 1h", OnCalendar daily entries → "daily/scheduled", derivedsync's .path PathModified → "on file-change", pulse's Type=simple with no timer/path → "at load"). The 10 not-yet-ported services (Conduit, healthsync, blogdiscovery, etc.) correctly show "✗ missing". bun Services.ts doc also verified — produces the same markdown table shape as the darwin-generated one, reflecting Linux's currently-narrower coverage.

darwin path unaffected: bunx tsc --noEmit shows only pre-existing @types/node-absence noise, no new errors; the 3 renamed *Darwin functions are byte-for-byte identical to their pre-change bodies.

Depends on: #1704 (the 4 installers whose systemd units this reads).

🤖 Generated with Claude Code

Services.ts's own doc comment says status "reports reality, not a
hand-maintained guess" — but loadedLabels()/findPlist()/cadenceOf() only
ever looked at launchctl/~/Library/LaunchAgents, so on Linux every one of
the 16 registered services reported "✗ missing" regardless of what's
actually installed. After the systemd backends landed for WorkSweep
(danielmiessler#1692) and DerivedSync/CommitmentSweep/UsageAggregator/CodexUpdate
(this branch's prior commit upstream), that's no longer true — but
Services.ts had no way to know it.

Adds a process.platform branch to the three discovery functions:

- loadedLabels(): darwin parses `launchctl list`; linux parses
  `systemctl --user list-units --all --type=service,timer,path`,
  stripping the .service/.timer/.path suffix so a label counts as loaded
  from any of its unit files (same "loaded, not necessarily running"
  semantics launchctl list already had).
- findPlist(): darwin looks for an installed plist then a template in
  TOOLS/PULSE; linux looks for an installed unit (preferring .timer or
  .path over .service, since that's where the schedule lives) then a
  template, falling back to a bare .service for persistent daemons with
  no timer pairing (pulse — the systemd analog of a RunAtLoad-only
  launchd job) or a bare non-.template unit (pulse's own manage.sh keeps
  its systemd source that way, mirroring the plist side's existing dual
  lookup).
- cadenceOf(): darwin parses StartInterval/StartCalendarInterval/
  WatchPaths/RunAtLoad from XML; linux parses PathModified/OnCalendar/
  OnUnitActiveSec/Type=simple from the ini-style unit file.

install/uninstall need no branch — they just run each service's
`install:` command, which is itself platform-dispatching inside the
Install*.ts script; Services.ts never had to know how a service installs
itself, only how to tell whether it did.

Services with no Linux port yet (com.lifeos.pulse-menubar,
com.lifeos.deriver — both launchd-only by design, deriver explicitly per
its own manage-deriver.sh: "Linux/systemd analog is intentionally not
implemented") correctly continue to report "✗ missing" on Linux. That's
fact, not a regression — same as before this change, just now for the
right reason instead of a systemic launchd-only blind spot.

Every deletion in this diff is a function signature line whose body
moved unchanged into a renamed *Darwin variant, with the original name
now the platform-dispatching wrapper — same pattern used across
InstallWorkSweep.ts and the four Install*.ts scripts this branch depends
on.

Verified on this host (Ubuntu 24.04, systemd 255) with all 6 currently-
installed systemd services live (pulse, derivedsync, worksweep,
commitmentsweep, usage-aggregator, codexupdate):

  bun Services.ts status
    ● running    at load         Pulse (dashboard server)
    ● running    on file-change  Derived-file sync
    ● running    every 1h        Work sweep
    ● running    daily/scheduled Commitment sweep
    ● running    daily/scheduled Codex update
    ● running    daily/scheduled Usage aggregator

Every cadence string matches the actual installed unit content
(OnUnitActiveSec=60min → "every 1h", OnCalendar daily entries →
"daily/scheduled", the derivedsync .path's PathModified → "on
file-change", pulse's Type=simple with no timer/path → "at load"). The 10
not-yet-ported services (Conduit, healthsync, blogdiscovery, etc.)
correctly show "✗ missing". `bun Services.ts doc` also verified —
produces the same markdown table shape as the darwin-generated one,
just reflecting Linux's currently-narrower coverage.

darwin path unaffected: `bunx tsc --noEmit` shows only pre-existing
@types/node-absence noise, no new errors; the 3 renamed *Darwin
functions are byte-for-byte identical to their pre-change bodies.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant