Skip to content

[deslop] Two Windows-specific bugs: literal nul file creation + broken jscpd output path #270

@giinie

Description

@giinie

Summary

The /deslop command creates two artifact files on Windows due to Unix-specific assumptions in the codebase. Both bugs are platform-specific — they do not affect macOS/Linux users.

Environment

  • OS: Windows 11 (Git Bash via Node.js child_process)
  • agentsys version: 5.1.0 (from ~/.claude/plugins/cache/agentsys/deslop/5.1.0/)
  • Host: oh-my-claudecode (opencode)

Bug 1: Literal nul file created by 2>/dev/null in SKILL.md

Location

skills/deslop/SKILL.md — Line 49 (approximate, in the detection script execution section)

The SKILL.md contains a shell command with 2>/dev/null. When this command is executed via Node.js child_process on Windows (through Git Bash), the redirect creates a literal file named nul (0 bytes) in the project directory instead of routing stderr to the null device.

Root Cause

On native Windows, NUL is a reserved device name. However, when Git Bash is invoked from Node.js child_process, the shell redirect 2>/dev/null can fail to resolve /dev/null correctly, falling back to creating a literal file.

Evidence

$ ls -la nul
-rw-r--r-- 1 user 197121 0 Feb 25 14:19 nul

File was created at session start time (10:48:46) and modified during deslop run (13:03:54).

Suggested Fix

Use platform-aware null device routing:

const nullDevice = process.platform === 'win32' ? 'NUL' : '/dev/null';
// Then use nullDevice in command construction

Or suppress stderr at the Node.js level instead of shell-level:

execSync(cmd, { stdio: ['pipe', 'pipe', 'ignore'] });

Bug 2: jscpd --output NUL creates broken path filename

Location

lib/patterns/cli-enhancers.js — Lines ~351-358

Description

The code correctly detects Windows and passes --output NUL to jscpd:

const nullOutput = process.platform === 'win32' ? 'NUL' : '/dev/null';
// ...
// --output ${nullOutput}

However, jscpd interprets NUL as a directory path, not a null device. It concatenates the project's absolute path with NUL without path separators, producing a mangled filename like:

D:JWSAIAgentvibecodingpracticefridge-chef.opencodedeslop-raw.txt

This creates a 264KB garbage file in the project root.

Evidence

The broken-path file is byte-identical to .opencode/deslop-raw.txt (264,029 bytes), confirming jscpd wrote the output to a mangled path instead of discarding it.

Suggested Fix

Instead of passing --output NUL to jscpd, use a temp directory and clean it up:

const os = require('os');
const tempDir = fs.mkdtempSync(path.join(os.tmpdir(), 'deslop-'));
// Use tempDir as --output target
// Clean up after jscpd completes
fs.rmSync(tempDir, { recursive: true, force: true });

Or simply omit the --output flag if jscpd supports it.


Impact

Both bugs are cosmetic but annoying — they leave unexpected files in the user's project directory that may get accidentally committed to git. The nul file is especially confusing as it has no extension and zero bytes.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions