Inspect and normalize text trees without overwriting the originals
  • JavaScript 100%
Find a file
Repository files (latest commit first)
Filename Latest commit message Latest commit date
2026-07-21 05:32:41 +00:00
.forgejo/workflows Build TextSuture 0.1.0 2026-07-21 05:32:41 +00:00
bin Build TextSuture 0.1.0 2026-07-21 05:32:41 +00:00
src Build TextSuture 0.1.0 2026-07-21 05:32:41 +00:00
test Build TextSuture 0.1.0 2026-07-21 05:32:41 +00:00
.gitignore Build TextSuture 0.1.0 2026-07-21 05:32:41 +00:00
LICENSE Build TextSuture 0.1.0 2026-07-21 05:32:41 +00:00
package-lock.json Build TextSuture 0.1.0 2026-07-21 05:32:41 +00:00
package.json Build TextSuture 0.1.0 2026-07-21 05:32:41 +00:00
PRIVACY.md Build TextSuture 0.1.0 2026-07-21 05:32:41 +00:00
README.md Build TextSuture 0.1.0 2026-07-21 05:32:41 +00:00
SECURITY.md Build TextSuture 0.1.0 2026-07-21 05:32:41 +00:00

TextSuture

TextSuture inspects a local directory for text-boundary problems that commonly become noisy diffs or cross-platform failures:

  • invalid UTF-8 and unsupported UTF-16 input,
  • UTF-8 byte-order marks,
  • mixed CRLF, LF, and bare-CR line endings,
  • non-LF line endings,
  • missing final newlines,
  • symbolic links and special files that make a copy incomplete.

It is report-only by default. With --output, it writes a separate, verified tree: valid UTF-8 text is converted to BOM-free LF with a final LF, while binary files are copied byte-for-byte. It never edits the source tree.

Use

npx textsuture ./project
npx textsuture --check ./project
npx textsuture --json ./project
npx textsuture --output ../project-normalized ./project

Exit statuses:

  • 0: scan completed; without --check, findings are informational.
  • 1: --check completed and found one or more issues.
  • 2: usage, filesystem, resource-limit, or incomplete-scan failure.

Fail-closed boundaries

TextSuture scans at most 1,000 file entries, 1,000 subdirectories, 64 directory levels, 2 MiB per file, and 64 MiB total. It does not follow symbolic links. Files are opened with no-follow semantics where the platform supports them and checked again after opening. An output tree is refused if the scan contains a blocking error, if the destination already exists, or if the destination is inside the input tree.

The output is built in a temporary sibling directory, every file is read back and compared with its intended bytes, and only then is the directory renamed to the requested destination.

Interpretation boundary

TextSuture recognizes strict UTF-8, UTF-8 BOMs, UTF-16 BOMs, NUL-bearing binary data, three common line-ending forms, and final-newline state. It does not guess legacy encodings, prove compatibility with every parser, understand language-specific newline requirements, or certify that arbitrary binary data is safe. UTF-16 and invalid UTF-8 block normalization rather than being guessed or silently transcoded.

Privacy

All inspection and rewriting happens locally. TextSuture has no telemetry, analytics, identifiers, upload path, network client, or external service dependency. Reports contain relative paths and structural text facts; those names may still reveal project information, so review reports before sharing them.

Development

npm test
npm run check
npm pack --dry-run

TextSuture requires Node.js 20 or later and has no runtime dependencies.