Skip to content

Repository files navigation

opencode-remote-worker

An opencode plugin that executes shell commands on a remote machine through sshd instead of (or in addition to) the local shell. No agent, daemon, or helper binary is installed on the remote: sshd is the only server-side requirement.

Architecture and design decisions: docs/design-docs.md.

Install

opencode plugin opencode-remote-worker -g # global install

Keep the plugin declared in exactly one scope. A global instance plus the projects map is the supported setup; declaring it in both global and project config registers two colliding instances.

Configure

Host aliases and credentials come from your existing SSH setup (agent, keys, ~/.ssh/config). known_hosts entries must be unhashed (plain) in v1; before first use, seed the entry with ssh-keyscan build.example.com >> ~/.ssh/known_hosts.

{
"plugin": [
["opencode-remote-worker", {
"hosts": {
"worker1": { "host": "build.example.com", "user": "builder", "port": 22, "shell": "bash", "timeout": 120 }
},
"default": "worker1",
"remoteCwd": "/var/builds",
"keepalive": 10,
"requireProjectMatch": false,
"projects": {
"/home/me/code/heavy-builds": { "host": "worker1", "remoteCwd": "/srv/builds/heavy-builds" }
}
}]
]
}
OptionMeaning
hostsMap of host name to { host?, user?, port?, shell?, remoteCwd?, timeout?, keepalive?, identityFile? }
defaultHost used when no project matches and no host arg is given
remoteCwdDefault remote working directory for hosts that do not set one
keepaliveSSH keepalive interval in seconds (maps to ServerAliveInterval semantics)
requireProjectMatchtrue denies remote execution outside listed projects
projectsMap of local directory (longest-prefix) to { host, remoteCwd? }
overrideBashtrue registers a tool named bash so all shell execution goes remote

Host resolution order: tool host arg, then project longest-prefix match on the session directory, then default. Working directory: tool cwd arg, then project remoteCwd, then host remoteCwd, then the remote home.

Usage

The plugin registers the remote_bash tool with args { command, host?, cwd?, env? }. Remote execution is independently allow/deniable under the remote_bash permission id:

{ "permission": { "remote_bash": { "allow": ["*"], "deny": ["rm -rf *"] } } }

In the TUI, open the panel via ctrl+p (commands) -> "Link this directory to a remote host": link the current directory to a host (probed through the plugin's own transport first) or unlink it. Changes apply on the next opencode start.

The TUI hides output of custom tools by default. To see remote_bash results, toggle "Show generic tool output" in the session menu. The overrideBash mode is not affected and always shows output.

Development

bun install
bun test# unit tests
bun typecheck

Environment variables:

VariablePurpose
OPENCODE_RW_SSH_DIROverrides ~/.ssh for config/known_hosts lookups (tests use a throwaway dir)
OPENCODE_RW_TEST_SSH_HOSTEnables the integration tests against a real sshd (host must be in known_hosts)
OPENCODE_RW_TEST_SSH_USER / OPENCODE_RW_TEST_SSH_PORTIntegration test credentials overrides

Integration test example with a throwaway ssh dir:

OPENCODE_RW_TEST_SSH_HOST=build.example.com \
OPENCODE_RW_SSH_DIR=/tmp/ssh-fixture \
bun test test/ssh.integration.test.ts

Security

  • Commands run as the remote SSH user with that user's environment; there is no sandbox on the worker in v1. Prefer a dedicated low-privilege SSH user.
  • Host keys are verified against known_hosts (plain entries only in v1).
  • The permission gate is the same trust surface as local bash.

About

An OpenCode plugin for executing commands on remote machines over ssh

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages