Install any skill in seconds. Free to start, no credit card required.
Get Started Free →Climate data analysis, modeling workflows, and carbon neutrality research met...
.claude/skills/brycewang-stanford-climate-science-guide/SKILL.md| Test case | Without → With | Effect | Δ tokens | Δ turns |
|---|---|---|---|---|
| case-01 | ✓→✓ | = Same ✓ | 15% | 0% |
| case-04 | ✓→✓ | = Same ✓ | 63% | 0% |
| case-05 | ✓→✓ | = Same ✓ | 89% | 0% |
| case-06 | ✓→✓ | = Same ✓ | 124% | 0% |
| case-08 | ✓→✓ | = Same ✓ | 140% | 0% |
A research skill for analyzing climate data, working with climate model outputs, and conducting carbon-related studies. Covers data sources, standard analytical workflows, and visualization techniques used in climate science publications.
| Dataset | Variables | Resolution | Period | Source | |---------|-----------|-----------|--------|--------| | ERA5 | Temperature, precipitation, wind, etc. | 0.25 deg, hourly | 1940-present | ECMWF/Copernicus | | GPCP | Precipitation | 2.5 deg, monthly | 1979-present | NASA | | HadCRUT5 | Surface temperature anomaly | 5 deg, monthly | 1850-present | Met Office | | NOAA GHCN | Station temperature, precipitation | Point data | 1850-present | NOAA | | CRU TS | Temperature, precipitation, vapor pressure | 0.5 deg, monthly | 1901-present | UEA CRU |
pythonimport xarray as xr def load_cmip6_data(model: str, experiment: str, variable: str, member: str = 'r1i1p1f1') -> xr.Dataset: """ Load CMIP6 model output from a local or cloud archive. Args: model: Model name (e.g., 'CESM2', 'UKESM1-0-LL') experiment: SSP scenario (e.g., 'ssp245', 'ssp585', 'historical') variable: Variable name (e.g., 'tas', 'pr', 'tos') member: Ensemble member ID """ # Using Pangeo cloud catalog import intake catalog = intake.open_esm_datastore( "https://storage.googleapis.com/cmip6/pangeo-cmip6.json" ) query = catalog.search( source_id=model, experiment_id=experiment, variable_id=variable, member_id=member, table_id='Amon' # Monthly atmospheric data ) ds = query.to_dataset_dict(zarr_kwargs={'consolidated': True}) key = list(ds.keys())[0] return ds[key]
pythonimport numpy as np def compute_global_mean_anomaly(ds: xr.Dataset, var: str = 'tas', baseline: tuple = (1850, 1900)) -> xr.DataArray: """ Compute area-weighted global mean temperature anomaly relative to a baseline period. """ # Area weighting by latitude weights = np.cos(np.deg2rad(ds.lat)) weights = weights / weights.sum() # Global mean global_mean = ds[var].weighted(weights).mean(dim=['lat', 'lon']) # Baseline climatology baseline_mean = global_mean.sel( time=slice(str(baseline[0]), str(baseline[1])) ).mean('time') anomaly = global_mean - baseline_mean return anomaly # Usage # anomaly = compute_global_mean_anomaly(historical_ds) # anomaly.plot() # produces a time series of temperature anomaly
Track cumulative CO2 emissions against the remaining carbon budget for temperature targets:
pythondef carbon_budget_tracker(cumulative_emissions_gtco2: float, target_warming: float = 1.5) -> dict: """ Estimate remaining carbon budget. Based on IPCC AR6 estimates. """ # IPCC AR6 remaining budget from 2020 (GtCO2) budgets = { 1.5: {'50pct': 500, '67pct': 400, '83pct': 300}, 2.0: {'50pct': 1350, '67pct': 1150, '83pct': 900} } budget = budgets[target_warming] remaining = {prob: val - cumulative_emissions_gtco2 for prob, val in budget.items()} # At ~40 GtCO2/year current rate years_left = {prob: max(0, val / 40) for prob, val in remaining.items()} return {'remaining_budget_GtCO2': remaining, 'years_at_current_rate': years_left} result = carbon_budget_tracker(cumulative_emissions_gtco2=200, target_warming=1.5) print(result)
pythonimport matplotlib.pyplot as plt import cartopy.crs as ccrs def plot_climate_map(data: xr.DataArray, title: str, cmap: str = 'RdBu_r', vmin: float = None, vmax: float = None): """Publication-quality climate map.""" fig = plt.figure(figsize=(12, 6)) ax = fig.add_subplot(1, 1, 1, projection=ccrs.Robinson()) ax.coastlines(linewidth=0.5) ax.gridlines(draw_labels=True, linewidth=0.3, alpha=0.5) im = data.plot(ax=ax, transform=ccrs.PlateCarree(), cmap=cmap, vmin=vmin, vmax=vmax, add_colorbar=False) cbar = plt.colorbar(im, ax=ax, orientation='horizontal', pad=0.05, shrink=0.7) cbar.set_label(data.attrs.get('units', '')) ax.set_title(title, fontsize=14) plt.tight_layout() return fig
cftime) for model outputs with non-standard calendars| Case | Status | Duration (ms) | Turns | Tokens | Tool calls | ||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| Without | With | Δ | Without | With | Δ | Without | With | Δ | Without | With | Δ | ||
case-17 | fail→fail | 17,725 | 10,400 | -41% | 1 | 1 | 0% | 2,752 | 3,248 | +18% | 0 | 0 | — |
case-01 | pass→pass | 16,884 | 22,407 | +33% | 1 | 1 | 0% | 3,115 | 3,597 | +15% | 0 | 0 | — |
case-02 | fail→fail | 30,932 | 15,502 | -50% | 1 | 1 | 0% | 6,190 | 4,606 | -26% | 0 | 0 | — |
case-03 | fail→fail | 20,313 | 17,091 | -16% | 1 | 1 | 0% | 4,344 | 4,776 | +10% | 0 | 0 | — |
case-04 | pass→pass | 7,415 | 4,023 | -46% | 1 | 1 | 0% | 1,377 | 2,245 | +63% | 0 | 0 | — |
case-05 | pass→pass | 7,377 | 4,579 | -38% | 1 | 1 | 0% | 1,227 | 2,318 | +89% | 0 | 0 | — |
case-06 | pass→pass | 5,556 | 3,073 | -45% | 1 | 1 | 0% | 890 | 1,991 | +124% | 0 | 0 | — |
case-07 | fail→fail | 17,222 | 18,142 | +5% | 1 | 1 | 0% | 2,723 | 4,235 | +56% | 0 | 0 | — |
case-08 | pass→pass | 4,970 | 3,345 | -33% | 1 | 1 | 0% | 815 | 1,960 | +140% | 0 | 0 | — |
case-09 | pass→pass | 4,336 | 1,941 | -55% | 1 | 1 | 0% | 717 | 1,860 | +159% | 0 | 0 | — |
case-10 | pass→pass | 6,332 | 3,255 | -49% | 1 | 1 | 0% | 1,129 | 2,019 | +79% | 0 | 0 | — |
case-11 | pass→pass | 9,373 | 3,259 | -65% | 1 | 1 | 0% | 1,477 | 1,991 | +35% | 0 | 0 | — |
case-12 | pass→pass | 4,883 | 3,541 | -27% | 1 | 1 | 0% | 755 | 2,076 | +175% | 0 | 0 | — |
case-13 | pass→pass | 6,782 | 5,799 | -14% | 1 | 1 | 0% | 1,426 | 2,543 | +78% | 0 | 0 | — |
case-14 | pass→pass | 6,273 | 3,888 | -38% | 1 | 1 | 0% | 1,074 | 2,232 | +108% | 0 | 0 | — |
case-15 | pass→pass | 7,272 | 5,859 | -19% | 1 | 1 | 0% | 1,179 | 2,474 | +110% | 0 | 0 | — |
case-16 | pass→pass | 12,212 | 2,292 | -81% | 1 | 1 | 0% | 2,073 | 1,864 | -10% | 0 | 0 | — |
case-18 | pass→pass | 10,094 | 8,568 | -15% | 1 | 1 | 0% | 1,741 | 2,908 | +67% | 0 | 0 | — |
case-19 | pass→pass | 17,152 | 13,365 | -22% | 1 | 1 | 0% | 2,492 | 3,605 | +45% | 0 | 0 | — |
case-20 | pass→pass | 18,594 | 19,397 | +4% | 1 | 1 | 0% | 2,812 | 4,415 | +57% | 0 | 0 | — |
case-21 | pass→pass | 25,284 | 24,736 | -2% | 1 | 1 | 0% | 4,570 | 6,481 | +42% | 0 | 0 | — |
case-22 | pass→pass | 19,841 | 16,948 | -15% | 1 | 1 | 0% | 3,394 | 4,586 | +35% | 0 | 0 | — |
case-23 | pass→pass | 19,716 | 21,182 | +7% | 1 | 1 | 0% | 3,372 | 4,850 | +44% | 0 | 0 | — |
DecimalAI ran this skill against gemini-3.6-flash twice over the same eval suite — once with the skill loaded and once without — and compared the two runs case by case. 23 cases were attempted. The headline lift of 0 percentage points is the difference between those two pass rates over the 23 comparable cases.
Other measured skills in the registry, with their headline benchmark lift.