How the Summarize Daemon Handles Autostart on macOS, Linux, and Windows

The steipete/summarize daemon implements cross-platform autostart by generating native service configurations—LaunchAgent plists for macOS, systemd units for Linux, and Task Scheduler jobs for Windows—and manages their lifecycle through dedicated TypeScript modules that interface with launchctl, systemctl, and schtasks.

The steipete/summarize repository provides a background daemon that automatically starts when users log in, eliminating manual service management across operating systems. By abstracting daemon autostart mechanisms into platform-specific modules, the codebase ensures consistent behavior while respecting each platform's native service architecture. The implementation targets user-level services rather than system-wide daemons, ensuring installation succeeds without administrative privileges.

macOS LaunchAgent Integration (launchd)

The macOS implementation in src/daemon/launchd.ts leverages launchd to manage the daemon as a user LaunchAgent. This approach ensures the service starts automatically upon user login without requiring system-wide installation privileges. The module handles the complete lifecycle from plist generation to service bootstrap using native macOS tooling.

Building the Plist Configuration

The buildLaunchAgentPlist function constructs a property list file defining service parameters including program arguments, working directory, and log redirection. Paths are resolved via resolveDaemonLogPaths, directing stdout and stderr to ~/.summarize/logs/daemon.log. The resulting plist targets the user domain through resolveLaunchctlDomains, ensuring proper GUI session integration.

Installation and Bootstrap Flow

The installLaunchAgent function orchestrates the installation through three critical operations:

  1. Resolves log paths and validates the environment using resolveDaemonLogPaths
  2. Writes the plist to ~/Library/LaunchAgents/ after removing any stale configurations
  3. Executes launchctl bootstrap followed by kickstart to load and activate the agent in the appropriate user domain

Linux systemd User Service

For Linux environments, src/daemon/systemd.ts implements systemd user-service integration, allowing the daemon to run within the user's session context. The module verifies systemd availability before attempting installation and manages the service through standard systemctl commands.

Unit File Generation and Validation

Before installation, assertSystemdAvailable verifies that systemctl --user status executes successfully, confirming the systemd user instance is functional. The buildSystemdUnit function generates a service unit file containing the ExecStart directive, environment variables, and working directory specifications, with output redirected to ~/.summarize/logs/daemon.log.

Service Lifecycle Management

The installSystemdService function writes the unit to ~/.config/systemd/user/ and executes a reload-enable-start sequence:

  • systemctl --user daemon-reload refreshes the systemd configuration
  • systemctl --user enable marks the service for autostart
  • systemctl --user restart immediately activates the daemon

Windows Task Scheduler Integration (schtasks)

The Windows implementation in src/daemon/schtasks.ts utilizes the Task Scheduler (schtasks) to register a logon-triggered task. This approach provides native Windows service management without requiring custom service wrappers or registry modifications.

Batch Script Preparation

Unlike Unix platforms that pass arguments directly to the executable, Windows requires an intermediary script. The buildTaskScript function generates daemon.cmd containing the execution command with working directory navigation via cd /d. This script is written to %USERPROFILE%\.summarize\daemon.cmd and serves as the task's action target.

Task Registration and Execution

The installScheduledTask function first validates Task Scheduler availability through assertSchtasksAvailable. It then registers a task named DAEMON_WINDOWS_TASK_NAME configured to trigger on user logon, immediately firing the task via the /Run parameter to start the daemon without requiring a logout cycle.

Cross-Platform CLI Abstraction

The daemon exposes these platform-specific implementations through a unified interface in src/daemon/cli.ts. Based on process.platform, the CLI delegates to the appropriate installer, providing consistent commands regardless of the underlying operating system.

Installing via Command Line

Users can install and enable autostart with a single command:

summarize daemon install

Programmatic API Usage

Developers can invoke platform installers directly for custom integration scenarios.

macOS implementation:

import { installLaunchAgent } from "./daemon/launchd.js";
import { stdout } from "process";

await installLaunchAgent({
  env: process.env,
  stdout,
  programArguments: ["summarize", "daemon", "run"],
  workingDirectory: "/Users/alice",
});

Linux implementation:

import { installSystemdService } from "./daemon/systemd.js";
import { stdout } from "process";

await installSystemdService({
  env: process.env,
  stdout,
  programArguments: ["summarize", "daemon", "run"],
  workingDirectory: "/home/alice",
});

Windows implementation:

import { installScheduledTask } from "./daemon/schtasks.js";
import { stdout } from "process";

await installScheduledTask({
  env: process.env,
  stdout,
  programArguments: ["summarize", "daemon", "run"],
  workingDirectory: "C:\\Users\\Alice",
});

Summary

  • The steipete/summarize daemon implements daemon autostart through native platform service managers: launchd on macOS, systemd on Linux, and Task Scheduler on Windows.
  • Each platform module handles configuration generation, installation to user-specific directories (~/Library/LaunchAgents/, ~/.config/systemd/user/, and %USERPROFILE%\.summarize\), and service activation through standard command-line tools.
  • The implementation provides complete lifecycle management through paired uninstall, restart, and status-check functions (uninstallLaunchAgent, restartSystemdService, isScheduledTaskInstalled, etc.).
  • The unified CLI in src/daemon/cli.ts automatically selects the correct backend based on process.platform, while programmatic APIs allow direct access to platform-specific installers.

Frequently Asked Questions

How does the daemon handle log file redirection across platforms?

All three platforms redirect stdout and stderr to ~/.summarize/logs/daemon.log. On macOS, the buildLaunchAgentPlist function embeds StandardOutPath and StandardErrorPath keys in the plist. On Linux, the systemd unit file generated by buildSystemdUnit includes shell redirection in the ExecStart directive. Windows achieves this through output redirection operators within the daemon.cmd batch script created by buildTaskScript.

Can the daemon autostart without administrator privileges?

Yes. The implementation specifically targets user-level service managers rather than system-level services. On macOS, it installs to ~/Library/LaunchAgents/ rather than /Library/LaunchDaemons/. On Linux, it uses systemctl --user commands targeting ~/.config/systemd/user/. On Windows, it registers tasks in the user context via schtasks without requiring elevation, ensuring the daemon starts only when the specific user logs in.

What happens if the service configuration already exists?

Each installer includes idempotent behavior to handle existing configurations. The macOS implementation removes stale plist copies before writing new configurations. The Linux module overwrites existing unit files and executes daemon-reload to ensure systemd recognizes changes. The Windows implementation updates or recreates the task named DAEMON_WINDOWS_TASK_NAME to ensure configuration consistency.

How does the CLI determine which autostart mechanism to use?

The src/daemon/cli.ts module inspects process.platform to select the appropriate backend. When process.platform equals darwin, it imports and calls functions from src/daemon/launchd.ts. For linux, it uses src/daemon/systemd.ts. For win32, it delegates to src/daemon/schtasks.ts. This platform detection occurs at runtime, allowing the same CLI binary to operate correctly across different operating systems without manual configuration.

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 →