Oct 19, 2026
Pinpoint Where a Photo Was Taken With geo-sleuth
geo-sleuth turns your coding agent into a photo-geolocation analyst: OpenStreetMap geometry, elevation skylines, satellite tiles, and street view — with an error radius and an evidence image behind every answer.
A photo with no GPS data, no signs, no plates, no landmarks — just a bridge, a mountain, and a rice paddy. geo-sleuth, a 3k-star agent skill from Oldcircle, hands that problem to your coding agent and makes it show its work: the answer comes back as a camera position plus a heading, an error radius, a graded confidence, and a satellite evidence image.
Why This Skill Matters
Most geolocation attempts by an agent are the model guessing from vibes. geo-sleuth inverts the division of labor: twenty-odd single-purpose Python scripts do the searching, scoring, and sorting, and the model only judges among the top few. Three rules from the README define the discipline:
- Every claim points at a file. A conclusion has to name the command that ran in the session and the file it produced. Population and fame are not evidence.
- Geometry instead of guesswork. Pier spacing becomes a distance ruler, shadows become a bearing, a ridge line becomes a fingerprint matched against elevation data.
- Exclusions need evidence. Observations and guesses can only lower a candidate's weight; ruling one out requires read or computed proof.
It works as a standard Agent Skill — one SKILL.md plus plain Python scripts — so the same folder runs in Claude Code, Codex, Cursor, Gemini CLI, OpenCode, and GitHub Copilot.
Installation
The documented one-liner installs it and prompts you to pick your agents:
npx skills add Oldcircle/geo-sleuth
To cover all six agents user-wide in one command:
npx skills add Oldcircle/geo-sleuth -g -a claude-code -a codex -a cursor -a gemini-cli -a opencode -a github-copilot -y
Prefer to copy the folder yourself? The README documents the manual git clone route into ~/.agents/skills/ (with a symlink for Claude Code). On first use, ask the agent to run doctor.py from the installed skill's scripts/ folder and address any failed checks. You need Python 3.10+, uv, curl, and — for reverse image search — Chrome or Playwright Chromium. The ML-backed scripts download their models on first use, so allow extra time and disk.
Real Workflow: Locate a Stripped Photo
Hand your agent a photo and say:
这张照片没有 GPS 信息。找出它是在哪里拍的:给出相机位置、朝向、误差半径和置信度,每个结论都要指向实际运行过的命令和产出的文件。
The skill's documented pipeline then runs: intake.py runs metadata, edge crops, OCR, and reverse image search in one pass; the candidate board collects clues and ranks hypotheses; terrain.py, osm.py, and sun.py scan regions and fit skylines; sat_scan.py and match.py rank satellite tiles and street view against the photo. The README's flagship case shows the funnel at full scale: from 27,335 OpenStreetMap railway-bridge segments in a region, through 171 candidate sites, 14,372 fitted camera positions, and a final pier-count check, down to a single spot rated ±2 m — a run that took about 72 minutes end to end.
Expect iteration, not a single answer: the desert case in the README documents the skill getting stuck around 10 pixels of skyline error until the fit was extended to solve a 1° camera tilt — that fix is now part of terrain.py fit by default.
Tips
- Run the local-only pipeline first with
intake.py photo.jpg --out-dir intake --no-revto check metadata, crops, and OCR before anything touches an online service. - Source evidence stays in its original language — the skill's maintained instructions are English, and the agent explains Chinese OCR text or place names in your language.
- The README publishes blind re-runs with a fresh agent: 87 m from the confirmed position on the desert photo (32 minutes), 3 m on the Vancouver cherry street (53 minutes). It also states plainly that both photos had been solved before, so these are regression checks, not accuracy numbers on unseen photos.
GEO_DEVICE=cpu|cuda|mpsforces the device for the ML scripts, which otherwise pick CUDA, then MPS, then CPU.
When Not to Use This
The README draws the line itself: run it on your own photos or ones you have permission to analyze, never to find people who have not agreed to be found. Results also vary by model and by the decisions made mid-run — the README warns that a different model may not reach the same result. And for photos that are simply documented somewhere ("Eiffel Tower, daytime"), a reverse image search in a browser answers faster than a 72-minute geometric pipeline.
See the leaderboard for more skills.