Zerowidth CleanerAll measured guides

CLAUDE WATERMARK REMOVER · PRACTICAL TEST

Why does a Windows filename still include backslashes on POSIX?

Deleting U+200B fixes our marked filename, but it does not change separator rules. Node path.win32 returns report.txt; path.posix treats the entire backslash path as the basename.

Tested October 10, 2026 · v24.19.0 · 4 measured runs

Open the Claude text cleaner · Full measured data

Code-point comparison for Marked backslash path

Measured inputs and outputs

These are locally constructed test strings, not evidence that Claude inserts these characters. We executed the saved homepage script snapshot with a minimal DOM harness and compared exact strings. The invisible-checkbox state and dash mode appear in each row. The observations below test this page's specific question. Destination observations run independently on the exact input and cleaned strings in the recorded Node runtime. We make no detector-score or statistical-watermark removal claim.

Before and after observations; full code points and strings are in the JSON download.
Fixture and modeInput string and code pointsOutput and cleaner statusObserved before / after
Marked backslash path
direct string / keep / invisible true
"C:\\docs\\re​port.txt"
U+0043 U+003A U+005C U+0064 U+006F U+0063 U+0073 U+005C U+0072 U+0065 U+200B U+0070 U+006F U+0072 U+0074 U+002E U+0074 U+0078 U+00 …
"C:\\docs\\report.txt"
Removed 1 invisible character
{"win32Base":"re​port.txt","posixBase":"C:\\docs\\re​port.txt"}
{"win32Base":"report.txt","posixBase":"C:\\docs\\report.txt"}
Plain backslash path
direct string / keep / invisible true
"C:\\docs\\report.txt"
U+0043 U+003A U+005C U+0064 U+006F U+0063 U+0073 U+005C U+0072 U+0065 U+0070 U+006F U+0072 U+0074 U+002E U+0074 U+0078 U+0074
"C:\\docs\\report.txt"
No selected invisible characters found
{"win32Base":"report.txt","posixBase":"C:\\docs\\report.txt"}
{"win32Base":"report.txt","posixBase":"C:\\docs\\report.txt"}
Forward slashes
direct string / keep / invisible true
"C:/docs/report.txt"
U+0043 U+003A U+002F U+0064 U+006F U+0063 U+0073 U+002F U+0072 U+0065 U+0070 U+006F U+0072 U+0074 U+002E U+0074 U+0078 U+0074
"C:/docs/report.txt"
No selected invisible characters found
{"win32Base":"report.txt","posixBase":"report.txt"}
{"win32Base":"report.txt","posixBase":"report.txt"}
Retained joiner
direct string / keep / invisible true
"C:\\docs\\re‍port.txt"
U+0043 U+003A U+005C U+0064 U+006F U+0063 U+0073 U+005C U+0072 U+0065 U+200D U+0070 U+006F U+0072 U+0074 U+002E U+0074 U+0078 U+00 …
"C:\\docs\\re‍port.txt"
No selected invisible characters found
{"win32Base":"re‍port.txt","posixBase":"C:\\docs\\re‍port.txt"}
{"win32Base":"re‍port.txt","posixBase":"C:\\docs\\re‍port.txt"}

The same cleaned spelling has two basenames

The first fixture is a Windows-looking path with a marker inside the final filename. Both observers receive exactly the same string. Before deletion, the Windows observer returns the marked filename while the POSIX observer returns the entire path, including its drive prefix and backslashes. After deletion, the Windows result is report.txt, but the POSIX result still includes C and both directory components. The plain backslash reference has that same dialect disagreement without any marker. Forward slashes produce report.txt in both observers. The retained joiner remains in the filename and is deliberately outside the selected deletion set.

An explicit dialect makes the experiment portable

We call path.win32.basename and path.posix.basename directly, so the host operating system does not choose the semantics. This experiment does not open a file, inspect a real drive or establish that a named resource exists. The earlier extension guide compares filename endings; this question concerns how a path parser recognizes directory separators before it extracts the final component. No separator is rewritten by the homepage callback. Removing an invisible character therefore cannot repair the wrong parser selection. All drive and folder labels are synthetic, and the reproducer needs no filesystem permission beyond reading its two downloaded local scripts.

Choose syntax from the originating format

Keep the original path and identify whether its producer promises Windows syntax, POSIX syntax or another representation such as a URL. Select the appropriate parsing API before extracting a basename. Do not infer success from a lower removal count if the result still contains directory text. Our four fixtures distinguish an edited filename, an unchanged dialect mismatch, a mutually recognized slash and a retained character. They do not test network paths, device paths, symlinks or a destination upload service. Validate the resulting component against that service separately, and avoid globally replacing punctuation without a format-specific reason.

Reproduce this test

Save reproduce.cjs and tested-app.js in the same folder. Run the command below with Node.js. The harness prints its runtime, script SHA-256 and every measured row. Compare those rows with the original record. Using a newer script or runtime creates a new experiment; retain the version information with your rerun.

node reproduce.cjs

Reference and next check

Node.js path API provides the relevant primary definition. The table and fixture analysis are original measurements. For broader inspection, use our Unicode inspector. Read the scope distinction before interpreting cleanup as a watermark result.