Print a weather forecast to a thermal receipt printer.
A small TypeScript / Node.js CLI that fetches a forecast from Open-Meteo and prints it to an Epson TM-T88V or TM-T88VII thermal printer (80 mm paper), optimized for the 40-character column width.
- Current conditions plus today's daily summary and an 8-slot hourly forecast (every 3 hours, 00:00-21:00), tomorrow-only view with its own hourly slots, or a multi-day rollup (1-7 days)
- Metric or imperial units
- Configurable default location via
~/.weather-receipts.config.json, override per run with--location - Connects to a printer over USB (libusb), raw TCP (network printers, port 9100 by default), or CUPS
- No API key required — Open-Meteo is free for non-commercial use
- Zero runtime dependencies beyond
commanderandusb
========================================
WEATHER FORECAST
Zurich, CH
1 Jun 2026 17:00 GMT+2
========================================
NOW
----------------------------------------
24°C
Partly cloudy
Feels like 23°C
Humidity 36%
Wind 8 km/h WNW
----------------------------------------
TODAY Mon, Jun 1
----------------------------------------
Light showers
High 24°C
Low 17°C
Precip 0.2 mm
Wind max 9 km/h
Sunrise 05:33
Sunset 21:14
----------------------------------------
HOURLY
----------------------------------------
00:00 18° Light rain 85%
03:00 17° Light showers 88%
06:00 17° Overcast 65%
09:00 17° Overcast 63%
12:00 20° Overcast 0%
15:00 23° Mainly clear 0%
18:00 24° Mainly clear 0%
21:00 22° Overcast 0%
Powered by Open-Meteo
- Node.js 22 or newer (uses native
fetch) - A supported thermal printer
- Epson TM-T88V (USB VID/PID
04b8:0202) - Epson TM-T88VII (USB VID/PID
04b8:0e28) - Or any ESC/POS-compatible printer reachable over TCP or CUPS
- Epson TM-T88V (USB VID/PID
- For USB on macOS / Linux:
libusb(bundled via theusbnpm package's native bindings; you may neednode-gypbuild tools for first install)
git clone https://github.com/TechPreacher/weather-receipts.git
cd weather-receipts
npm install
npm run buildTo run the CLI directly:
node bin/weather-receipts.js printTo install globally so weather-receipts is on your PATH:
npm link
weather-receipts print# Set a default location
weather-receipts config --set location="Zurich, CH"
# Print today's forecast
weather-receipts print
# Print tomorrow's forecast only
weather-receipts print --tomorrow
# Print the next 7 days
weather-receipts print --days 7
# One-off override
weather-receipts print --location "Tokyo, JP" --units imperialweather-receipts [command] [options]
Fetches and prints a weather forecast.
| Option | Description | Default |
|---|---|---|
-d, --days <n> |
Number of days to forecast (1-7); mutually exclusive with --tomorrow |
1 |
-t, --tomorrow |
Print tomorrow's forecast only (daily summary + 8 hourly slots) | off |
-l, --location <text> |
Location query (e.g. "Zurich, CH", "Tokyo") |
from config |
-u, --units <units> |
metric or imperial |
metric |
-p, --printer <iface> |
usb, usb:VID:PID, tcp://host:port, or a CUPS printer name |
usb |
--printermodel <m> |
t88v or t88vii (selects USB Product ID when --printer usb) |
t88v |
--dry-run |
Print a decoded preview to the terminal (or raw ESC/POS bytes when piped to a file) | off |
Manages persistent configuration stored at ~/.weather-receipts.config.json.
| Option | Description |
|---|---|
--show |
Print current configuration (default if no flags given) |
--set <key=value> |
Set one configuration key |
--reset |
Reset configuration to defaults |
Allowed keys: location, units, printer, printermodel, timezone.
Examples:
weather-receipts config --show
weather-receipts config --set location="Zurich, CH"
weather-receipts config --set units=imperial
weather-receipts config --set printer="tcp://192.168.1.100:9100"
weather-receipts config --set printermodel=t88vii
weather-receipts config --resetLocations are resolved through the
Open-Meteo geocoding API.
You can pass either a bare city name or "City, CC" / "City, Country":
weather-receipts print --location "Zurich"
weather-receipts print --location "Zurich, CH"
weather-receipts print --location "Zurich, Switzerland"
weather-receipts print --location "Springfield, US"When a country qualifier is supplied, the resolver picks the first geocoding result that matches the ISO 3166-1 alpha-2 code or full name, falling back to the top hit if no match is found.
Plug an Epson TM-T88V or TM-T88VII into a USB port:
weather-receipts print --printer usb --printermodel t88vIf you have a different ESC/POS printer over USB, find its VID/PID with
lsusb (Linux) or system_profiler SPUSBDataType (macOS), then:
weather-receipts print --printer usb:04b8:0202macOS: the OS may claim the printer. The tool detaches the kernel
driver automatically when needed. If you hit permission errors, run with
sudo or grant your user access to the USB device.
Linux: create a udev rule so non-root users can talk to the printer. Example for an Epson VID:
SUBSYSTEM=="usb", ATTR{idVendor}=="04b8", MODE="0666"
Save to /etc/udev/rules.d/99-thermal-printer.rules and reload udev.
weather-receipts print --printer tcp://192.168.1.100:9100If the printer is configured in CUPS (any name supported by lpstat):
weather-receipts print --printer "Epson_TM_T88V"The tool spools the raw ESC/POS bytes via lp -o raw.
# TypeScript watch build
npm run dev
# Run tests
npm test
# Watch tests
npm run test:watch
# Inspect the receipt buffer without a printer
node bin/weather-receipts.js print --location "Zurich, CH" --dry-run \
> /tmp/receipt.binsrc/
├── cli.ts # commander entry
├── commands/
│ ├── print.ts # main: fetch + render + print
│ └── config.ts # config get/set/reset
├── core/
│ ├── thermal-printer.ts # EscPosBuilder + USB/TCP/CUPS senders
│ ├── weather-fetcher.ts # Open-Meteo forecast client
│ ├── geocoder.ts # Open-Meteo geocoding client
│ ├── receipt-builder.ts # composes the ESC/POS receipt
│ └── config-manager.ts # ~/.weather-receipts.config.json I/O
├── types/
│ ├── config.ts
│ └── weather.ts
└── utils/
├── formatting.ts # temp, wind, precip, time helpers
└── weather-codes.ts # WMO code → description
Vitest covers the pure helpers, both API clients
(with mocked fetch), and the receipt-builder (decoded text + 40-column
width invariant + final cut command).
npm test- Open-Meteo for the free weather and geocoding APIs
- Inspired by
claude-receiptsby Chris Hutchinson, whose ESC/POS builder and USB/CUPS handling served as the starting point for the thermal-printer code
MIT

