[PR #13406] fix: prevent undeletable nul file on Windows #14650

Open
opened 2026-02-16 18:19:25 -05:00 by yindo · 0 comments
Owner

Original Pull Request: https://github.com/anomalyco/opencode/pull/13406

State: open
Merged: No


Problem

On Windows, OpenCode uses Git Bash as the shell for executing commands. When the AI model generates commands with Windows-style > nul or 2>nul redirection, Git Bash interprets this literally (creating a file named nul) instead of routing to the null device. Since nul is a reserved Windows device name, the file cannot be deleted through normal Windows file operations.

Before (v1.1.63) — nul file created, shows in Modified Files

before (1 1 63)

The undeletable nul file in Windows Explorer

nul

After (this fix) — no nul file created

after

Root cause

spawn('echo test 2>nul', { shell: 'C:/Program Files/Git/bin/bash.exe' }) creates a literal nul file because Git Bash doesn't recognize nul as a Windows null device — it treats it as a regular filename.

Fix

Two-pronged approach:

  1. Command sanitization (Shell.sanitizeNullRedirect()): Before spawning any command, rewrites null-device redirections to match the actual shell:

    • Git Bash: >nul / 2>nul>/dev/null / 2>/dev/null
    • cmd.exe/PowerShell: >/dev/null>NUL (reverse direction)

    Applied in both bash.ts (tool execution) and prompt.ts (shell execution path).

  2. Model guidance: Added a note to the bash tool description instructing models to use /dev/null instead of nul on Windows.

Changes

  • packages/opencode/src/shell/shell.ts: Added isUnixLike() and sanitizeNullRedirect() utilities to the Shell namespace
  • packages/opencode/src/tool/bash.ts: Call Shell.sanitizeNullRedirect() before spawning
  • packages/opencode/src/tool/bash.txt: Added Windows /dev/null guidance for models
  • packages/opencode/src/session/prompt.ts: Call Shell.sanitizeNullRedirect() before spawning in shell execution path

Tested

On Windows 11 with Git Bash. Before: echo test 2>nul creates an undeletable nul file. After: no nul file is created, output is correctly suppressed.

Fixes https://github.com/anomalyco/opencode/issues/13369
Fixes https://github.com/anomalyco/opencode/issues/11586
Fixes https://github.com/anomalyco/opencode/issues/11403
Fixes https://github.com/anomalyco/opencode/issues/8108

**Original Pull Request:** https://github.com/anomalyco/opencode/pull/13406 **State:** open **Merged:** No --- ## Problem On Windows, OpenCode uses Git Bash as the shell for executing commands. When the AI model generates commands with Windows-style `> nul` or `2>nul` redirection, Git Bash interprets this literally (creating a file named `nul`) instead of routing to the null device. Since `nul` is a reserved Windows device name, the file cannot be deleted through normal Windows file operations. ### Before (v1.1.63) — `nul` file created, shows in Modified Files <img width="1348" height="951" alt="before (1 1 63)" src="https://github.com/user-attachments/assets/be691ff9-7388-40d7-8f23-70432893f1d5" /> ### The undeletable `nul` file in Windows Explorer <img width="706" height="118" alt="nul" src="https://github.com/user-attachments/assets/080f1ffc-2e3c-4d6b-8680-f39f72e509ea" /> ### After (this fix) — no `nul` file created <img width="1348" height="951" alt="after" src="https://github.com/user-attachments/assets/477ce1c0-7f65-491f-9078-119a9f911e83" /> ## Root cause `spawn('echo test 2>nul', { shell: 'C:/Program Files/Git/bin/bash.exe' })` creates a literal `nul` file because Git Bash doesn't recognize `nul` as a Windows null device — it treats it as a regular filename. ## Fix Two-pronged approach: 1. **Command sanitization** (`Shell.sanitizeNullRedirect()`): Before spawning any command, rewrites null-device redirections to match the actual shell: - Git Bash: `>nul` / `2>nul` → `>/dev/null` / `2>/dev/null` - cmd.exe/PowerShell: `>/dev/null` → `>NUL` (reverse direction) Applied in both `bash.ts` (tool execution) and `prompt.ts` (shell execution path). 2. **Model guidance**: Added a note to the bash tool description instructing models to use `/dev/null` instead of `nul` on Windows. ## Changes - **`packages/opencode/src/shell/shell.ts`**: Added `isUnixLike()` and `sanitizeNullRedirect()` utilities to the `Shell` namespace - **`packages/opencode/src/tool/bash.ts`**: Call `Shell.sanitizeNullRedirect()` before spawning - **`packages/opencode/src/tool/bash.txt`**: Added Windows `/dev/null` guidance for models - **`packages/opencode/src/session/prompt.ts`**: Call `Shell.sanitizeNullRedirect()` before spawning in shell execution path ## Tested On Windows 11 with Git Bash. Before: `echo test 2>nul` creates an undeletable `nul` file. After: no `nul` file is created, output is correctly suppressed. Fixes https://github.com/anomalyco/opencode/issues/13369 Fixes https://github.com/anomalyco/opencode/issues/11586 Fixes https://github.com/anomalyco/opencode/issues/11403 Fixes https://github.com/anomalyco/opencode/issues/8108
yindo added the pull-request label 2026-02-16 18:19:25 -05:00
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: anomalyco/opencode#14650