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 SophonNodeOr use the bundled installer:
sophon-node service install
sophon-node service startManaging the service
sophon-node service status # running / stopped
sophon-node service start
sophon-node service stop
sophon-node service restart
sophon-node service uninstall # 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/dev.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>dev.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/dev.sophon.node.plist
launchctl start dev.sophon.nodeManaging
launchctl list | grep sophon
launchctl stop dev.sophon.node
launchctl unload ~/Library/LaunchAgents/dev.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.
Auto-update
The Node can check for updates on startup if you set autoUpdate: true in ~/.sophon-node/config.json:
{
"gatewayUrl": "https://gw.example.com",
"nodeToken": "...",
"autoUpdate": true,
"updateChannel": "stable"
}On each startup, the Node checks https://releases.sophon.dev/node/latest/<channel> for a newer version. If found, it downloads, verifies signature, swaps itself in, and restarts. Rollback on failure.
Channels: stable (recommended), beta, nightly.
Manual update: sophon-node update downloads and installs immediately.
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