CLI and Go weather package
  • Go 99.8%
  • Pkl 0.2%
Find a file
Repository files (latest commit first)
Filename Latest commit message Latest commit date
Tim Hårek Andreassen 2631e6ba02
All checks were successful
check / check (push) Successful in 32s
ci: Migrate from Sourcehut builds to Forgejo Actions
- ci.yml: branch pushes run check:ci on the mise-labeled runner
- release.yml: tags build 5-platform tarballs (darwin/linux x amd64/arm64,
  windows) with sha256 checksums and upload them via forgejo-release,
  with the annotated tag's message as release notes
- mise.toml: drop hut; build-release only stages tarballs
- needs RELEASE_TOKEN secret with write:repository on tags
2026-09-11 12:37:54 +02:00
.forgejo/workflows ci: Migrate from Sourcehut builds to Forgejo Actions 2026-09-11 12:37:54 +02:00
cmd/lyn build: Move module path to src.timharek.no/tim/lyn 2026-09-09 21:51:28 +02:00
internal build: Move module path to src.timharek.no/tim/lyn 2026-09-09 21:51:28 +02:00
pkg build: Move module path to src.timharek.no/tim/lyn 2026-09-09 21:51:28 +02:00
vhs demo: Update 2026-02-23 23:20:08 +01:00
.gitignore chore: Untrack build binary, prune dead code, refresh CLAUDE.md 2026-06-10 22:31:43 +02:00
.golangci.toml lint: Upgrade golangci-lint and fix all issues 2026-02-21 15:10:00 +01:00
AGENTS.md ci: Migrate from Sourcehut builds to Forgejo Actions 2026-09-11 12:37:54 +02:00
alerts.go build: Move module path to src.timharek.no/tim/lyn 2026-09-09 21:51:28 +02:00
alerts_test.go build: Move module path to src.timharek.no/tim/lyn 2026-09-09 21:51:28 +02:00
clothing.go feat: Add HeatIndex 2026-04-07 22:47:01 +02:00
clothing_test.go feat: Add HeatIndex 2026-04-07 22:47:01 +02:00
CONTRIBUTING.md build: Move module path to src.timharek.no/tim/lyn 2026-09-09 21:51:28 +02:00
dewpoint.go feat(dewpoint): Include optional emoji for certain thresholds 2026-08-19 14:52:13 +02:00
dewpoint_test.go feat(dewpoint): Include optional emoji for certain thresholds 2026-08-19 14:52:13 +02:00
direction.go Rename yr to lyn 2026-02-23 23:01:44 +01:00
direction_test.go Rename yr to lyn 2026-02-23 23:01:44 +01:00
forecast.go build: Move module path to src.timharek.no/tim/lyn 2026-09-09 21:51:28 +02:00
go.mod build: Move module path to src.timharek.no/tim/lyn 2026-09-09 21:51:28 +02:00
go.sum config: Replace custom with viper pkg 2026-08-11 14:13:16 +02:00
hk.pkl ci: Split into two files 2026-08-19 14:56:41 +02:00
LICENSE.md chore: Add license 2024-09-29 19:21:46 +02:00
location.go build: Move module path to src.timharek.no/tim/lyn 2026-09-09 21:51:28 +02:00
lyn.go build: Move module path to src.timharek.no/tim/lyn 2026-09-09 21:51:28 +02:00
lyn_test.go build: Move module path to src.timharek.no/tim/lyn 2026-09-09 21:51:28 +02:00
mise.toml ci: Migrate from Sourcehut builds to Forgejo Actions 2026-09-11 12:37:54 +02:00
README.md ci: Migrate from Sourcehut builds to Forgejo Actions 2026-09-11 12:37:54 +02:00
summary.go feat(dewpoint): Include optional emoji for certain thresholds 2026-08-19 14:52:13 +02:00
summary_test.go feat(dewpoint): Include optional emoji for certain thresholds 2026-08-19 14:52:13 +02:00
sunprotection.go Remove decimal point from String methods 2026-04-15 22:07:35 +02:00
sunprotection_test.go Remove decimal point from String methods 2026-04-15 22:07:35 +02:00
symbol.go cmd: Add emoji and symbol flags and config options 2026-04-02 14:12:14 +02:00
symbol_test.go Rename yr to lyn 2026-02-23 23:01:44 +01:00
uv.go Remove decimal point from String methods 2026-04-15 22:07:35 +02:00
uv_test.go Remove decimal point from String methods 2026-04-15 22:07:35 +02:00
warnings.go Remove decimal point from String methods 2026-04-15 22:07:35 +02:00
warnings_test.go feat: Add weather change warnings 2026-03-20 20:50:40 +01:00
wind.go feat: Add wind_format option (ms, kmh, mph, knots) 2026-08-18 00:01:00 +02:00
wind_test.go feat: Add wind_format option (ms, kmh, mph, knots) 2026-08-18 00:01:00 +02:00

lyn

lyn means lightning in Norwegian.

Quick Start:

lyn now "your city"

demo

Get the weather delivered to your command-line, or use as a Go package, without the need for an API key!

The project uses Meteorologisk institutt's public API, LocationForecast, Sunrise, and MetAlerts, and OpenStreetMap's Nominatim API.

Install CLI

Using go:

go install src.timharek.no/tim/lyn/cmd/lyn@latest

Using Homebrew

brew tap timharek/tap
brew trust timharek/tap
brew install timharek/tap/lyn

Adding more methods in the future. Help is wanted to achieve the best coverage.

Using pre-compiled binary

Select the version you want to install available releases and download it and add it to your $PATH or something similar.

Example:

wget https://src.timharek.no/tim/lyn/releases/download/<release>/lyn-<version>-linux-amd64.tar.gz
tar xf lyn-<version>-linux-amd64.tar.gz
cd lyn-<version>
cp lyn /usr/local/bin

Configuration

lyn uses a TOML config file located at $HOME/.config/lyn.toml. You can set a default location and preferences so you don't have to specify them every time.

Example lyn.toml:

use_utc = false
show_uv = false
show_beaufort = true
show_dewpoint = false
show_humidity = true
show_cloud = false
show_sun_protection = false
show_wear = false
skin_type = 0
temperature_format = "celsius"
wind_format = "ms"

[location]
name = "Bergen, Norway"
longitude = 5.3221
latitude = 60.3913

With a default location configured, you can run commands without specifying a location:

lyn now
lyn forecast
lyn today

Usage

# Get help
lyn --help

# Current forecast for location
lyn now bergen

# Or with a space
lyn now "new york"

# Use default location from config
lyn now

# Forecast for multiple hours
lyn forecast "new york"

# Forecast for next 5 hours
lyn forecast "new york" -n 5

# Today's weather, or at a specific hour
lyn today bergen
lyn today bergen --hour 14

# Tomorrow's weather at a specific hour
lyn tomorrow bergen --hour 08

# Concise day summary with walk recommendation
lyn today summary bergen
lyn tomorrow sum "new york"
lyn today summary bergen --wear

# Include UV index
lyn now bergen --uv

# Show Beaufort scale description alongside wind
lyn now bergen --beaufort

# Include cloud cover
lyn now bergen --cloud

# Dew point with comfort level (Comfortable, Sticky, Oppressive, etc.)
lyn now bergen --dewpoint

# Sun protection advice (effective UV, sunscreen/sunglasses, safe exposure)
lyn now bergen --sunprotection --skin-type 2

# Clothing advice based on temperature, wind chill, rain, humidity, and UV
lyn now bergen --wear
lyn forecast bergen --wear

# Weather alerts in effect for your location, a place, or an area
lyn alerts
lyn alerts bergen
lyn alerts "Deler av Vestland"

# Every alert in effect, land only, orange level and above
lyn alerts list
lyn alerts ls --land
lyn alerts ls --level orange

# Temperature in Fahrenheit
lyn now bergen --temperature fahrenheit

# Wind speed in km/h (or mph, knots)
lyn now bergen --wind kmh

# Open forecast in your web browser
lyn forecast "new york" --web

# Open now in your web browser
lyn now "new york" --web

# View current config
lyn config

# View paths lyn uses (config file, cache dir)
lyn path-list

As an MCP server

lyn can run as a Model Context Protocol (MCP) server, letting AI assistants query weather data through lyn's tools.

lyn mcp

This starts a stdio-based MCP server exposing the following tools:

Tool Description
get_current_weather Current weather conditions for a location
get_forecast Hourly weather forecast (default: 24 hours)
get_alerts Weather alerts in effect, optionally narrowed by location
get_clothing_advice Clothing recommendations based on current weather
get_weather_warnings Detect ice risk, rapid temp swings, and snow/ice buildup
get_sun_protection UV exposure advice and safe exposure time by skin type
get_sunrise_sunset Sunrise and sunset times for a location and date

Claude Code

Add to your .claude/settings.json:

{
  "mcpServers": {
    "lyn": {
      "command": "lyn",
      "args": ["mcp"]
    }
  }
}

Claude Desktop

Add to your Claude Desktop config (~/Library/Application Support/Claude/claude_desktop_config.json on macOS):

{
  "mcpServers": {
    "lyn": {
      "command": "lyn",
      "args": ["mcp"]
    }
  }
}

As a package

go get src.timharek.no/tim/lyn
import "src.timharek.no/tim/lyn"

func weather() {
  client, err := lyn.New()
  if err != nil {
    panic(err)
  }

  now, err := client.Now(lyn.Location{Name: "bergen"})
  // now.Entries[0].Temperature, now.Entries[0].Wind, etc.
  // now.Entries[0].CloudCover, now.Entries[0].Dewpoint, etc.

  // Clothing advice based on current conditions
  // advice := now.Entries[0].ClothingRecommendation()

  // Sun protection assessment
  // sp := now.Entries[0].SunProtection(lyn.SkinTypeII)

  // Weather change warnings from forecast data
  // forecast, _ := client.Forecast("bergen")
  // warnings := lyn.DetectWarnings(forecast.Entries)

  // Day summary with walk recommendation
  // summary := lyn.Summarize(forecast.Entries)

  // Weather alerts in effect (area name match, geocoded fallback)
  // alerts, _ := client.Alerts("Vestland")
  // alerts, _ := client.AlertsAt(lyn.Location{Name: "bergen"})

  sun, err := client.Sun(lyn.Location{Name: "bergen"}, time.Now())
  // sun.Sunrise, sun.Sunset
}

Development

This project uses mise to manage the Go toolchain and tasks.

# Install Go toolchain
mise install

# Build CLI to ./build/lyn
mise run build

# Run tests
go test ./...

# Run linters
mise run check

# Run linters with auto-fix
mise run check-fix

# Build release tarball (needs GOOS, GOARCH, ARCH env)
GOOS=linux GOARCH=amd64 ARCH=amd64 mise run build-release

# Generate VHS demo gif
mise run vhs

# Remove build artifacts
mise run clean

See mise.toml for the full task list.

Similar projects

Contributing

Anyone can contribute to lyn. Please refer to the contribution guidelines.

Open pull requests on lyn, report bugs on the issue tracker.

Data Attribution

Weather data from MET Norway, licensed under Creative Commons Attribution 4.0 International (CC BY 4.0).