Cloudinary image optimization CLI with Node.js wrappers for select Cloudinary Node.js APIs
covering image transformation, optimization, and asset management.
- 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