# How to Use Clap for Command-Line Argument Parsing in ImageKit

> Learn how to use Clap for command-line argument parsing in ImageKit. Leverage derive macros for robust, validated options like hex colors and watermark positions with ease.

- Repository: [hzbd/imagekit](https://github.com/hzbd/imagekit)
- Tags: how-to-guide
- Published: 2026-03-03

---

**ImageKit uses Clap's derive macro API to parse command-line arguments into a strongly-typed `Cli` struct defined in [`src/cli.rs`](https://github.com/hzbd/imagekit/blob/main/src/cli.rs), enabling complex options like hex colors and watermark positions with automatic validation.**

The `hzbd/imagekit` repository demonstrates idiomatic Rust CLI design by leveraging **clap for command-line argument parsing**. The implementation separates parsing logic from business logic, converting raw arguments into a type-safe configuration struct that drives the image processing pipeline.

## Clap Integration Architecture in ImageKit

### Entry Point Bootstrap in main.rs

At the application entry point in [`src/main.rs`](https://github.com/hzbd/imagekit/blob/main/src/main.rs), the binary delegates argument parsing immediately to the library layer. Line 7 invokes `Cli::parse()`, which triggers clap's derive macro to process `std::env::args()` and construct the configuration object before passing it to `imagekit::run`.

### The Cli Struct Definition

The core parsing logic resides in [`src/cli.rs`](https://github.com/hzbd/imagekit/blob/main/src/cli.rs) (lines 9-41), where the `Cli` struct derives `Parser` from clap. Each field uses `#[arg]` attributes to define short/long flags, help text, and default values. This approach eliminates boilerplate while maintaining compile-time guarantees about argument structure.

## Custom Parsers and Validation

### HexColor for RGBA Values

ImageKit supports hexadecimal color codes through the `HexColor` wrapper struct (lines 46-68 in [`src/cli.rs`](https://github.com/hzbd/imagekit/blob/main/src/cli.rs)). By implementing `FromStr`, this type allows clap to parse strings like `#ffffff80` directly into `image::Rgba<u8>` values for watermark transparency.

### WatermarkPosition with FromStr

The `WatermarkPosition` enum (lines 81-90) maps textual descriptions such as `nw`, `center`, and `se` to positional variants. Clap utilizes this `FromStr` implementation when processing the `--watermark-position` flag, converting user input into typed enum variants.

### OutputFormat Using ValueEnum

For output format selection, `OutputFormat` derives clap's `ValueEnum` trait (lines 99-106). This automatically generates valid value lists for the `--output-format` argument, restricting inputs to supported variants like `jpg`, `png`, and `webp` while providing shell completion hints.

### Range Validation for Quality

JPEG quality validation occurs at line 36 in [`src/cli.rs`](https://github.com/hzbd/imagekit/blob/main/src/cli.rs) using `clap::value_parser!(u8).range(1..=100)`. This ensures the `--quality` flag accepts only values between 1 and 100, failing fast with a descriptive error before image processing begins.

## Parsing Flow Execution

The argument resolution follows a strict pipeline:

1. **Invocation**: `main()` calls `Cli::parse()` to ingest environment arguments.
2. **Default Application**: Fields with `default_value_t` attributes (e.g., `watermark_position`, `font_size`) populate automatically when omitted.
3. **Custom Conversion**: Clap invokes `FromStr` for `HexColor` and `WatermarkPosition`, and `ValueEnum` for `OutputFormat`.
4. **Validation**: Numeric ranges and enum variants are verified against user input.
5. **Execution**: The fully populated `Cli` instance transfers to `imagekit::run` to drive resizing and watermarking operations.

## Practical Usage Examples

Basic batch resizing maintains aspect ratio while converting to PNG:

```bash
imagekit -i ./photos -o ./out --width 800

```

Adding a semi-transparent watermark in the bottom-right corner:

```bash
imagekit \
  -i ./photos \
  -o ./out \
  --width 1024 \
  --watermark-text "© My Company" \
  --watermark-position se \
  --font-size 36 \
  --watermark-color "#ffffff80"

```

Forcing JPEG output with specific quality constraints:

```bash
imagekit \
  -i ./photos \
  -o ./out \
  --output-format jpg \
  --quality 90

```

## Programmatic Usage

External crates can leverage ImageKit's parser directly:

```rust
use imagekit::cli::Cli;
use clap::Parser;

fn main() {
    let args = Cli::parse();
    
    println!("Input directory: {:?}", args.input_dir);
    println!("Resize width: {:?}", args.width);
    println!("Watermark color: {}", args.watermark_color);
}

```

## Summary

- ImageKit implements **clap for command-line argument parsing** through the derive API in [`src/cli.rs`](https://github.com/hzbd/imagekit/blob/main/src/cli.rs).
- The `Cli` struct at lines 9-41 encapsulates all configuration with compile-time type safety.
- Custom `FromStr` implementations in `HexColor` (lines 46-68) and `WatermarkPosition` (lines 81-90) enable complex string parsing.
- `ValueEnum` derivation for `OutputFormat` (lines 99-106) provides automatic validation and completion.
- Range validation via `clap::value_parser` ensures JPEG quality stays between 1-100 as defined at line 36.
- The binary entry point at [`src/main.rs`](https://github.com/hzbd/imagekit/blob/main/src/main.rs) line 7 delegates immediately to `Cli::parse()` before executing `imagekit::run`.

## Frequently Asked Questions

### How does ImageKit handle default values for CLI arguments?

Clap's `default_value_t` attribute on struct fields automatically populates omitted arguments. For example, `watermark_position`, `font_size`, and `quality` receive preset values when users skip those flags, ensuring the `Cli` struct always contains valid configuration data.

### What validation does clap perform on the quality argument?

The quality flag uses `clap::value_parser!(u8).range(1..=100)` at line 36 of [`src/cli.rs`](https://github.com/hzbd/imagekit/blob/main/src/cli.rs) to restrict inputs to the 1-100 range. If a user provides a value outside this range or a non-numeric string, clap exits with an error message before `imagekit::run` executes.

### Can I use ImageKit's CLI parser in my own Rust application?

Yes, import the `Cli` struct from `imagekit::cli` and invoke `Cli::parse()` as shown in [`src/main.rs`](https://github.com/hzbd/imagekit/blob/main/src/main.rs). This returns a fully populated struct with typed fields, allowing your application to leverage ImageKit's argument definitions and validation logic for custom image processing workflows.

### Which clap features enable the custom color parsing?

The `HexColor` type implements the standard library's `FromStr` trait, which clap automatically invokes when parsing the `--watermark-color` argument. This integration at lines 46-68 of [`src/cli.rs`](https://github.com/hzbd/imagekit/blob/main/src/cli.rs) allows the derive macro to accept hex strings like `#ffffff80` and convert them into `image::Rgba<u8>` instances.