Available Commands
The complete reference for every command a Sophon Node can execute — parameters, responses, scopes, risk levels.
Commands are invoked from the agent via the node.command tool, from the Dashboard's Node Console, or from the CLI (sophon node exec). Every command runs inside the Node's platform abstraction — same API surface on Windows, macOS, and Linux with OS-specific implementations under the hood.
Required scopes appear in every section. See Permissions & Scopes for scope configuration.
Screen
screen.capture
Captures the full primary display.
Scope: screen.capture · Risk: Low
| Param | Type | Default | Notes |
|---|---|---|---|
quality | int | 80 | JPEG quality (1–100) |
maxWidth | int? | null | Optional max width; aspect ratio preserved |
Response: { image: "<base64-jpeg>", sizeBytes, format: "jpeg" }
screen.region
Captures a rectangular region.
Scope: screen.capture · Risk: Low
| Param | Type | Required | Notes |
|---|---|---|---|
x, y, width, height | int | yes | Region bounds |
quality | int | no (80) | JPEG quality |
Response: { image, sizeBytes, format, region: { x, y, width, height } }
Mouse
input.mouse.move
Move cursor to absolute coordinates.
Scope: input.control · Risk: Medium
| Param | Type | Required | Notes |
|---|---|---|---|
x, y | int | yes | Target coordinates |
input.mouse.click
Scope: input.control · Risk: Medium
| Param | Type | Default | Notes |
|---|---|---|---|
x, y | int | required | Click coordinates |
button | string | "left" | "left", "right", "middle" |
doubleClick | bool | false | Double-click |
input.mouse.scroll
Scope: input.control · Risk: Medium
| Param | Type | Default | Notes |
|---|---|---|---|
x, y | int | required | Scroll anchor |
deltaX, deltaY | int | 0 | Scroll amount (pixels) |
Keyboard
input.keyboard.type
Types a string character by character.
Scope: input.control · Risk: Medium
| Param | Type | Required | Notes |
|---|---|---|---|
text | string | yes | Text to type |
input.keyboard.press
Presses a single named key.
Scope: input.control · Risk: Medium
| Param | Type | Required | Notes |
|---|---|---|---|
keys | string | yes | Key name — enter, escape, tab, f5, backspace, delete, home, end, pageup, pagedown, arrows, etc. |
input.keyboard.hotkey
Modifier combinations.
Scope: input.control · Risk: Medium
| Param | Type | Required | Notes |
|---|---|---|---|
keys | string | yes | "ctrl+c", "alt+f4", "cmd+space", "win+d", "ctrl+shift+t" |
Applications
app.launch
Launch an application by name or path.
Scope: app.manage · Risk: Medium
| Param | Type | Required | Notes |
|---|---|---|---|
name | string | yes | App name (chrome, notepad) or full path |
args | string[] | no | Command-line args |
Response: { pid: 5678, app: "chrome.exe" }
app.close
Close a running application (graceful — sends WM_CLOSE or equivalent, then kills after 5 s).
Scope: app.manage · Risk: Medium
| Param | Type | Required | Notes |
|---|---|---|---|
name | string | either | App name |
pid | int | either | Process ID |
app.focus
Bring an app's window to the foreground.
Scope: app.manage · Risk: Medium
| Param | Type | Required | Notes |
|---|---|---|---|
name | string | either | App name |
pid | int | either | Process ID |
app.list
List apps with visible windows.
Scope: app.manage · Risk: Medium
Response: { count: 5, apps: [ { name, pid, windowTitle } ] }
Windows
window.list
All visible windows with geometry.
Scope: window.manage · Risk: Low
Response:
{
"count": 3,
"windows": [
{ "id": "0x00010234", "title": "Untitled - Notepad",
"x": 100, "y": 100, "width": 800, "height": 600,
"processName": "notepad.exe" }
]
}window.move
Move and optionally resize.
Scope: window.manage · Risk: Low
| Param | Type | Required | Notes |
|---|---|---|---|
windowId | string | yes | From window.list |
x, y | int | yes | New position |
width, height | int | no | Keeps current if omitted |
window.minimize, window.maximize
Scope: window.manage · Risk: Low
| Param | Type | Required | Notes |
|---|---|---|---|
windowId | string | yes | From window.list |
Clipboard
clipboard.read
Scope: clipboard.access · Risk: Low
Response: { text: "...", length: 42 }
clipboard.write
Scope: clipboard.access · Risk: Low
| Param | Type | Required | Notes |
|---|---|---|---|
text | string | yes | Text to write |
System
system.info
Machine info.
Scope: system.info · Risk: None
Response:
{
"osDescription": "Microsoft Windows 11.0.26200",
"machineName": "DESKTOP-ABC",
"processorCount": 8,
"totalMemoryMb": 16384,
"dotnetVersion": ".NET 10.0.0",
"uptime": 3600,
"platform": "windows",
"architecture": "x64"
}system.processes
All running processes.
Scope: system.info · Risk: None
Response: { count: 42, processes: [ { pid, name, cpuPercent, memoryMb } ] }
system.execute
Run shell command. Always approval-gated regardless of scope config.
Scope: system.execute · Risk: Critical
| Param | Type | Required | Notes |
|---|---|---|---|
command | string | yes | Command or executable |
args | string[] | no | Arguments |
timeoutMs | int | no | Execution timeout (ms) |
Runs via platform shell:
- Windows:
cmd.exe /c "<command> <args>" - macOS:
/bin/zsh -c "<command> <args>" - Linux:
/bin/bash -c "<command> <args>"
Response: { exitCode, stdout, stderr, durationMs }
Output truncated to 1 MB per stream.
Notifications
notify.show
Show an OS notification.
Scope: notify.send · Risk: None
| Param | Type | Default | Notes |
|---|---|---|---|
title | string | required | Notification title |
message | string | required | Notification body |
urgency | string | "normal" | "low", "normal", "critical" (Linux only) |
timeoutMs | int | 5000 | Auto-dismiss after this long |
Implementation:
- Windows:
Microsoft.Toolkit.Uwp.Notificationsor shell toast - macOS:
osascript -e 'display notification ...' - Linux:
notify-send
Filesystem (High risk)
filesystem.list
Scope: filesystem.access · Risk: High
| Param | Type | Required | Notes |
|---|---|---|---|
path | string | yes | Directory to list |
pattern | string | no | Glob pattern (e.g., *.pdf) |
Response: { entries: [ { name, path, isDirectory, sizeBytes, modifiedUtc } ] }
filesystem.read
Scope: filesystem.access · Risk: High
| Param | Type | Required | Notes |
|---|---|---|---|
path | string | yes | File path |
maxBytes | int | no (1 MB) | Max bytes to return |
Response: { content: "<base64 or text>", encoding, sizeBytes }
filesystem.write
Scope: filesystem.access · Risk: High
| Param | Type | Required | Notes |
|---|---|---|---|
path | string | yes | File path |
content | string | yes | Content to write (text or base64) |
encoding | string | "utf8" | "utf8" or "base64" |
createDirs | bool | true | Create parent directories |
filesystem.delete
Scope: filesystem.access · Risk: High
| Param | Type | Required | Notes |
|---|---|---|---|
path | string | yes | File or directory path |
recursive | bool | false | Required to delete non-empty directories |
Calling conventions
From an agent
node.command({
nodeId: "office-pc",
command: "screen.capture",
params: { quality: 80, maxWidth: 1280 }
})The agent selects the target Node by ID. For users with multiple Nodes, agents can call node.list first and ask which to use.
From the Dashboard Node Console
Settings → Devices → <node> → Console has a live interactive REPL. Type commands and see results immediately. Useful for debugging scope configuration.
From the CLI
sophon node list
sophon node exec <node-id> screen.capture --quality 80
sophon node exec <node-id> input.mouse.click --x 100 --y 200
sophon node exec <node-id> system.execute --command "echo hello"Timeouts
Every command has a default 30-second execution timeout. Long-running commands (large screen captures, shell commands) should pass timeoutMs explicitly.
If the Node doesn't respond within the timeout, the Gateway returns { error: "timeout" } but doesn't cancel the in-flight work on the Node. For commands that can't be interrupted cleanly, the side effect may still complete.
Error responses
{
"ok": false,
"error": "not_authorized",
"message": "Node does not have required scope: input.control"
}Common error codes:
not_authorized— scope missingapproval_rejected— approval gate rejected (Critical commands only)timeout— command exceeded its execution budgetnode_offline— Node isn't connected to the Gatewayplatform_unsupported— command not available on this OSinvalid_params— params failed validationinternal_error— unexpected failure on the Node (check Node logs)
Where to go next
- Install & Pair a Node
- Permissions & Scopes — scopes required per command
- Running as a Service — keep the Node online