Skip to content

fix: prevent undeletable nul file on Windows#13406

Open
ASidorenkoCode wants to merge 1 commit intoanomalyco:devfrom
ASidorenkoCode:fix/windows-nul-file
Open

fix: prevent undeletable nul file on Windows#13406
ASidorenkoCode wants to merge 1 commit intoanomalyco:devfrom
ASidorenkoCode:fix/windows-nul-file

Conversation

@ASidorenkoCode
Copy link
Contributor

@ASidorenkoCode ASidorenkoCode commented Feb 13, 2026

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 #13369
Fixes #11586
Fixes #11403
Fixes #8108

On Windows, OpenCode uses Git Bash as the shell. When the AI model generates
Windows-style `> nul` or `2>nul` redirection, Git Bash interprets this literally
and creates 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.

This adds a `sanitizeNullRedirect()` helper that rewrites null-device redirections
to match the actual shell: `>nul` becomes `>/dev/null` for Git Bash, and vice versa
for cmd.exe/PowerShell. Applied in both the bash tool and the shell execution path.
Also adds guidance to the bash tool description so models prefer `/dev/null`.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@adrunkhuman
Copy link

The regex (\d?>)\s*(?:nul|NUL)\b will convert >nul even inside quoted strings, comments, and heredocs:

echo "Use >nul here"           # becomes "Use >/dev/null here"
# Tip: use >nul on Windows     # becomes # Tip: use >/dev/null on Windows

The \b word boundary also matches at /, so >nul/backup.txt becomes >/dev/null/backup.txt.

@breggles
Copy link

How to delete the undeletable file: https://dev.to/tishonator/how-to-delete-the-un-deletable-nul-file-created-by-claude-console-on-windows-11-33a9

(Still needs fixing, of course.)

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

Projects

None yet

3 participants