Winix.Squeeze
0.4.0
Prefix Reserved
dotnet tool install --global Winix.Squeeze --version 0.4.0
dotnet new tool-manifest
dotnet tool install --local Winix.Squeeze --version 0.4.0
#tool dotnet:?package=Winix.Squeeze&version=0.4.0
nuke :add-package Winix.Squeeze --version 0.4.0
squeeze
Compress and decompress files using gzip, brotli, or zstd.
Supports pipe mode (stdin/stdout), multi-file batch processing, and gzip-compatible flags for muscle memory.
Multi-format gzip replacement (and works on Linux/macOS too).
Install
Scoop (Windows)
scoop bucket add winix https://github.com/Yortw/winix
scoop install winix/squeeze
Winget (Windows, stable releases)
winget install Winix.Squeeze
.NET Tool (cross-platform)
dotnet tool install -g Winix.Squeeze
Direct Download
Download native binaries from GitHub Releases.
Usage
squeeze [options] [file...]
Examples
# Compress a file (gzip, keeps original)
squeeze data.csv
# Decompress (auto-detects format)
squeeze -d data.csv.gz
# Use brotli at maximum compression
squeeze --brotli --level 11 largefile.bin
# Use zstd (fast default)
squeeze --zstd data.csv
# Pipe mode — compress stdin to stdout
cat data.csv | squeeze > data.csv.gz
# Pipe mode — decompress
cat data.csv.gz | squeeze -d > data.csv
# Stdout mode — decompress to stdout
squeeze -c -d archive.gz | head -20
# Explicit output file
squeeze -o compressed.gz data.csv
# gzip-compatible shortcuts
squeeze -9 data.csv # max compression
squeeze -1 data.csv # fastest compression
squeeze -d -c archive.gz # decompress to stdout
# Batch compress
squeeze *.log
# JSON output for scripts
squeeze --json data.csv
Output Formats
Human (terminal, stderr):
data.csv → data.csv.gz 1,234,567 → 456,789 (63.0% saved) gzip/6 0.12s
JSON (--json, stderr):
{"tool":"squeeze","version":"0.1.0","exit_code":0,"exit_reason":"success","files":[{"input":"data.csv","output":"data.csv.gz","input_bytes":1234567,"output_bytes":456789,"ratio":0.630,"format":"gz","level":6,"seconds":0.120}]}
Options
| Option | Description |
|---|---|
-d, --decompress |
Decompress (auto-detects format from magic bytes) |
-b, --brotli |
Use brotli format |
-z, --zstd |
Use zstd format |
--level N |
Compression level (see table below) |
-1..-9 |
Shortcut for --level 1..--level 9 |
-c, --stdout |
Write to stdout instead of creating output file |
-o, --output FILE |
Explicit output file (single input only; - for stdout) |
-f, --force |
Overwrite existing output files |
--remove |
Delete input file after successful operation |
-k, --keep |
Keep original file (default; takes precedence over --remove if both supplied — emits a warning) |
-v, --verbose |
Show stats even when piped |
-q, --quiet |
Suppress stats even on terminal |
--json |
JSON output to stderr |
--no-color |
Disable colored output |
--color[=auto\|always\|never] |
Colored output: auto (default when omitted), always, or never. |
--version |
Show version |
-h, --help |
Show help |
Compression Levels
| Format | Range | Default | Notes |
|---|---|---|---|
| gzip | 1-9 | 6 | Standard deflate |
| brotli | 0-11 | 6 | Higher levels much slower but smaller |
| zstd | 1-22 | 3 | Fast default, excellent ratio at higher levels |
Wildcards on Windows
cmd.exe and PowerShell don't expand */? wildcards before starting programs, so
squeeze expands them itself on Windows — squeeze *.log works the same as in bash.
* and ? work in any path segment. [...] is matched literally (brackets are legal
Windows filename characters), and ** is rejected with an error — use Git Bash for
recursive patterns. A pattern that matches nothing is passed through unchanged,
so you get the normal "not found" error. In cmd, quoting a pattern ("*.log")
suppresses expansion; PowerShell removes quotes before squeeze sees them, so use --%
there if you need a literal. On Linux/macOS your shell expands wildcards as usual and
squeeze does nothing extra.
Exit Codes
| Code | Meaning |
|---|---|
| 0 | Success |
| 1 | Compression/decompression error: corrupt input, truncated gzip stream (ISIZE mismatch), unknown format, write failed |
| 2 | Usage error: bad arguments, missing input, --brotli with --zstd, --output empty/whitespace, --output with multiple inputs, level out of range |
When decompressing, gzip streams are validated against their RFC 1952 trailer (CRC32 + ISIZE). Truncated or corrupt streams that .NET's GZipStream would silently treat as terminated are rejected with exit 1.
Known limitation: multi-member gzip is rejected as corrupt. Concatenated gzip streams (cat a.gz b.gz, gzip file1 file2 && cat *.gz) currently fail the ISIZE check because the LAST member's ISIZE doesn't match the cumulative decompressed bytes. squeeze emits the full content to stdout, then exits 1. Workaround: use gzip -dc concat.gz directly, or decompress members individually. The trade-off was deliberate — preferring loud false-positive on rare multi-member input over silent corruption on common incompressible-truncation input. A future version may add member-by-member parsing.
The format field in JSON output emits the short form (gz, br, zst).
The errors JSON field is present (array of strings) when exit_reason is partial_failure or failure, listing per-file error messages.
Colour
- Automatic: colour when outputting to a terminal, plain when piped
--colorforces colour on (overridesNO_COLOR)--no-colorforces colour off- Respects the
NO_COLORenvironment variable (no-color.org)
Part of Winix
squeeze is part of the Winix CLI toolkit.
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net10.0 is compatible. net10.0-android was computed. net10.0-browser was computed. net10.0-ios was computed. net10.0-maccatalyst was computed. net10.0-macos was computed. net10.0-tvos was computed. net10.0-windows was computed. |
This package has no dependencies.
| Version | Downloads | Last Updated |
|---|---|---|
| 0.4.0 | 141 | 6/13/2026 |
| 0.3.0 | 122 | 5/26/2026 |
| 0.3.0-rc2 | 131 | 5/10/2026 |
| 0.2.0 | 131 | 4/16/2026 |
| 0.2.0-test4 | 120 | 4/15/2026 |
| 0.1.0 | 127 | 4/2/2026 |
| 0.1.0-preview.4 | 75 | 3/30/2026 |
| 0.1.0-preview.3 | 75 | 3/30/2026 |
| 0.1.0-preview.2 | 65 | 3/30/2026 |
| 0.1.0-preview.1 | 75 | 3/30/2026 |
## [0.3.0] - 2026-05-10
### Changed (BREAKING)
- Multi-member gzip detection dropped. Pre-fix some incompressible binary inputs triggered false multi-member detection on decode. The detection logic is now removed; the trade-off is a louder false-positive footprint on legitimately-multi-member archives in exchange for never silently corrupting single-member output. Single-member gzip — the overwhelming common case — is unaffected.
### Fixed
- Truncated gzip decode no longer silently ships garbage. ISIZE field validation now rejects malformed input with a clear error message instead of completing exit 0 with a partial / corrupt stdout.
- Framework SR resource keys (e.g. `Arg_ParamName_Name`) no longer leak into user-facing error output under `InvariantGlobalization=true`. Tool-supplied English messages now used throughout.
- IOException on read/write paths now caught and surfaced with context rather than escaping as a stack trace.
- `--version` output no longer carries the `+gitsha` SourceLink suffix the .NET SDK appends by default. Users see plain `squeeze 0.3.0`, matching the convention across the rest of the suite.
### Added
- Library seam `Winix.Squeeze.Cli.Run` for orchestration testing without process spawning. Matches the suite-wide pattern.
### Internal
- UTF-8 console adoption via `ConsoleEnv.UseUtf8Streams` so multi-byte filenames round-trip correctly on Windows.
- Standard `<PackageTags>` set on the NuGet package so it's discoverable via tag filters on nuget.org.
See full changelog at https://github.com/Yortw/winix/blob/main/src/squeeze/CHANGELOG.md