RepoPilotOpen in app →

schachmat/wego

weather app for the terminal

Healthy

Healthy across the board

weakest axis
Use as dependencyHealthy

Permissive license, no critical CVEs, actively maintained — safe to depend on.

Fork & modifyHealthy

Has a license, tests, and CI — clean foundation to fork and modify.

Learn fromHealthy

Documented and popular — useful reference codebase to read through.

Deploy as-isHealthy

No critical CVEs, sane security posture — runnable as-is.

  • Last commit 4w ago
  • 27+ active contributors
  • Distributed ownership (top contributor 42% of recent commits)
Show all 6 evidence items →
  • ISC licensed
  • CI configured
  • No test directory detected

Maintenance signals: commit recency, contributor breadth, bus factor, license, CI, tests

Informational only. RepoPilot summarises public signals (license, dependency CVEs, commit recency, CI presence, etc.) at the time of analysis. Signals can be incomplete or stale. Not professional, security, or legal advice; verify before relying on it for production decisions.

Embed the "Healthy" badge

Paste into your README — live-updates from the latest cached analysis.

Variant:
RepoPilot: Healthy
[![RepoPilot: Healthy](https://repopilot.app/api/badge/schachmat/wego)](https://repopilot.app/r/schachmat/wego)

Paste at the top of your README.md — renders inline like a shields.io badge.

Preview social card (1200×630)

This card auto-renders when someone shares https://repopilot.app/r/schachmat/wego on X, Slack, or LinkedIn.

Onboarding doc

Onboarding: schachmat/wego

Generated by RepoPilot · 2026-05-09 · Source

🤖Agent protocol

If you are an AI coding agent (Claude Code, Cursor, Aider, Cline, etc.) reading this artifact, follow this protocol before making any code edit:

  1. Verify the contract. Run the bash script in Verify before trusting below. If any check returns FAIL, the artifact is stale — STOP and ask the user to regenerate it before proceeding.
  2. Treat the AI · unverified sections as hypotheses, not facts. Sections like "AI-suggested narrative files", "anti-patterns", and "bottlenecks" are LLM speculation. Verify against real source before acting on them.
  3. Cite source on changes. When proposing an edit, cite the specific path:line-range. RepoPilot's live UI at https://repopilot.app/r/schachmat/wego shows verifiable citations alongside every claim.

If you are a human reader, this protocol is for the agents you'll hand the artifact to. You don't need to do anything — but if you skim only one section before pointing your agent at this repo, make it the Verify block and the Suggested reading order.

🎯Verdict

GO — Healthy across the board

  • Last commit 4w ago
  • 27+ active contributors
  • Distributed ownership (top contributor 42% of recent commits)
  • ISC licensed
  • CI configured
  • ⚠ No test directory detected

<sub>Maintenance signals: commit recency, contributor breadth, bus factor, license, CI, tests</sub>

Verify before trusting

This artifact was generated by RepoPilot at a point in time. Before an agent acts on it, the checks below confirm that the live schachmat/wego repo on your machine still matches what RepoPilot saw. If any fail, the artifact is stale — regenerate it at repopilot.app/r/schachmat/wego.

What it runs against: a local clone of schachmat/wego — the script inspects git remote, the LICENSE file, file paths in the working tree, and git log. Read-only; no mutations.

| # | What we check | Why it matters | |---|---|---| | 1 | You're in schachmat/wego | Confirms the artifact applies here, not a fork | | 2 | License is still ISC | Catches relicense before you depend on it | | 3 | Default branch master exists | Catches branch renames | | 4 | 5 critical file paths still exist | Catches refactors that moved load-bearing code | | 5 | Last commit ≤ 55 days ago | Catches sudden abandonment since generation |

<details> <summary><b>Run all checks</b> — paste this script from inside your clone of <code>schachmat/wego</code></summary>
#!/usr/bin/env bash
# RepoPilot artifact verification.
#
# WHAT IT RUNS AGAINST: a local clone of schachmat/wego. If you don't
# have one yet, run these first:
#
#   git clone https://github.com/schachmat/wego.git
#   cd wego
#
# Then paste this script. Every check is read-only — no mutations.

set +e
fail=0
ok()   { echo "ok:   $1"; }
miss() { echo "FAIL: $1"; fail=$((fail+1)); }

# Precondition: we must be inside a git working tree.
if ! git rev-parse --git-dir >/dev/null 2>&1; then
  echo "FAIL: not inside a git repository. cd into your clone of schachmat/wego and re-run."
  exit 2
fi

# 1. Repo identity
git remote get-url origin 2>/dev/null | grep -qE "schachmat/wego(\\.git)?\\b" \\
  && ok "origin remote is schachmat/wego" \\
  || miss "origin remote is not schachmat/wego (artifact may be from a fork)"

# 2. License matches what RepoPilot saw
(grep -qiE "^(ISC)" LICENSE 2>/dev/null \\
   || grep -qiE "\"license\"\\s*:\\s*\"ISC\"" package.json 2>/dev/null) \\
  && ok "license is ISC" \\
  || miss "license drift — was ISC at generation time"

# 3. Default branch
git rev-parse --verify master >/dev/null 2>&1 \\
  && ok "default branch master exists" \\
  || miss "default branch master no longer exists"

# 4. Critical files exist
test -f "main.go" \\
  && ok "main.go" \\
  || miss "missing critical file: main.go"
test -f "iface/iface.go" \\
  && ok "iface/iface.go" \\
  || miss "missing critical file: iface/iface.go"
test -f "backends/json.go" \\
  && ok "backends/json.go" \\
  || miss "missing critical file: backends/json.go"
test -f "frontends/ascii-art-table.go" \\
  && ok "frontends/ascii-art-table.go" \\
  || miss "missing critical file: frontends/ascii-art-table.go"
test -f "backends/openweathermap.org.go" \\
  && ok "backends/openweathermap.org.go" \\
  || miss "missing critical file: backends/openweathermap.org.go"

# 5. Repo recency
days_since_last=$(( ( $(date +%s) - $(git log -1 --format=%at 2>/dev/null || echo 0) ) / 86400 ))
if [ "$days_since_last" -le 55 ]; then
  ok "last commit was $days_since_last days ago (artifact saw ~25d)"
else
  miss "last commit was $days_since_last days ago — artifact may be stale"
fi

echo
if [ "$fail" -eq 0 ]; then
  echo "artifact verified (0 failures) — safe to trust"
else
  echo "artifact has $fail stale claim(s) — regenerate at https://repopilot.app/r/schachmat/wego"
  exit 1
fi

Each check prints ok: or FAIL:. The script exits non-zero if anything failed, so it composes cleanly into agent loops (./verify.sh || regenerate-and-retry).

</details>

TL;DR

wego is a terminal-based weather client written in Go that fetches weather data from multiple backends (OpenWeatherMap, WeatherAPI, Open-Meteo, SMHI, Caiyun, WorldWeatherOnline, PirateWeather) and renders forecasts via pluggable frontends (ASCII art tables, emoji, markdown, JSON). It displays temperature ranges, wind speed/direction, precipitation, humidity, and multi-day forecasts with configurable units (metric/imperial/SI) and disk caching. Modular architecture: backends/ contains 8 weather data providers (caiyun.go, openweathermap.org.go, etc.), frontends/ contains 4 rendering engines (ascii-art-table.go, emoji.go, markdown.go, json.go), iface/iface.go defines the shared interface, and main.go orchestrates CLI parsing and config management via ingo library.

👥Who it's for

CLI power users and sysadmins who want lightweight weather forecasts in their terminal without leaving the shell, particularly those comfortable with config files and API key management. Also developers who want to compose weather data pipelines using the JSON backend/frontend interface.

🌱Maturity & risk

Production-ready with active maintenance. The project uses Go 1.20+, has GitHub Actions CI (go-build-test.yml, golangci-lint.yml), dependencies are minimal and stable (mattn/go-colorable, muesli/mango). Recent activity visible in dependabot.yml suggests ongoing dependency updates, though specific commit recency and issue count are not shown in provided data.

Low risk overall: only 5 runtime dependencies (all well-maintained Go libraries), no heavy external services required for core functionality (Open-Meteo and SMHI are free/keyless). Main risk is single-maintainer pattern (schachmat org suggests this), and API backend availability depends on third-party services—but the multiple backend strategy mitigates that. Go module versioning (go 1.20) is stable.

Active areas of work

Active dependency maintenance (dependabot.yml) and CI pipeline for go-build-test and linting. The project accepts contributions (CONTRIBUTING.md exists) and maintains a pull request template. No specific milestone or open PR data provided, but the presence of recent GitHub Actions suggests regular activity.

🚀Get running

Clone: git clone https://github.com/schachmat/wego.git && cd wego. Install: go install github.com/schachmat/wego@latest. First run: wego (generates config at $XDG_CONFIG_HOME/wego/wegorc or ~/.config/wego/wegorc), then edit config with API key and location, run wego again.

Daily commands: Run binary: wego [location] [days] or just wego (uses config default). Build from source: go build -o wego in repo root, then ./wego. View help: wego --help. View man page: wego --man. Change backend/frontend in config or CLI flags.

🗺️Map of the codebase

  • main.go — Entry point that orchestrates CLI argument parsing, backend selection, frontend rendering, and caching logic—all contributors must understand the request flow.
  • iface/iface.go — Defines the core Weather interface and data structures that all backends and frontends depend on; changes here ripple across the entire codebase.
  • backends/json.go — Reference backend implementation that demonstrates the interface contract; new backend contributors should study this first.
  • frontends/ascii-art-table.go — Default frontend renderer showing the primary output formatting; essential for understanding how weather data is visualized.
  • backends/openweathermap.org.go — Most commonly used backend (OpenWeatherMap); stability and changes here have the highest user impact.
  • go.mod — Declares all external dependencies and Go version requirement; critical for reproducible builds and understanding the dependency attack surface.

🧩Components & responsibilities

  • main.go (Go flag package, custom CLI logic) — CLI argument parsing, backend/frontend selection, cache management, and orchestration of the fetch-render pipeline
    • Failure mode: Invalid flag combinations, missing config file, or cache corruption → error message and graceful exit
  • Weather Backend (e.g., openweathermap.org.go) (HTTP client, JSON/XML parsing) — Fetches and normalizes weather data from a specific external API into the common []Day format
    • Failure mode: API down, invalid credentials, rate limit, or parse error → returns error; main.go handles fallback or reports to user

🛠️How to make changes

Add a new weather backend

  1. Create a new file in backends/ directory (e.g., backends/newprovider.go) implementing the Weather interface from iface/iface.go (backends/newprovider.go)
  2. Implement Fetch(location string) ([]Day, error) and Name() string methods to normalize the provider's API response into []Day (backends/newprovider.go)
  3. Register the backend as a case in the backend selection logic in main.go by adding a new condition in the backend flag parsing section (main.go)
  4. Test by running wego -b newprovider -l 'City,Country' to verify data fetching and rendering

Add a new terminal output frontend

  1. Create a new file in frontends/ directory (e.g., frontends/newtable.go) implementing the Frontend interface (frontends/newtable.go)
  2. Implement the Render(days []iface.Day, location string) string method to format weather data for terminal output; reuse colors.go utilities if needed (frontends/newtable.go)
  3. Register the frontend by adding a case in the frontend selection logic in main.go (main.go)
  4. Test by running wego -f newtable to verify output rendering

Modify cached weather data structure

  1. Update the Day struct or Weather interface definition in iface/iface.go to add/remove fields (iface/iface.go)
  2. Update all backend implementations (backends/*.go) to populate or ignore the new fields when parsing API responses (backends/openweathermap.org.go)
  3. Update all frontend renderers (frontends/*.go) to display or exclude the modified fields in output (frontends/ascii-art-table.go)
  4. Consider cache invalidation strategy in main.go if the change breaks backward compatibility (e.g., bump cache version or clear old cache entries)

🔧Why these technologies

  • Go 1.20+ — Lightweight, single-binary deployment, fast compilation, and standard library sufficient for HTTP clients and file I/O; ideal for CLI tooling
  • Pluggable backend architecture — Decouples weather provider API specifics from the core app; users can switch providers via CLI flag without code changes; simplifies testing and maintenance
  • Pluggable frontend architecture — Allows multiple output formats (ASCII, emoji, markdown, JSON) for different use cases; JSON frontend enables composability and piping
  • Disk-based TTL caching — Reduces API calls and latency on repeated queries; configurable TTL balances freshness vs. network overhead; no external cache service required
  • mattn/go-colorable & go-runewidth — Portable cross-platform terminal color and Unicode width support; critical for correct ASCII art rendering on Windows, macOS, and Linux

⚖️Trade-offs already made

  • Multiple independent backends vs. unified API wrapper

    • Why: Each weather provider has different response formats, fields, and limitations; unifying them in a wrapper would add abstraction cost and hide important nuances
    • Consequence: More code duplication across backends, but each backend can be optimized for its provider and tested in isolation; easier to add/remove providers without breaking others
  • Disk cache instead of in-memory or external cache service

    • Why: Simplicity and no external dependencies; single-user terminal app doesn't need distributed caching
    • Consequence: Cache is process/machine-local and persists across restarts, but not shared across users or machines; file I/O slightly slower than memory but acceptable for CLI
  • CLI-only interface (no daemon/server mode)

    • Why: Stateless, simple deployment; user runs wego on demand
    • Consequence: Each invocation re-fetches and re-renders; no background refresh; efficient for occasional queries but not ideal for constant monitoring
  • JSON backend and frontend for composability

    • Why: Enables piping weather data between instances without external formats; users can pre-fetch once and render multiple times
    • Consequence: Adds two extra implementations but keeps the architecture pure; minimal code bloat; powerful for scripting/automation

🚫Non-goals (don't propose these)

  • Real-time weather alerts or notifications (static forecast only)
  • Graphical UI (terminal/CLI only)
  • Historical weather data or archival
  • Multi-user or network server mode
  • Custom unit conversions beyond metric/imperial/SI/metric-ms presets
  • Geolocation auto-detection (manual location input only)

🪤Traps & gotchas

Config file resolution order is non-obvious: $WEGORC env var overrides $XDG_CONFIG_HOME/wego/wegorc (or OS equivalent) which overrides legacy ~/.wegorc — must understand OS-specific config paths (os.UserConfigDir()). Most backends require API keys (exceptions: Open-Meteo, SMHI); invalid/missing keys fail silently or return errors. Terminal must support 256 colors and monospaced font with full unicode rune coverage (dejavu sans mono recommended) for emoji/ascii-art frontends. Cache TTL (--cache-ttl) defaults may need tuning per backend's rate limits.

🏗️Architecture

💡Concepts to learn

  • Backend abstraction / Provider pattern — wego's core strength—8 interchangeable weather APIs behind a single interface (iface.go) lets users switch providers without code changes; critical for understanding how to extend the system
  • Frontend abstraction / Adapter pattern — Same weather data can be rendered as ASCII tables, emoji, markdown, or JSON without duplicating fetch logic; teaches separation of data from presentation
  • HTTP caching with TTL (time-to-live) — wego implements disk-based caching with configurable --cache-ttl to reduce API calls; understanding cache invalidation strategies is essential for backend optimization
  • Unicode rune handling and terminal width calculation — Dependencies like mattn/go-runewidth are used because emoji and symbols have variable display widths in terminals; critical for correct ASCII table alignment
  • ANSI 256-color terminal control codes — Frontends like ascii-art-table and emoji use mattn/go-colorable to emit color codes for terminal rendering; understanding escape sequences is needed to enhance output
  • XDG Base Directory specification — Config file resolution follows XDG spec ($XDG_CONFIG_HOME/wego/wegorc) on Linux and uses os.UserConfigDir() for OS-agnostic paths; required knowledge for config management and distribution
  • Composable data pipelines (JSON backend + JSON frontend) — wego can fetch raw JSON from one backend and format it via JSON frontend, enabling Unix-style composition (pipe to jq, other tools); demonstrates functional data flow design
  • chubin/wttr.in — Alternative web-based weather service (similar terminal-friendly output); shows different approach to same problem via HTTP instead of local CLI
  • jqlang/jq — JSON query tool often piped with wego's JSON backend/frontend for composable weather data processing
  • golang/image — Core Go imaging library; could be used to enhance emoji/color rendering in custom frontends
  • spf13/cobra — Popular Go CLI framework; wego uses simpler flag parsing, but Cobra is de facto standard for complex CLI projects in Go ecosystem
  • schachmat/ingo — Direct dependency used for wego's config file management; fork/fork-aware if you need to extend config behavior

🪄PR ideas

To work on one of these in Claude Code or Cursor, paste: Implement the "<title>" PR idea from CLAUDE.md, working through the checklist as the task list.

Add unit tests for backend implementations (backends/*.go)

The repo has 8 different weather backends (openweathermap, weatherapi, open-meteo, smhi, caiyun, worldweatheronline, pirateweather, json) but no visible test files in the backends directory. Given the CI workflow runs go-build-test.yml, adding comprehensive unit tests would catch integration issues early and ensure each backend's JSON parsing and data transformation logic works correctly across API variations.

  • [ ] Create backends/*_test.go files for each backend with mock HTTP responses
  • [ ] Test JSON parsing for each backend's API response format
  • [ ] Test error handling when APIs return malformed or unexpected data
  • [ ] Ensure tests run in the existing golangci-lint.yml and go-build-test.yml workflows without modification

Add integration tests for frontend renderers (frontends/*.go)

The repo has 4 frontend formatters (ascii-art-table, emoji, markdown, json) but no visible test files validating their output. These frontends transform weather data into different formats, and without tests, regressions in table alignment, emoji rendering, or markdown formatting could slip through. This is especially important given the ascii-art-table frontend is the default.

  • [ ] Create frontends/*_test.go files with sample weather data structures
  • [ ] Test ascii-art-table.go output formatting, column alignment, and special character handling
  • [ ] Test emoji.go rendering with various weather conditions
  • [ ] Test markdown.go and json.go output structure and escaping
  • [ ] Verify tests pass in existing CI workflows

Add GitHub Action workflow for cross-platform binary releases

The repo has go-build-test.yml and golangci-lint.yml workflows, but no release automation. Given wego is a terminal CLI tool meant for end users, a .github/workflows/release.yml that builds and publishes binaries for multiple OS/arch combinations (linux, darwin, windows on amd64, arm64) would significantly improve accessibility and follow standard Go project practices.

  • [ ] Create .github/workflows/release.yml triggered on git tags
  • [ ] Use goreleaser or native GitHub Actions to build binaries for linux-amd64, linux-arm64, darwin-amd64, darwin-arm64, windows-amd64
  • [ ] Generate checksums and upload artifacts to GitHub Releases
  • [ ] Document the release process in CONTRIBUTING.md with tag versioning scheme
  • [ ] Test with a beta release tag before promoting to main workflow

🌿Good first issues

  • Add unit tests for backends/json.go and backends/smhi.go—these are critical data-path files with no visible test coverage in the file list; create backends/json_test.go and backends/smhi_test.go with mock weather data
  • Document the iface.go interface contract with examples in a new ARCHITECTURE.md file—show how to implement a custom backend and frontend with code snippets, lowering contributor friction
  • Add integration tests for frontend rendering (e.g., frontends/emoji_test.go) to verify emoji and color codes render correctly on different terminals; use testable package structure

Top contributors

Click to expand

📝Recent commits

Click to expand
  • 1237276 — Replace deprecated smhi pmp3g api with new SNOW api (#220) (nopil3os)
  • a7739fd — Move config file default path to os.UserConfigDir() (#229) (Copilot)
  • b520ebe — Add pirateweather.net backend (#231) (Copilot)
  • c8ba05e — Add color configuration support: --monochrome flag and NO_COLOR env var (#230) (Copilot)
  • c28cf3d — Remove legal disclaimer from README (kordianbruck)
  • 60d20f4 — Remove ISC license section from README (kordianbruck)
  • 65cdb7e — docs: freshen up README.md with latest features (#228) (Copilot)
  • d27dcd7 — Better errors for openweather API (#227) (anveshthakur)
  • 03a03b5 — Fix low temperature text visibility on dark terminal backgrounds (#225) (Copilot)
  • 4f77ff7 — Explicitly ignore Fprintln error in Markdown frontend. (kordianbruck)

🔒Security observations

The wego weather application has a generally good security posture with no critical vulnerabilities identified in the visible code structure. The main concerns are: (1) use of outdated Go version 1.20 which is no longer maintained, (2) dependency on a very old unmaintained package (ingo from 2017), and (3) potential credential exposure risks when handling API keys for external weather services. The application lacks explicit documentation on security best practices. The codebase itself appears to avoid common vulnerability patterns like SQL injection (no database operations visible) and has no obvious hardcoded secrets. Recommendations focus on modernizing the Go version, evaluating dependency maintenance status, and enhancing security documentation.

  • Medium · Outdated Go Version — go.mod. The project specifies Go 1.20 in go.mod, which is an older version. Go 1.20 reached end-of-life in August 2023. Using outdated Go versions may miss critical security patches and bug fixes available in newer releases. Fix: Update to the latest stable Go version (1.23 or newer) to ensure security patches and improvements are included.
  • Medium · Potential Dependency Vulnerabilities — go.mod - schachmat/ingo dependency. The dependency 'github.com/schachmat/ingo' uses a very old commit hash (20170403011506) from 2017, indicating this is an unmaintained dependency. This package may contain unpatched security vulnerabilities and should be evaluated for modern alternatives. Fix: Review if ingo is still necessary. If yes, check for maintained forks or modern alternatives. If kept, audit the code for known vulnerabilities.
  • Low · External API Dependency Without Validation — backends/ directory (multiple backend implementations). The application integrates with multiple external weather API backends (openweathermap, weatherapi, open-meteo, etc.). These backends likely require API keys for authentication. While caching is mentioned as a feature, there's risk of API key exposure if not properly handled during configuration. Fix: Ensure API credentials are never hardcoded. Use environment variables or secure config management. Validate HTTPS connections to backend APIs. Implement rate limiting and timeout controls.
  • Low · JSON Parsing Without Input Validation — backends/json.go, frontends/json.go. The application includes a 'json' backend and frontend that parse external JSON data. Without explicit input validation, malicious JSON payloads could potentially cause issues. Fix: Implement strict JSON schema validation. Use type-safe JSON parsing with struct tags. Limit JSON nesting depth and size. Validate all external data before processing.
  • Low · Missing Security Headers in Documentation — README.md, CONTRIBUTING.md. No evidence of security best practices documentation (e.g., secure credential handling, API key management) visible in README or CONTRIBUTING files. Fix: Add security guidelines documentation covering: credential management, data privacy, reporting security issues, and secure usage patterns.

LLM-derived; treat as a starting point, not a security audit.


Generated by RepoPilot. Verdict based on maintenance signals — see the live page for receipts. Re-run on a new commit to refresh.

Healthy signals · schachmat/wego — RepoPilot