No description
Find a file
Love Billenius 75f9df41f3 Declare verified dependency floors and the MSRV
Dependency requirements pinned the versions that happened to be
current, which demands needlessly new crates from anyone building
the workspace. Each requirement is now the oldest version the
workspace was verified to build and pass its tests with, all floors
together; Cargo.lock still pins the versions actually used.

Declare rust-version 1.85 (edition 2024 and clap 4.6 both need it;
verified by testing with 1.85) and the repository URL, and document
installing with cargo install --locked --git.
2026-09-28 14:53:45 +02:00
crates Declare verified dependency floors and the MSRV 2026-09-28 14:53:45 +02:00
.gitignore Add CLI that selects images matching a question 2026-09-28 14:41:18 +02:00
Cargo.lock Add CLI that selects images matching a question 2026-09-28 14:41:18 +02:00
Cargo.toml Declare verified dependency floors and the MSRV 2026-09-28 14:53:45 +02:00
clippy.toml Add CLI that selects images matching a question 2026-09-28 14:41:18 +02:00
README.md Declare verified dependency floors and the MSRV 2026-09-28 14:53:45 +02:00

classify

Asks Claude Opus, through claude -p, which of a set of images match a question.

$ classify "Which images contain a traffic light?" -i a.png -i b.png -i c.jpg
{"matches":["a.png","c.jpg"]}

Install

Requires Rust 1.85 or newer.

cargo install --locked --git https://git.billenius.com/Love/classify.git

--locked builds with the exact dependency versions in Cargo.lock. The binary is installed as classify.

Usage

Each -i/--image is one image (PNG, JPEG, GIF or WebP; at most 100). Claude sees all of them in one request, each labelled Image 1:, Image 2:, ..., and answers with structured output (--json-schema), with no tools enabled. The model is always Opus.

Output contract: on success, stdout is exactly one line of JSON, {"matches":[...]}, holding the matching paths exactly as given, in the order given (empty if none match), and the exit status is 0. On failure stdout is empty, stderr has a message, and the exit status is 1 (2 for invalid arguments). Paths must be UTF-8 so they can be represented in JSON.

Requires a logged-in Claude Code. The claude executable is found automatically: every PATH entry first, then the native installer (~/.local/bin, ~/.local/share/claude/versions/*, newest first), the legacy ~/.claude/local, npm/bun/pnpm/volta/yarn global directories (honouring NPM_CONFIG_PREFIX, BUN_INSTALL, PNPM_HOME, VOLTA_HOME, ...), nvm and fnm Node versions (newest first), asdf/mise shims, Homebrew and system directories. A candidate is accepted only if --version identifies it as Claude Code, so another program named claude is skipped. If none is found, the error lists what was rejected and why.

Layout

  • crates/classify is the library: image format detection, answer validation, and the claude -p adapter behind the ImageModel trait. It leaves reading files and printing results to the caller.
  • crates/claude-locate finds the Claude Code executable. It reaches the machine only through its System trait, so the whole search is tested against a simulated machine.
  • crates/classify-cli is the classify binary.

cargo build, cargo test, cargo clippy --all-targets.

Dependency requirements in the root Cargo.toml are the oldest versions the workspace builds and passes its tests with; raise one only when code starts needing something newer.