Platform Specific Code in herdr src/platform: Linux, macOS and Fallback Implementations

The src/platform module in herdr isolates all OS-dependent behavior behind a unified Rust API, providing concrete implementations for Linux via the /proc filesystem, macOS via proc_* syscalls, and no-op stubs for unsupported systems.

herdr is a Rust-based process management and automation tool that requires deep integration with operating system primitives for clipboard access, process inspection, and desktop notifications. To maintain cross-platform compatibility without scattering conditional compilation directives throughout the codebase, the project centralizes all platform specific code in the src/platform directory, exposing a consistent interface defined in src/platform/mod.rs.

Architecture of the Platform Abstraction Layer

The platform module uses Rust's conditional compilation attributes to select the appropriate implementation at compile time based on the target operating system.

The Public API in mod.rs

src/platform/mod.rs defines the shared types and function signatures that every platform must implement:

  • Process structures – ForegroundProcess and ForegroundJob for grouping related processes
  • Signal enumeration – Signal variants including Hangup, Terminate, and Kill
  • Clipboard abstractions – ClipboardCommand and ClipboardImage for handling system clipboard data
  • I/O helpers – read_limited_reader and the LimitedRead enum for safe data consumption

This file also declares the platform-specific functions—such as foreground_job(), write_clipboard(), open_url(), and show_desktop_notification()—without providing implementations. The actual logic resides in OS-specific submodules.

Conditional Compilation Strategy

The module uses #[cfg] attributes to re-export the correct implementation:

  • #[cfg(target_os = "linux")] mod linux; pub use linux::*;
  • #[cfg(target_os = "macos")] mod macos; pub use macos::*;
  • #[cfg(not(any(target_os = "linux", target_os = "macos")))] mod fallback; pub use fallback::*;

This approach ensures that calling code simply imports from herdr::platform without needing to know the underlying operating system.

Linux Implementation (src/platform/linux.rs)

src/platform/linux.rs provides the Linux-specific implementation using procfs and external command-line utilities. According to the herdr source code, this file avoids GUI library dependencies by shelling out to standard Unix tools.

Process Inspection via /proc

The Linux implementation reads from the virtual /proc filesystem to gather process information:

  • foreground_job() parses /proc/<pid>/stat and iterates /proc directories to construct a ForegroundJob containing all processes sharing the same terminal process group
  • process_pgrp_and_comm() extracts process group ID and command name from procfs entries
  • process_argv() and process_cwd() read command-line arguments and current working directory from /proc/<pid>/cmdline and /proc/<pid>/cwd symlinks
  • session_processes() identifies all PIDs belonging to the same session ID

Signal Handling

The signal_processes() function uses libc::kill to deliver signals to process groups, implementing the Signal enum variants defined in the public API.

Clipboard Integration

Linux clipboard handling detects the display server environment at runtime:

  • Wayland: Uses wl-copy and wl-paste when WAYLAND_DISPLAY is present
  • X11: Falls back to xclip or xsel when DISPLAY is set
  • Reading images: Executes wl-paste or xclip with size limits to prevent memory exhaustion

System Integration

  • open_url() invokes xdg-open to launch the default browser or application handler
  • show_desktop_notification() executes notify-send when an X server is available
  • raise_server_nofile_limit() currently exists as a stub preparing for future file descriptor limit adjustments

macOS Implementation (src/platform/macos.rs)

src/platform/macos.rs replaces Linux's procfs approach with macOS-specific proc_* syscalls and system frameworks, providing equivalent functionality through the BSD process management interface.

Process Inspection via proc_ Syscalls*

macOS uses the libproc API for process enumeration and inspection:

  • foreground_job() calls libc::proc_pidinfo with PROC_PIDTBSDINFO to obtain the e_tpgid (terminal process group ID), then uses proc_listpids to enumerate all PIDs in that process group
  • process_argv() implements kern_procargs2 via sysctl(KERN_PROCARGS2) to read the complete argument vector, accurately capturing process titles even after modification
  • process_cwd() retrieves the current working directory through proc_pidinfo(PROC_PIDVNODEPATHINFO) and the pvi_cdir.vip_path field
  • session_processes() groups processes using libc::getsid to identify session leaders

Signal Handling

Like Linux, macOS uses libc::kill for delivering signals to processes, maintaining API consistency across platforms.

Clipboard and System Integration

  • write_clipboard() invokes the native pbcopy command
  • open_url() uses the macOS open command
  • show_desktop_notification() first attempts to use terminal-notifier (allowing terminal activation), falling back to an AppleScript osascript notification if the former is unavailable
  • read_clipboard_image() executes an AppleScript that extracts PNG data from the system clipboard into a temporary file

Terminal Detection

The macOS implementation includes helpers to detect the current terminal emulator via TERM_PROGRAM, TERM, and window-ID environment variables, enabling notifications to correctly activate the originating terminal window.

Fallback Implementation (src/platform/fallback.rs)

For targets other than Linux and macOS, src/platform/fallback.rs provides safe no-op implementations that compile successfully but return empty results or errors. This guarantees that the herdr codebase remains portable and compiles on unsupported platforms without modification, though runtime functionality is limited.

Each function in the fallback module mirrors the public API signatures, ensuring type compatibility while gracefully degrading when OS-specific features are unavailable.

Practical Usage Examples

The following examples demonstrate how consuming code interacts with the platform layer without conditional compilation:

Open a URL in a Platform-Agnostic Way

use herdr::platform::open_url;

fn launch_manual() -> std::io::Result<()> {
    // Resolves to xdg-open on Linux, open on macOS
    open_url("https://herdr.dev")?;
    Ok(())
}

Write Text to the System Clipboard

use herdr::platform::write_clipboard;

fn copy_my_text(text: &str) -> bool {
    // Linux: wl-copy/xclip, macOS: pbcopy, Other: returns false
    write_clipboard(text.as_bytes())
}

Show a Desktop Notification

use herdr::platform::show_desktop_notification;

fn notify(title: &str, body: Option<&str>) {
    // Linux uses notify-send, macOS uses terminal-notifier or AppleScript
    let _ = show_desktop_notification(title, body);
}

Retrieve Foreground Job Information

use herdr::platform::foreground_job;

fn list_foreground_processes(pid: u32) {
    if let Some(job) = foreground_job(pid) {
        for proc in job.processes {
            println!("{} (pid {})", proc.name, proc.pid);
        }
    } else {
        println!("No foreground job found for pid {}", pid);
    }
}

Summary

  • Centralized abstraction: src/platform/mod.rs defines types like ForegroundProcess and functions like foreground_job(), hiding OS differences behind a unified API.
  • Linux implementation: Located in src/platform/linux.rs, uses /proc filesystem parsing, libc::kill, and external commands including xdg-open, wl-copy, and notify-send.
  • macOS implementation: Located in src/platform/macos.rs, leverages proc_pidinfo, sysctl(KERN_PROCARGS2), pbcopy, and AppleScript for equivalent functionality.
  • Fallback safety: src/platform/fallback.rs provides no-op stubs ensuring compilation on unsupported platforms.
  • Zero GUI dependencies: Both platforms shell out to command-line tools rather than linking GUI frameworks, keeping the binary lightweight.

Frequently Asked Questions

What is the purpose of the src/platform directory in herdr?

The src/platform directory isolates operating system-specific code from the rest of the application. It defines a common API in mod.rs and provides separate implementations for Linux (linux.rs), macOS (macos.rs), and unsupported systems (fallback.rs). This architecture allows the rest of herdr to call platform functions without knowing which operating system is running.

How does herdr handle clipboard operations differently on Linux and macOS?

On Linux, src/platform/linux.rs detects the display server by checking WAYLAND_DISPLAY or DISPLAY environment variables, then calls wl-copy/wl-paste for Wayland or xclip/xsel for X11. On macOS, src/platform/macos.rs simply invokes the built-in pbcopy command. For reading clipboard images, Linux uses the same command-line tools with size limits, while macOS executes an AppleScript to extract PNG data to a temporary file.

Why does the macOS implementation use proc_pidinfo instead of /proc?

macOS does not provide a /proc filesystem like Linux. Instead, src/platform/macos.rs uses the proc_* family of system calls available in libproc, such as proc_pidinfo with PROC_PIDTBSDINFO and PROC_PIDVNODEPATHINFO, to retrieve process group information, arguments, and current working directories. This provides equivalent functionality to Linux's procfs using native BSD-derived APIs.

What happens when herdr is compiled on Windows or other unsupported platforms?

When the target is neither Linux nor macOS, the build system selects src/platform/fallback.rs, which provides stub implementations that return empty results or errors. This ensures the codebase compiles successfully on any Rust-supported platform, though OS-specific features like clipboard access and process enumeration will not function at runtime.

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:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →