description:Execute commands on reverse-connected nodes without SSH keys. Nodes connect to gateway via WebSocket, with integrated permission approval system.
- Any remote execution that would have used OpenClaw permission-controlled
❌ **DON'T use this skill when:**
- The node is not connected to the gateway
- You need interactive shell sessions (use SSH for that)
- File operations on local machine (use file tools)
## Prerequisites
1.**Hermes Agent running** with the embedded `hermes-node-gateway` plugin loaded
2.**Node agent running** on each remote machine
3.**Nodes connected** to the plugin (check with the Hermes `node_list` tool)
4.**Permission rules configured** in each node's config.json (allow/ask/deny patterns)
## Config Paths & Live-Reload Reality
**Current Linux node-agent config path in this environment:**
-`/home/nextime/.config/hermes-node/config.json`
Do not assume older paths like `~/.hermes-node-agent/config.json`; verify the live install path on the node if uncertain.
**Practical workflow when a remote command should be auto-allowed but is being blocked:**
1. Use `node_exec` to inspect the live config path on the target node.
2. Update `permissions.allow` in `/home/nextime/.config/hermes-node/config.json` on that node.
3. Re-read the file to verify the JSON actually contains the new entries.
4. Then verify whether the running agent process needs a restart to pick up config changes.
**Important:** config edits alone are not proof the running agent reloaded them. If expected behavior does not change, locate the actual process supervisor/startup path on the node and restart that agent.
## Available Nodes
| Node | IP | Description |
|------|-----|-------------|
| zeiss | 192.168.42.3 | Workstation |
| slut | 192.168.42.115 | Laptop |
| ganeti1 | 192.168.250.1 | Ganeti server |
| ganeti2 | 192.168.11.1 | Ganeti server |
| spank | 192.168.231.26 | Router |
## Commands
### Primary Interface: Hermes Tools
Use the in-process Hermes tools, not `curl`, for routine node work:
-`node_list` — list connected nodes
-`node_status(node_name=...)` — inspect one node
-`node_exec(node_name=..., command=[...])` — run a command on a node
- "Run df -h on sissy" → call `node_exec(node_name='sissy', command=['df','-h'])`
### HTTP Endpoint Note
The plugin may expose localhost HTTP endpoints for internal diagnostics, but they are **not** the normal interface and must not be used as the default execution path when Hermes node tools are available.
## Permission System
Commands are executed via the agent's built-in permission system (`_handle_exec` method), which enforces allow/ask/deny patterns configured in each node's config.json:
### Allow List (auto-execute)
```json
{
"allow":[
"df -h",
"hostname",
"uptime",
"sudo gnt-instance list",
"sudo gnt-cluster info"
]
}
```
**Ganeti nightly-health example allow patterns used in this environment:**
```json
{
"allow":[
"ping -c 1",
"cat /proc/drbd",
"/home/nextime/bin/ganeti-*",
"find /var/log",
"grep -iE",
"wc -l",
"ls /home/nextime/bin"
]
}
```
These patterns are useful when a scheduled health-check wrapper is dispatching simple Ganeti and log-inspection commands through `node_exec`.
**Important pitfall from Ganeti wrapper troubleshooting:**
- Do not assume the executable names under `/home/nextime/bin` are literally `gnt-cluster`, `gnt-instance`, and `gnt-node`.
- On `ganeti1` and `ganeti2`, first verify the actual filenames in `/home/nextime/bin` before hardcoding paths into wrappers or cron scripts.
- In this environment the wrappers may instead be named things like `ganeti-clusterinfo`, `ganeti-instancelist`, and `ganeti-nodelist`.
-`ganeti-clusterinfo` returns a full multi-line cluster report, not just the master hostname; if a script needs only the master, extract the `Master node:` line instead of treating the whole stdout as a hostname.
- If `ls /home/nextime/bin` or `find /home/nextime/bin ...` is denied, treat that as a node permission-policy problem, not a missing-file problem.
- For this class of task, the correct sequence is: inspect directory contents -> confirm exact executable names -> run the wrappers manually once -> inspect stdout shape -> update wrapper/script -> then re-test the remote command path.
### Ask List (requires approval)
```json
{
"ask":[
"sudo gnt-instance stop *",
"sudo gnt-instance remove *",
"rm -rf *"
]
}
```
Commands matching the **ask** list should be surfaced to the user as **approval required** — not as crashes or generic tool failures. The caller should be told the command can be retried only after explicit approval.
**Assistant UX rule:** when a `node_exec` call comes back with `status: approval_required`, do not stop at reporting diagnostics like "the ask path works". Present it to the user as a real approval request for that exact command and node, and only re-run with `approved=true` after explicit approval in chat.
### Deny List (rejected immediately)
```json
{
"deny":[
"chmod 777 /",
"> /dev/sda"
]
}
```
Commands matching the **deny** list are **not approvable**. They should return a normal structured **denied** result to the caller, and the user-facing response should plainly say the command is not allowed by policy. Do **not** present deny-list hits as approval requests, plugin/tool crashes, or Python tracebacks.
## Examples
### Check disk usage on all nodes
Use repeated `node_exec` tool calls, one node at a time:
**Solution:** Ask the user for approval, then re-run with `"approved": true`.
### Embedded plugin path issues
If the Hermes node tools fail, debug the embedded plugin/tool dispatch path first. The Hermes Node Gateway runs *inside the Hermes process* for this setup, so the right fix is usually in plugin registration, schema handling, or argument normalization — not in any localhost HTTP workaround.
**Correct diagnostic order:**
1. Use the Hermes tools first and treat them as the authoritative interface (`node_list`, `node_status`, `node_exec`).
2. If `node_exec` fails with argument-shape errors like `Missing required parameter: 'node_name'`, `unhashable type: 'slice'`, or similar dispatch/adapter errors, treat that as a *tool bridge/plugin dispatch problem*, not a node connectivity problem.
3. Inspect the live plugin code and Hermes tool dispatch path before blaming the node.
4. If tools fail and the plugin is not loaded correctly, debug the plugin registration/load path using `hermes-gateway-plugin-debugging`.
5. Do not switch to `curl` for normal execution just because the tool bridge is broken; fix the in-process plugin path instead.
**Do not assume systemd.** On this setup all machines use SysV init, not systemd.
**If you need service-level checks, use SysV-style commands instead:**
```bash
/etc/init.d/hermes-node-gateway status
/etc/init.d/hermes-node-gateway restart
```
### Tool dispatch weirdness
**Symptoms:**
-`node_list` works, but `node_exec` or `node_status` fails before reaching the node
- other argument-shape failures even though the caller clearly supplied the node name or command
**Interpretation:**
These errors usually mean Hermes/plugin argument passing is broken or inconsistent for that tool call path. They do **not** prove the remote node is disconnected or that command execution on the node itself failed.
**Most common root cause:**
The handler assumes one payload shape, but Hermes may pass any of these: