Skip to content

feat(exec): Support custom shell path for executing commands#39413

Closed
ZtRXR wants to merge 1 commit intoopenclaw:mainfrom
ZtRXR:feat/custom-shell-path
Closed

feat(exec): Support custom shell path for executing commands#39413
ZtRXR wants to merge 1 commit intoopenclaw:mainfrom
ZtRXR:feat/custom-shell-path

Conversation

@ZtRXR
Copy link
Copy Markdown

@ZtRXR ZtRXR commented Mar 8, 2026

Summary

Describe the problem and fix in 2–5 bullets:

  • Problem: The exec tool hardcodes shell paths and cannot be customized by users. Windows defaults to PowerShell without providing configuration options to specify other shells (e.g., bash, zsh, custom shells).
  • Why it matters: Users may need to execute commands in specific shell environments (e.g., bash scripts, custom shells), and hardcoded shell selection limits flexibility and cross-platform compatibility.
  • What changed: Added tools.exec.shell configuration option that allows users to specify custom shell paths in configuration files or at the Agent level. Configured paths take priority, with fallback to default logic if not configured.
  • What did NOT change (scope boundary): Default shell selection logic remains unchanged and backward compatible. No modifications to security policies, permission checks, or command execution flows.

Change Type (select all)

  • Bug fix
  • Feature
  • Refactor
  • Docs
  • Security hardening
  • Chore/infra

Scope (select all touched areas)

  • Gateway / orchestration
  • Skills / tool execution
  • Auth / tokens
  • Memory / storage
  • Integrations
  • API / contracts
  • UI / DX
  • CI/CD / infra

Linked Issue/PR

  • Closes # (none)
  • Related # (none)

User-visible / Behavior Changes

List user-visible changes (including defaults/config).

  • New configuration option tools.exec.shell (string type, optional):
    • Global level: tools.exec.shell
    • Agent level: agents[].tools.exec.shell
  • Configuration priority: Agent level > Global level > Default logic
  • Default behavior unchanged: Windows uses PowerShell, Linux/macOS uses $SHELL or sh
  • Configuration examples:
    tools:
      exec:
        shell: "/bin/bash"  # Linux/macOS
        # or
        shell: "C:\\Windows\\System32\\WindowsPowerShell\\v1.0\\powershell.exe"  # Windows

Security Impact (required)

  • New permissions/capabilities? No
  • Secrets/tokens handling changed? No
  • New/changed network calls? No
  • Command/tool execution surface changed? No - Only changes shell path, does not modify command execution permission checks or security policies
  • Data access scope changed? No
  • If any Yes, explain risk + mitigation: N/A

Repro + Verification

Environment

  • OS: Windows 11 / Linux / macOS
  • Runtime/container: Node.js 22+
  • Model/provider: N/A
  • Integration/channel (if any): N/A
  • Relevant config (redacted): tools.exec.shell

Steps

  1. Add tools.exec.shell configuration option to config file
  2. Execute command using openclaw agent
  3. Verify that the configured shell path is used

Expected

  • Use configured shell path for command execution
  • Fallback to default logic if not configured

Actual

  • Matches expected behavior

Evidence

Attach at least one:

  • Failing test/log before + passing after - Build passes, no type errors
  • Trace/log snippets
  • Screenshot/recording
  • Perf numbers (if relevant)

Build verification:

✓ Build complete in 3584ms
327 files, total: 10.20 MB

Human Verification (required)

What you personally verified (not just CI), and how:

  • Verified scenarios:
    • Custom shell path takes priority when configured
    • Fallback to default logic when not configured
    • Windows correctly identifies PowerShell and cmd.exe
    • Type definitions and config schema are correct
  • Edge cases checked:
    • Empty string shell path
    • Non-existent shell path (runtime error, not config error)
    • Windows .ps1 and .exe extension handling
  • What you did not verify:
    • Actual execution on Linux/macOS (only verified compilation on Windows)
    • Compatibility with all existing tools (relies on CI)

Compatibility / Migration

  • Backward compatible? Yes - Default behavior completely unchanged
  • Config/env changes? Yes - New optional configuration option
  • Migration needed? No
  • If yes, exact upgrade steps: N/A

Failure Recovery (if this breaks)

  • How to disable/revert this change quickly: Remove tools.exec.shell from configuration to restore default behavior
  • Files/config to restore: No restoration needed, configuration option is optional
  • Known bad symptoms reviewers should watch for:
    • If configured shell path doesn't exist, command execution will fail
    • If configured shell arguments are incorrect, command parsing errors may occur

Risks and Mitigations

List only real risks for this PR. Add/remove entries as needed. If none, write None.

  • Risk: Users may configure incorrect shell paths or arguments, causing command execution failures

    • Mitigation:
      1. Configuration is optional, default behavior is well-tested
      2. Runtime errors will provide clear messages (shell not found or cannot execute)
      3. Documentation will explain correct configuration format
  • Risk: Windows shell arguments differ from Unix (-NoProfile -NonInteractive -Command vs -c)

    • Mitigation:
      1. Code automatically determines which arguments to use based on file extension
      2. .ps1/.exe or no extension uses PowerShell arguments
      3. Other extensions use cmd.exe arguments
  • Risk: Cross-platform configuration sync issues (same config behaves differently on different OS)

    • Mitigation:
      1. Recommend users use different configs for different platforms
      2. Or use environment variables/conditional configs (if supported)

允许在执行命令时指定自定义shell路径,增强在不同环境下的兼容性。修改包括类型定义、配置验证和执行逻辑的调整。
@openclaw-barnacle openclaw-barnacle Bot added agents Agent runtime and tooling size: XS labels Mar 8, 2026
@greptile-apps
Copy link
Copy Markdown
Contributor

greptile-apps Bot commented Mar 8, 2026

Greptile Summary

This PR adds a tools.exec.shell configuration option allowing users to specify a custom shell executable path at the global or per-agent level, with automatic fallback to existing default logic when unset. The change is backward compatible and touches the config schema, type definitions, and the shell-resolution utility in a consistent and minimally invasive way.

Key observations:

  • The overall implementation is clean and follows the existing patterns for how exec defaults are resolved and threaded through the call stack.
  • Windows shell detection correctly identifies pwsh/powershell and cmd by stripping the file extension before comparison, falling back to -c for all other shells (appropriate for bash-like shells on Windows via Git Bash / WSL).
  • The configured shell is correctly bypassed when sandbox (Docker) mode is active, since the host shell path is meaningless inside a container — though this is done silently without any user-facing warning.
  • A minor edge case: a whitespace-only shell string (e.g., " ") passes the if (configuredShell) truthy guard and results in a runtime spawn failure rather than falling back to the default logic, which would be the more user-friendly outcome.

Confidence Score: 4/5

  • This PR is safe to merge — it is purely additive, backward compatible, and touches only shell resolution logic with no changes to security policy or permission checks.
  • The implementation is well-structured and consistent with existing patterns. Default behavior is fully preserved when the option is not set. The two issues noted (whitespace-only input edge case and silent ignore in sandbox mode) are minor style/UX concerns, not blocking bugs. No tests were added or modified, but the PR author notes only compilation was verified, which is appropriate for a config-passthrough change of this scope.
  • src/agents/shell-utils.ts — the new getShellConfig branch is the heart of the feature and warrants the most scrutiny, particularly the Windows fallback path and the whitespace-string edge case.

Comments Outside Diff (1)

  1. src/agents/bash-tools.exec-runtime.ts, line 369-386 (link)

    shell config silently ignored in sandbox mode

    When opts.sandbox is set the function returns early with a Docker-based spec, and the configured opts.shell value is never used. This is architecturally correct (the host shell path is irrelevant inside a container), but a user who sets tools.exec.shell in their config while also running in sandbox mode will get no indication that the setting has no effect. A debug-level log or a warning added to opts.warnings before the early return would make this much easier to diagnose.

    Prompt To Fix With AI
    This is a comment left during a code review.
    Path: src/agents/bash-tools.exec-runtime.ts
    Line: 369-386
    
    Comment:
    **`shell` config silently ignored in sandbox mode**
    
    When `opts.sandbox` is set the function returns early with a Docker-based spec, and the configured `opts.shell` value is never used. This is architecturally correct (the host shell path is irrelevant inside a container), but a user who sets `tools.exec.shell` in their config while also running in sandbox mode will get no indication that the setting has no effect. A debug-level log or a warning added to `opts.warnings` before the early return would make this much easier to diagnose.
    
    How can I resolve this? If you propose a fix, please make it concise.

Last reviewed commit: c672c0f

Comment thread src/agents/shell-utils.ts

export function getShellConfig(): { shell: string; args: string[] } {
export function getShellConfig(configuredShell?: string): { shell: string; args: string[] } {
if (configuredShell) {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Whitespace-only shell path passes truthy check

if (configuredShell) is truthy for strings like " ", which would result in an attempt to spawn " " as the shell executable at runtime. While any invalid shell path is documented to produce a runtime error, trimming first would give a cleaner developer experience (falling back to the default logic instead of a confusing spawn failure).

Suggested change
if (configuredShell) {
if (configuredShell?.trim()) {
Prompt To Fix With AI
This is a comment left during a code review.
Path: src/agents/shell-utils.ts
Line: 43

Comment:
**Whitespace-only shell path passes truthy check**

`if (configuredShell)` is truthy for strings like `"   "`, which would result in an attempt to spawn `"   "` as the shell executable at runtime. While any invalid shell path is documented to produce a runtime error, trimming first would give a cleaner developer experience (falling back to the default logic instead of a confusing spawn failure).

```suggestion
  if (configuredShell?.trim()) {
```

How can I resolve this? If you propose a fix, please make it concise.

Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: c672c0ff6c

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

Comment on lines 388 to 389
if (opts.usePty) {
return {
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Propagate configured shell to PTY executions

When usePty is true, this branch returns only ptyCommand, and the supervisor later chooses its own shell via getShellConfig() without the configured override, so tools.exec.shell is ignored unless PTY startup fails and falls back to child argv. In PTY-heavy workflows (interactive tools, terminal UIs), users who set a custom shell will silently run under the default shell, which can break shell-specific commands or environment setup.

Useful? React with 👍 / 👎.

scopeKey: defaults?.scopeKey,
sessionKey: notifySessionKey,
timeoutSec: effectiveTimeout,
shell: defaults?.shell,
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Pass configured shell into gateway approval runs

The configured shell is threaded only through this direct runExecProcess call, but approved gateway executions still invoke runExecProcess from processGatewayAllowlist without a shell argument (src/agents/bash-tools.exec-host-gateway.ts:247-263). That makes behavior inconsistent: the same command honors tools.exec.shell in the normal path but reverts to default shell once it goes through approval, which is a user-visible regression for gateway/ask flows.

Useful? React with 👍 / 👎.

@openclaw-barnacle
Copy link
Copy Markdown

This pull request has been automatically marked as stale due to inactivity.
Please add updates or it will be closed.

@openclaw-barnacle openclaw-barnacle Bot added the stale Marked as stale due to inactivity label Apr 23, 2026
@clawsweeper
Copy link
Copy Markdown
Contributor

clawsweeper Bot commented Apr 26, 2026

Thanks for the context here. I swept through the related work, and this is now duplicate or superseded.

Close as duplicate/superseded: the remaining configurable exec shell work is already tracked by the canonical open issue, while this PR is an incomplete, conflicting implementation of the same security-sensitive exec contract.

So I’m closing this here and keeping the remaining discussion on the canonical linked item.

Review details

Best possible solution:

Keep the canonical issue open for a maintainer-approved shell-selection contract, and close this stale branch rather than splitting design review across duplicate implementations.

Do we have a high-confidence way to reproduce the issue?

Yes. Static tracing shows the PR would pass defaults?.shell only to direct host exec, while PTY supervisor and approval follow-up paths still resolve shell context independently; current main also lacks the requested config key.

Is this the best way to solve the issue?

No. A simple string passthrough is not the narrow maintainable solution for this command-execution boundary; the contract needs consistent PTY, approval, node/sandbox, policy, docs, and test coverage and is already tracked at #49931.

Security review:

Security review needs attention: The patch changes command interpreter selection without preserving that execution context through approval-backed and PTY runs.

  • [medium] Bind shell overrides into approval semantics — src/agents/bash-tools.exec.ts:485
    A configured shell changes how command text is interpreted, but the PR does not carry that shell into gateway approval follow-up execution or define policy coverage for allowlists, safe bins, PATH, WSL, node, and sandbox behavior.
    Confidence: 0.78

What I checked:

Likely related people:

  • steipete: Recent GitHub file history shows repeated maintenance across exec runtime, exec config types/schema, supervisor, and exec docs that define this surface. (role: recent maintainer; confidence: high; commits: c6817d8d7ab9, 66336bf7c846, fa525bf21280; files: src/agents/bash-tools.exec-runtime.ts, src/config/types.tools.ts, src/config/zod-schema.agent-runtime.ts)
  • NewdlDewdl: The merged shell startup-file suppression repair credits NewdlDewdl for work that changed src/agents/shell-utils.ts, which any shell override must preserve. (role: adjacent shell behavior contributor; confidence: medium; commits: ea9f17256a4b; files: src/agents/shell-utils.ts, src/agents/shell-utils.test.ts)
  • sk7n4k3d: Authored the current placeholder-shell fallback for /usr/bin/false and nologin, another branch of the shell-selection contract touched by this request. (role: adjacent shell behavior contributor; confidence: medium; commits: 7b414d8c0b9f; files: src/agents/shell-utils.ts)
  • vincentkoc: Recently touched exec runtime telemetry and is tied to adjacent runtime-marker documentation that intersects with shell execution behavior. (role: recent adjacent maintainer; confidence: medium; commits: 3e3bba4f305e; files: src/agents/bash-tools.exec-runtime.ts, docs/help/environment.md)

Codex review notes: model gpt-5.5, reasoning high; reviewed against 624af621e663.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

agents Agent runtime and tooling size: XS

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant