@ritam369/imgbadlo
v0.3.1
Published
Local CLI to convert and compress images between JPEG, PNG, and WebP. No uploads, no network calls.
Maintainers
Readme
imgbadlo
Local CLI to convert and compress images between JPEG, PNG, and WebP. No uploads, no network calls.
Everything runs locally via sharp. No server, no browser, no network requests — just your image and your terminal.
Install
Global install — makes imgbadlo available as a command from any folder (recommended for regular use):
npm install -g @ritam369/imgbadloLocal install — install within a specific project folder and run via npx:
npm install @ritam369/imgbadlo
npx imgbadlo --version
npx imgbadlo convert photo.png --to webpUsage
Interactive mode (guided)
Run imgbadlo with no arguments to launch the guided flow:
$ imgbadloAn ASCII banner appears, then you choose between Type Conversion and Compression. From there a file browser lets you navigate your filesystem and pick an image, and menus guide the rest.
Flag-based mode (scriptable)
Convert
imgbadlo convert <input> --to <format> [options]| Argument / Flag | Description |
|-----------------------|-----------------------------------------------------------------------------|
| <input> | Path to the input image (jpeg, jpg, png, or webp) |
| --to <format> | Required. Target format: jpeg, jpg, png, webp |
| -o, --output <path> | Custom output path. Default: same directory, same basename, new extension |
| -q, --quality <n> | Quality 1–100 for lossy formats (jpeg/webp). Default: 80. Ignored for PNG |
| -f, --force | Overwrite output if it already exists |
Compress
imgbadlo compress <input> [options]| Argument / Flag | Description |
|-----------------------|--------------------------------------------------------------------------|
| <input> | Path to the input image (jpeg, jpg, png, or webp) |
| --level <level> | low, mid, high. Default: mid |
| -o, --output <path> | Custom output path. Default: <basename>-compressed.<ext> next to input |
| -f, --force | Overwrite output if it already exists |
Compression levels
Quality targets for JPEG and WebP are computed dynamically based on the image's estimated current quality, so the output is always smaller than the input regardless of how compressed the source already is.
| Level | Label | Effect |
|--------|------------------------------------|---------------------------------------------|
| low | Less Compression, High Quality | Gentle reduction — best visual fidelity |
| mid | Medium Compression, Medium Quality | Balanced reduction (default) |
| high | High Compression, Low Quality | Aggressive reduction — smallest file size |
For PNG, compression uses palette quantization (256 / 128 / 64 colours per level).
⚠ PNG is a lossless format. Palette quantization may visibly affect image quality, especially for photos.
Examples
# Interactive guided mode (ASCII banner + menus)
imgbadlo
# Convert PNG to WebP
imgbadlo convert photo.png --to webp
# Convert with custom output path
imgbadlo convert ./assets/banner.jpg --to png -o ./out/banner.png
# Convert with quality setting and force overwrite
imgbadlo convert icon.webp --to jpeg -q 90 --force
# Compress with default (mid) level
imgbadlo compress photo.jpg
# Compress with high level
imgbadlo compress photo.jpg --level high
# Compress PNG with custom output
imgbadlo compress photo.png -o ./out/photo-small.png --force
# Show detailed guide
imgbadlo --guide
imgbadlo convert --guide
imgbadlo compress --guideOutput
Conversion:
✔ Conversion complete
Input: /home/ritam/pictures/photo.png
Output: /home/ritam/pictures/photo.webp
Size: 142.3 KB → 88.1 KB (-38%)Compression:
✔ Compression complete
Input: /home/ritam/pictures/photo.jpg
Output: /home/ritam/pictures/photo-compressed.jpg
Size: 1.24 MB → 105.1 KB (-92%)Behaviour
- Format detection is done from file content (via
sharpmetadata), not the file extension. - No-op prevention — converting a PNG to PNG exits cleanly with a message.
- No silent overwrites — without
--force, an existing output path is an error. In interactive mode it prompts Y/N instead. - Output directory must exist — the tool does not create missing directories.
- Dynamic compression — for JPEG and WebP, quality targets are calculated relative to the image's estimated current quality so all levels always produce a smaller file.
- Compression pre-calculation — in interactive mode, all options are calculated in RAM (no temp files) before showing the menu, so you see the projected output size before committing.
- Smart PNG suggestion — when compressing a PNG in interactive mode, a "Convert to JPEG" option is shown only if it produces a smaller file than the best PNG compression level. If PNG compression is already better, the option is hidden.
- Exit code
0on success,1on any handled error.
Supported Formats
| Format | Input | Output | |--------|-------|--------| | JPEG | ✔ | ✔ | | JPG | ✔ | ✔ | | PNG | ✔ | ✔ | | WebP | ✔ | ✔ |
Requirements
- Node.js >= 18
Changelog
v0.3.1
- Documented local install usage via
npxin README and--guide
v0.3.0
- Dynamic compression quality: targets calculated from estimated current image quality, guaranteeing output is always smaller than input
- PNG compression now steps through palette sizes to guarantee smaller output
- PNG interactive menu shows a "Convert to JPEG" option with pre-calculated size — only when JPEG produces a smaller result than the best PNG level
- Fixed size-increase issue when compressing already-compressed images
v0.2.0
- Added
compresscommand with three levels (low / mid / high) - Interactive mode now shows an ASCII banner and an operation menu (Convert / Compress)
- Compression interactive mode pre-calculates output sizes in RAM and shows them live
- PNG compression warning added
- Added
--guideflag to every command for detailed usage examples
v0.1.0
- Initial release:
convertcommand (flag-based + interactive file browser)
