Remote Sensing Research Radar
limi124/remote-sensing-research-radar
Track, retrieve, screen, and synthesize research frontiers for geospatial AI, remote sensing big data, and transferable computer vision methods.
Geolocate or chronolocate a photo with tool-verified reasoning (where was this taken / when was it taken / photo geolocation / geo-guessing).
$ npx skills add Oldcircle/geo-sleuth --skill geo-sleuth -a claude-codeProject install by default; add -g for ~/.claude/skills/.
$ gh skill install Oldcircle/geo-sleuth geo-sleuth --agent claude-codeProject scope by default; add --scope user for a personal install. Needs GitHub CLI 2.90.0 or later (public preview).
$ git clone --depth 1 https://github.com/Oldcircle/geo-sleuth.git skills-src && mkdir -p .claude/skills && cp -r skills-src/skills/geo-sleuth .claude/skills/geo-sleuth && rm -rf skills-srcUse ~/.claude/skills/ instead of .claude/skills for a personal install. The folder must contain SKILL.md.
Claude Code skills documentation · loads skills from .claude/skills/
Install the "geo-sleuth" agent skill from https://github.com/Oldcircle/geo-sleuth/tree/main/skills/geo-sleuth into .claude/skills/geo-sleuth/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "geo-sleuth", then confirm the skill loads.Claude Code copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$skill-installer install https://github.com/Oldcircle/geo-sleuth/tree/main/skills/geo-sleuthType this inside Codex. $skill-installer <name> installs a curated skill from openai/skills. The installer writes to $CODEX_HOME/skills (default ~/.codex/skills). Restart Codex if the skill does not show up.
$ npx skills add Oldcircle/geo-sleuth --skill geo-sleuth -a codexProject install goes to .agents/skills/; add -g for ~/.codex/skills/.
$ gh skill install Oldcircle/geo-sleuth geo-sleuth --agent codexProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/Oldcircle/geo-sleuth.git skills-src && mkdir -p .agents/skills && cp -r skills-src/skills/geo-sleuth .agents/skills/geo-sleuth && rm -rf skills-srcUse ~/.agents/skills/ instead of .agents/skills for a personal install.
Codex skills documentation · loads skills from .agents/skills/
Install the "geo-sleuth" agent skill from https://github.com/Oldcircle/geo-sleuth/tree/main/skills/geo-sleuth into .agents/skills/geo-sleuth/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "geo-sleuth", then confirm the skill loads.Codex copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ npx skills add Oldcircle/geo-sleuth --skill geo-sleuth -a cursorProject install goes to .agents/skills/; add -g for ~/.cursor/skills/.
$ gh skill install Oldcircle/geo-sleuth geo-sleuth --agent cursorProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/Oldcircle/geo-sleuth.git skills-src && mkdir -p .cursor/skills && cp -r skills-src/skills/geo-sleuth .cursor/skills/geo-sleuth && rm -rf skills-srcUse ~/.cursor/skills/ instead of .cursor/skills for a personal install.
Cursor skills documentation · loads skills from .cursor/skills/, .agents/skills/, .claude/skills/, .codex/skills/
Install the "geo-sleuth" agent skill from https://github.com/Oldcircle/geo-sleuth/tree/main/skills/geo-sleuth into .cursor/skills/geo-sleuth/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "geo-sleuth", then confirm the skill loads.Cursor copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ gemini skills install https://github.com/Oldcircle/geo-sleuth.git --path skills/geo-sleuth--scope user (default) or --scope workspace; --path is the subfolder of the repo that holds the skill; --consent skips the security confirmation prompt.
$ npx skills add Oldcircle/geo-sleuth --skill geo-sleuth -a gemini-cliProject install goes to .agents/skills/; add -g for ~/.gemini/skills/.
$ gh skill install Oldcircle/geo-sleuth geo-sleuth --agent gemini-cliProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/Oldcircle/geo-sleuth.git skills-src && mkdir -p .gemini/skills && cp -r skills-src/skills/geo-sleuth .gemini/skills/geo-sleuth && rm -rf skills-srcUse ~/.gemini/skills/ instead of .gemini/skills for a personal install, then run /skills reload.
Gemini CLI skills documentation · loads skills from .gemini/skills/, .agents/skills/
Install the "geo-sleuth" agent skill from https://github.com/Oldcircle/geo-sleuth/tree/main/skills/geo-sleuth into .gemini/skills/geo-sleuth/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "geo-sleuth", then confirm the skill loads.Gemini CLI copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ gh skill install Oldcircle/geo-sleuth geo-sleuthInstalls for Copilot at project scope by default; add --scope user for a personal install. Preview a skill first with gh skill preview. Needs GitHub CLI 2.90.0 or later (public preview).
$ npx skills add Oldcircle/geo-sleuth --skill geo-sleuth -a github-copilotProject install goes to .agents/skills/; add -g for ~/.copilot/skills/.
$ git clone --depth 1 https://github.com/Oldcircle/geo-sleuth.git skills-src && mkdir -p .github/skills && cp -r skills-src/skills/geo-sleuth .github/skills/geo-sleuth && rm -rf skills-srcUse ~/.copilot/skills/ instead of .github/skills for a personal install. Commit .github/skills so cloud agent and code review can use it.
GitHub Copilot skills documentation · loads skills from .github/skills/, .claude/skills/, .agents/skills/
Install the "geo-sleuth" agent skill from https://github.com/Oldcircle/geo-sleuth/tree/main/skills/geo-sleuth into .github/skills/geo-sleuth/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "geo-sleuth", then confirm the skill loads.GitHub Copilot copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ npx skills add Oldcircle/geo-sleuth --skill geo-sleuth -a opencodeOpenCode documents no install command of its own. Project install goes to .agents/skills/; add -g for ~/.config/opencode/skills/.
$ gh skill install Oldcircle/geo-sleuth geo-sleuth --agent opencodeProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/Oldcircle/geo-sleuth.git skills-src && mkdir -p .opencode/skills && cp -r skills-src/skills/geo-sleuth .opencode/skills/geo-sleuth && rm -rf skills-srcUse ~/.config/opencode/skills/ instead of .opencode/skills for a personal install.
OpenCode skills documentation · loads skills from .opencode/skills/, .claude/skills/, .agents/skills/
Install the "geo-sleuth" agent skill from https://github.com/Oldcircle/geo-sleuth/tree/main/skills/geo-sleuth into .opencode/skills/geo-sleuth/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "geo-sleuth", then confirm the skill loads.OpenCode copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
geo-sleuthGeolocate or chronolocate a photo with tool-verified reasoning (where was this taken / when was it taken / photo geolocation / geo-guessing).
Geo Sleuth is an agent skill from Oldcircle/geo-sleuth. Geolocate or chronolocate a photo with tool-verified reasoning (where was this taken / when was it taken / photo geolocation / geo-guessing). Given one or more photos, one command does metadata, OCR and reverse image search (intake.py); clues and candidates go on a candidate board (board.py) that ranks them by script and gives the next step; lookup-table clues via clues.py (plates, area codes, calling codes, driving side, territories); satellite imagery and street view are both "the machine ranks first, you look…
Its SKILL.md is about 6.1k tokens, which your agent loads only when the skill is triggered. The skill folder holds 48 other files, including scripts and reference files (for example `data/README.md`, `data/calling_codes.json` and `data/cn_admin.json`).
It sits in Data & Analytics, covering Geospatial analysis. The repository describes itself as: 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… The licence is MIT.
6 steps, taken from the step headings in SKILL.md.
Read from SKILL.md and the folder at commit 88b64c0. It shows what the files ask for, not the result of running them.
Pre-approves nothing: there is no allowed-tools line, so your agent's usual permission prompts apply.
From allowed-tools in the SKILL.md frontmatter.
Ships 1 file in scripts/, which the agent can run.
Shell commands in SKILL.md call:
uvuvxbashFrom the folder's file list and the shell code blocks in SKILL.md.
No URLs in SKILL.md. Its commands use uv and uvx, which can reach the network depending on how they are called.
From URLs in SKILL.md, links to its own repository left out.
Names no API keys, tokens, secrets or passwords.
From names ending in _API_KEY, _TOKEN, _SECRET, _KEY or _PASSWORD in SKILL.md.
Geo Sleuth loads about 6.1k tokens when it runs, and up to ~45k if it reads all its reference files. Until then it costs about 254 tokens; SKILL.md has 3,175 words of instructions outside code blocks.
Estimates: characters ÷ 4, the usual rule of thumb; real counts depend on the model's tokenizer. Scripts and assets cost tokens only if the agent reads them.
The automated check found no risky patterns in SKILL.md.
Automated static check — not a guarantee. Review scripts before installing. It scans the text of SKILL.md for risky patterns (piping downloads into a shell, reading credential files, hidden Unicode, destructive commands); the scripts in this folder are not scanned.
The full file from Oldcircle/geo-sleuth at commit 88b64c0, republished under its MIT licence (© Oldcircle). 3,175 words, ~6,137 tokens.
.claude/skills/geo-sleuth/SKILL.md (or your agent's skills folder). This skill also uses 45 other files; get the full folder from GitHub.Goal: find a location that holds up under checking. Every conclusion must point to the clue it used, the command it ran and the file it produced.
${CLAUDE_SKILL_DIR}in commands means the directory containing this SKILL.md (the same for commands in references). Claude Code substitutes it automatically; in other agents, firstexport CLAUDE_SKILL_DIR=<absolute path of this directory>before running (if the shell doesn't keep variables between commands, prefix every command with it), or replace it with that path directly.
The work is split into three layers. Remember this first, then read the flow:
| Layer | Who | Tools |
|---|---|---|
| Decision: which candidates exist, how evidence is scored, whether a candidate can be excluded, what to scan next | Script (candidate board) | board.py |
| Perception: reading text, table lookups, finding targets in satellite imagery, street-view matching | Scripts compute and rank first; you look only at the top few | intake.py ocr.py clues.py sat_scan.py match.py geo.py bearings |
| Judgment: pulling clues out of the image, proposing hypotheses when the tables have nothing, deciding among the machine's top few | You | — |
The method comes from breaking down 14 photo-geolocation (网络迷踪) creator videos and 22 puzzles, plus several rounds of blind-test comparisons; the breakdown notes are not published with the repo. The lesson of v1: rules written as prose don't get executed, and two runs of the same skill version gave very different results; so v2 puts every rule that can be written as code into board.py.
pose.py project --horizon <sea-horizon row> computes what the pitch should be and each feature's "expected row" for the current camera position; reconcile that with the photo (the depression angle to a target ≠ the camera's pitch; look up the camera position's elevation with terrain.py elev — if the height difference doesn't match the depression angles in the image, the camera position is wrong).sun.py compass or a confirmed landmark, then use geo.py bearings to see which outline around the candidate camera position falls on that bearing; when nothing fits, first try both templates ("original/mirrored", "sunrise/sunset"); if not verified, only lower the tier, don't exclude.board.py children to add all subordinate admin divisions as candidates, then rank them with evidence. Don't default to the main urban district, don't pick by population.clues.py lookup territories <country A> --continent <continent>.board.py report is always the top-ranked candidate; the rest go into alternatives with discriminating tests.board.py exclude only accepts read/computed clues + a computed file (output of geo.py frame, terrain.py, etc.); observed and inferred clues can only down-weight via evidence --against, with the likelihood ratio clamped to 1/3–3 (inferred) or 1/5–5 (observed). Generating candidates from "there's an X nearby" is also filtering, and X must be something confirmed in the image. Fine-level candidates such as campuses, residential compounds and street segments must go on the board too: add a batch at once with board.py add --from <poi.py --out / osm.py geom output> --level area/road, don't hand-pick; when you drop one, write evidence --against with a comparison image, and check lists candidates without a single piece of evidence (meaning nobody looked at them); labels from third-party data (tree species in a municipal inventory, an exact school-name match) can only down-weight, never justify exclusion (in two cases the ground truth was skipped by hand exactly this way). The excluded extent must be ≤ the evidence extent: for candidates with extent, such as districts, areas and roads, exclude needs --covers lat,lon[:lat,lon] stating which stretch the evidence covers; the script rejects coverage below half (excluding a whole road after looking at one point on it failed in two cases).board.py next): finish the small districts first, put large districts last with a page cap.You don't have to go through every step: if reverse image search in step 1 hits directly, jump to steps 6 and 7 to confirm. Every step's output goes on the candidate board.
uv run ${CLAUDE_SKILL_DIR}/scripts/intake.py photo.jpg --out-dir intake/ [--box x0,y0,x1,y1 ...]
uv run ${CLAUDE_SKILL_DIR}/scripts/board.py init --photo photo.jpgintake.py usually takes 1–2 minutes, longer on the first run because it installs dependencies: give the command a generous timeout (10+ minutes) or run it in the background. If a command timeout interrupts it, the reverse-image-search subprocesses may still be writing into rev/, but intake.md won't be generated; don't treat it as finished.
intake.md contains: metadata, OCR text (lines read from upscaled/tiled passes are marked pass=up/tile and are hypotheses), Baidu similar images (source-site counts + numbered contact sheet), reverse-image-search labels with tiered vote counts, likely residential compound/development names, the list of edge crops, and failed items. Then you do four things:
edges/ (four edges, four corners); run through the checklist in references/observe.md; log each clue with board.py clue "<text>" --kind <kind> --status observed|read|inferred|computed --file <zoomed crop>. Be honest about status: text you read is read; "the building is probably 8 floors", "the road goes uphill" are inferred.clues.py lookup <kind> <value>; for those that resolve to an admin division, use board.py apply --kind plate --value 渝G --file <zoomed crop> directly (adds candidates and evidence automatically; the other candidates at the same level are only down-weighted, not excluded).rev/<name>_baidu_similar.jpg (the top-left tile is the query image) and look for near-duplicates of the same object or the same scene; if there are any, go by number to similar[i].from in the JSON to see the source page; compound, development or hotel names in the labels → poi.py "<name>" --city <city> --out pois.json to get coordinates; for same-name hits (several campuses, several branches) put them all on the board with board.py add --from pois.json --level area, then check; always open the screenshots, and once a post hits, look through the rest of its photo set. Choose where to search by object type (references/search.md).uv run ${CLAUDE_SKILL_DIR}/scripts/board.py children <parent admin area> # municipality → all districts; country → first-level admin divisions (gazetteer.py queries OSM, with bbox)
uv run ${CLAUDE_SKILL_DIR}/scripts/board.py evidence --clue K1 --for <candidate A>:5 --for <candidate B>:2 --against <candidate C>:0.3 --why "…" --file <comparison image>
uv run ${CLAUDE_SKILL_DIR}/scripts/board.py rank
uv run ${CLAUDE_SKILL_DIR}/scripts/board.py nextnext only ever says one of two things:
tiles.py fetch --zoom 13 or terrain.py) → vehicle livery (revimg.py --query "<城市> <颜色> 公交" (Chinese query: "<city> <color> bus"); read route signs from the result images, compare the stripe along the bus rear by district) → street fixtures (baidu_pano.py sample --bbox <built-up area> --n 24) → river/road-network templates. Still can't separate after all of them: don't stop; scan in the "share ÷ pages" order it gives.board.py urban <candidate> (or give it by hand with scan-bbox), then write a falsification condition with board.py falsify <candidate> --text "…", then go to step 3.The coarse environmental-location rules still apply: terrain before river width and building color; phenology must be paired with the month; take the intersection of rare facility combinations; recognizable species are only an exclusion tool; when all you have is a land type, first narrow to that type of land with a land-cover map (references/clues/).
| What you have | Approach | Read |
|---|---|---|
| A unique anchor (building, statue, tower, scenic-area building) | Anchor geometry: sight-line intersection, alignment lines, tangent lines, filtering buildings by camera height | geometry.md |
| Distant mountains, skyline | Render candidate camera positions with terrain.py view and compare; this fixes only one sight line, then find a second constraint | geometry.md |
| Clear shadows, lit faces, the sun in the frame | sun.py locate / when / facing / compass: latitude band, time, heading, true bearing of objects in the image | sky.md |
| Route numbers, railway or power-line specs, a large river | Linear corridor + line-to-point: osm.py route / crossings / along | corridors.md |
| Two or three kinds of infrastructure in one frame | osm.py near --report; crossings of two linear types osm.py intersect (bends are only annotated, not removed) | corridors.md |
| Linear infrastructure + unrecognized mountains, no text | Compute horizons from elevation along the infrastructure and filter a whole region → score skyline + distance to infrastructure numerically → overlay the top 3–5 → fix the camera position from evenly spaced structures: terrain.py scan --lines … --out hits.json --clusters-out clusters.json → terrain.py ridge photo.jpg --x0 … --x1 … --out ridge.json → terrain.py fit --hits hits.json --ridge ridge.json [--line … --line-dist …] --sheet top.jpg --photo photo.jpg (for the fine search switch to --at lat,lon --radius 800 --grid 100 --zoom 13) → imgprep.py piers photo.jpg --rows … --out cols.json --sheet piers.jpg → geo.py spacing --cols … --line … --span … --center lat,lon --ridge ridge.json | corridors.md 4.3, geometry.md 7.4 / 7.7 |
| Clear street layout, no anchor | osm.py street-scan to filter intersections → tiles.py sheet → street view | corridors.md |
| No near-duplicates from reverse image search, no text, only a set of scene elements (road spec + adjacent features + landform) | Don't hand-pick spots first: write the scene as one English query and let CLIP rank with sat_scan.py grid --bbox <coastal strip/corridor> --zoom 17 --cell 360 --query … --neg …; look only at the top 20–30 thumbnails; grid beats points because OSM features like amenity=parking may be incomplete | search.md |
| ≥4 points of known location in the frame (window views, looking down; also level shots of distant towers, bridges, piers — fix the height) | pose.py solve solves camera position, heading and height; when several candidate positions all fit, score them one by one with pose.py check --cands; only robust Δchi2 > 9 may go to board.py exclude --computed | geometry.md section 10 |
| Want to exclude by "there's no X in the frame" | geo.py frame first computes whether X should be inside the frame, large enough and not occluded; only what it says can exclude goes to board.py exclude --computed | geometry.md section 11 |
| Recognizable facility type (grain dryer tower, feed mill, sugar mill, concrete batching plant) | Look up the industry's distribution → enumerate large buildings with osm.py buildings → rank with sat_scan.py points | search.md |
| Stores of a chain's sub-brand | First search opening press releases for the address; use store locators only as a candidate pool → osm.py along + street-view sampling | search.md |
| Plane window, drone shots looking down | Aerial branch | aerial.md |
uv run ${CLAUDE_SKILL_DIR}/scripts/sat_scan.py grid --bbox <scan_bbox> --zoom 17 --preset track --multi-scale --top 30 --out sat.json --sheet sat_top.jpg --heat heat.jpg
uv run ${CLAUDE_SKILL_DIR}/scripts/poi.py "<district> 学校" --city <prefecture-level city> --out schools.json # Chinese query "<district> school"; seeds: --seeds schools.json boosts nearby cells
uv run ${CLAUDE_SKILL_DIR}/scripts/sat_scan.py points --points big.json --preset factory --out r.json --sheet r.jpg # rank candidate points from osm.py buildings / poi.py--query. In tests: across 300-odd cells of an urban area, more than half of the OSM-mapped running tracks made the top 30; in an old town in China where OSM is blank, a school's sports field still ranked first. It ranks, it doesn't decide: look at the thumbnails of the top 20–30 cells, then check them against the bearing and shape in the photo.board.py check and to the falsification conditions, then switch preset or go to z18, and only then widen the area.uv run ${CLAUDE_SKILL_DIR}/scripts/baidu_pano.py scan <lat,lon> --radius 300 --out panos.json # China; outside China use gsv.py
uv run ${CLAUDE_SKILL_DIR}/scripts/match.py rank --query photo.jpg --panos panos.json --toward <landmark lat,lon> --spread 15 --refine sift --top 10 --out m.json --sheet m.jpg
uv run ${CLAUDE_SKILL_DIR}/scripts/match.py rank --query photo.jpg --items around.index.json --render gsv --spread-headings -30,0,30 --out m.json --sheet m.jpgmatch.py coarse-ranks by DINOv2 global similarity and fine-ranks by SIFT inliers; in tests, ground-truth street views of the same place from different years all made the top 4. Open only the top 10 and compare invariant features (building outline, window positions, balconies, pole positions, curbs, ridgelines), not vehicles, signs or foliage. ≥2 features for road level, ≥3 for building level. Not a single image with ≥15 inliers doesn't mean it's wrong: with a change of season, an old capture, or the photo taken from the sidewalk while street view was shot from the middle of the road, the ground truth had only 5 and 0–8 inliers in tests (two cases); first open the top 10 and compare invariant features, and only if none fit change --spread-headings or widen --within. The global score gets dominated by season (a blossom-season capture ranks high wherever it is), so compare against a historical capture from the same season as the photo when you can (gsv.py sheet --date).sheet --road <road name> --spread 60 shows one road only; older captures have a more open view.terrain.py view --photo; find a name for the candidate facility (OSM name, nearby place name + the facility-type word in the local language) and search news, encyclopedias and official-site photos to compare facade details.geo.py intersect sight-line intersection, geo.py line alignment line, pose.py multi-point solve, camera height, reverse street view); with only one, building-level confidence is at most "medium".sun.py facing --lit left --shaded camera. For photos taken from a car, boat or train, state the direction of travel.uv run ${CLAUDE_SKILL_DIR}/scripts/board.py check # before concluding: do exclusions have files, does the main answer have verified evidence, which clues went unused
uv run ${CLAUDE_SKILL_DIR}/scripts/board.py report --merge result.json # main answer = top-ranked; alternatives, exclusions and unused clues are written into result.json automatically
uv run ${CLAUDE_SKILL_DIR}/scripts/evidence.py spec.json --out evidence.jpgOutput:
geo.py convert), with error radiusboard.py report)Use English for tool messages, report headings and generated labels. Preserve source text (OCR, place names, service responses) verbatim as evidence; explain or translate it for the reader. Write the agent's final report in the user's language. In Chinese, use 高/中/低 for high/medium/low and 城市/片区/路/楼/楼层 for city/area/road/building/floor.
| Level | High | Medium | Low |
|---|---|---|---|
| City | Text, plates, area codes or a confirmed anchor | Several independent weak clues agree | A single weak clue, or only the hint |
| Area | A unique facility or landmark matches ≥3 top-down features in satellite imagery (whole candidate area checked, no second match) | The most similar spot in the candidate area, with candidates still unchecked | Inferred |
| Road | Ground-level match on ≥2 unique features | Layout consistent, 1 unique feature; when there is no ground-level imagery at all: area level high + bearing self-check passed | Satellite layout only |
| Building | Two independent constraints + ground-level match on ≥3 features | One of the two | Inferred |
| Floor | Two kinds of reference agree | A single reference | Don't give |
intake.py counts as one call; if reverse image search with 3 different keyword sets finds nothing, stop and go back to the checklist for other clues.board.py next says "can't separate", do the discriminating tests first); if they still can't be separated after the cheap tests, scan in the order it gives, the first 3 pages of each candidate's built-up area first.sat_scan.py and the top 10 images from match.py; widen only when all of the top ones are wrong, instead of paging through.osm.py coverage before enumerating candidates with OSM: districts with sparse data get silently excluded; switch to sat_scan.py grid and say so in the conclusion.board.py report to report which level is settled.board.py check: go back through the top 20 candidates, in ranking order, that were down-weighted by inference but not excluded.uv, and curl. Always use uv run ${CLAUDE_SKILL_DIR}/scripts/xxx.py; each script declares its dependencies. scripts/ in references is relative to this skill directory.uv run ${CLAUDE_SKILL_DIR}/scripts/doctor.py; add --network to check service reachability. Read the English checks and fixes before starting an expensive scan. It uploads no photos and does not load ML models.uvx playwright install chromium). If neither starts, use intake.py --no-rev and report the skipped search. OCR prefers Apple Vision on macOS and uses RapidOCR elsewhere or as a fallback.match.py and sat_scan.py install ML dependencies and download model weights on first use. Allow extra time and disk space..geo-cache/ in the current directory; the candidate board is board.json in the current directory. Script list and data sources: references/data-sources.md.timeout command; in zsh $var doesn't word-split, so use bash -c or ${=var} in loops. A province-wide Overpass query can take several minutes; run it in the background.© Oldcircle, MIT. Rendered from Markdown: HTML in the file is shown as text, images as links, and headings moved down two levels. Raw file
SKILL.md and 45 other files (scripts, references) in skills/geo-sleuth of Oldcircle/geo-sleuth.
Open the folder on GitHubat commit 88b64c0
Geo Sleuth next to the 5 skills that share the most tags, products or categories with it. Stars are the repository's; “used in” counts other GitHub owners with a copy.
| Skill | Stars | Used in | Tokens | Auto-check | Licence | Repo updated |
|---|---|---|---|---|---|---|
| Geo Sleuth this skillOldcircle/geo-sleuth | 1.3k | — | ~6.1k | Automated safety check: Pass | MIT | |
| Remote Sensing Research Radarlimi124/remote-sensing-research-radar | 142 | — | ~1.3k | Automated safety check: Pass | None | |
| Matlab Process Large Imagesmatlab/matlab-agentic-toolkit | 1.1k | — | ~3k | Automated safety check: Pass | Custom licence | |
| Antv L7antvis/L7 | 4.1k | — | ~1.4k | Automated safety check: Pass | MIT | |
| Portaljs Add Geodatopian/portaljs | 2.4k | 1 repos | ~1.7k | Automated safety check: Pass | MIT | |
| Thematic Mapzzhonglei/GeoCode-Release | 187 | — | ~3.1k | Automated safety check: Pass | MIT |
limi124/remote-sensing-research-radar
Track, retrieve, screen, and synthesize research frontiers for geospatial AI, remote sensing big data, and transferable computer vision methods.
matlab/matlab-agentic-toolkit
Patterns for using blockedImage to process large images, harness parallel compute for image processing, and write custom adapters.
antvis/L7
Comprehensive guide for AntV L7 geospatial visualization library.
datopian/portaljs
Auto-ingest a geospatial file (GeoJSON, Shapefile, GeoPackage, KML/KMZ, FlatGeobuf, CSV-with-geometry) into a PortalJS portal on the user's own machine, with no server.
zzhonglei/GeoCode-Release
Create well-designed maps that follow standard cartographic conventions.
thinson/RS-PaperClaw
A skill your agent uses when operating or maintaining the RS-PaperClaw pipeline that fetches remote-sensing arXiv papers, creates per-paper issues, builds daily digests, reconciles issue sets, and…
Geolocate or chronolocate a photo with tool-verified reasoning (where was this taken / when was it taken / photo geolocation / geo-guessing). Geo Sleuth is an agent skill from Oldcircle/geo-sleuth. Geolocate or chronolocate a photo with tool-verified reasoning (where was this taken / when was it taken / photo geolocation / geo-guessing).
Geo Sleuth fits situations like: the user shares a photo and asks where was this taken / geolocate this / when was this taken / 这是哪 / 在哪拍的 / 帮我定位这张照片 / 网络迷踪 / 图寻 / 几点拍的; tasks that involve Geospatial analysis.
Run `npx skills add Oldcircle/geo-sleuth --skill geo-sleuth -a claude-code`. Or copy the skill folder (skills/geo-sleuth in Oldcircle/geo-sleuth) into .claude/skills/geo-sleuth in your project. Claude Code loads it when a task matches its description.
Run `npx skills add Oldcircle/geo-sleuth --skill geo-sleuth -a codex`. Or copy the skill folder (skills/geo-sleuth in Oldcircle/geo-sleuth) into .agents/skills/geo-sleuth in your project. Codex loads it when a task matches its description.
Cursor, Gemini CLI, GitHub Copilot and OpenCode also load SKILL.md folders. With the skills CLI, run `npx skills add Oldcircle/geo-sleuth --skill geo-sleuth -a cursor` (or -a gemini-cli, github-copilot or opencode for the others). To copy it by hand, put the folder in .cursor/skills/geo-sleuth, .gemini/skills/geo-sleuth, .github/skills/geo-sleuth and .opencode/skills/geo-sleuth in your project.
Going by SKILL.md and its folder, Geo Sleuth needs the command-line tools its instructions call (uv, uvx and bash).
SKILL.md contains no URLs. Its commands use uv and uvx, which can reach the network depending on how they are called. This is read from the text; nothing was executed.
Our automated static check of SKILL.md found no risky patterns, such as piping downloads into a shell, reading credential files or hidden Unicode. It is not a guarantee. The check reads SKILL.md only: the scripts in the folder are not scanned, so read them before running anything.
Geo Sleuth is published under the MIT licence (the repository's licence). It allows redistribution, so the full SKILL.md is shown on this page.
About 6.1k tokens (SKILL.md is roughly 25k characters). Agents keep only the skill's name and description in context until a task matches; then they load SKILL.md in full. Its references folder adds about 39k tokens, read only when the agent opens those files.
Skills that share tags, products or a category with Geo Sleuth: Remote Sensing Research Radar (limi124/remote-sensing-research-radar, 142 stars), Matlab Process Large Images (matlab/matlab-agentic-toolkit, 1.1k stars), Antv L7 (antvis/L7, 4.1k stars) and Portaljs Add Geo (datopian/portaljs, 2.4k stars). The comparison table on this page puts their stars, adoption, token cost, safety result and licence side by side.
Oldcircle (a GitHub user) maintains it in Oldcircle/geo-sleuth, which has 1,272 GitHub stars. The repository was last updated on October 7, 2026.
Source: Oldcircle/geo-sleuth on GitHub. Facts on this page come from the repository at the commit we read; the author's words are quoted as theirs.