Winix.Squeeze 0.4.0

Prefix Reserved
dotnet tool install --global Winix.Squeeze --version 0.4.0
                    
This package contains a .NET tool you can call from the shell/command line.
dotnet new tool-manifest
                    
if you are setting up this repo
dotnet tool install --local Winix.Squeeze --version 0.4.0
                    
This package contains a .NET tool you can call from the shell/command line.
#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
  • --color forces colour on (overrides NO_COLOR)
  • --no-color forces colour off
  • Respects the NO_COLOR environment variable (no-color.org)

Part of Winix

squeeze is part of the Winix CLI toolkit.

Product 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. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.

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