Zero-config whitespace doctor: find (and --fix) trailing whitespace, mixed line endings, missing/extra final newlines, BOMs and mixed indentation. Zero dependencies.
Project description
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.
pipx run 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)
pipx run wssweep --fix # clean them in place
No config file, no framework. Exits non-zero when it finds issues, so it drops
straight into CI. Pure standard library. Also on npm (npx 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, 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 — pip/npx, 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 Python and Node.
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 Python and Node 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
pip install wssweep # or pipx run wssweep
npm i -g wssweep # Node build, identical behaviour
Python ≥ 3.8 or Node ≥ 18. No dependencies.
License
MIT
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file wssweep-0.1.0.tar.gz.
File metadata
- Download URL: wssweep-0.1.0.tar.gz
- Upload date:
- Size: 13.6 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.11.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
587cede635bc43f91d69628ecfb3117037152b496265e5e59b8f27b09c63c597
|
|
| MD5 |
f40f39ed099fe825bf735d21b5bec12b
|
|
| BLAKE2b-256 |
af2aa0a12a27dfb9ef19440016e678095f15e31d6b8a6406b1ae04f7c1d3f8e0
|
File details
Details for the file wssweep-0.1.0-py3-none-any.whl.
File metadata
- Download URL: wssweep-0.1.0-py3-none-any.whl
- Upload date:
- Size: 11.9 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.11.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
51b15adc3c3162e6cdd516cff8e9affc13a25a2cd3e7984ca7740c8917f1a025
|
|
| MD5 |
63e1fab976dbcd0a14e3e4758860252d
|
|
| BLAKE2b-256 |
804157735a5bd7dae6e6d39e635c20d0f18604b20211ccbacb517536da8a595d
|