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

81 lines
3.0 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

---
name: sg-weather
description: "Singapore weather and air quality - 2-hour forecast by area, 24-hour outlook, PSI. Official NEA data, no API key."
metadata: { "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.
```bash
# 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".