Files
u-claw/portable/skills/en/sg-weather/SKILL.md
zheng dd8e0f55c3 fix(portable): Gemini keys, Telegram pairing UI, and config durability
Improve first-run and channel setup for non-technical users: detect newer
Gemini key formats, pin Node 22.22.3, add Control Panel Telegram approve
flow, and keep channels/models when config is rewritten. Persist uclaw
wizard state via uclaw-meta.json so restarts skip language/persona prompts.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-08-18 18:45:03 +08:00

3.0 KiB
Raw Permalink Blame History

name, description, metadata
name description metadata
sg-weather Singapore weather and air quality - 2-hour forecast by area, 24-hour outlook, PSI. Official NEA data, no API key.
openclaw
emoji
🌦️

Singapore Weather

Live weather and air quality from NEA via data.gov.sg. No API key, no sign-up.

Worth knowing why this exists as its own skill: Singapore rain is intensely local. It can pour in Bukit Timah while Changi stays dry, so a national forecast is close to useless. The 2-hour forecast is published per area — use it.

What it does

  • Next 2 hours, by area — 47 areas, refreshed every half hour
  • Next 24 hours — general outlook plus morning/afternoon/night
  • PSI — air quality by region, which matters during haze season

How to run it

Use the Bash tool. These are public endpoints.

# Right now, for one area
curl -s "https://api-open.data.gov.sg/v2/real-time/api/two-hr-forecast" \
| python3 -c "
import json,sys
area='Ang Mo Kio'   # change this
d=json.load(sys.stdin)['data']
item=d['items'][0]
hit=[f['forecast'] for f in item['forecasts'] if f['area']==area]
print(f'{area}: {hit[0] if hit else \"area not found\"}')
print('valid until', item['validPeriod']['end'])
"

# Every area at once — useful for 'is it raining anywhere near me'
curl -s "https://api-open.data.gov.sg/v2/real-time/api/two-hr-forecast" \
| python3 -c "
import json,sys
for f in json.load(sys.stdin)['data']['items'][0]['forecasts']:
    print(f\"{f['area']:22} {f['forecast']}\")
"

# 24-hour outlook
curl -s "https://api-open.data.gov.sg/v2/real-time/api/twenty-four-hr-forecast" \
| python3 -c "
import json,sys
r=json.load(sys.stdin)['data']['records'][0]
print('General:', r['general']['forecast']['text'])
print('Temp:', r['general']['temperature']['low'], '-', r['general']['temperature']['high'], 'C')
for p in r['periods']:
    print(p['timePeriod']['text'], '->', p['regions']['central']['text'])
"

# Air quality (PSI) by region
curl -s "https://api-open.data.gov.sg/v2/real-time/api/psi" \
| python3 -c "
import json,sys
psi=json.load(sys.stdin)['data']['items'][0]['readings']['psi_twenty_four_hourly']
for region,value in psi.items():
    band=('Good' if value<=50 else 'Moderate' if value<=100 else
          'Unhealthy' if value<=200 else 'Very unhealthy' if value<=300 else 'Hazardous')
    print(f'{region:8} {value:4}  {band}')
"

Working notes

  • Ask which area they are in, or infer it from context. Do not report a national average — the whole point is that it differs across the island.
  • The 2-hour forecast is a short text like Thundery Showers. Quote it; do not embellish it into a narrative.
  • PSI bands: ≤50 Good · 51100 Moderate · 101200 Unhealthy · 201300 Very unhealthy · >300 Hazardous. During haze, people are deciding whether to run outdoors or keep a child home — give them the number and the band, not a mood.
  • Times come back in SGT. Report them in SGT.
  • If the endpoint is down, say so. Do not fall back to guessing from memory — yesterday's weather stated confidently is worse than "I could not reach NEA".