Skip to content

videre search

Terminal window
videre search "sunset over water" # search by description
videre search 'person:özgür (tag:deniz OR tag:plaj)' # filters in a query
videre search --image photo.jpg # find photos like this one
videre search --person "Alice" # photos of a named person
videre search --people Erhan # photos of everyone named Erhan
videre search --category screenshot # photo / screenshot / document / meme / unknown
videre search --location "Berlin, Germany" # photos taken near a place
videre search "a dog" -k 50 # more results, default 20 (--top-k works too)
videre search "a dog" --scores # show how well each result matched
videre search "a dog" --json # print one JSON object instead
videre search --location "Rome" --radius 5 # tighter radius in km (default 20)
videre --library ~/Photos search "a dog" # select a different library
videre search "a dog" --model <model-id> # search a specific model's data
videre search --date 2019-09 # only that month
videre search --after 2020-01-01 # inclusive lower bound
videre search --before 2020-01-01 # exclusive upper bound
videre search --type video # only videos
videre search --ext mov,mp4 # only these extensions
videre search --mime video/quicktime # an exact type
videre search --path ~/Photos/2024 # only files under a folder
videre search --missing gps # files missing GPS coordinates
videre search --has gps,date # files with GPS and a date
videre search --sort=distance,date # order, with tie-breaks
Mode Requires
Text, --image videre embed
--person, --people videre faces, then naming via gallery
--category videre classify
--location GPS data in your photos

Matching paths print to stdout, all duplicate paths for each matched file.

The text argument is a query: its words are what to search for, and it can also hold filters such as person:, tag:, date:, rating: and place:, combined with OR, - and parentheses, the way Gmail and GitHub search work. Quote the whole query in single quotes. Query syntax lists every key.

Terminal window
videre search 'kumsalda gün batımı tag:deniz -tag:ekran'
videre search '(person:özgür OR person:ayşe) date:2023 is:liked'

--people (and people: in a query) finds everyone whose name has the words you give, as whole words, in any case and with or without accents: --people Erhan finds Erhan Gündoğan and Erhan Kaya but not Serhan, --people gündoğan finds anyone with that surname, and --people "Erhan Gündoğan" needs both words, in that order. A part of a word matches nothing: --people Gül finds Gül, not Gülşen.

The model matches images to descriptions of what is visible. Plain descriptive phrases work best:

Terminal window
videre search "a dog on a beach"
videre search "snow covered mountains"
videre search "birthday cake with candles"
videre search "close up of a red flower"
videre search "people sitting around a dinner table"

Things it is good at: subjects, scenes, colours, weather, obvious activities, broad settings such as indoors, city street, forest.

Things it is not:

  • Reading text. It is not OCR. “the receipt from the hardware store” will not work; try --category document to narrow to documents instead.
  • Counting. “three cats” is treated much like “cats”.
  • Boolean logic. There is no AND, OR or NOT. “dog not cat” is just a phrase, and the negation is ignored.
  • Names and dates. It has no idea who Alice is or when a photo was taken. Use --person for people, and the date view in gallery for time.

A text search’s score is the model’s own estimate that the photo matches the words, from 0 to 1, and --scores shows it:

Terminal window
videre search "a dog on a beach" --scores
0.973 /Photos/2019/beach-day-12.jpg
0.912 /Photos/2019/beach-day-08.jpg
0.184 /Photos/2021/garden.jpg

Weak matches are left out: a result needs at least a 10% match. So a query nothing fits returns nothing, rather than the least bad photos, and fewer than -k results is normal. Change the cutoff per library:

Terminal window
videre config set search-min-match 0.5 # only strong matches
videre config set search-min-match 0 # every ranked result, as before

The score means the same for every query and every model, so one cutoff fits them all. It is computed from the model’s own trained scale for matching text to images, which raw similarity is not: the same similarity can be a strong match on one model and noise on another.

Terminal window
videre search --image ~/Desktop/reference.jpg -k 40

The query image does not need to be in your library. This is often the fastest way to find a series: pick one frame you remember and pull the rest.

An image search scores by similarity, from -1 to 1, and keeps every ranked result unless you set a floor; the gallery’s Similar uses the same one:

Terminal window
videre config set similar-min-score 0.6

Paths print one per line, so this pipes like any other tool:

Terminal window
videre search "screenshots of code" -k 100 > /tmp/found.txt
videre search "blurry photo" -k 50 | xargs -I{} mv {} ~/to-review/
open $(videre search "golden gate bridge" -k 5)

With --json you get structured output for scripting:

Terminal window
videre search "sunset" --json | jq -r '.results[] | select(.score > 0.9) | .path'

-k limits how many come back; the score says how well each one matched.

If you have prepared more than one model, each is searched separately:

Terminal window
videre search "sunset over water" --model google/siglip2-base-patch16-384

Comparing the same query across two models on your own library is the practical way to decide whether a larger one is worth its cost:

Terminal window
videre search "kids playing in snow" --scores
videre search "kids playing in snow" --scores --model google/siglip2-base-patch16-384

Asking for a model you have not prepared gives an error naming the ones you do have, rather than silently returning nothing.

Four filters need no metadata beyond the file itself:

Flag Selects
--type image or video
--ext file extension, e.g. mov
--mime exact type, e.g. video/quicktime
--path files under a folder

--type, --ext and --mime are repeatable and accept comma-separated lists, so --ext mov,avi and --ext mov --ext avi are the same request. --type is the broad one: it covers every image or video format rather than a named list.

Terminal window
videre search "sunset" --type video
videre search "birthday" --ext heic --path ~/Photos/2024

These same four work on videre scan, watch, embed, faces and classify, where they narrow the work rather than the results. See scoping a run.

Presence filters select by whether videre has metadata for a file:

Flag Selects
--has <field> files where this metadata exists
--missing <field> files where this metadata is absent

Supported fields are gps and date. Both flags are repeatable and accept comma-separated lists, so --missing gps,date and --missing gps --missing date are the same request.

Terminal window
videre search --missing gps
videre search --missing gps,date --json
videre search --has gps --missing date

gps means both latitude and longitude are present. A file missing either coordinate matches --missing gps, and it does not match --location.

Photos you have marked with videre mark filter here too:

Flag Selects
--rating <N> rating of at least N stars (0-5)
--pick <keep|reject> that pick state exactly
--label <colour> that colour label exactly
--like liked (favourite) photos
Terminal window
videre search --rating 4 --person "Alice" # 4+ stars, of Alice
videre search --pick reject | tr '\n' '\0' | xargs -0 trash # cull what you flagged
videre search --like --date 2024 # favourites from 2024

A photo with no mark never matches, the same rule every filter follows.

Free-form tags set with videre tag filter here as well:

Flag Selects
--tag <tag> files carrying this tag. Repeatable; every named tag must be present
Terminal window
videre search --tag beach --tag summer --person "Alice"

--person, --category, --location, --type, --ext, --mime, --path, --has, --missing, --rating, --pick, --label, --like and the date bounds are filters: give any combination and they AND together, each narrowing further.

A text query or --image is a ranker: at most one, and it orders whatever the filters left.

Terminal window
# every axis at once: what it is, who is in it, where and when
videre search "cake" --category photo --person "Alice" \
--location "Istanbul" --radius 5 --date 2025-05 --type image
# the videos from one trip, newest first
videre search --type video --location "Rome" --after 2024-06-01 \
--before 2024-07-01 --sort date:desc
# a visual match, restricted to originals rather than exports
videre search --image ~/Desktop/reference.jpg --ext heic --path ~/Photos/originals
# documents photographed in one city, best match first
videre search "receipt" --category document --location "Berlin, Germany" --radius 10
# clips only, from one folder, ignoring everything re-encoded to mp4
videre search "beach" --ext mov --path ~/Photos/2024 -k 50

Order does not matter, and neither does how many you give. Filtering happens before ranking, so a heavily filtered query scores fewer vectors and returns faster than an unfiltered one.

-k truncates the result of all of it, and --sort decides the order. See compositional searches for the full model, worked examples and recipes.

Terminal window
videre search --date 2019 # a whole year
videre search --date 2019-09 # a month
videre search --date 2019-09-14 # a day
videre search --after 2020-01-01 # everything since (inclusive)
videre search --before 2020-01-01 # everything before (exclusive)

--date is shorthand and conflicts with --after/--before. --before is exclusive so adjacent ranges never both claim the boundary.

Dates match the capture date when the file has one, otherwise its modification time, so screenshots and anything without embedded metadata are still reachable. That fallback can mix “when taken” with “when last written”; see the guide for what that means in practice.

Videos carry their own capture date and coordinates, so they match date and location filters like photos do. See videos below.

Since v0.14.0 videre reads each video’s capture date, coordinates, duration and codec, so videos appear in date and location results alongside photos. No separate flag: the same filters cover both.

Terminal window
videre search --location "Los Angeles, USA" --radius 30 --date 2024-12

On a real library that returns 349 photos and 6 videos together. Before v0.14.0 the videos could not have matched either half, because neither field existed for them.

The date a video matches is when it was recorded, not when the file was written. Those often differ by years: a clip exported or copied last week still matches the month it was shot.

If a result looks misplaced, compare Finder’s “Created” against the capture date; Finder shows the filesystem timestamp, videre uses the capture time embedded in the file.

A clip recorded with location services off carries none, and no amount of scanning invents them. On one real library 16 of 260 were in that position. Those videos are fully searchable by date and text, they simply cannot appear in --location results.

Terminal window
videre search --date 2019 --sort date:asc # oldest first
videre search --location "Berlin" --sort=distance,date

--sort takes a comma-separated field[:asc|desc] list over relevance, distance, date and size. Later fields break ties in earlier ones. Directions are optional: relevance, date and size default to descending, distance to ascending.

Omitted, it defaults to relevance if you gave a query or --image, else distance if you gave --location, else date.

Asking for a sort whose input is missing is an error rather than a silent fallback:

$ videre search --sort distance
error: --sort distance needs --location <place>

--location is the one mode that uses the network

Section titled “--location is the one mode that uses the network”

It looks up an arbitrary place name, not limited to places already in your library, via the Nominatim (OpenStreetMap) public geocoding API. Geocoding is the only network call the command line ever makes; the only other outbound request videre makes at all is the gallery Map view’s one-time basemap download (see Install).

Terminal window
videre search --location "Kreuzberg, Berlin" --radius 3
videre search --location "Iceland" --radius 300 -k 200

Radius matters more than it looks: a city name with the default 20 km will include its suburbs, while a neighbourhood needs a few km to be meaningful.

The result is cached locally, keyed by the query string, so repeating a query never repeats the lookup. That cache write makes --location the only search filter that writes to the database, including when it is used through videre mcp, which exposes it under the same name.

For grouping photos by places already in your library, with no network at all, use videre locations instead.

Every filter follows one rule: it matches on the best evidence available, and excludes a file only when there is no evidence at all.

For location there is no fallback. A file either carries coordinates or it carries nothing, so a file without them is not a near-miss, it is not a candidate: asking for a place is asking for files known to have been there, and an unknown location is not evidence of being anywhere.

Dates are the one axis where a fallback exists, which is why they behave differently: every file has a modification time, so there is always some evidence. The capture date is preferred and the file’s timestamp is used only when that is all there is. --person and --category work like location: no recorded face or classification means no evidence, so the file is excluded.

This surprises people most often with:

  • Screenshots, downloads and received images, which carry no GPS at all
  • Photos taken with location services off, which are ordinary photos in every other respect
  • Videos scanned before v0.14.0, which had no coordinates recorded even when the file contained them; a re-scan fixes those

So a result count smaller than you expect usually means part of the library has no coordinates rather than that the radius is too small. To see how much of your library can participate at all:

Terminal window
videre stats

Widening --radius cannot bring in a file that has no coordinates, however large you make it.

-k now applies to --person and --category. They previously returned every match, unordered. They are now truncated like any other search and ordered deterministically. Pass a large -k for the full set.

Video results are weaker. Videos are embedded from a single frame, so a clip only matches if its opening frame shows the subject.

Results are as fresh as your last embed. New photos are not searchable until videre embed has covered them. Running videre watch keeps that current for you.

Search never reads your files. It compares stored vectors, so it works with the drive unplugged; the paths it prints just will not resolve.

--json emits a single document with schema_version, query, count, and results. Fields per hit vary by mode:

Mode Fields
Text, --image path, hash, score
--person path
--category path, hash
--location path, hash, distance_km

--scores is a no-op under --json, since the score is always included. For a filter-only search, query.value summarizes the active filters, including ratings, picks, colour labels, likes, and tags.

--html writes the results to a browsable file, in the order they were ranked.

Terminal window
videre search "sunset over water" --html # writes <db>_search.html
videre search --person "Ahmet" --html ~/ahmet.html # somewhere specific

Matching paths still go to stdout, so piping is unaffected.