#19904: Add remote-ssh/remote-k8s-pod/remote-docker for exec
docs
gateway
agents
size: XL
## Summary
Describe the problem and fix in 2–5 bullets:
- Problem: `exec` supported only `sandbox|gateway|node`, so running commands in remote SSH hosts, remote Docker containers, or Kubernetes pods required manual wrappers and reconnecting repeatedly.
- Why it matters: remote workflows are a primary use case for agent operations, and reconnecting on every command breaks stateful shell workflows (`cd`, environment setup, etc.).
- What changed: added `remote-ssh|remote-container|remote-k8s-pod` as first-class exec hosts; added remote target params/config defaults; integrated remote hosts with approvals/allowlist policy and `/exec` directive parsing/session patching; added docs and tests.
- What did NOT change (scope boundary): no automatic host switching, no remote filesystem sync, and no changes to existing `sandbox/gateway/node` execution semantics.
## Change Type (select all)
- [ ] Bug fix
- [x] Feature
- [ ] Refactor
- [x] Docs
- [ ] Security hardening
- [ ] Chore/infra
## Scope (select all touched areas)
- [x] Gateway / orchestration
- [x] Skills / tool execution
- [ ] Auth / tokens
- [ ] Memory / storage
- [ ] Integrations
- [x] API / contracts
- [x] UI / DX
- [ ] CI/CD / infra
## Linked Issue/PR
- Closes #
- Related #
## User-visible / Behavior Changes
List user-visible changes (including defaults/config).
If none, write `None`.
- `exec.host` now supports `remote-ssh`, `remote-container`, and `remote-k8s-pod`.
- New exec parameters for remote targets: `sshTarget`, `containerContext`, `containerName`, `k8sNamespace`, `k8sPod`, etc.
- New config defaults under `tools.exec.remote.{ssh,container,k8sPod}`.
- `/exec` directive/session overrides now accept remote host values.
- Remote execution reuses an interactive remote shell per target (30-minute idle TTL), so stateful commands like `cd` persist across commands.
## Security Impact (required)
- New permissions/capabilities? (`Yes/No`) Yes
- Secrets/tokens handling changed? (`Yes/No`) No
- New/changed network calls? (`Yes/No`) Yes
- Command/tool execution surface changed? (`Yes/No`) Yes
- Data access scope changed? (`Yes/No`) Yes
- If any `Yes`, explain risk + mitigation:
Remote execution broadens where commands can run (SSH/remote Docker/kubectl). Mitigation: remote hosts use the same exec approval/allowlist gate model as gateway execution; defaults remain safety-oriented (`security=deny` unless configured), host env hardening still blocks `PATH` and loader overrides, and remote targets require explicit configuration.
## Repro + Verification
### Environment
- OS: macOS 26.3
- Runtime/container: Node v25.5.0, Bun 1.2.7
- Model/provider: N/A (tool/runtime path)
- Integration/channel (if any): N/A
- Relevant config (redacted):
```json
{
"tools": {
"exec": {
"host": "remote-k8s-pod",
"security": "full",
"ask": "off",
"remote": {
"k8sPod": {
"namespace": "openclaw",
"pod": "openclaw-dev"
}
}
}
}
}
```
### Steps
1. Configure `tools.exec.host=remote-k8s-pod` and set `tools.exec.remote.k8sPod.namespace/pod`.
2. Run `exec` command `pwd`.
3. Run `exec` command `cd /tmp && pwd`, then run `exec` command `pwd` again.
### Expected
- Commands run inside target pod.
- Second `pwd` returns `/tmp` (session state persisted).
### Actual
- Matched expected behavior:
- `pwd` -> `/app`
- `cd /tmp && pwd` -> `/tmp`
- `pwd` -> `/tmp`
## Evidence
Attach at least one:
- [x] Failing test/log before + passing after
- [x] Trace/log snippets
- [ ] Screenshot/recording
- [ ] Perf numbers (if relevant)
- Targeted tests passed:
- `bunx vitest run src/config/config-misc.test.ts src/auto-reply/reply.directive.parse.test.ts src/agents/bash-tools.exec.remote-hosts.test.ts src/gateway/sessions-patch.test.ts`
- `bunx vitest run --config vitest.e2e.config.ts src/auto-reply/reply.directive.directive-behavior.shows-current-verbose-level-verbose-has-no.e2e.test.ts src/agents/bash-tools.exec.path.e2e.test.ts`
- Live pod verification (namespace `hy`, pod `prollama-b7944954f-nrm22`) confirmed remote interactive state persistence.
## Human Verification (required)
What you personally verified (not just CI), and how:
- Verified scenarios:
- `createExecTool` with `host=remote-k8s-pod` executes commands successfully.
- Remote shell state persistence across commands (`cd /tmp` then `pwd` => `/tmp`).
- `/exec` host validation and session patch handling include remote host values.
- Edge cases checked:
- Validation errors for missing required remote target fields (e.g., `k8sNamespace/k8sPod`).
- Invalid `execHost` error messaging updated to include new host values.
- What you did **not** verify:
- Live remote-SSH and remote-container endpoint execution in this environment.
## Compatibility / Migration
- Backward compatible? (`Yes/No`) Yes
- Config/env changes? (`Yes/No`) Yes (optional)
- Migration needed? (`Yes/No`) No
- If yes, exact upgrade steps:
## Failure Recovery (if this breaks)
- How to disable/revert this change quickly:
- Set `tools.exec.host` back to `sandbox`, `gateway`, or `node`.
- Set `tools.exec.security=deny` to hard-stop non-sandbox exec.
- Revert commit `7f9a3a9b5`.
- Files/config to restore:
- `openclaw.json` `tools.exec.*` keys.
- Modified runtime/config files under `src/agents/*`, `src/config/*`, `src/gateway/sessions-patch*`.
- Known bad symptoms reviewers should watch for:
- Remote exec commands hang/timeout on initial connect.
- Unexpected prompt/control-sequence noise in captured output.
- Incorrect allowlist/approval behavior for remote hosts.
## Risks and Mitigations
List only real risks for this PR. Add/remove entries as needed. If none, write `None`.
- Risk: Long-lived remote interactive sessions can carry unexpected shell state across commands.
- Mitigation: Session keying is explicit per target; idle sessions are pruned after 30 minutes; callers can reset by changing target/session.
- Risk: Remote connectivity/tooling (`ssh`, `docker`, `kubectl`) failures produce timeouts and reduce reliability.
- Mitigation: Timeout handling and explicit error propagation are included; approvals and status events surface failed runs quickly.
- Risk: Broader execution surface increases blast radius if misconfigured.
- Mitigation: Existing exec approvals/allowlist/security gates apply to remote hosts; defaults remain restrictive unless explicitly loosened.
<!-- greptile_comment -->
<h3>Greptile Summary</h3>
Adds first-class remote execution hosts (`remote-ssh`, `remote-container`, `remote-k8s-pod`) to the exec tool, enabling stateful shell sessions on SSH targets, Docker containers, and Kubernetes pods with 30-minute idle TTL.
- **Core addition**: `src/agents/exec-remote.ts` implements session management with marker-based exit code detection, shell escaping via `shellEscapeArg`, and idle session pruning. Sessions are keyed per unique target configuration.
- **Security integration**: Remote hosts use the same approval/allowlist/security gate model as gateway execution — `resolveExecApprovals`, `evaluateShellAllowlist`, and `requiresExecApproval` are all applied before remote commands run. SSH target parsing rejects hostnames starting with `-` to prevent argument injection.
- **Config/schema**: New `tools.exec.remote.{ssh,container,k8sPod}` config defaults with Zod `.strict()` validation. Three copies of `normalizeExecHost` (runtime, directive, sessions-patch) are consistently updated.
- **Docs and tests**: Comprehensive documentation updates and new unit tests covering SSH routing, container defaults, and missing k8s field validation. E2e test updated for new `/exec` options display.
- **Minor style note**: `dockerExec` variable in `buildConnectCommand` is allocated unconditionally but only used in the SSH-over-container path.
<h3>Confidence Score: 4/5</h3>
- This PR is safe to merge — it extends exec with remote hosts behind the existing security gate model, with no changes to sandbox/gateway/node execution semantics.
- Score of 4 reflects: well-structured feature addition with proper security integration (approval/allowlist gates), comprehensive validation of required fields, consistent updates across all three normalizeExecHost copies, good test coverage, and thorough documentation. Deducted one point for: the inherent complexity of remote interactive shell session management (marker-based output parsing, PTY echo noise), and the broadened execution surface requiring careful real-world testing beyond the unit tests provided.
- `src/agents/exec-remote.ts` (new core remote execution logic with session management) and `src/agents/bash-tools.exec.ts` (320+ lines of new remote host approval flow that closely mirrors but duplicates the gateway approval flow).
<sub>Last reviewed commit: 32c2fed</sub>
<!-- greptile_other_comments_section -->
<sub>(2/5) Greptile learns from your feedback when you react with thumbs up/down!</sub>
<!-- /greptile_comment -->
Most Similar PRs
#13246: feat: inject agent/session context as environment variables in exec...
by LePetitPince · 2026-02-10
71.0%
#11300: feat(exec): make shell configurable via tools.exec.shell
by imjszhang · 2026-02-07
70.9%
#11961: fix: exec tool wraps shebang scripts in heredoc to use correct inte...
by scott-memco · 2026-02-08
70.5%
#9433: fix: pass raw command string to node exec instead of argv array
by dbottme · 2026-02-05
68.4%
#9200: Fix: Strip dangerous env vars from baseEnv in host execution
by vishaltandale00 · 2026-02-05
68.4%
#15983: feat(exec): support env field in tools.exec config
by Imccccc · 2026-02-14
68.4%
#14211: feat: Add Stateful SSH Plugin with Auto-Key Detection
by schmiereck · 2026-02-11
68.0%
#14127: fix(exec): return command output when gateway approval is Always Allow
by Siziff · 2026-02-11
67.8%
#3907: fix(sandbox): use absolute /bin/sh path + add allowedReadPaths config
by pvoo · 2026-01-29
67.6%
#20435: fix(exec): prioritize user 'always allow' config over tool defaults...
by ChisomUma · 2026-02-18
67.5%