Standalone Hermes Agent plugin for using one long-lived Hermes gateway as an explicit SSH control plane for configured remote host aliases.
This is intentionally not a replacement for the built-in terminal() backend. The normal local terminal stays stable; the model must opt into remote execution by calling remote_terminal(host=...), remote_read_file(host=...), or remote_write_file(host=...) against a human-configured alias.
hermes plugins install donovan-yohan/hermes-plugin-remote-hosts --enableOr, if already installed:
hermes plugins enable remote-hostsRestart the Hermes gateway after changing plugin or remote_hosts config.
- Local
sshmust be installed on the Hermes gateway host. - Remote hosts must provide
python3andbash. - SSH key authentication must work non-interactively. The plugin runs SSH with
BatchMode=yes. - Host keys should already be present in local
known_hostswhenstrict_host_key_checking: trueis used, which is the default.
Add host aliases to config.yaml:
remote_hosts:
hosts:
desktop:
host: desktop.example.com
user: donovan
port: 22
identity_file: ~/.ssh/id_ed25519
workdir: ~/Documents/Programs
enabled: true
connect_timeout: 10
command_timeout: 120
strict_host_key_checking: true
allow_read: false
allow_write: false
allowed_roots:
- ~/Documents/Programs
workdir_only: falseShorthand is also supported:
remote_hosts:
hosts:
homelab: donovan@homelabDisabled hosts are omitted:
remote_hosts:
hosts:
old-box:
enabled: false
host: old-box.example.com
user: donovanremote_hosts_list()— lists enabled aliases without exposingidentity_fileor raw SSH options.remote_terminal(host, command, workdir?, timeout?)— runs a foreground command with remotebash -lc.remote_read_file(host, path, offset?, limit?)— reads text with line pagination using a remotepython3helper; disabled unless the host hasallow_read: true.remote_write_file(host, path, content)— atomically overwrites a text file using a remotepython3helper; disabled unless the host hasallow_write: true. Content above 200,000 characters is rejected before SSH.
Read and write tools also require either non-empty allowed_roots or workdir_only: true; unconstrained remote file access is rejected.
- The model can only target configured aliases. It cannot provide arbitrary SSH destinations.
- Local SSH is invoked as an argv list with
shell=False. - SSH uses
BatchMode=yes,RequestTTY=no,ConnectTimeout,ServerAliveInterval,ServerAliveCountMax, andStrictHostKeyChecking=yesby default. user,host, alias, port, timeouts, identity file paths,workdir, andallowed_rootsare validated before use.workdirandallowed_rootsmust be non-root absolute remote paths or~/...-anchored remote paths such as~/src; relative paths,/, and bare~are rejected.remote_terminalruns Hermes' existing dangerous-command guard with SSH semantics before execution. If that guard cannot be imported or fails, remote command execution fails closed instead of running unguarded.remote_read_fileandremote_write_filepass JSON over stdin/stdout; file contents are not shell-embedded.allow_readandallow_writedefault tofalse.allowed_rootsrestricts remote file read/write paths and is required for file tools unlessworkdir_only: trueis set. It is a guardrail enforced by the helper, not an OS sandbox.workdir_only: truerestricts file tools to the configuredworkdirand disables per-call terminal workdir overrides.remote_write_filepreserves an existing target file's mode when replacing it. Other metadata such as owner, group, ACLs, extended attributes, and timestamps may change.- Tool timeouts include SSH connection and helper execution. A per-call
remote_terminal(timeout=...)can only lower the host'scommand_timeout, not raise it. Remote-side processes may continue if the SSH client is killed by a local timeout.
This plugin is a routing boundary, not a sandbox. Remote commands still have whatever permissions the SSH user has on the remote machine; avoid configuring high-privilege SSH accounts unless the operational risk is intentional.