fix(daemon): bake PATH into systemd unit so shell tool can resolve netclaw CLI#948
Merged
Aaronontheweb merged 3 commits intonetclaw-dev:devfrom May 9, 2026
Conversation
…tclaw CLI systemctl --user services start with a sanitized PATH that excludes ~/.local/bin and any custom install directory, so ShellTool and BackgroundJobExecutionActor (which invoke `bash -c`) failed to resolve the `netclaw` CLI when the daemon was installed via `netclaw daemon install`. Compose Environment=PATH explicitly in the unit template: installDir first (so the daemon's bundled CLI wins), then ~/.local/bin, then the standard system PATH. Add SystemdUnitPathDoctorCheck to flag stale unit files that lack the PATH directive on existing installs. The check is Linux-only and returns Pass when no systemd user unit is present (e.g., daemon started directly via `netclaw daemon start`), so it does not produce noise for users who don't install as a service. Existing installs need `netclaw daemon uninstall && netclaw daemon install` to refresh the unit file; the install command's success message now mentions this. Update netclaw-operations skill (1.27.0 -> 1.28.0) with a diagnostic table entry pointing at the new check.
Windows test runs failed because Path.GetDirectoryName() normalizes Unix-style paths to backslash separators on Windows, breaking the installDir comparison in SystemdUnitPathDoctorCheck. systemd unit files always use forward-slash paths regardless of host OS, so parse them with literal '/' semantics instead of the platform-aware Path API.
3 tasks
Aaronontheweb
added a commit
to netclaw-dev/netclaw-website
that referenced
this pull request
May 9, 2026
…17) The netclaw daemon install command now bakes Environment=PATH= into the generated systemd user unit so the agent's shell tool can resolve netclaw and other user-installed binaries (netclaw-dev/netclaw#948). Update the systemd deployment doc to match: - Add a "Why user-level systemd?" section that frames the choice as security-neutral relative to running the daemon from the shell — same privileges, same blast radius, plus operational reliability. The contrast that matters is user-level vs. system-level. - Update both unit-file examples (auto-generated and manual) with the Environment=PATH= line and explain why it's needed. - Add a troubleshooting entry for "shell tool can't find netclaw" on upgraded installs that still have the older unit file, with uninstall+install migration steps and a /proc verification command. Also surface the security framing one click away from where users encounter the install command: - Make the daemon install/uninstall rows in cli/overview.md link to the systemd page. - Add a one-line note under the Daemon Management table summarizing the user-level model.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
systemctl --userservices start with a sanitized PATH that doesn't include~/.local/binor any custom install directory. BecauseShellToolandBackgroundJobExecutionActorinvokebash -cwith the daemon's inherited environment, the agent can't resolvenetclaw(or other user-installed binaries) when the daemon is installed vianetclaw daemon install. Running the daemon directly from a shell hides the bug because the operator's PATH is inherited.This PR fixes the install template and adds a doctor check for stale unit files.
Changes
DaemonManager.InstallAsyncnow bakesEnvironment=PATH={installDir}:{home}/.local/bin:/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbininto the generated unit file.installDircomes first (so the daemon's bundled CLI wins) and~/.local/binis included for the typical user-tools location.DaemonManager.SystemdUserUnitDirectory/SystemdUserUnitFilePath— used by Install, Uninstall, and the new doctor check.SystemdUnitPathDoctorCheck— Linux-only; parses~/.config/systemd/user/netclaw.serviceand warns ifEnvironment=PATH=is missing or doesn't include the daemon's install directory. Skips silently on non-Linux and on Linux hosts without a service installed (e.g., users running the daemon directly viadaemon start).netclaw-operationsskill bumped 1.27.0 → 1.28.0 with a new diagnostic-table row pointing the agent at the new check.Migration for existing installs
Existing service installs need the unit file refreshed:
netclaw daemon uninstall && netclaw daemon install systemctl --user restart netclawnetclaw doctorwill surface a Warning for any stale unit on Linux until this is done.Test plan
dotnet build src/Netclaw.Cli/Netclaw.Cli.csprojcleandotnet test src/Netclaw.Cli.Tests/Netclaw.Cli.Tests.csproj— 630 passed (including 7 new tests for the doctor check)dotnet slopwatch analyze— 0 issues.csfiles (PowerShell not installed locally to runAdd-FileHeaders.ps1)cat /proc/$(pgrep -u "$USER" netclawd)/environ | tr '\0' '\n' | grep PATHshould show installDir present afterdaemon uninstall && daemon install && systemctl --user restart netclaw