Skip to content

Repository files navigation


Imago logo

imago

Understand your images. Locally. No uploads. No API keys.

Semantic search · Perceptual hashing · Metadata analysis · Safe trash · Extensible agent runtime

Python 3.11+ MIT License PRs Welcome Local-First


Why Imago?

Every image tool does one thing.

  • dupeGuru finds duplicates but can't search by content.
  • exiftool reads metadata but can't compare images.
  • CLIP-as-service needs a cloud account.
  • ImageMagick compares pixels but knows nothing about semantics.

To organize a photo library you need four different tools, each with its own CLI, its own config, and its own way of doing things.

Imago is the one tool that does all of it — and is built to grow.

search-text "a photo of a strawberry" dir=~/Photos
search-img reference.jpg dir=~/Photos
diff photo1.jpg photo2.jpg
meta image.jpg
find-similar ~/Photos threshold=8
trash unwanted.jpg

Everything runs locally. Nothing leaves your machine. No API costs. No privacy violations.


Quick start

pip install imago
imago view ~/Pictures

Or from source:

git clone https://github.com/your-org/imago
cd imago
pip install -e .
imago --help

Feature comparison

Capability Imago dupeGuru exiftool CLIP-as-a-service ImageMagick
Semantic search (text → image)
Perceptual hash search
Metadata reading + search
Pixel-level diff heatmap
Near-duplicate grouping
Safe trash (undo delete)
Fully local, zero cloud
Extensible tool architecture
Interactive CLI
LLM planner ready

How it works

Imago uses a layered agent architecture that separates concerns cleanly:

  1. CLI parses commands (view, search-text, diff, …) and routes them through the runtime.
  2. Runtime maintains a registry of all available tools. The executor invokes the right tool with parsed arguments. A Planner stub is already in place for future LLM-driven multi-step workflows.
  3. Tools are tiny self-contained modules. Each implements Tool.execute() and registers itself on import. Adding a new capability means writing one file — no CLI changes, no config, no wiring.
  4. Core algorithms (CLIP embedding, perceptual hashing, metadata parsing, image differencing, similarity grouping, trash management) live in image_agent/core/. These are pure functions with no dependency on the runtime or CLI.
  5. Infrastructure (config, logging, cache) provides shared services to everything above.

The result: a CLI that grows by addition, not by modification.


Architecture

graph TB
    subgraph CLI["CLI — imago"]
        DP[Command Dispatcher]
    end

    subgraph Runtime["Runtime Layer"]
        REG[ToolRegistry]
        EXEC[Executor]
        PLAN[Planner<br/><i>coming soon</i>]
    end

    subgraph Tools["Tool Layer — 11 tools"]
        T1[search-text / search-img / search-meta]
        T2[view / meta / diff]
        T3[find-similar]
        T4[trash · trash-list · trash-restore · trash-empty]
    end

    subgraph Core["Core Algorithms"]
        C1[CLIP Engine]
        C2[phash Engine]
        C3[Metadata Reader / Searcher]
        C4[Image Differ]
        C5[Similarity Grouper]
        C6[Trash Manager]
    end

    subgraph Infra["Infrastructure"]
        I1[Config]
        I2[Logging]
        I3[Cache]
    end

    DP --> REG
    REG --> EXEC
    EXEC --> Tools
    PLAN --> EXEC
    Tools --> Core
    Core --> Infra
Loading

Commands

Command Description
view [dir] List all images in a directory with dimensions, format, size
meta <path> Show full EXIF / image metadata
search-text <query> Semantic search by text description using CLIP
search-meta <key> <value> Search images by EXIF metadata field
search-img <image> Find visually similar images using perceptual hashing
diff <img1> <img2> Pixel-level difference heatmap with MSE + phash distance
find-similar [dir] Group near-duplicates in a directory
trash <path> Move to ~/.opencode-trash (safe delete)
trash-list List trashed files
trash-restore <file> Restore from trash
trash-empty Permanently delete all trash

Examples

# Browse a directory
imago view ~/Downloads

# Semantic search — CLIP understands content, not just filenames
imago search-text "a person standing on a beach" dir=~/vacation

# Find images visually similar to a reference
imago search-img reference_product.jpg dir=~/catalog

# Compare two near-identical images
imago diff original.jpg edited.jpg

# Deep metadata dive
imago meta photo.jpg

# Find and group near-duplicates
imago find-similar ~/Pictures threshold=8

# Safe delete with undo
imago trash unwanted.jpg
imago trash-list
imago trash-restore unwanted.jpg

Extending

Add a new capability in one file. No CLI changes. No wiring.

# imago/tools/ocr.py
from ..runtime.tool import Tool, ToolParameter
from ..runtime.registry import ToolRegistry

class OcrTool(Tool):
    name = "ocr"
    description = "Extract text from images"
    parameters = [ToolParameter(name="path", type="string")]
    def execute(self, path: str = "") -> dict:
        # Your OCR logic here
        return {"text": "..."}

ToolRegistry.register(OcrTool())

Add from .ocr import OcrTool to image_agent/tools/__init__.py. Done.

This architecture makes it trivial to add:

  • OCR (Tesseract wrapper)
  • Face detection / recognition
  • Object detection (YOLO, DETR)
  • Reverse image search
  • AI captioning
  • Video keyframe extraction + analysis
  • Web UI (gradio, streamlit)

Roadmap

  • Semantic text → image search (CLIP)
  • Perceptual hash image search
  • EXIF metadata reading + search
  • Pixel-level diff with heatmap
  • Near-duplicate grouping
  • Safe trash management
  • OCR tool (Tesseract wrapper)
  • Face detection & recognition
  • Object detection (YOLO / DETR)
  • CLIP-based reverse image search
  • AI captioning (BLIP / GIT)
  • Video keyframe analysis
  • Web UI (gradio)
  • LLM planner (multi-step workflows via natural language)

Project structure

imago/
├── image_agent/
│   ├── cli.py                  # CLI entry point + command dispatch
│   ├── tools/                  # 11 auto-registered tools
│   │   ├── view.py
│   │   ├── metadata.py
│   │   ├── search_image.py
│   │   ├── search_text.py
│   │   ├── compare.py
│   │   ├── similarity.py
│   │   └── trash.py
│   ├── core/                   # Algorithm implementations
│   │   ├── clip_engine.py
│   │   ├── phash_engine.py
│   │   ├── image_differ.py
│   │   ├── image_viewer.py
│   │   ├── metadata_reader.py
│   │   ├── metadata_searcher.py
│   │   ├── similarity_grouper.py
│   │   └── trash_manager.py
│   ├── runtime/                # Agent runtime
│   │   ├── tool.py             # Tool ABC + ToolParameter
│   │   ├── registry.py         # ToolRegistry
│   │   ├── executor.py         # Executor
│   │   └── planner.py          # Planner stub
│   └── infrastructure/        # Shared services
│       ├── config.py
│       ├── logging.py
│       └── cache.py
├── tests/                      # pytest suite (17 tests)
│   ├── test_registry.py
│   ├── test_executor.py
│   └── test_tools.py
├── pyproject.toml
└── README.md

License

MIT. See LICENSE.

Contributions welcome — see CONTRIBUTING.md and the architecture checklist before opening a PR.

Releases

Packages

Contributors

Languages