Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
31 commits
Select commit Hold shift + click to select a range
55b994c
fix(hermes): accept GPU-supervised startup owner
ericksoa Jul 1, 2026
91f3c44
test(hermes): add GPU startup live proof
ericksoa Jul 1, 2026
e0c7388
test(hermes): keep live GPU proof linear
ericksoa Jul 1, 2026
14c9a82
test(hermes): isolate GPU startup proof
ericksoa Jul 1, 2026
97584bd
test(hermes): capture GPU restart topology
ericksoa Jul 1, 2026
3351571
fix(test): replace if with ternary in hermes-gpu-startup to satisfy g…
prekshivyas Jul 1, 2026
17a2e38
fix(gpu): preserve OpenShell command boundary
ericksoa Jul 1, 2026
722c5e2
test(hermes): prove GPU startup authority boundary
ericksoa Jul 1, 2026
4e52301
Merge branch 'main' into fix/hermes-gpu-startup-6110
cv Jul 1, 2026
8c083f7
test(gpu): close supervisor boundary proof gaps
ericksoa Jul 1, 2026
97e3e7e
fix(gpu): capture failed clone before rollback
ericksoa Jul 1, 2026
351061d
fix(gpu): prefer native OpenShell injection
ericksoa Jul 2, 2026
362a172
Merge remote-tracking branch 'origin/main' into fix/hermes-gpu-startu…
ericksoa Jul 2, 2026
1918ffe
refactor(gpu): keep onboarding entrypoint neutral
ericksoa Jul 2, 2026
7cb219d
test(gpu): keep diagnostic fixtures linear
ericksoa Jul 2, 2026
5a200ae
fix(gpu): preserve gateway routing invariant
ericksoa Jul 2, 2026
9a4b54c
fix(gpu): prime diagnostics redaction before capture
ericksoa Jul 2, 2026
9e971b5
test(gpu): normalize OpenShell readiness output
ericksoa Jul 2, 2026
22de6ea
test(gpu): expose forced legacy live route
ericksoa Jul 2, 2026
a1fc52c
test(e2e): detect forbidden inference markers
ericksoa Jul 2, 2026
54cf259
fix(hermes): accept OpenShell TLS key path
ericksoa Jul 2, 2026
970803a
fix(hermes): update validator integrity hash
ericksoa Jul 2, 2026
7335903
test(gpu): use canonical placeholder transport
ericksoa Jul 2, 2026
c5a67c4
docs(gpu): document native OpenShell routing
ericksoa Jul 2, 2026
a04a70a
test(gpu): verify managed startup trust boundary
ericksoa Jul 2, 2026
6ac4ebc
test(gpu): run gateway cleanup through built CLI
ericksoa Jul 2, 2026
65b06d6
test(gpu): tolerate clean preinstall teardown
ericksoa Jul 2, 2026
7b75355
fix(gpu): centralize diagnostic redaction
ericksoa Jul 2, 2026
5c87782
test(gpu): harden live proof isolation
ericksoa Jul 2, 2026
e077aa6
fix(gpu): redact generic key diagnostics
ericksoa Jul 2, 2026
d76f164
merge: sync current main into gpu fix
ericksoa Jul 2, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
50 changes: 48 additions & 2 deletions .github/workflows/e2e.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ on:
default: ""
type: string
jobs:
description: "Optional comma-separated free-standing live E2E job ids. Empty runs default-enabled jobs only when targets is also empty; explicit-only jobs openshell-gateway-auth-contract, jetson-nvmap-gpu, and sandbox-rlimits-connect are skipped unless selected."
description: "Optional comma-separated free-standing live E2E job ids. Empty runs default-enabled jobs only when targets is also empty; explicit-only jobs hermes-gpu-startup, openshell-gateway-auth-contract, jetson-nvmap-gpu, and sandbox-rlimits-connect are skipped unless selected."
required: false
default: ""
type: string
Expand Down Expand Up @@ -1578,6 +1578,51 @@ jobs:
shell: bash
run: bash .github/scripts/docker-auth-cleanup.sh

hermes-gpu-startup:
needs: generate-matrix
if: ${{ contains(format(',{0},', inputs.jobs), ',hermes-gpu-startup,') || contains(format(',{0},', inputs.targets), ',hermes-gpu-startup,') }}
runs-on: linux-amd64-gpu-rtxpro6000-latest-1
timeout-minutes: 75
env:
E2E_JOB: "1"
E2E_DEFAULT_ENABLED: "0"
E2E_TARGET_ID: "hermes-gpu-startup"
E2E_ARTIFACT_DIR: ${{ github.workspace }}/e2e-artifacts/live/hermes-gpu-startup
NEMOCLAW_CLI_BIN: ${{ github.workspace }}/bin/nemoclaw.js
NEMOCLAW_RUN_LIVE_E2E: "1"
NEMOCLAW_ACCEPT_THIRD_PARTY_SOFTWARE: "1"
NEMOCLAW_AGENT: hermes
NEMOCLAW_NON_INTERACTIVE: "1"
NEMOCLAW_RECREATE_SANDBOX: "1"
NEMOCLAW_SANDBOX_GPU: "1"
NEMOCLAW_SANDBOX_NAME: e2e-hermes-gpu-startup
NEMOCLAW_ONBOARD_VALIDATION_TIMEOUT_SECONDS: "60"
steps:
- uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
with:
persist-credentials: false

- *dockerhub-auth

- name: Prepare E2E workspace
uses: NVIDIA/NemoClaw/.github/actions/prepare-e2e@50281ee84c4a6fc759da95ea28fc0b7d9c378a28

- name: Run Hermes GPU startup live Vitest test
run: |
set -euo pipefail
npx vitest run --project e2e-live \
test/e2e/live/hermes-gpu-startup.test.ts \
--silent=false --reporter=default

- name: Upload Hermes GPU startup artifacts
if: always()
uses: NVIDIA/NemoClaw/.github/actions/upload-e2e-artifacts@7768e15eb90d3ee2d33432f481dfe8747e4f6d57

- name: Clean up Docker auth
if: always()
shell: bash
run: bash .github/scripts/docker-auth-cleanup.sh

hermes-dashboard:
needs: generate-matrix
if: ${{ (github.event_name != 'workflow_dispatch' || (inputs.jobs == '' && inputs.targets == '')) || contains(format(',{0},', inputs.jobs), ',hermes-dashboard,') || contains(format(',{0},', inputs.targets), ',hermes-dashboard,') }}
Expand Down Expand Up @@ -4426,6 +4471,7 @@ jobs:
sessions-agents-cli,
runtime-overrides,
hermes-e2e,
hermes-gpu-startup,
hermes-dashboard,
hermes-slack,
hermes-discord,
Expand Down Expand Up @@ -4639,7 +4685,7 @@ jobs:
? '**Requested jobs:** _(selector rejected by workflow validation)_'
: requestedJobs
? `**Requested jobs:** \`${requestedJobs}\``
: '**Requested jobs:** _(default — all default-enabled free-standing jobs; explicit-only jobs `openshell-gateway-auth-contract`, `jetson-nvmap-gpu`, and `sandbox-rlimits-connect` are skipped unless selected)_',
: '**Requested jobs:** _(default — all default-enabled free-standing jobs; explicit-only jobs `hermes-gpu-startup`, `openshell-gateway-auth-contract`, `jetson-nvmap-gpu`, and `sandbox-rlimits-connect` are skipped unless selected)_',
`**Summary:** ${passed.length} passed, ${failed.length} failed, ${cancelled.length} cancelled, ${skipped.length} skipped`,
'',
'| Job | Result |',
Expand Down
2 changes: 1 addition & 1 deletion agents/hermes/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -168,7 +168,7 @@ RUN test -x /usr/local/lib/nemoclaw/validate-hermes-env-secret-boundary.py \
# also rewrite the Dockerfile-committed hash, which reviewers gate). Regenerate
# with `sha256sum agents/hermes/{hermes-wrapper.py,validate-env-secret-boundary.py}`.
ARG NEMOCLAW_HERMES_WRAPPER_SHA256=03e0afbe00e352d0dfcf14b99ea1821f9fd29f87dad49ce19add2ec96d1941cc
ARG NEMOCLAW_HERMES_VALIDATOR_SHA256=d8ebac7143ce79061a86fefb79f2be9fb1d73f41229dc7144a1c157384947fd1
ARG NEMOCLAW_HERMES_VALIDATOR_SHA256=970d7ff03bc409ff1d5ca46bfdbd2a42ac28a32a810ccc147a508301bff38496
# hadolint ignore=DL4006
RUN printf '%s %s\n' \
"$NEMOCLAW_HERMES_VALIDATOR_SHA256" /usr/local/lib/nemoclaw/validate-hermes-env-secret-boundary.py \
Expand Down
17 changes: 16 additions & 1 deletion agents/hermes/runtime-config-guard.py
Original file line number Diff line number Diff line change
Expand Up @@ -321,7 +321,22 @@ def _pid1_is_nemoclaw_start() -> bool:
os.close(proc_pid_fd)
if proc_root_fd >= 0:
os.close(proc_root_fd)
return _cmdline_is_nemoclaw_start(cmdline)
# SOURCE_OF_TRUTH_REVIEW (#6110): OpenShell owns PID 1 in Docker-driver
# sandboxes and starts the workload as its direct non-root child. NemoClaw's
# GPU recreate used to append that workload to the supervisor argv; the
# source fix is buildDockerGpuCloneRunArgs() in docker-gpu-patch.ts, which
# now preserves an empty Config.Cmd. An attacker controlling an image or
# recreate argv could otherwise append `nemoclaw-start`, impersonate direct
# PID 1 authority, and bypass the startup identity check. Keep this
# exclusion as defense in depth; live proof is in
# assertHermesGpuStartupProof() in
# test/e2e/live/hermes-gpu-startup-proof.ts. The dual-mode authorization
# branch can be removed only after direct-PID1 images are no longer
# supported; this supervisor exclusion itself remains a security invariant.
return (
not _cmdline_is_openshell_supervisor(cmdline)
and _cmdline_is_nemoclaw_start(cmdline)
)


def _pinned_process_matches_startup_identity(
Expand Down
4 changes: 2 additions & 2 deletions agents/hermes/start.sh
Original file line number Diff line number Diff line change
Expand Up @@ -1681,8 +1681,8 @@ ensure_hermes_runtime_api_server_key() {
rm -f "$result_file"
return 1
}
# Keep the guard as PID 1's direct child: --startup-owner is authenticated by
# exact parent identity. The guard's own alarm bounds this startup-only call;
# Keep the guard as the startup owner's direct child: --startup-owner is
# authenticated by exact parent identity. Its own alarm bounds this call;
# wrapping it in `timeout` would interpose a different parent process.
if "$_HERMES_PYTHON" -I "$_HERMES_RUNTIME_CONFIG_GUARD" ensure-api-key \
--hermes-dir "$HERMES_DIR" \
Expand Down
9 changes: 9 additions & 0 deletions agents/hermes/validate-env-secret-boundary.py
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,13 @@
}
)
RUNTIME_ALLOWED_RAW_SECRET_KEYS = frozenset({"OPENCLAW_GATEWAY_TOKEN"})
# OpenShell's Docker/Podman supervisor owns this variable and injects a mounted
# file path, not private-key material. Keep the allowance exact and runtime-only
# so a caller cannot use the secret-shaped name to smuggle an arbitrary value or
# persist it in Hermes' mutable .env file.
RUNTIME_ALLOWED_PLATFORM_PATH_VALUES = frozenset(
{("OPENSHELL_TLS_KEY", "/etc/openshell/tls/client/tls.key")}
)
ALLOWED_LITERALS = frozenset({"", "[STRIPPED_BY_MIGRATION]"})
MAX_ENV_BYTES = 4 * 1024 * 1024
MAX_ENV_LINE_BYTES = 256 * 1024
Expand Down Expand Up @@ -480,6 +487,8 @@ def validate_runtime_env(env: dict[str, str] | None = None) -> int:
key, value
):
continue
if (key, value) in RUNTIME_ALLOWED_PLATFORM_PATH_VALUES:
continue
if not KEY_NAME_RE.fullmatch(key):
continue
if not SECRET_KEY_RE.search(key):
Expand Down
17 changes: 12 additions & 5 deletions docs/reference/commands-nemohermes.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -360,9 +360,11 @@ Use `--no-gpu` to opt out when you want host-side inference providers only and d
Use `--gpu` to require GPU passthrough and fail fast if an NVIDIA GPU is not detected.
Use `--sandbox-gpu` or `--no-sandbox-gpu` to control only direct NVIDIA GPU access inside the sandbox.
Use `--sandbox-gpu --sandbox-gpu-device <device>` to pass a specific OpenShell GPU device selector to `openshell sandbox create`; device selectors require explicit sandbox GPU enablement.
On Linux Docker-driver gateways, NemoClaw can create the sandbox first and then recreate the OpenShell-managed Docker container with NVIDIA GPU access when that compatibility path is needed.
When this compatibility path recreates the Docker container, NemoClaw uses an available NVIDIA CDI spec before falling back to Docker `--gpus all` or the NVIDIA runtime.
On Jetson/Tegra hosts, it also adds the host group IDs that own `/dev/nvmap` and `/dev/nvhost-*` so the sandbox user can initialize CUDA.
On ordinary native Linux Docker-driver hosts with usable CDI, NemoClaw uses OpenShell native GPU injection by default.
On Docker Desktop WSL and Jetson/Tegra, NemoClaw creates the sandbox first and then recreates the OpenShell-managed Docker container with NVIDIA GPU access by default.
When you force this compatibility path on ordinary native Linux, NemoClaw uses an available NVIDIA CDI spec before falling back to Docker `--gpus all` or the NVIDIA runtime.
On Docker Desktop WSL, the compatibility path skips CDI and tries Docker `--gpus all` before the NVIDIA runtime.
On Jetson/Tegra hosts, the compatibility path uses the NVIDIA runtime and adds the host group IDs that own `/dev/nvmap` and `/dev/nvhost-*` so the sandbox user can initialize CUDA.
If the patch fails, onboarding keeps diagnostics and prints a manual cleanup command rather than deleting the failed sandbox automatically.

Prerequisites:
Expand All @@ -376,7 +378,12 @@ When GPU passthrough is enabled and a gateway already exists without it, onboard
If no other registered sandbox depends on that gateway, or if `--recreate-sandbox` is recreating the only registered sandbox with the same name, onboarding cleans up the stale gateway and continues.
If other sandboxes depend on the gateway or Docker state is unclear, onboarding exits without cleanup and prints targeted destroy or gateway-removal guidance.
To add GPU to an existing sandbox, rerun with `--recreate-sandbox`.
Set `NEMOCLAW_DOCKER_GPU_PATCH=0` only when you need to bypass the Linux Docker-driver compatibility patch during troubleshooting.
Leave `NEMOCLAW_DOCKER_GPU_PATCH` unset or set it to `auto` to use the platform default.
Set `NEMOCLAW_DOCKER_GPU_PATCH=1` to force the legacy Docker container-swap path on ordinary native Linux.
Set `NEMOCLAW_DOCKER_GPU_PATCH=0` to select native OpenShell GPU injection on ordinary native Linux or Jetson/Tegra.
Use `NEMOCLAW_DOCKER_GPU_PATCH=0` on Jetson/Tegra only for troubleshooting because it bypasses Tegra device-group propagation and CUDA may not initialize.
Docker Desktop WSL ignores `NEMOCLAW_DOCKER_GPU_PATCH=0` because GPU passthrough on that runtime requires the compatibility patch.
Use `--no-sandbox-gpu`, `--no-gpu`, or `NEMOCLAW_SANDBOX_GPU=0` when you want to disable sandbox GPU passthrough on Docker Desktop WSL.

### `nemohermes list`

Expand Down Expand Up @@ -2037,7 +2044,7 @@ Set them before running `nemohermes onboard`.
| `NEMOCLAW_RAM` | percentage or Kubernetes memory quantity | Overrides the selected profile's memory size passed to OpenShell `--memory`. Percentages resolve against detected capacity. |
| `NEMOCLAW_SANDBOX_GPU` | `auto`, `1`, or `0` | Controls sandbox GPU passthrough during onboarding. `auto` enables GPU passthrough when an NVIDIA GPU is detected, `1` requires GPU passthrough, and `0` forces CPU-only sandbox creation. |
| `NEMOCLAW_SANDBOX_GPU_DEVICE` | OpenShell GPU device selector | Selects the GPU device passed with `openshell sandbox create --gpu-device`. Requires explicit sandbox GPU enablement with `NEMOCLAW_SANDBOX_GPU=1` (or `--sandbox-gpu` for CLI-driven onboarding); otherwise onboarding rejects the selector instead of treating it as an implicit opt-in. |
| `NEMOCLAW_DOCKER_GPU_PATCH` | `0` to disable, anything else to keep the default | Controls the Linux Docker-driver GPU sandbox compatibility patch. Set to `0` only as an escape hatch when the patch fails and you need onboarding to continue without patching the GPU sandbox container. |
| `NEMOCLAW_DOCKER_GPU_PATCH` | unset, `auto`, `1`, or `0` | Selects Linux Docker-driver GPU routing. Unset or `auto` uses native OpenShell GPU injection on ordinary native Linux and the compatibility patch on Docker Desktop WSL and Jetson/Tegra. `1` forces the compatibility patch. `0` selects native injection on ordinary native Linux and Jetson/Tegra, but Docker Desktop WSL ignores it. On Jetson/Tegra, use `0` only for troubleshooting because it bypasses the device-group propagation needed for CUDA. |
| `NEMOCLAW_OPENSHELL_GATEWAY_CONTAINER_PATCH` | `1` to enable; disabled by default | Explicitly opts into the Linux gateway compatibility container for an older host ABI or a diagnostic run. This mode uses host networking and mounts the Docker socket read-only, but the socket still exposes the privileged Docker API. Use it only on a trusted local host; prefer OpenShell 0.0.71's directly supported glibc 2.28+ path. See the [OpenShell 0.0.71 gateway auth review](../security/openshell-0.0.71-gateway-auth-review#source-of-truth-boundaries). |
| `NEMOCLAW_OPENSHELL_GATEWAY_BIN` | path | Advanced override for the `openshell-gateway` binary used by the Linux Docker-driver standalone fallback. Defaults to the binary next to `openshell`, then common install paths. |
| `NEMOCLAW_OPENSHELL_SANDBOX_BIN` | path | Advanced override for the `openshell-sandbox` binary used by the Linux Docker-driver standalone fallback. Defaults to the binary next to `openshell`, then common install paths. |
Expand Down
17 changes: 12 additions & 5 deletions docs/reference/commands.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -454,9 +454,11 @@ Use `--no-gpu` to opt out when you want host-side inference providers only and d
Use `--gpu` to require GPU passthrough and fail fast if an NVIDIA GPU is not detected.
Use `--sandbox-gpu` or `--no-sandbox-gpu` to control only direct NVIDIA GPU access inside the sandbox.
Use `--sandbox-gpu --sandbox-gpu-device <device>` to pass a specific OpenShell GPU device selector to `openshell sandbox create`; device selectors require explicit sandbox GPU enablement.
On Linux Docker-driver gateways, NemoClaw can create the sandbox first and then recreate the OpenShell-managed Docker container with NVIDIA GPU access when that compatibility path is needed.
When this compatibility path recreates the Docker container, NemoClaw uses an available NVIDIA CDI spec before falling back to Docker `--gpus all` or the NVIDIA runtime.
On Jetson/Tegra hosts, it also adds the host group IDs that own `/dev/nvmap` and `/dev/nvhost-*` so the sandbox user can initialize CUDA.
On ordinary native Linux Docker-driver hosts with usable CDI, NemoClaw uses OpenShell native GPU injection by default.
On Docker Desktop WSL and Jetson/Tegra, NemoClaw creates the sandbox first and then recreates the OpenShell-managed Docker container with NVIDIA GPU access by default.
When you force this compatibility path on ordinary native Linux, NemoClaw uses an available NVIDIA CDI spec before falling back to Docker `--gpus all` or the NVIDIA runtime.
On Docker Desktop WSL, the compatibility path skips CDI and tries Docker `--gpus all` before the NVIDIA runtime.
On Jetson/Tegra hosts, the compatibility path uses the NVIDIA runtime and adds the host group IDs that own `/dev/nvmap` and `/dev/nvhost-*` so the sandbox user can initialize CUDA.
If the patch fails, onboarding keeps diagnostics and prints a manual cleanup command rather than deleting the failed sandbox automatically.

Prerequisites:
Expand All @@ -470,7 +472,12 @@ When GPU passthrough is enabled and a gateway already exists without it, onboard
If no other registered sandbox depends on that gateway, or if `--recreate-sandbox` is recreating the only registered sandbox with the same name, onboarding cleans up the stale gateway and continues.
If other sandboxes depend on the gateway or Docker state is unclear, onboarding exits without cleanup and prints targeted destroy or gateway-removal guidance.
To add GPU to an existing sandbox, rerun with `--recreate-sandbox`.
Set `NEMOCLAW_DOCKER_GPU_PATCH=0` only when you need to bypass the Linux Docker-driver compatibility patch during troubleshooting.
Leave `NEMOCLAW_DOCKER_GPU_PATCH` unset or set it to `auto` to use the platform default.
Set `NEMOCLAW_DOCKER_GPU_PATCH=1` to force the legacy Docker container-swap path on ordinary native Linux.
Set `NEMOCLAW_DOCKER_GPU_PATCH=0` to select native OpenShell GPU injection on ordinary native Linux or Jetson/Tegra.
Use `NEMOCLAW_DOCKER_GPU_PATCH=0` on Jetson/Tegra only for troubleshooting because it bypasses Tegra device-group propagation and CUDA may not initialize.
Docker Desktop WSL ignores `NEMOCLAW_DOCKER_GPU_PATCH=0` because GPU passthrough on that runtime requires the compatibility patch.
Use `--no-sandbox-gpu`, `--no-gpu`, or `NEMOCLAW_SANDBOX_GPU=0` when you want to disable sandbox GPU passthrough on Docker Desktop WSL.

### `$$nemoclaw list`

Expand Down Expand Up @@ -2522,7 +2529,7 @@ Set them before running `$$nemoclaw onboard`.
| `NEMOCLAW_RAM` | percentage or Kubernetes memory quantity | Overrides the selected profile's memory size passed to OpenShell `--memory`. Percentages resolve against detected capacity. |
| `NEMOCLAW_SANDBOX_GPU` | `auto`, `1`, or `0` | Controls sandbox GPU passthrough during onboarding. `auto` enables GPU passthrough when an NVIDIA GPU is detected, `1` requires GPU passthrough, and `0` forces CPU-only sandbox creation. |
| `NEMOCLAW_SANDBOX_GPU_DEVICE` | OpenShell GPU device selector | Selects the GPU device passed with `openshell sandbox create --gpu-device`. Requires explicit sandbox GPU enablement with `NEMOCLAW_SANDBOX_GPU=1` (or `--sandbox-gpu` for CLI-driven onboarding); otherwise onboarding rejects the selector instead of treating it as an implicit opt-in. |
| `NEMOCLAW_DOCKER_GPU_PATCH` | `0` to disable, anything else to keep the default | Controls the Linux Docker-driver GPU sandbox compatibility patch. Set to `0` only as an escape hatch when the patch fails and you need onboarding to continue without patching the GPU sandbox container. |
| `NEMOCLAW_DOCKER_GPU_PATCH` | unset, `auto`, `1`, or `0` | Selects Linux Docker-driver GPU routing. Unset or `auto` uses native OpenShell GPU injection on ordinary native Linux and the compatibility patch on Docker Desktop WSL and Jetson/Tegra. `1` forces the compatibility patch. `0` selects native injection on ordinary native Linux and Jetson/Tegra, but Docker Desktop WSL ignores it. On Jetson/Tegra, use `0` only for troubleshooting because it bypasses the device-group propagation needed for CUDA. |
| `NEMOCLAW_OPENSHELL_GATEWAY_CONTAINER_PATCH` | `1` to enable; disabled by default | Explicitly opts into the Linux gateway compatibility container for an older host ABI or a diagnostic run. This mode uses host networking and mounts the Docker socket read-only, but the socket still exposes the privileged Docker API. Use it only on a trusted local host; prefer OpenShell 0.0.71's directly supported glibc 2.28+ path. See the [OpenShell 0.0.71 gateway auth review](../security/openshell-0.0.71-gateway-auth-review#source-of-truth-boundaries). |
| `NEMOCLAW_OPENSHELL_GATEWAY_BIN` | path | Advanced override for the `openshell-gateway` binary used by the Linux Docker-driver standalone fallback. Defaults to the binary next to `openshell`, then common install paths. |
| `NEMOCLAW_OPENSHELL_SANDBOX_BIN` | path | Advanced override for the `openshell-sandbox` binary used by the Linux Docker-driver standalone fallback. Defaults to the binary next to `openshell`, then common install paths. |
Expand Down
Loading
Loading