cli-weather is a command line weather app for macOS and Linux.
It can:
- print current conditions plus a 7-day forecast
- send the same report by email
- run scheduled email delivery, with Docker Compose as the preferred scheduler path
The preferred installation model is:
- add
cli-weatherto your own existing Docker Compose stack - use the included
.debor.rpmpackage for native host installs only when you want a host-level command
If you already run other containers with Docker Compose, treat cli-weather as one more service in your own compose.yaml.
From the directory that contains your compose.yaml, such as ~/docker-media:
Step 1: bootstrap the cli-weather folder
git clone https://github.com/c1aytonnet/cli-weather.git
cd cli-weather
./scripts/init-docker-config.sh ~/docker-mediaStep 2: add these service definitions to ~/docker-media/compose.yaml
services:
cli-weather:
image: ghcr.io/c1aytonnet/cli-weather:latest
env_file:
- ./cli-weather/.env
environment:
CLI_WEATHER_CONFIG_DIR: /data
CLI_WEATHER_SMTP_PASSWORD_FILE: /run/secrets/cli_weather_smtp_password
secrets:
- cli_weather_smtp_password
volumes:
- ./cli-weather:/data
command: ["cli-weather", "--help"]
cli-weather-scheduler:
image: ghcr.io/c1aytonnet/cli-weather:latest
env_file:
- ./cli-weather/.env
environment:
CLI_WEATHER_CONFIG_DIR: /data
CLI_WEATHER_SMTP_PASSWORD_FILE: /run/secrets/cli_weather_smtp_password
secrets:
- cli_weather_smtp_password
volumes:
- ./cli-weather:/data
entrypoint: ["/app/docker/scheduler-entrypoint.sh"]
restart: unless-stopped
secrets:
cli_weather_smtp_password:
file: ./cli-weather/secrets/cli_weather_smtp_password.txtIf you use visualcrossing, also add:
environment:
CLI_WEATHER_VISUALCROSSING_API_KEY_FILE: /run/secrets/cli_weather_visualcrossing_api_key
secrets:
- cli_weather_visualcrossing_api_keyand:
secrets:
cli_weather_visualcrossing_api_key:
file: ./cli-weather/secrets/cli_weather_visualcrossing_api_key.txtStep 3: edit your new files
~/docker-media/cli-weather/.env~/docker-media/cli-weather/secrets/cli_weather_smtp_password.txt
For the most common Docker setup using metno plus an SMTP password secret file, uncomment this line in ~/docker-media/cli-weather/.env:
CLI_WEATHER_SMTP_PASSWORD_FILE=/run/secrets/cli_weather_smtp_passwordIf you use visualcrossing, also uncomment this line:
CLI_WEATHER_VISUALCROSSING_API_KEY_FILE=/run/secrets/cli_weather_visualcrossing_api_keyStep 4: start the services
cd ~/docker-media
docker compose pull cli-weather cli-weather-scheduler
docker compose run --rm cli-weather cli-weather "Austin, TX"
docker compose up -dRecommended host layout for Docker:
docker-media/
compose.yaml
cli-weather/
.env
config.json
scheduler.log
secrets/
cli_weather_smtp_password.txt
cli_weather_visualcrossing_api_key.txt
In this layout:
cli-weather/is a normal host folder next to yourcompose.yaml- the container bind-mounts that folder and persists its config and scheduler log there
config.jsonis created if you usecli-weather config setor otherwise save config from inside the containerscheduler.logis created when the scheduler container starts.envand any secret files are files you create on the host
- Current weather and 7-day forecast in Fahrenheit
- U.S. ZIP code lookups
- U.S. city/state lookups such as
Austin, TX - International city/country lookups such as
Paris, FranceandLondon, GB - MET Norway as the default provider, with Open-Meteo and Visual Crossing as alternates
- Source attribution in the report output
- SMTP email delivery
- Docker Compose scheduler for preferred recurring jobs
- Native
crontabscheduling as an alternative .deband.rpmpackaging assets for Linux distribution
This is the recommended setup.
Recommended configuration model:
- put normal non-secret settings in
./cli-weather/.env - reference that file with
env_file: ./cli-weather/.env - keep secrets such as SMTP passwords and API keys out of
compose.yaml - prefer Docker secrets or mounted secret files with
*_FILEvariables for secrets
Use the published GitHub Container Registry image, then add these services to your own compose.yaml:
services:
cli-weather:
image: ghcr.io/c1aytonnet/cli-weather:latest
env_file:
- ./cli-weather/.env
environment:
CLI_WEATHER_CONFIG_DIR: /data
CLI_WEATHER_SMTP_PASSWORD_FILE: /run/secrets/cli_weather_smtp_password
secrets:
- cli_weather_smtp_password
volumes:
- ./cli-weather:/data
command: ["cli-weather", "--help"]
cli-weather-scheduler:
image: ghcr.io/c1aytonnet/cli-weather:latest
env_file:
- ./cli-weather/.env
environment:
CLI_WEATHER_CONFIG_DIR: /data
CLI_WEATHER_SMTP_PASSWORD_FILE: /run/secrets/cli_weather_smtp_password
secrets:
- cli_weather_smtp_password
volumes:
- ./cli-weather:/data
entrypoint: ["/app/docker/scheduler-entrypoint.sh"]
restart: unless-stopped
secrets:
cli_weather_smtp_password:
file: ./cli-weather/secrets/cli_weather_smtp_password.txtIf you use visualcrossing as the provider, add this to both services:
environment:
CLI_WEATHER_VISUALCROSSING_API_KEY_FILE: /run/secrets/cli_weather_visualcrossing_api_key
secrets:
- cli_weather_visualcrossing_api_keyand add this secret definition:
secrets:
cli_weather_visualcrossing_api_key:
file: ./cli-weather/secrets/cli_weather_visualcrossing_api_key.txtCreate the app folder and secret folder on the host:
./scripts/init-docker-config.sh .That script:
- creates
./cli-weather/ - copies
.env.exampleto./cli-weather/.envif it does not already exist - creates
./cli-weather/secrets/cli_weather_smtp_password.txt - creates
./cli-weather/secrets/cli_weather_visualcrossing_api_key.txt - sets the secret file permissions to
0600 - leaves existing files in place if you already customized them
After running the script, you still need to edit ./cli-weather/.env and uncomment the secret-file lines you are actually using.
If you prefer to create the files manually, the equivalent commands are:
mkdir -p ./cli-weather/secrets
printf '%s\n' 'your-app-password' > ./cli-weather/secrets/cli_weather_smtp_password.txt
chmod 600 ./cli-weather/secrets/cli_weather_smtp_password.txtIf you use Visual Crossing:
printf '%s\n' 'your-visual-crossing-api-key' > ./cli-weather/secrets/cli_weather_visualcrossing_api_key.txt
chmod 600 ./cli-weather/secrets/cli_weather_visualcrossing_api_key.txtCreate ./cli-weather/.env for the non-secret settings:
CLI_WEATHER_PROVIDER=metno
CLI_WEATHER_LOCATION=Austin, TX
CLI_WEATHER_RECIPIENT=you@example.com,friend@example.com
CLI_WEATHER_SENDER=you@example.com
CLI_WEATHER_SMTP_HOST=smtp.example.com
CLI_WEATHER_SMTP_PORT=587
CLI_WEATHER_SMTP_USERNAME=you@example.com
CLI_WEATHER_SMTP_STARTTLS=true
CLI_WEATHER_SMTP_SSL=false
CLI_WEATHER_CRON_SCHEDULE=0 7 * * *
TZ=America/ChicagoThen enable the secret source that matches your setup:
metnooropen-meteowith an SMTP password file:
CLI_WEATHER_SMTP_PASSWORD_FILE=/run/secrets/cli_weather_smtp_passwordvisualcrossingwith an SMTP password file and API key file:
CLI_WEATHER_SMTP_PASSWORD_FILE=/run/secrets/cli_weather_smtp_password
CLI_WEATHER_VISUALCROSSING_API_KEY_FILE=/run/secrets/cli_weather_visualcrossing_api_key- less secure fallback using plain env vars in
.env:
CLI_WEATHER_SMTP_PASSWORD=app-password
CLI_WEATHER_VISUALCROSSING_API_KEY=your-visual-crossing-api-keyIn this model:
./cli-weather/.envis the preferred place for ordinary configuration values- the Compose
secrets:section is the preferred place for SMTP passwords and API keys - the bind-mounted
./cli-weatherfolder is where the app storesconfig.jsonwhen you save config andscheduler.logwhen the scheduler runs - you only put secrets directly in
environment:when you intentionally accept that tradeoff
Then run:
docker compose pull cli-weather cli-weather-scheduler
docker compose run --rm cli-weather cli-weather "Austin, TX"
docker compose up -dWhat those commands do:
docker compose pull cli-weather cli-weather-schedulerPulls the published image from GitHub Container Registry.docker compose run --rm cli-weather cli-weather "Austin, TX"Runs a one-off weather lookup inside a temporary container so you can verify the app works before enabling scheduled jobs.docker compose up -dStarts the background scheduler container, which uses cron to send email on the schedule defined byCLI_WEATHER_CRON_SCHEDULE.
This model is ideal when:
- you already manage services in your own Compose stack
- you want scheduled jobs to live alongside your other containers
- you prefer configuration to live in your own
./cli-weather/.env, Compose secrets, andcompose.yaml
Use this if you want a quick standalone setup from this repo without merging into your existing stack.
Requirements:
- Docker
- Docker Compose
- access to
ghcr.io/c1aytonnet/cli-weather:latest
Initial setup:
./scripts/init-docker-config.sh .
docker compose pullAfter that, you can run one-off commands:
docker compose run --rm cli-weather cli-weather 78613
docker compose run --rm cli-weather cli-weather "Paris, France"
docker compose run --rm cli-weather cli-weather email sendPrebuilt package artifact is tracked in git at:
release-assets/v0.7.0/cli-weather_0.7.0_all.debInstall directly from the checked-out repository:
sudo dpkg -i release-assets/v0.7.0/cli-weather_0.7.0_all.debOr build a fresh package on Linux with dpkg-deb available:
./scripts/build-deb.shInstall:
sudo dpkg -i dist/cli-weather_0.7.0_all.debPrebuilt package artifact is tracked in git at:
release-assets/v0.7.0/cli-weather-0.7.0-1.noarch.rpmInstall directly from the checked-out repository:
sudo rpm -i release-assets/v0.7.0/cli-weather-0.7.0-1.noarch.rpmOr build a fresh package on Linux with rpmbuild available:
./scripts/build-rpm.shInstall:
sudo rpm -i dist/rpmbuild/RPMS/noarch/cli-weather-0.7.0-1.noarch.rpmpython3 -m venv .venv
source .venv/bin/activate
python3 -m pip install --upgrade pip
python3 -m pip install .If you want to use cli-weather as a normal persistent command on macOS, pipx is the recommended installation method.
Install pipx:
brew install pipx
pipx ensurepathThen install cli-weather from the cloned repo:
git clone https://github.com/c1aytonnet/cli-weather.git
cd cli-weather
pipx install .After that, you should be able to run:
cli-weather 78613
cli-weather "Austin, TX"
cli-weather "Paris, France"If you prefer not to use pipx, you can still install from source with Python:
python3 -m venv .venv
source .venv/bin/activate
python3 -m pip install --upgrade pip
python3 -m pip install .cli-weather 78613
cli-weather "Austin, TX"
cli-weather "Paris, France"
cli-weather "London, GB"The report includes:
- current conditions
- 7-day forecast
- rain probability and amount when available
- a source line at the bottom showing where the data came from
Config is stored at:
~/.config/cli-weather/config.jsonIn Docker, if you set CLI_WEATHER_CONFIG_DIR=/data and bind-mount ./cli-weather:/data, the config file is stored at:
./cli-weather/config.jsonSet a default location and provider:
cli-weather config set --location "Austin, TX"
cli-weather config set --provider metnoSet email configuration:
cli-weather config set --recipient you@example.com
cli-weather config set --sender you@example.com
cli-weather config set --smtp-host smtp.example.com --smtp-port 587
cli-weather config set --smtp-username you@example.com --smtp-password "app-password"
cli-weather config set --smtp-starttls trueMultiple recipients are supported by separating email addresses with commas:
cli-weather config set --recipient "you@example.com,friend@example.com"Show the saved config:
cli-weather config showSensitive fields such as SMTP passwords and API keys are redacted in config show.
Default:
cli-weather config set --provider metnoOther options:
cli-weather config set --provider open-meteo
cli-weather config set --provider visualcrossing --visualcrossing-api-key "your-api-key"Provider notes:
metnois the default and does not require an API keyopen-meteodoes not require an API keyvisualcrossingrequires an API key- when
metnois missing precipitation probability, the app automatically fills it from Open-Meteo
Send an email immediately:
cli-weather email send
cli-weather email send --location "Paris, France" --recipient friend@example.comYou can also send to multiple recipients:
cli-weather email send --recipient "you@example.com,friend@example.com"The email body intentionally matches the normal CLI text output.
Copy the sample environment file:
./scripts/init-docker-config.sh .Edit ./cli-weather/.env with your provider, location, SMTP settings, schedule, and timezone.
For the included Compose setup, ./cli-weather/.env is the preferred way to provide non-secret configuration. If you want stronger secret handling, replace plain password or API key values with *_FILE variables that point to mounted secret files.
Useful example values:
CLI_WEATHER_PROVIDER=metno
CLI_WEATHER_LOCATION=Austin, TX
CLI_WEATHER_RECIPIENT=you@example.com,friend@example.com
CLI_WEATHER_SENDER=you@example.com
CLI_WEATHER_SMTP_HOST=smtp.example.com
CLI_WEATHER_SMTP_PORT=587
CLI_WEATHER_SMTP_USERNAME=you@example.com
CLI_WEATHER_SMTP_PASSWORD=app-password
CLI_WEATHER_SMTP_STARTTLS=true
CLI_WEATHER_CRON_SCHEDULE=0 7 * * *
TZ=America/ChicagoIf you are using secret files, remove plain secret values such as CLI_WEATHER_SMTP_PASSWORD and CLI_WEATHER_VISUALCROSSING_API_KEY from ./cli-weather/.env.
Common .env choices:
- default provider
metnowith secret-file SMTP password: uncommentCLI_WEATHER_SMTP_PASSWORD_FILE open-meteowith secret-file SMTP password: uncommentCLI_WEATHER_SMTP_PASSWORD_FILEvisualcrossingwith secret files: uncomment bothCLI_WEATHER_SMTP_PASSWORD_FILEandCLI_WEATHER_VISUALCROSSING_API_KEY_FILE- plain env fallback: leave the
*_FILElines commented and setCLI_WEATHER_SMTP_PASSWORDand optionallyCLI_WEATHER_VISUALCROSSING_API_KEY
Safer secret-file example:
CLI_WEATHER_SMTP_PASSWORD_FILE=/run/secrets/cli_weather_smtp_password
CLI_WEATHER_VISUALCROSSING_API_KEY_FILE=/run/secrets/cli_weather_visualcrossing_api_keySupported Docker environment variables:
CLI_WEATHER_PROVIDERSupported values:metno,open-meteo,visualcrossingCLI_WEATHER_LOCATIONExamples:78613,Austin, TX,Paris, FranceCLI_WEATHER_VISUALCROSSING_API_KEYRequired only when provider isvisualcrossingCLI_WEATHER_RECIPIENTDestination email address for scheduled and immediate sends. Multiple addresses can be separated with commas.CLI_WEATHER_SENDERFrom address used in SMTP mailCLI_WEATHER_SMTP_HOSTSMTP server hostnameCLI_WEATHER_SMTP_PORTSMTP server portCLI_WEATHER_SMTP_USERNAMESMTP login username when requiredCLI_WEATHER_SMTP_PASSWORDSMTP login password when required. PreferCLI_WEATHER_SMTP_PASSWORD_FILEfor Docker deployments.CLI_WEATHER_SMTP_PASSWORD_FILEOptional path to a file containing the SMTP password. Prefer this over plain env vars when using Docker secrets.CLI_WEATHER_SMTP_STARTTLStrueorfalseCLI_WEATHER_SMTP_SSLtrueorfalseCLI_WEATHER_VISUALCROSSING_API_KEY_FILEOptional path to a file containing the Visual Crossing API key. Prefer this over plain env vars in Docker when possible.CLI_WEATHER_CRON_SCHEDULEStandard cron expression used by the scheduler container, for example0 7 * * *TZTimezone used by the scheduler container, for exampleAmerica/Chicago
Run an interactive weather check in Docker:
docker compose run --rm cli-weather cli-weather "Austin, TX"Send a test email in Docker:
docker compose run --rm cli-weather cli-weather email sendStart the scheduler:
docker compose up -dView scheduler logs:
docker compose logs -f cli-weather-schedulerStop the scheduler:
docker compose stop cli-weather-schedulerWhy Docker is recommended for scheduled jobs:
- keeps runtime and environment variables together
- avoids cron/path drift on the host
- makes scheduled behavior easier to move between machines
- fits naturally into existing multi-service Compose stacks
- gives the app a visible host folder such as
./cli-weatherfor config and logs - supports secret-file based configuration through
*_FILEvariables
If you prefer a lighter native setup:
cli-weather schedule add --time 07:00
cli-weather schedule list
cli-weather schedule remove --time 07:00This uses your user crontab and runs the installed cli-weather email send command automatically.
The Linux packages install:
- the Python source into
/opt/cli-weather/src - a wrapper command at
/usr/bin/cli-weather - documentation in
/usr/share/doc/cli-weather
The packages are intentionally simple and depend only on system python3.
- Config files are written with owner-only permissions when possible.
cli-weather config showredacts sensitive fields.- For containerized deployments, prefer
CLI_WEATHER_SMTP_PASSWORD_FILEandCLI_WEATHER_VISUALCROSSING_API_KEY_FILEover plain environment variables when you have Docker secrets or mounted secret files available. - For Docker deployments, use a bind-mounted app folder such as
./cli-weathersoconfig.jsonandscheduler.logare easy to find on the host. - Set host secret files such as
./cli-weather/secrets/cli_weather_smtp_password.txtto0600.
The published container image is:
ghcr.io/c1aytonnet/cli-weather:latestGitHub Actions publishes:
latestfrom the default branchv*tag images from git release tags
- If
cli-weatheris not found after a pip install, activate the virtual environment again withsource .venv/bin/activate. - If city/state lookups fail, use
City, STfor U.S. searches andCity, CountryorCity, CountryCodefor international searches. - If Visual Crossing is selected without a key, switch to
metnooropen-meteo, or configure--visualcrossing-api-key. - If Docker scheduling is not sending mail, confirm the values in
./cli-weather/.env, especially SMTP settings,CLI_WEATHER_LOCATION,CLI_WEATHER_CRON_SCHEDULE, andTZ.
MIT. See LICENSE.