diff --git a/website/docs/reference/environment-variables.md b/website/docs/reference/environment-variables.md index 7ec0875b2d..bd75b2cbe6 100644 --- a/website/docs/reference/environment-variables.md +++ b/website/docs/reference/environment-variables.md @@ -93,6 +93,7 @@ For native Anthropic auth, Hermes prefers Claude Code's own credential files whe | `TERMINAL_SSH_USER` | SSH username | | `TERMINAL_SSH_PORT` | SSH port (default: 22) | | `TERMINAL_SSH_KEY` | Path to private key | +| `TERMINAL_SSH_PERSISTENT` | Override persistent shell for SSH (default: follows `TERMINAL_PERSISTENT_SHELL`) | ## Container Resources (Docker, Singularity, Modal, Daytona) @@ -104,6 +105,14 @@ For native Anthropic auth, Hermes prefers Claude Code's own credential files whe | `TERMINAL_CONTAINER_PERSISTENT` | Persist container filesystem across sessions (default: `true`) | | `TERMINAL_SANDBOX_DIR` | Host directory for workspaces and overlays (default: `~/.hermes/sandboxes/`) | +## Persistent Shell + +| Variable | Description | +|----------|-------------| +| `TERMINAL_PERSISTENT_SHELL` | Enable persistent shell for non-local backends (default: `true`). Also settable via `terminal.persistent_shell` in config.yaml | +| `TERMINAL_LOCAL_PERSISTENT` | Enable persistent shell for local backend (default: `false`) | +| `TERMINAL_SSH_PERSISTENT` | Override persistent shell for SSH backend (default: follows `TERMINAL_PERSISTENT_SHELL`) | + ## Messaging | Variable | Description | diff --git a/website/docs/user-guide/configuration.md b/website/docs/user-guide/configuration.md index f8a111520f..b6922f381a 100644 --- a/website/docs/user-guide/configuration.md +++ b/website/docs/user-guide/configuration.md @@ -462,6 +462,9 @@ terminal: container_memory: 5120 # MB (default 5GB) container_disk: 51200 # MB (default 50GB) container_persistent: true # Persist filesystem across sessions + + # Persistent shell — keep a long-lived bash process across commands + persistent_shell: true # Enabled by default for SSH backend ``` ### Common Terminal Backend Issues @@ -517,6 +520,46 @@ This is useful for: Can also be set via environment variable: `TERMINAL_DOCKER_VOLUMES='["/host:/container"]'` (JSON array). +### Persistent Shell + +By default, each terminal command runs in its own subprocess — working directory, environment variables, and shell variables reset between commands. When **persistent shell** is enabled, a single long-lived bash process is kept alive across `execute()` calls so that state survives between commands. + +This is most useful for the **SSH backend**, where it also eliminates per-command connection overhead. Persistent shell is **enabled by default for SSH** and disabled for the local backend. + +```yaml +terminal: + persistent_shell: true # default — enables persistent shell for SSH +``` + +To disable: + +```bash +hermes config set terminal.persistent_shell false +``` + +**What persists across commands:** +- Working directory (`cd /tmp` sticks for the next command) +- Exported environment variables (`export FOO=bar`) +- Shell variables (`MY_VAR=hello`) + +**Precedence:** + +| Level | Variable | Default | +|-------|----------|---------| +| Config | `terminal.persistent_shell` | `true` | +| SSH override | `TERMINAL_SSH_PERSISTENT` | follows config | +| Local override | `TERMINAL_LOCAL_PERSISTENT` | `false` | + +Per-backend environment variables take highest precedence. If you want persistent shell on the local backend too: + +```bash +export TERMINAL_LOCAL_PERSISTENT=true +``` + +:::note +Commands that require `stdin_data` or sudo automatically fall back to one-shot mode, since the persistent shell's stdin is already occupied by the IPC protocol. +::: + See [Code Execution](features/code-execution.md) and the [Terminal section of the README](features/tools.md) for details on each backend. ## Memory Configuration