$npx -y skills add opengeos/geoai-skills --skill download-dataDownload NAIP aerial imagery for a bounding box. Specify coordinates as minx,miny,maxx,maxy in WGS84 and optionally a year.
| 1 | You are helping the user download NAIP aerial imagery using geoai. |
| 2 | |
| 3 | Input: `$@` |
| 4 | |
| 5 | Follow these steps in order. |
| 6 | |
| 7 | ## Step 1 -- Parse arguments |
| 8 | |
| 9 | Extract the bounding box from the first argument (comma-separated `minx,miny,maxx,maxy`). |
| 10 | |
| 11 | Parse optional flags from remaining arguments: |
| 12 | - `--year YYYY` -> download year (default: most recent available) |
| 13 | - `--output DIR` -> output directory (default: `./naip_data/`) |
| 14 | - `--max-items N` -> maximum number of items to download (default: 10) |
| 15 | |
| 16 | If the input is natural language (e.g. "download NAIP imagery for Knoxville, TN"), extract or infer the bounding box. If you cannot determine the bbox, ask the user for coordinates. |
| 17 | |
| 18 | ## Step 2 -- Validate the bounding box |
| 19 | |
| 20 | Confirm the bounding box has 4 numeric values and represents a valid geographic extent: |
| 21 | - `minx < maxx` and `miny < maxy` |
| 22 | - Longitude values within -180 to 180 |
| 23 | - Latitude values within -90 to 90 |
| 24 | - The area is not unreasonably large (warn if the bbox spans more than 1 degree in either direction) |
| 25 | |
| 26 | If validation fails, report the issue and ask for corrected coordinates. |
| 27 | |
| 28 | ## Step 3 -- Run the download |
| 29 | |
| 30 | ```bash |
| 31 | python3 -c " |
| 32 | import geoai, os |
| 33 | |
| 34 | bbox = (MINX, MINY, MAXX, MAXY) |
| 35 | output_dir = 'OUTPUT_DIR' |
| 36 | os.makedirs(output_dir, exist_ok=True) |
| 37 | |
| 38 | result = geoai.download_naip( |
| 39 | bbox=bbox, |
| 40 | output_dir=output_dir, |
| 41 | year=YEAR, |
| 42 | max_items=MAX_ITEMS, |
| 43 | ) |
| 44 | if isinstance(result, list): |
| 45 | for f in result: |
| 46 | size_mb = os.path.getsize(f) / (1024 * 1024) if os.path.exists(f) else 0 |
| 47 | print(f'{f} ({size_mb:.1f} MB)') |
| 48 | print(f'Total files: {len(result)}') |
| 49 | elif isinstance(result, str): |
| 50 | size_mb = os.path.getsize(result) / (1024 * 1024) if os.path.exists(result) else 0 |
| 51 | print(f'{result} ({size_mb:.1f} MB)') |
| 52 | else: |
| 53 | print(f'Result: {result}') |
| 54 | " |
| 55 | ``` |
| 56 | |
| 57 | Replace `MINX`, `MINY`, `MAXX`, `MAXY`, `OUTPUT_DIR`, `YEAR`, and `MAX_ITEMS` with actual values. |
| 58 | |
| 59 | For the year parameter: |
| 60 | - If `--year` was specified, use that value (e.g. `year=2022`) |
| 61 | - If not specified, omit the parameter or pass `year=None` to get the most recent available |
| 62 | |
| 63 | ## Step 4 -- Update state |
| 64 | |
| 65 | If a state directory exists, update it with the downloaded file paths: |
| 66 | |
| 67 | ```bash |
| 68 | STATE_DIR="" |
| 69 | test -f .geoai-skills/state.json && STATE_DIR=".geoai-skills" |
| 70 | PROJECT_ROOT="$(git rev-parse --show-toplevel 2>/dev/null || echo "$PWD")" |
| 71 | PROJECT_ID="$(echo "$PROJECT_ROOT" | tr '/' '-')" |
| 72 | test -f "$HOME/.geoai-skills/$PROJECT_ID/state.json" && STATE_DIR="$HOME/.geoai-skills/$PROJECT_ID" |
| 73 | ``` |
| 74 | |
| 75 | If `STATE_DIR` is set: |
| 76 | |
| 77 | ```bash |
| 78 | python3 -c " |
| 79 | import json, os |
| 80 | state_file = 'STATE_DIR/state.json' |
| 81 | state = {} |
| 82 | if os.path.exists(state_file): |
| 83 | with open(state_file) as f: |
| 84 | state = json.load(f) |
| 85 | state.setdefault('downloaded_files', []) |
| 86 | state['downloaded_files'].extend(DOWNLOADED_FILES) |
| 87 | with open(state_file, 'w') as f: |
| 88 | json.dump(state, f, indent=2) |
| 89 | " |
| 90 | ``` |
| 91 | |
| 92 | ## Step 5 -- Report results |
| 93 | |
| 94 | Summarize the download: |
| 95 | - Number of files downloaded |
| 96 | - File paths and sizes |
| 97 | - Coverage area (bounding box) |
| 98 | - Year of imagery |
| 99 | |
| 100 | Then suggest: *"Use `/geoai-skills:inspect-geo` to examine the downloaded imagery, or `/geoai-skills:detect-objects` to run AI models on it."* |
| 101 | |
| 102 | ## Error handling |
| 103 | |
| 104 | - **`import geoai` fails** -> delegate to `/geoai-skills:install-geoai`. |
| 105 | - **Network error** -> report the error and suggest retrying. |
| 106 | - **No data available** for the specified region/year -> suggest trying a different year or expanding the bounding box. |
| 107 | - **Timeout** -> suggest reducing `--max-items` or using a smaller bounding box. |