LinhGo
LinhGo

Contents

Building a .NET CLI Tool with .NET 8

This guide walks you through creating a simple .NET CLI tool using .NET 8. The tool will fetch and display the current weather for any city you specify.

The goal is to create a simple yet powerful CLI tool named weathercli that fetches the current weather of any city using the OpenWeatherMap API.

This guide walks you through everything step-by-step.


Before starting, ensure you have the following installed:

Tool Description
.NET 8 SDK Required to build and run .NET 8 apps
OpenWeatherMap API Key Sign up here for free
Terminal CLI interface like Bash, PowerShell, or CMD
Optional: Visual Studio Code For easier coding and debugging

Open your terminal and run:

dotnet new console -n WeatherCliTool
cd WeatherCliTool

This creates a new folder and scaffolds a basic console app.


Open WeatherCliTool.csproj and replace the content with:

<Project Sdk="Microsoft.NET.Sdk">
  <PropertyGroup>
    <OutputType>Exe</OutputType>
    <TargetFramework>net8.0</TargetFramework>
    <PackAsTool>true</PackAsTool>
    <ToolCommandName>weathercli</ToolCommandName>
  </PropertyGroup>
</Project>

Explanation:

Property Purpose
PackAsTool Enables dotnet pack to generate a CLI tool
ToolCommandName Defines the command-line alias (e.g., weathercli)
TargetFramework Targets .NET 8

Install the JSON and HTTP packages needed for calling APIs and handling responses:

dotnet add package System.Net.Http.Json

using System.Net.Http;
using System.Net.Http.Json;

class Program
{
    static async Task Main(string[] args)
    {
        if (args.Length == 0)
        {
            Console.WriteLine("Usage: weathercli <city>");
            Console.WriteLine("Example: weathercli Tokyo");
            return;
        }

        string city = string.Join(" ", args);
        string? apiKey = Environment.GetEnvironmentVariable("OPENWEATHER_API_KEY");

        if (string.IsNullOrWhiteSpace(apiKey))
        {
            Console.WriteLine("❌ ERROR: OpenWeatherMap API key not found.");
            Console.WriteLine("Set it using: export OPENWEATHER_API_KEY=your_key");
            return;
        }

        string url = $"https://api.openweathermap.org/data/2.5/weather?q={city}&appid={apiKey}&units=metric";

        try
        {
            using HttpClient client = new();
            var weather = await client.GetFromJsonAsync<WeatherResponse>(url);

            if (weather is not null)
            {
                Console.WriteLine($"\n🌍 City: {weather.Name}");
                Console.WriteLine($"🌡 Temperature: {weather.Main.Temp}°C");
                Console.WriteLine($"🌦 Condition: {weather.Weather[0].Main} ({weather.Weather[0].Description})");
                Console.WriteLine($"💨 Wind: {weather.Wind.Speed} m/s\n");
            }
            else
            {
                Console.WriteLine("❌ Could not retrieve weather data.");
            }
        }
        catch (HttpRequestException)
        {
            Console.WriteLine("❌ Network error. Please check your internet connection.");
        }
        catch (Exception ex)
        {
            Console.WriteLine($"❌ Unexpected error: {ex.Message}");
        }
    }
}

// API Response Models
public class WeatherResponse
{
    public string Name { get; set; }
    public MainWeather Main { get; set; }
    public List<WeatherInfo> Weather { get; set; }
    public Wind Wind { get; set; }
}

public class MainWeather
{
    public double Temp { get; set; }
}

public class WeatherInfo
{
    public string Main { get; set; }
    public string Description { get; set; }
}

public class Wind
{
    public double Speed { get; set; }
}

Do not hardcode the API key. Instead, set it as an environment variable:

export OPENWEATHER_API_KEY=your_api_key
setx OPENWEATHER_API_KEY your_api_key
$env:OPENWEATHER_API_KEY = "your_api_key"

Run this command to package the tool:

dotnet pack -c Release

The .nupkg file will be created in:

bin/Release/<project-name>.1.0.0.nupkg

Install your packed CLI as a global tool:

dotnet tool install --global --add-source ./nupkg WeatherCliTool

Replace ./nupkg with the path to your .nupkg folder.


Now you can call it from anywhere:

weathercli Hanoi
weathercli "New York"

Sample Output:

🌍 City: Hanoi
🌡 Temperature: 32.5°C
🌦 Condition: Clear (clear sky)
💨 Wind: 2.3 m/s

dotnet tool uninstall --global weathercli

Feature Description
--help argument Show usage instructions
System.CommandLine Advanced argument parsing
Spectre.Console Rich terminal output
Cache Store recent queries to avoid API limits
Unit conversion Add support for Fahrenheit/Imperial units
JSON output Add --json flag for scripting support


Step Task
1 Create console app
2 Configure .csproj
3 Implement CLI logic
4 Add HTTP & JSON handling
5 Secure API key via environment variable
6 Pack using dotnet pack
7 Install with dotnet tool install
8 Use with weathercli <city>
9 Enhance for real-world usage