Running as a Service
Install Sophon Node as a system service so it survives reboots — Windows Services, systemd, launchd.
For always-on automation you want the Node to start when the machine boots, stay running in the background, and restart automatically on crash. Each OS has its own service system; Sophon Node integrates with all three.
Windows Services
Register the Node as a Windows service using sc.exe:
# Run from elevated PowerShell
$exe = "$env:LOCALAPPDATA\SophonNode\sophon-node.exe"
sc.exe create SophonNode binPath= "`"$exe`" start --service" start= auto DisplayName= "Sophon Node"
sc.exe description SophonNode "Sophon desktop automation agent — connects to the Sophon Gateway to execute commands."
sc.exe start SophonNodeManaging the service
sc.exe query SophonNode # running / stopped
sc.exe start SophonNode
sc.exe stop SophonNode
sc.exe delete SophonNode # removes the service entryLogs
When running as a service, logs still go to %USERPROFILE%\.sophon-node\logs\sophon-node-YYYYMMDD.log. The service runs under LocalSystem by default, which means %USERPROFILE% resolves to C:\Windows\System32\config\systemprofile.
For user-scoped automation, run the service under the logged-in user's account:
sc.exe config SophonNode obj= "<DOMAIN>\<user>" password= "<password>"This lets the Node access the user's clipboard, screen, and profile — important for most automation.
Tray icon
Interactive mode (sophon-node start) shows a tray icon on Windows. Service mode runs headless. You can run both simultaneously — service handles reliability, interactive tray handles pause/resume UI — they share the same token.
systemd user service
Create ~/.config/systemd/user/sophon-node.service:
[Unit]
Description=Sophon Node
After=network-online.target
[Service]
Type=simple
ExecStart=/usr/local/bin/sophon-node start --service
Restart=on-failure
RestartSec=5s
Environment=DISPLAY=:0
[Install]
WantedBy=default.targetEnable and start:
systemctl --user daemon-reload
systemctl --user enable sophon-node
systemctl --user start sophon-nodeManaging
systemctl --user status sophon-node
systemctl --user restart sophon-node
systemctl --user stop sophon-node
journalctl --user -u sophon-node -f # follow logsLingering
By default, user services only run while the user is logged in. To keep the Node running across logouts:
sudo loginctl enable-linger $USERWayland vs X11
- X11 — set
Environment=DISPLAY=:0in the unit file (as above). Make surexhost +SI:localuser:$USERis set if running under a different user. - Wayland —
ydotoolneeds its own service. Install and enableydotool.servicebefore starting Sophon Node. Some Wayland compositors restrict input automation entirely; if commands silently fail, check the compositor's input-method policy.
System-wide service
If you want the Node to run without a logged-in user (rare — most automation needs user session access), create /etc/systemd/system/sophon-node.service instead and run systemctl enable sophon-node. You'll need to manually configure DISPLAY / screen sessions for GUI commands to work.
launchd user agent
Create ~/Library/LaunchAgents/ai.sophon.node.plist:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTD/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>Label</key>
<string>ai.sophon.node</string>
<key>ProgramArguments</key>
<array>
<string>/usr/local/bin/sophon-node</string>
<string>start</string>
<string>--service</string>
</array>
<key>RunAtLoad</key>
<true/>
<key>KeepAlive</key>
<true/>
<key>StandardOutPath</key>
<string>/Users/you/.sophon-node/logs/stdout.log</string>
<key>StandardErrorPath</key>
<string>/Users/you/.sophon-node/logs/stderr.log</string>
</dict>
</plist>Load and start:
launchctl load ~/Library/LaunchAgents/ai.sophon.node.plist
launchctl start ai.sophon.nodeManaging
launchctl list | grep sophon
launchctl stop ai.sophon.node
launchctl unload ~/Library/LaunchAgents/ai.sophon.node.plist # remove agent
tail -f ~/.sophon-node/logs/sophon-node-*.logAccessibility permission
On first mouse/keyboard command, macOS prompts for Accessibility permission for sophon-node (via cliclick). Without this, automation commands fail silently.
Grant in System Settings → Privacy & Security → Accessibility. You may need to re-grant after updating the binary (macOS ties the permission to the exact binary signature).
Background app permissions
On macOS 13+, user agents need Login Items permission:
System Settings → General → Login Items → Allow in the Background. Toggle Sophon Node on.
Updating
The Node checks for newer releases in the background and surfaces them in its logs and in the Dashboard. To update, reinstall the tool:
dotnet tool update -g sophon-nodeIf you installed a self-contained binary instead, replace it with the latest build for your platform. Restart the service afterwards (sc.exe stop/start, systemctl --user restart sophon-node, or reload the launchd agent).
Monitoring
The Dashboard's Settings → Devices page shows each Node's state:
- Online — connected, heartbeats arriving on time
- Offline — no heartbeat in > 90 seconds (service probably stopped)
- Stale — heartbeats arriving but slowly (network issues)
- Error — authentication or scope configuration error
Set up an outbound webhook on node.offline to alert yourself when an automation-critical Node goes down.
Troubleshooting
Service starts but no heartbeats — network or TLS issue. Check ~/.sophon-node/logs/sophon-node-YYYYMMDD.log for SignalR connection errors.
Commands time out after adding service — check that the service account has the same permissions as the interactive user. On Windows, the LocalSystem account can't access user desktops; configure the service to run as the interactive user.
macOS accessibility permission reset after update — macOS re-prompts when the binary changes. Re-grant in System Settings.
Linux Wayland commands fail — ydotool requires a running ydotoold daemon. On Ubuntu 22.04+, install ydotool and enable systemctl --user enable --now ydotool.service.
Where to go next
- Install & Pair a Node — the pre-service setup
- Permissions & Scopes — scope config that survives restarts
- Available Commands — what your service Node can do