Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Service Management

ZeroClaw ships with first-class service integration for systemd (Linux), launchctl (macOS), and Task Scheduler / Windows Service (Windows). All three are driven by one CLI surface:

sh

zeroclaw service install     # register the service
zeroclaw service start       # start it
zeroclaw service stop        # stop it
zeroclaw service restart     # stop + start
zeroclaw service status      # running / stopped, last exit code
zeroclaw service uninstall   # remove it

The platform-specific backends are implemented in crates/zeroclaw-runtime/src/service/. You don’t have to think about them, but knowing what they produce helps when debugging.

Linux: systemd

zeroclaw service install writes a user-scoped unit at ~/.config/systemd/user/zeroclaw.service.

The unit:

  • Type=simple with the agent process staying in the foreground
  • ExecStart={cargo-bin}/zeroclaw daemon
  • Restart=always with RestartSec=3
  • Environment=HOME=%h and PassEnvironment=DISPLAY XDG_RUNTIME_DIR so headless browser tools can create profile/cache dirs and reach the user session
  • WantedBy=default.target

Manual control (systemd)

sh

systemctl --user start zeroclaw
systemctl --user stop zeroclaw
systemctl --user status zeroclaw
systemctl --user enable zeroclaw     # start on login

Logs

sh

journalctl --user -u zeroclaw -f        # follow
journalctl --user -u zeroclaw --since "1h ago"

Starting before user login

The CLI only ever writes a user-scoped unit (systemctl --user), which by default starts at login and stops at logout. To keep ZeroClaw running on a headless box without an active session, enable lingering for the service user:

sh

sudo loginctl enable-linger $USER
systemctl --user enable --now zeroclaw

If you need a true system-scope unit (root-owned, /etc/systemd/system/, dedicated service account, or hardware groups via SupplementaryGroups), the CLI does not generate one; adapt the system-level template at scripts/zeroclaw.service and install it yourself. On OpenRC hosts, sudo zeroclaw service install does provision a dedicated zeroclaw user and system paths (see below).

Linux: OpenRC

Detected automatically when /run/openrc exists (Alpine, some Gentoo configs).

sh

zeroclaw service install   # writes /etc/init.d/zeroclaw
rc-service zeroclaw start
rc-update add zeroclaw default    # start on boot

macOS: LaunchAgent

zeroclaw service install writes ~/Library/LaunchAgents/com.zeroclaw.daemon.plist and loads it.

sh

launchctl list | grep zeroclaw
launchctl unload ~/Library/LaunchAgents/com.zeroclaw.daemon.plist
launchctl load ~/Library/LaunchAgents/com.zeroclaw.daemon.plist

Logs go to <config-dir>/logs/ as daemon.stdout.log and daemon.stderr.log (for a default install, ~/.zeroclaw/logs/). Homebrew installs write to $HOMEBREW_PREFIX/var/zeroclaw/logs/ instead.

Homebrew-managed

If installed via Homebrew, brew services is the preferred interface:

sh

brew services start zeroclaw
brew services restart zeroclaw
brew services info zeroclaw

Don’t mix zeroclaw service CLI commands with brew services, pick one. Both end up writing a plist; having both around confuses launchctl.

Windows: Task Scheduler

zeroclaw service install creates a per-user scheduled task named ZeroClaw Daemon:

  • Trigger: at logon (/SC ONLOGON)
  • Run level: LIMITED (runs as the current user, not elevated)
  • Action: runs the install wrapper zeroclaw-daemon.cmd, which launches zeroclaw daemon

Verify in Task Scheduler GUI (taskschd.msc) under Task Scheduler Library → ZeroClaw Daemon.

Logs go to <config-dir>\logs\ as daemon.stdout.log and daemon.stderr.log (for a default install, %USERPROFILE%\.zeroclaw\logs\):

cmd

type %USERPROFILE%\.zeroclaw\logs\daemon.stdout.log

Manual control (Task Scheduler)

The task is driven through zeroclaw service start|stop|status, which wrap schtasks /Run, /End, and /Query against the ZeroClaw Daemon task. You can also manage it directly:

cmd

schtasks /Run /TN "ZeroClaw Daemon"
schtasks /End /TN "ZeroClaw Daemon"
schtasks /Query /TN "ZeroClaw Daemon" /FO LIST

The CLI installs only a per-user ONLOGON task; it does not register a LocalSystem Windows Service. For a true system service, wrap the binary with a third-party supervisor (e.g. NSSM) yourself.

Config path resolution

The service reads config from whichever directory resolved at install time. Precedence (first match wins):

  1. $ZEROCLAW_CONFIG_DIR (config lives directly under $ZEROCLAW_CONFIG_DIR)
  2. $ZEROCLAW_DATA_DIR
  3. $ZEROCLAW_WORKSPACE (deprecated, prefer ZEROCLAW_DATA_DIR; resolves either $ZEROCLAW_WORKSPACE or the legacy sibling .zeroclaw/)
  4. On macOS only, the Homebrew config dir ($HOMEBREW_PREFIX/var/zeroclaw/) when installed via Homebrew
  5. Default ~/.zeroclaw/ (Linux/macOS) or %USERPROFILE%\.zeroclaw\ (Windows)

ZEROCLAW_CONFIG_DIR overrides everything; setting it alongside ZEROCLAW_DATA_DIR or ZEROCLAW_WORKSPACE logs a warning and ignores the others.

If your service seems to ignore config changes, check which path the daemon resolved against, zeroclaw status reports the active config file, and the runtime logs a resolution-source line at startup:

sh

zeroclaw status

The output includes the config file path it resolved against.

Auto-update

The service does not auto-update. That’s deliberate; you pick when to take new code. Subscribe to the GitHub release feed or the Discord #releases channel (see Contributing → Communication).

See also