Airsc is free for everyone. If it helps you, support it with $2–$20.

Support
SkillSafeImages, video & audioBeginner friendly

geo-sleuth

Oldcircle · Oldcircle/geo-sleuth

An agent skill that identifies the location where a photo was taken using OpenStreetMap, satellite imagery, and elevation data.

An agent skill that finds where a photo was taken — OpenStreetMap geometry, elevation skylines, satellite imagery and street view — and shows its work. Works with Claude Code, Codex, Cursor, Gemini CLI, OpenCode and GitHub Copilot.

1.5k stars144License: MITUpdated 10 days ago0 opens

See it in action

Skyline overlays comparing the photo to potential locations in China

From the author's READMESkyline overlays comparing the photo to potential locations in China

1/2

From the author's README Oldcircle ·Source

What you can do with it

  • Locate a specific bridge or mountain in a photo within meters using satellite data
  • Provide agents with specialized tools for OSINT and geographic investigations
  • Generate satellite evidence images to verify a physical location claim

Safety check

Safe

No risky patterns found in the files we scanned.

Automated scan of the repo files. Always review code you run.

From the README

🧭 geo-sleuth

An agent skill that finds where a photo was taken — and shows its work.

Works with

…and any other agent that reads SKILL.md and runs shell commands.

No text. No plates. No landmarks. One bridge, one mountain. Located to within 2 m.


Quick start

npx skills add Oldcircle/geo-sleuth

Pick your agents when prompted. Then hand your agent a photo and say:

find where this photo was taken

On first use, ask the agent to run doctor.py from the installed skill’s scripts/ folder and address any failed checks (see Requirements and setup). That is the whole interface. The agent reads SKILL.md, runs the scripts, and comes back with the camera position, the direction it was facing and a satellite evidence image. Prefer to copy the folder yourself? See Installation.

Why geo-sleuth

  • One photo, one sentence. Give your agent a photo and say find where this photo was taken. You get back the camera position, the direction it was facing, and a satellite evidence image.
  • It works when there is nothing to read. No sign, no plate, no landmark: OpenStreetMap geometry, elevation data, satellite tiles and street view carry the search on their own.
  • Geometry instead of guesswork. Pier spacing becomes a distance ruler, shadows become a bearing, a ridge line becomes a fingerprint that elevation data can be matched against.
  • 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.
  • Scripts rank, the model judges. Twenty single-purpose scripts search, score and sort; the model only picks among the top few.
  • One skill, every agent. A standard Agent Skill — SKILL.md plus plain Python scripts — so the same folder runs in Claude Code, Codex, Cursor, Gemini CLI, OpenCode and GitHub Copilot.
  • Answers carry an error radius. Coordinates ± radius, the camera heading, an evidence image and a graded confidence.

Cases

None of these photos had GPS data. Each case lists what the skill read from the photo, how it narrowed the search, and how far the result landed from the confirmed camera position.

1 · Rice paddy and viaductRailway bridges × skyline × pier count. 2 · Desert skylinePower lines × skyline × a phone tilted by 1°. 3 · Cherry streetStreet-tree open data × shadows × street view.

±2 mQingyuan, Guangdong within 100 mDa Qaidam, Qinghai 3 mVancouver, Canada

1. A rice paddy and a viaduct

A phone photo with the EXIF stripped: a white oven at the edge of a harvested rice paddy, a long viaduct in the distance, a steep mountain on the right. Not a single character in the frame. One message to an agent with this skill installed, and it came back with the camera position and the direction the camera was facing.

photo → 27,335 → 171 → 14,372 → 22 → 3 → 1 → ±2 m

StepWhat it didCandidates left
Read the photoPoles on the viaduct are catenary masts, so it is an electrified railway. Pier spacing used as a ruler (32 m span assumed): the left segment is about 0.5 km away, the right one over 1 km. A steep mountain about 3 km away. Rice harvested but grass still green, so no frost yet.South China, as a bet, not a proof
Region scanPulled every railway bridge in the region from OpenStreetMap: 27,335 segments. Sampled a point every 400 m and computed the 360° horizon from elevation data at each one. Kept points with flat ground nearby, a clear mountain within a few km, and a flat horizon next to it.171 sites
Skyline fitPlaced candidate camera positions around each site and rendered the ridge line seen from each one: 14,372 positions. The top 20 were within 0.1° of each other, so it added a constraint: the bridge must be near on the left and far on the right.22
Overlay checkDrew the top three ridge lines back onto the photo. Score #1 (Fuzhou) had a bump hidden behind the oven, which is why it scored well. #3 (Huizhou) sloped where the photo is flat. #2 (Qingyuan) fit from the foot of the mountain to the edge of the frame.1
Pier count17 piers in the photo become 17 bearings from the camera. Where they hit the railway line, the intersections must be evenly spaced. Combined with the skyline: first a band about 300 m long, then a single spot.±2 m

Piers as a ruler: wide spacing on the left means near, tight spacing on the right means far.

Left: the top three ridge lines drawn onto the photo. Right: the evidence image the skill produced.

More figures from this run

Region scan: every railway bridge in the region (grey), sites that pass the horizon test (orange).

Pier count: bearings to the 17 piers intersect the line; only one camera position makes the spacing even. The run took about 72 minutes end to end, roughly half of it waiting on computation.

2. A desert skyline, one degree off

A sand dune in the foreground, a range of bare dark mountains behind it, and a few pylons at the foot of the range. There is no text, road or building in the frame, and reverse image search returned only generic desert photos from northwest China.

photo → 1,537 sites → stuck around 10 px → solve a 1° tilt → 1 site → one dune

StepWhat it didLeft
Read the photoThe pylons are the only man-made objects, so the camera is within a few kilometres of a power line. Sand, gravel and bare rock point to northwest China.4 provinces
Power lines × terrainosm.py geom pulled every power line in Xinjiang, Gansu, Ningxia and Qinghai. terrain.py scan worked along them with elevation data and kept the places where mountains fill the view.1,537 sites
Skyline fitterrain.py ridge traced the ridge in the photo, and terrain.py fit com
View source on GitHub