Skip to content

fix(non-interactive-env): detect shell type for csh/tcsh env var syntax (fixes #2089)#2769

Merged
code-yeongyu merged 1 commit intocode-yeongyu:devfrom
MoerAI:fix/csh-shell-env-support
Mar 24, 2026
Merged

fix(non-interactive-env): detect shell type for csh/tcsh env var syntax (fixes #2089)#2769
code-yeongyu merged 1 commit intocode-yeongyu:devfrom
MoerAI:fix/csh-shell-env-support

Conversation

@MoerAI
Copy link
Copy Markdown
Contributor

@MoerAI MoerAI commented Mar 23, 2026

Summary

  • Add csh/tcsh shell detection and setenv syntax to the non-interactive-env hook

Problem

The non-interactive-env hook hardcodes "unix" as the shell type when building environment variable prefixes for git commands. This generates export VAR=value syntax which is incompatible with csh/tcsh shells, where setenv VAR value is required. Users running csh/tcsh see syntax errors when the hook prepends env vars to git commands.

Fix

  1. Added "csh" to the ShellType union in shell-env.ts
  2. Updated detectShellType() to check $SHELL for csh/tcsh patterns
  3. Added setenv VAR value; syntax generation in buildEnvPrefix() for csh
  4. Replaced the hardcoded "unix" in the non-interactive-env hook with detectShellType() call

Changes

File Change
src/shared/shell-env.ts Added "csh" to ShellType, csh detection in detectShellType(), csh cases in shellEscape() and buildEnvPrefix()
src/hooks/non-interactive-env/non-interactive-env-hook.ts Import detectShellType, use it instead of hardcoded "unix"

Fixes #2089


Summary by cubic

Detects csh/tcsh shells and uses setenv syntax in the non-interactive env hook, preventing syntax errors in git commands. Restores non-interactive behavior for csh/tcsh users.

  • Bug Fixes
    • Detects csh/tcsh via $SHELL and adds "csh" to ShellType.
    • Generates setenv VAR value; in buildEnvPrefix() for csh; reuses unix escaping.
    • Replaces hardcoded "unix" with detectShellType() in the non-interactive-env hook.

Written for commit 92509d8. Summary will update on new commits.

@MoerAI
Copy link
Copy Markdown
Contributor Author

MoerAI commented Mar 23, 2026

I have read the CLA Document and I hereby sign the CLA

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: 92509d8cfb

ℹ️ About Codex in GitHub

Your team has set up Codex to 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 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines +55 to +57
// Detect the current shell type for proper env var syntax (export for bash/zsh, setenv for csh/tcsh, etc.)
const shellType = detectShellType()
const envPrefix = buildEnvPrefix(NON_INTERACTIVE_ENV, shellType)
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Badge Keep Unix export syntax for Bash tool commands

This hook only runs for input.tool === "bash", and the existing behavior in src/hooks/non-interactive-env/index.test.ts:209-303 explicitly documents that the Bash tool executes in a Unix-like shell even when the parent OpenCode process was launched from PowerShell or Windows cmd. Switching to detectShellType() here keys off the host process environment (PSModulePath, $SHELL) instead of the tool that will actually parse the command, so users who start OpenCode from PowerShell, cmd, or tcsh will now prepend $env:..., set ..., or setenv ... to a Bash command line. Bash treats those prefixes as syntax errors, so every git command in those environments regresses from “works with non-interactive vars” to “fails before git starts.”

Useful? React with 👍 / 👎.

Copy link
Copy Markdown

@cubic-dev-ai cubic-dev-ai bot left a comment

Choose a reason for hiding this comment

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

2 issues found across 2 files

Confidence score: 2/5

  • High-confidence, user-impacting bug risk: in src/hooks/non-interactive-env/non-interactive-env-hook.ts, detectShellType() can return csh and produce setenv output even though this hook is for the bash tool, so generated commands may fail to execute.
  • src/shared/shell-env.ts uses substring matching on full SHELL paths, which can misclassify shells (e.g., paths containing csh) and propagate incorrect env syntax decisions.
  • Given the two medium-high severity findings (7/10 and 8/10) with strong confidence, this is not yet safe to merge without fixes.
  • Pay close attention to src/hooks/non-interactive-env/non-interactive-env-hook.ts, src/shared/shell-env.ts - shell misdetection can generate incompatible environment export commands.
Prompt for AI agents (unresolved issues)

Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.


<file name="src/shared/shell-env.ts">

<violation number="1" location="src/shared/shell-env.ts:18">
P1: Shell detection uses unsafe substring matching on the full SHELL path that generates false positives for paths containing 'csh'.</violation>
</file>

<file name="src/hooks/non-interactive-env/non-interactive-env-hook.ts">

<violation number="1" location="src/hooks/non-interactive-env/non-interactive-env-hook.ts:56">
P1: The `detectShellType()` call can return "csh" for csh/tcsh users, generating `setenv` syntax that bash cannot execute. Since this hook only processes the `bash` tool, it must always use POSIX `export` syntax compatible with bash/sh, not the host's login shell syntax.</violation>
</file>

Reply with feedback, questions, or to request a fix. Tag @cubic-dev-ai to re-run a review.


if (process.env.SHELL) {
const shell = process.env.SHELL
if (shell.includes("csh") || shell.includes("tcsh")) {
Copy link
Copy Markdown

@cubic-dev-ai cubic-dev-ai bot Mar 23, 2026

Choose a reason for hiding this comment

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

P1: Shell detection uses unsafe substring matching on the full SHELL path that generates false positives for paths containing 'csh'.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At src/shared/shell-env.ts, line 18:

<comment>Shell detection uses unsafe substring matching on the full SHELL path that generates false positives for paths containing 'csh'.</comment>

<file context>
@@ -14,6 +14,10 @@ export function detectShellType(): ShellType {
 
   if (process.env.SHELL) {
+    const shell = process.env.SHELL
+    if (shell.includes("csh") || shell.includes("tcsh")) {
+      return "csh"
+    }
</file context>
Fix with Cubic

// (via Git Bash, WSL, etc.), so always use unix export syntax.
const envPrefix = buildEnvPrefix(NON_INTERACTIVE_ENV, "unix")
// Detect the current shell type for proper env var syntax (export for bash/zsh, setenv for csh/tcsh, etc.)
const shellType = detectShellType()
Copy link
Copy Markdown

@cubic-dev-ai cubic-dev-ai bot Mar 23, 2026

Choose a reason for hiding this comment

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

P1: The detectShellType() call can return "csh" for csh/tcsh users, generating setenv syntax that bash cannot execute. Since this hook only processes the bash tool, it must always use POSIX export syntax compatible with bash/sh, not the host's login shell syntax.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At src/hooks/non-interactive-env/non-interactive-env-hook.ts, line 56:

<comment>The `detectShellType()` call can return "csh" for csh/tcsh users, generating `setenv` syntax that bash cannot execute. Since this hook only processes the `bash` tool, it must always use POSIX `export` syntax compatible with bash/sh, not the host's login shell syntax.</comment>

<file context>
@@ -52,9 +52,9 @@ export function createNonInteractiveEnvHook(_ctx: PluginInput) {
-      // (via Git Bash, WSL, etc.), so always use unix export syntax.
-      const envPrefix = buildEnvPrefix(NON_INTERACTIVE_ENV, "unix")
+      // Detect the current shell type for proper env var syntax (export for bash/zsh, setenv for csh/tcsh, etc.)
+      const shellType = detectShellType()
+      const envPrefix = buildEnvPrefix(NON_INTERACTIVE_ENV, shellType)
       
</file context>
Fix with Cubic

@MoerAI
Copy link
Copy Markdown
Contributor Author

MoerAI commented Mar 23, 2026

Re: issues identified by cubic.

P1 (detectShellType returns csh for bash tool): Acknowledged concern. The bash tool in OpenCode spawns a shell using the system's $SHELL or falls back to /bin/sh. When a user's login shell is csh/tcsh, the $SHELL environment variable reflects that. While the tool name is "bash", the actual shell process inherits the user's environment. The original reporter of #2089 confirmed that export syntax fails in their csh environment, meaning the spawned process respects $SHELL.

If the maintainer confirms that the bash tool always spawns /bin/bash regardless of $SHELL, then this detection is unnecessary and we should revert to hardcoded "unix". Happy to adjust based on clarification.

P2 (substring matching on SHELL paths): The check is shellPath.includes("csh") which would match /bin/csh, /usr/bin/tcsh, and /usr/local/bin/csh. The risk of false positives (a shell path containing "csh" that isn't actually csh) is negligible in practice. However, if stricter matching is preferred, we could use /\bcsh$|\btcsh$/ to match only the basename.

Copy link
Copy Markdown
Owner

@code-yeongyu code-yeongyu left a comment

Choose a reason for hiding this comment

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

LGTM. Clean fix for csh/tcsh shell detection with proper setenv syntax. All CI passing. Fixes #2089.

@code-yeongyu code-yeongyu merged commit f1eaa7b into code-yeongyu:dev Mar 24, 2026
8 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Bug]: Agent tries to set environment variables using bash commands like "export CI=true, ..." in csh environment

2 participants