wssweep
v0.1.0
Published
Zero-config whitespace doctor: find (and --fix) trailing whitespace, mixed line endings, missing/extra final newlines, BOMs and mixed indentation. Zero dependencies.
Maintainers
Readme
wssweep
A zero-config whitespace doctor. Run it on any repo and it instantly finds —
and with --fix, cleans — the whitespace problems that pollute diffs and break
across platforms: trailing whitespace, mixed CRLF/LF line endings, a missing
final newline, extra trailing blank lines, a UTF-8 BOM, lone CRs, and tabs mixed
with spaces in indentation.
npx wssweep
# config.yml (1)
# - mixed-eol mixed line endings (CRLF×3, LF×1)
#
# src/app.js (2)
# - missing-final-newline no newline at end of file
# 14: trailing-whitespace trailing whitespace
#
# ✖ 3 whitespace issues in 2 files (missing-final-newline=1, mixed-eol=1, trailing-whitespace=1)
npx wssweep --fix # clean them in placeNo config file, no framework. Exits non-zero when it finds issues, so it drops
straight into CI. Also on PyPI (pipx run wssweep) — the two builds produce
byte-for-byte identical output and identical fixes.
Why another whitespace tool?
Because today this takes three or four tools wired together:
- editorconfig-checker reports, but needs you to author an
.editorconfigfirst, and it can't fix anything. - pre-commit's
trailing-whitespace/end-of-file-fixer/mixed-line-endinghooks do fix — but only inside the pre-commit framework, they're Python-only, and they're three separate hooks. Nobody runs them ad-hoc on a fresh checkout. - prettier fixes whitespace only as a side effect of reformatting all your code, is language-aware, and won't touch files it can't parse.
- dos2unix only does line endings.
wssweep is the one command — npx/pip, zero config — that reports all
seven whitespace smells at once with line numbers and optionally fixes them in
place, with a clean CI exit code, identical on Node and Python.
What it checks
| check | what | --fix |
|---|---|---|
| trailing-whitespace | space/tab at end of a line | trims it |
| mixed-eol | a file containing both CRLF and LF | normalizes to LF |
| lone-cr | a bare CR (old-Mac line ending) | normalizes |
| missing-final-newline | non-empty file not ending in a newline | appends one |
| trailing-blank-lines | extra blank line(s) at end of file | collapses to one |
| utf8-bom | a leading UTF-8 BOM | strips it |
| mixed-indentation | tabs and spaces in one indent | report-only (needs your tab width) |
Opinionated, zero-config defaults: a consistently-CRLF file is fine (only
mixed endings are flagged), .bat/.cmd keep CRLF when fixed, and Markdown's
two-trailing-spaces hard line break is preserved (trailing-whitespace is skipped
in .md).
Usage
wssweep # scan the current directory
wssweep src/ docs/ # scan specific paths
wssweep --fix # fix in place (atomic; only files that change)
wssweep --crlf --fix # normalize endings to CRLF instead of LF
wssweep --skip=mixed-indentation # turn off a check
wssweep --exclude='*.min.js' # skip paths by glob (repeatable)
wssweep --json # machine output (byte-identical both builds).git, node_modules, dist, build, vendor, .venv and friends are
skipped by default, as are binary files (detected by extension + a NUL-byte /
non-UTF-8 content check) and files over 5 MB. --all overrides those skips.
Exit codes: 0 clean · 1 issues found · 2 error. (--fix exits 0 once
everything fixable is fixed; a leftover mixed-indentation keeps it 1.)
How it works
It reads every file as raw bytes and scans a byte-faithful (latin-1) view, so
it never mangles encodings and the Node and Python builds agree to the byte: line
endings are classified from the bytes (never splitlines, which over-splits),
"whitespace" means exactly space and tab (never \s, which differs across
languages), and --fix writes raw bytes atomically (temp file + rename),
touching only files that actually change and preserving file modes. Fixing is
idempotent — run it twice, the second run does nothing.
Install
npm i -g wssweep # or npx wssweep
pip install wssweep # Python build, identical behaviourNode ≥ 18 or Python ≥ 3.8. No dependencies.
License
MIT
