# 𧬠Image Metadata Editor
**ime** is a fast, lightweight, and portable [CLI](https://en.wikipedia.org/wiki/Command-line_interface) written in [Rust](https://rust-lang.org/) for **reading**, **writing**, and completely **wiping** metadata from image files.
## π¦ Installation
### Pre-built binaries
You can download a pre-built executable for your operating system from the [Releases](https://github.com/Avaray/image-metadata-editor/releases/latest) page.
### Using Cargo (Rust ecosystem)
If you have Rust installed, you can easily install the latest version directly from crates.io:
```bash
cargo install ime
```
### Using Bun / NPM / PNPM (JavaScript ecosystem)
You can run `ime` instantly without installation using `bunx`, or install it globally via `npm` or `pnpm`:
```bash
# Run instantly without installation using Bun
bunx @avaray/ime photo.jpg
# Install globally with NPM
npm install -g @avaray/ime
```
These are just two simple examples. Any well-known package manager should be able to install `@avaray/ime` globally, and most of them also offer running it without the need for installation.
## β‘οΈ Usage
```
ime <file> [OPTIONS]
```
| `--output <path>` | `-o` | Write result (or modified file) to `<path>` instead of stdout / in-place |
| `--strip` | `-s` | Remove all metadata from the file (JPEG & PNG only) |
| `--tui` | `-t` | Launch the Interactive Terminal UI (TUI) Mode |
| `--set Key=Value` | | Inject a metadata tag; repeatable (JPEG & PNG only) |
| `--set-json <JSON>` | | Inject multiple tags at once from a JSON string |
| `--key <path>` | `-k` | Extract a single value using a dot-notation path |
| `--dir` | `-d` | Explicitly indicate the input is a directory (optional) |
| `--recursive` | `-r` | Recursively process subdirectories when a directory is provided |
| `--version` | `-v` | Print the semver version number and exit |
| `--help` | `-h` | Print help and exit |
### Reading metadata
Outputs all extracted metadata as a flat JSON object (one key per metadata directory).
```bash
# Print all metadata to stdout
ime photo.jpg
# Save to a file
ime photo.jpg -o meta.json
```
**Output example:**
```json
{
"Exif": {
"DateTimeOriginal": "2023-08-14 10:20:30",
"FocalLength": "24/1 (24.0000)",
"ISOSpeedRatings": "400"
},
"Tiff": {
"Make": "SONY",
"Model": "DSC-RX100M5A"
},
"PngText": {
"parameters": "beautiful landscape ...",
"workflow": "{\"nodes\": [...]}"
}
}
```
### Extracting a single value (`-k` / `--key`)
Use dot-notation (same style as `jq`) to extract a single tag from the metadata.
- Leading `.` is optional β both `.Tiff.Make` and `Tiff.Make` work.
- Array indices are supported: `nodes[0].type`.
- **Smart JSON traversal:** if a tag value is itself a JSON string (common in ComfyUI `workflow` or `prompt` keys), `ime` automatically parses it and continues traversal.
```bash
# Extract a scalar value (printed as raw text, no quotes)
ime photo.jpg -k Tiff.Make
# Kyocera Visual Phone
# Same with leading dot
ime photo.jpg -k .Tiff.Model
# VP-210
# Extract the raw generation parameters from a ForgeUI/A1111 PNG
ime image.png -k PngText.parameters
# Enter a ComfyUI workflow JSON embedded inside a tEXt chunk
ime image.png -k PngText.workflow.nodes[0].class_type
# Missing key β exit code 1
ime photo.jpg -k Exif.NonExistent
# Error: Key 'Exif.NonExistent' not found in metadata
```
When the result is a plain string it is printed without surrounding quotes.
When the result is an object or array it is printed as pretty-printed JSON.
### Stripping metadata (`-s` / `--strip`)
Removes all EXIF and embedded metadata from the file in-place.
Use `-o` to write to a new file instead (original is left untouched).
Supported formats: **JPEG**, **PNG**.
```bash
# In-place
ime photo.jpg -s
# Write to a new file
ime photo.jpg -s -o clean.jpg
```
### Injecting metadata (`--set`)
Sets one or more metadata tags. Existing tags that are not mentioned are preserved.
Can be combined with `-o` to write to a new file.
Supported formats: **JPEG**, **PNG**.
```bash
# Standard EXIF tag
ime photo.jpg --set "ImageDescription=Sunset at the lake"
# Multiple tags
ime photo.jpg --set "Artist=Jan Kowalski" --set "Copyright=2025 Jan Kowalski"
# Write to a new file
ime photo.jpg --set "Software=ime" -o tagged.jpg
# Custom key (PNG β tEXt chunk; JPEG β UserComment JSON)
ime image.png --set "prompt=a cat sitting on a roof" --set "negative_prompt=blurry"
# Inject multiple tags from a JSON object
ime image.png --set-json '{"prompt":"a cat","steps":30,"cfg":7}'
```
### Interactive TUI Mode
`ime` includes a built-in Interactive Terminal UI (TUI) for browsing and editing metadata visually without leaving your terminal.
```bash
ime ./photos --tui
```
### Batch Processing
If you provide a directory path instead of a file, `ime` will automatically process all supported files in that directory. Use the `-r` flag to process subdirectories recursively.
```bash
# Strip metadata from all images in the 'photos' directory and its subdirectories
ime ./photos -s -r
```
## πΌοΈ Supported formats
| Image | JPEG, PNG | β
| β
|
| Image | WebP | β
| β
|
| Image | HEIC/HEIF, AVIF, TIFF, CR3, RAF, IIQ | β
| β |
| Video | MP4, MOV, 3GP, MKV, WebM | β
| β |
## π
ΎοΈ Exit codes
| `0` | Success |
| `1` | Runtime error (I/O error, unsupported format, key not found, corrupt file) |
| `2` | Usage error (bad flags, missing file argument) |
## π§Ύ Changelog
All notable changes to this project will be documented in the [CHANGELOG.md](CHANGELOG.md) file.
## π License
This project is licensed under the [CC-BY-NC-4.0](LICENSE) License.