Cloudinary-powered image optimization CLI with Node.js wrappers for select Cloudinary Node.js APIs, covering automatic image optimization, transformation, and asset management.
Cloudinary's automatic optimization reduces the need to manually tune image dimensions, quality, compression, and formats. Unlike libraries such as Sharp or FFmpeg, where developers often need to experiment with processing parameters to find the right balance between visual quality and file size, Cloudinary can automatically optimize images for efficient delivery while preserving visual quality.
The result: less optimization guesswork, smaller assets, and better image delivery with less application-side processing.
Tip
-
Run via npx (no installation required)
- Requirements: NodeJS LTS v24.11.0 or later, and a
.envfile - Run
npx cloudinary-image -f ./full/path/to/picture.jpg -u -d
- Requirements: NodeJS LTS v24.11.0 or later, and a
-
Node.js package
A Node.js package is available at
https://www.npmjs.com/package/cloudinary-image -
Docker image
A Docker image is available at
https://hub.docker.com/r/weaponsforge/cloudinary-cli
- Node v24+
- Docker (optional)
- Cloudinary account
Create a .env file in the /app directory, replacing the contents of the .env.example file with actual values.
| Variable Name | Description |
|---|---|
| CLOUDINARY_NAME | Cloudinary account name |
| CLOUDINARY_API_KEY | Cloudinary API key |
| CLOUDINARY_API_SECRET | Cloudinary API secret |
| CHOKIDAR_USEPOLLING | Enables file watching on tsx watch running inside Docker containers on a Windows host. Set it to true if running Docker Desktop with WSL2 on a Windows OS host. |
| CHOKIDAR_INTERVAL | Chokidar polling interval. Set it along with CHOKIDAR_USEPOLLING=true if running Docker Desktop with WSL2 on a Windows OS host. The default value is 1000. |
-
Build the image.
docker compose build -
Run the container.
docker compose up -
Edit the
.tssource files and watch for changes. -
Run the Available Scripts using Docker.
-
See the examples under the Code Samples section for more information.
Example using the development Docker image
(PowerShell - development)
docker exec cloudinary-cli-dev npm run docker:debug -- -f /opt/app/assets/sunset.jpg -u -dExample using stand-alone production Docker image
(PowerShell - production)
Build the production image with
docker compose -f docker-compose.prod.yml build
docker run --rm --env-file .env `
-v ${pwd}/assets:/images `
weaponsforge/cloudinary-cli `
-f /images/sunset.jpg -u-
Install dependencies.
cd app npm install -
Run the app in development mode.
npm run dev -
Edit the
.tssource files and watch for changes. -
Run the Available Scripts.
-
See the examples under the Code Samples section for more information.
Optimizes an input image using the Cloudinary image transformations.
Downloads the optimized image to a /processed directory relative to the input file, or to a specified output directory.
NOTE: this requires transpiling TypeScript into JavaScript first via
npm run build.
Example Usage
npm start -- -f /path/to/file.jpg -u -dCLI Guide
npm start -- \
-f /path/to/file.jpg # Full input image file path
-o /output/folder/path # (Optional) output folder
-a my-asset-folder # (Optional) Cloudinary asset folder
-t cars,vehicles,tech # (Optional) image tags
-w 600 # (Optional) width to resize the image. Default is 800
-u # (Optional) flag to upload the input image to Cloudinary. Required on 1st run.
-d # (Optional) flag to delete the uploaded image in CloudinaryNOTE: This script is also accessible using
npx optimizeminus the--flag.
Runs the npm start script in development mode with file watching using tsx.
Example usage:
npm run dev -- -f /assets/sunset.jpg -u
Logs the installed Node.js and npm version, environment platform, architecture and V8 version.
Builds JavaScript, .d.ts declaration files, and map files from the TypeScript source files in the /src directory to the /dist directory.
Runs type-checking without generating the JavaScript or declaration files from the TypeScript files in the /src directory.
Lints TypeScript source codes.
Fixes lint errors in TypeScript files.
Watches file changes in .ts files using the tsc --watch option.
Docker counterpart of the npm run dev script. Exports the IS_DOCKER=true variable and runs the npm run dev script in development mode with file watching using tsx within Docker.
Tip
Set CHOKIDAR_USEPOLLING=true and CHOKIDAR_INTERVAL=1000 in the .env file to enable file watching on when running inside Docker containers on a Windows host.
Uncomment and use _values in /src/scripts/optimize/index.ts to manually set optimize(_values) not from CLI input.
Watches file changes in .ts files using the tsc --watch option with dynamicPriorityPolling in Docker containers running in Windows WSL2.
import { join } from 'node:path'
import dotenv from 'dotenv'
import { CloudinaryImage } from '@/lib/image.js'
dotenv.config()
const main = async () => {
const filePath = join(process.cwd(), 'boat.jpg')
const image = new CloudinaryImage({
localFile: filePath,
cloudinaryAssetFolder: 'my-folder',
})
await image.upload('sea,travel')
await image.optimize(600)
await image.delete()
}
main()import dotenv from 'dotenv'
import { CloudinaryImage } from '@/lib/image.js'
import { join } from 'node:path'
dotenv.config()
const main = async () => {
const filePath = join(process.cwd(), 'boat.jpg')
const image = new CloudinaryImage({
localFile: filePath,
cloudinaryAssetFolder: 'my-folder',
})
// Upload image to Cloudinary
await image.upload('sea,travel')
// Generate URL of resized image
const urlResize = await image.transformer
.resize(image.publicId, {
width: 450
})
// Generate URL of cropped image
const urlCropped = await image.transformer
.crop(image.publicId, {
width: 400,
height: 200,
crop: 'scale'
})
// Generate URL of image's new format
const urlFormat = await image.transformer
.format(image.publicId, 'webp')
// Generate URL of image with improved quality
const urlQuality = await image.transformer
.quality(image.publicId, 'auto')
// Download one of the generated images
const downloadFilePath = join(process.cwd(), image.name)
await image.service.fetch(urlCropped, downloadFilePath)
}
main()import { join } from 'node:path'
import { AssetManager } from '@/lib/cloudinary/manager.js'
import { AssetService } from '@/lib/cloudinary/service.js'
import { BaseImage } from '@/lib/cloudinary/baseimage.js'
import { Transform } from '@/lib/cloudinary/transform.js'
// Class for managing Cloudinary assets
const _manager = new AssetManager()
// Class for uploading and fetching images from Cloudinary
const _service = new AssetService()
// Class for generating Cloudinary image transformations
const _transformer = new Transform()
// Initialize a new BaseImage - no Cloudinary libraries
const inputFile = join(process.cwd(), 'boat.jpg')
const outputFile = join(process.cwd(), 'images', 'done', 'processed.jpg')
const _image = new BaseImage({
localFile: inputFile,
cloudinaryAssetFolder: 'my-folder',
localDestination: outputFile, // optional
})
// Note: the CloudinaryImage class is composed of all these components@weaponsforge
20260817