Files
claudetools/.claude/standards/gururmm/platform-parity.md
Mike Swanson dd0ef45645 feat: implement agent-os standards system and feature planning tools
- Split CODING_GUIDELINES.md into 19 indexed standards files under .claude/standards/
  - 9 from CODING_GUIDELINES (conventions, powershell, security, api, git, gururmm)
  - 10 from session log tribal knowledge (syncro, ssh, gitea, python, client, gururmm)
- Add .claude/standards/index.yml for cheap relevance-based lookup
- Add /inject-standards command: load targeted standards per task instead of full guidelines
- Add /shape-spec command: pre-implementation spec for GuruRMM features (plan.md,
  shape.md, references.md, standards.md) with mandatory out-of-scope gate
- Add docs/tech-stack.md and docs/mission.md for ClaudeTools API
- Add projects/msp-tools/guru-rmm/docs/tech-stack.md and mission.md for GuruRMM
- Update CLAUDE.md commands table with /inject-standards and /shape-spec

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-16 12:59:49 -07:00

5.5 KiB

name, description, applies-to
name description applies-to
platform-parity All agent features must ship on Windows, Linux, and macOS; silent no-ops on one platform are bugs gururmm

GuruRMM Agent — Platform Parity

All agent features that are not inherently platform-specific must ship on Windows, Linux, and macOS. A feature that silently no-ops on one platform is a gap, not a cross-platform implementation.

The rule

"Add feature X to the agent" means Windows + Linux + macOS. All three, in the same change. No exceptions for convenience. If a real implementation is not feasible on a given platform, add a working stub and a // TODO(platform): <os> — <reason> comment in the same commit. A feature that silently no-ops on one platform without a stub and TODO is a bug, not a gap.

cfg gating — choose the right target

Condition Attribute When to use
Windows only #[cfg(windows)] Windows API (Win32, WMI, SCM, OpenSSH registry)
Linux + macOS #[cfg(unix)] POSIX: nix crate, signals, /proc, /sys, sockets
Linux only #[cfg(target_os = "linux")] /sys/class/thermal, systemd, procfs, D-Bus
macOS only #[cfg(target_os = "macos")] CoreFoundation, IOKit, launchd, NSStatusBar
Build flag #[cfg(feature = "native-service")] Service harness (Windows only in Cargo.toml)

Never use #[cfg(not(windows))] as a proxy for "Linux + macOS works the same" without verifying the macOS codepath. Linux and macOS diverge on /sys, D-Bus, and GUI IPC.

Current parity matrix (as of 2026-05-15)

Feature Windows Linux macOS
CPU / memory / disk / network metrics [OK] [OK] [OK]
Temperature via sysinfo [OK] fallback [WARN] empty if no hwmon [WARN] empty if no sensors
Temperature via LibreHardwareMonitor [OK] primary N/A N/A
Temperature via /sys/class/thermal N/A [GAP] not implemented N/A
User detection (logged-in user) [OK] [OK] nix crate [OK] nix crate
User idle time [OK] GetLastInputInfo [GAP] returns None [GAP] returns None
IPC / tray [OK] named pipe + WinTray [GAP] stub no-op [GAP] stub no-op
Watchdog (process monitor) [OK] native-service [GAP] stub no-op [GAP] stub no-op
Script execution [OK] cmd / PowerShell [OK] bash / sh [OK] bash / sh
Hardware inventory [OK] WMI [OK] /proc + lshw [OK] system_profiler
Auto-updater [OK] full [OK] simpler [OK] simpler
Checks (AV, updates, firewall) [OK] full [WARN] partial stub [WARN] partial stub
Network discovery [OK] [OK] [OK]

Known gaps — priority order

1. Linux temperature collection (agent/src/metrics/mod.rs)

  • sysinfo Components returns empty on most Linux systems (requires kernel hwmon driver exposure).
  • Correct approach: read /sys/class/thermal/thermal_zone*/temp directly (always available on Linux).
  • Pattern:
    #[cfg(target_os = "linux")]
    fn collect_temps_linux() -> (Option<f32>, Option<f32>, Vec<TemperatureReading>) {
        // read /sys/class/thermal/thermal_zone*/temp
        // parse millidegrees, classify by type label in /sys/class/thermal/thermal_zone*/type
    }
    

2. Linux / macOS user idle time (agent/src/metrics/mod.rsget_user_idle_time())

  • Linux: use X11 XScreenSaverQueryInfo (display sessions) or parse /proc/interrupts delta (headless).
  • macOS: use CGEventSourceSecondsSinceLastEventType (IOKit, always available).
  • Stub is acceptable short-term; mark with // TODO(platform): linux/macos idle time.

3. Watchdog on Linux / macOS (agent/src/watchdog/)

  • Windows: Windows Service Control Manager restarts the agent.
  • Linux: systemd Restart=on-failure in the unit file is the correct equivalent — no in-process watchdog needed.
  • macOS: launchd KeepAlive key in the plist.
  • Document the OS-native mechanism in build-agents.sh / installer rather than porting the Rust watchdog.

4. Checks on Linux / macOS (agent/src/checks.rs)

  • Windows-specific checks (Windows Update pending, Windows Defender status, Windows Firewall) have no direct equivalents; that is expected.
  • Cross-platform checks (disk SMART, certificate expiry, open ports) should run on all platforms.
  • Add // TODO(platform): linux/macos — <check name> for each unimplemented cross-platform check.

Cargo.toml dependency discipline

  • Platform-specific crates go in [target.'cfg(...)'.dependencies], never in [dependencies].
  • Keep lhm (LibreHardwareMonitor) and windows-service under cfg(windows).
  • Keep nix under cfg(unix).
  • When adding a new crate, verify it compiles on all three targets before merging. Use the build server for Windows; CI covers Linux. macOS cross-compile via --target aarch64-apple-darwin on Linux (requires osxcross toolchain — see build-agents.sh TODO-MACOS).

Additional notes from past sessions

service.rs must mirror main.rs AppState: On Windows, the agent runs as a Windows Service via a separate entry point in service.rs that constructs AppState independently. Any field added to AppState in main.rs must also be added to the AppState struct literal in service.rs. This has caused Windows-only build failures in the past (missing agent_id field). There is no shared constructor — both sites must be updated manually.

sc.exe over Get-Service: Get-Service silently fails to enumerate GuruRMMAgent even with the exact service name in some session contexts. sc.exe queryex "GuruRMMAgent" is reliable. All PS1-based service checks in agent code use sc.exe query equivalents.