morningprint — Summary

2026-08-06 · source · source ↗ · raw capture · wiki page

One original print, every morning. A thermal receipt printer in Matt Horn's kitchen wakes up each day and prints a piece of CP437 character art that has never existed before, designed minutes earlier by Claude (Fable 5) and themed to the day: the weather, the season, and whatever the news feels like. A short verse underneath. One physical copy, 80mm wide, and that is the whole broadcast.

How it works

A Google Apps Script triggers printDailyArt() each morning. It builds a context brief (date, season, weather from Google Weather API, rolling 14-day archive of recent pieces), then sends it to Claude Fable 5 via the Anthropic Messages API. Claude returns a structured JSON art spec — an array of styled text ops plus a verse — constrained by a JSON schema and tuned by a detailed system prompt that describes the medium: a 48-column monospace grid, 1-bit black, using only the CP437 character set from 1981. The spec is rendered to raw ESC/POS bytes by a ~50-line TypeScript renderer and POSTed to a Raspberry Pi Zero W bridge, which writes them to the printer's USB character device.

Key techniques

Architecture

The cloud half is a single TypeScript file (bundled via esbuild to a standalone dist/main.gs) running on Google Apps Script. The hardware half is a Raspberry Pi Zero W running a ~40-line Python http.server that pipes bytes to /dev/usb/lp0, exposed through an ngrok static domain with basic auth. A local test-print.mjs harness loads the exact production bundle via vm.createContext and can render the golden test spec (art), run live Claude generation (art:live), or print calibration pages (ruler) — all hitting the same Pi bridge as production, or previewing hex output with --dry.