Voice-to-print for AxiDraw pen plotters and thermal printers. Dictate a message, type something, or point it at RSS feeds — PrintPulse renders text in single-stroke Hershey fonts and sends it to a pen plotter or thermal receipt printer. Retro 80's terminal aesthetic throughout.
Three builds:
| Build | What it does | |
|---|---|---|
| 🖊️ | AxiDraw desktop | Type or speak → pen-plotted output on paper |
| 🧾 | Thermal printer desktop | RSS feeds → headlines printed on receipt paper |
| 📰 | Pi Zero news appliance | Always-on headless ticker, configure from your phone |
Hey folks — this is my first real use of Claude Code, so I hope you find it useful. I had some old hardware sitting around: an AxiDraw plotter and a thermal printer. Strange what you accumulate. I always wanted to use them in a coding project but never had the skills to interface with them directly. When Claude came along I knew that was the missing piece. Now these old printers actually get used — the thermal one is my analog news reader (just top stories), and the AxiDraw prints handwritten cards since my penmanship is illegible. I'm sure you'll find even better uses for this.
Day-to-day the Pi is controlled entirely from your browser — no SSH required. Open http://PI_IP:5000 from any device on your network.
Configuration — RSS feeds, poll interval, quiet hours, auto-update:
Service control — start, stop, update, test print:
Print history — every headline with source and timestamp:
- AxiDraw V3 or any AxiDraw model (~$475)
- Pens — Pilot G2, Uni-ball, Staedtler, anything that fits the pen holder
- Paper — copy paper is fine
- A computer with Python 3.9+
- Travelmate 58mm USB thermal printer (~$35) — or any ESC/POS compatible 58mm printer
- 58mm paper rolls (usually included; cheap to replace)
- A computer with Python 3.9+
Everything in the thermal printer list, plus:
- Raspberry Pi Zero 2 W (~$15) — buy here
- Micro SD card, 16GB+
- Micro USB OTG adapter (~$5) — converts the Pi's USB port so you can plug in the printer
- 5V micro USB power supply (an old phone charger works)
git clone https://github.com/jampick/PrintPulse.git
cd PrintPulse
pip install -e .The AxiDraw library isn't on PyPI — Evil Mad Scientist distributes it separately:
- Download: AxiDraw API zip
- Extract and run
pip install .from inside the extracted folder
Plug in the AxiDraw, load paper and a pen, then:
# Type and plot
printpulse -i text -t "Hello from the plotter!"
# Record from mic (press Enter to stop)
printpulse -i mic
# Different font
printpulse -i text -t "In the year 2525" -f gothic
# Render to SVG without touching the hardware
printpulse -i text -t "Test layout" --dry-rungit clone https://github.com/jampick/PrintPulse.git
cd PrintPulse
pip install -e .On Windows, also run pip install pywin32. On Linux the printer shows up at /dev/usb/lp0 with no extra drivers needed.
printpulse -i text -t "Extra! Extra!" --printer thermal
# Watch a feed and print new headlines as they appear
printpulse --watch "https://feeds.npr.org/1002/rss.xml" --printer thermal
# Multiple feeds
printpulse --watch "https://feeds.npr.org/1002/rss.xml" \
--watch "http://feeds.bbci.co.uk/news/world/rss.xml" \
--printer thermal --max-prints 3The goal is a box that sits on a shelf, stays on, and prints news. No screen, no keyboard after initial setup — everything runs over Wi-Fi.
Download Raspberry Pi Imager, insert your SD card, and:
- Choose Raspberry Pi OS Lite (32-bit) under "Raspberry Pi OS (other)"
- Click the gear icon ⚙ before writing — this is where you pre-configure SSH, Wi-Fi credentials, and your timezone so you don't need a monitor at all
Write it out (~5 min), put the card in the Pi, and plug in power. First boot takes a couple of minutes.
Check your router's device list for raspberrypi, or from your computer:
ping raspberrypi.local
If that doesn't work, the Fing app (free, phone) will find it in a few seconds.
ssh pi@YOUR_PI_IPType yes on the fingerprint prompt, enter your password. You'll land at pi@raspberrypi:~ $.
git clone https://github.com/jampick/PrintPulse.git
bash PrintPulse/pi/setup.shTakes 5–10 minutes on a Pi Zero. When it finishes, reboot once:
sudo rebootThe Pi Zero has two micro-USB ports — one is power-only, the other is data. Use the data port (closer to center). Plug in your OTG adapter there, then connect the printer to that. Power on the printer and check the Pi sees it:
ls /dev/usb/lp0Open http://YOUR_PI_IP:5000, paste in your RSS feed URLs, and hit [ SAVE & RESTART ]. Headlines start printing as new stories appear.
Some feeds to start with:
https://feeds.npr.org/1002/rss.xml
http://feeds.bbci.co.uk/news/world/rss.xml
https://rsshub.app/apnews/topics/apf-topnews
https://rss.nytimes.com/services/xml/rss/nyt/HomePage.xml
After that, you don't need SSH again. Settings live at http://YOUR_PI_IP:5000, the Update button pulls the latest code from GitHub, and everything restarts automatically on power loss.
# Is the watcher running?
sudo systemctl status printpulse
# Live logs
sudo journalctl -u printpulse -f
# Printer not found?
lsusb
ls -la /dev/usb/
# Restart
sudo systemctl restart printpulse printpulse-webPolls feeds on a configurable interval and prints new stories. Remembers what it's already printed so you don't get duplicates across restarts.
# Single feed
printpulse --watch "http://feeds.bbci.co.uk/news/world/rss.xml"
# Multiple feeds, thermal printer, check every 10 minutes
printpulse --watch "https://feeds.npr.org/1002/rss.xml" \
--watch "http://feeds.bbci.co.uk/news/world/rss.xml" \
--printer thermal --watch-interval 600
# Quiet hours — nothing prints overnight, queued items print in the morning
printpulse --watch "https://feeds.npr.org/1002/rss.xml" \
--printer thermal \
--quiet-start 23:00 --quiet-end 07:00
# Both printers at once
printpulse --watch "..." --printer bothItems found during quiet hours are saved to disk, not just skipped — so nothing gets lost even if the story has rotated out of the feed by morning.
Uses OpenAI Whisper running locally — no API key or internet connection required for transcription.
printpulse -i mic # press Enter to stop
printpulse -i mic -d 15 # record for 15 seconds
printpulse -i file -a recording.wavWhisper downloads the model on first use. The base model (~150MB) is fine for most uses. If accuracy matters more than speed, try small or medium:
printpulse -i mic -m smallModels in order: tiny → base (default) → small → medium → large
PrintPulse uses Hershey fonts — single-stroke vector fonts designed for plotters and CNC machines, where each letter is drawn as a continuous path rather than filled outlines. They're what makes the output look hand-drawn.
printpulse -i text -t "Hello" -f cursive
printpulse -i text -t "Hello" -f gothic
printpulse -i text -t "Hello" -f romanAvailable: block (default), cursive, script-bold, roman, typewriter, times, gothic, italic, and several others including Greek, Cyrillic, Japanese, and symbol sets.
Letter mode formats text with a decorative letterhead — useful for actually printing correspondence on the plotter:
printpulse -i text -t letter.txt --letter
printpulse --letter-template # interactive compose
printpulse -i text -t letter.txt --letter --stationery victorianJournal mode adds a timestamp and tracks page position across multiple entries:
printpulse -i mic --journal
printpulse -i text -t "Finished the prototype today." --journal--dry-run # render SVG and preview without printing
--printer thermal # thermal instead of AxiDraw
--printer both # both at once
-y # skip confirmation prompts
-o output.svg # save the SVG
--portrait # portrait orientation (default is landscape)
--theme amber # amber instead of green terminal themeprintpulse [-h] [-i {mic,file,text}] [-a AUDIO_FILE] [-t TEXT]
[-d DURATION] [-f FONT] [--font-size POINTS]
[--page {letter,a4,a3}] [--portrait] [-o OUTPUT]
[--preview | --no-preview] [--dry-run] [-y]
[-m {tiny,base,small,medium,large}]
[--theme {green,amber}]
[--journal] [--journal-reset]
[--watch URL [URL ...]] [--watch-interval SECONDS]
[--max-prints N] [--quiet-start HH:MM] [--quiet-end HH:MM]
[--printer {axidraw,thermal,both}]
[--letter] [--letter-template]
[--stationery PROFILE] [--list-stationery]
State files in your home directory:
~/.printpulse_seen.json # which RSS items have been printed
~/.printpulse_history.json # print history
~/.printpulse_retry.json # retry queue for failed prints
~/.printpulse_quiet_queue.json # items held during quiet hours
~/.printpulse/config.json # settings and defaults
~/.printpulse/stationery/ # custom letterhead profiles (JSON)
Custom stationery example:
{
"name": "myheader",
"header": {
"prefix": "FROM THE DESK OF",
"name": "Your Name",
"title": "Your Title",
"font": "scripts",
"font_size": 20.0,
"frame_style": "ornamental"
},
"body_font": "futural",
"body_font_size": 12.0
}printpulse/
app.py CLI + argparse
config.py Config dataclass, font map, page presets
ui.py Retro terminal UI (Rich)
speech.py Mic recording + Whisper transcription
text_to_svg.py Hershey font rendering + SVG generation
plotter.py AxiDraw control
thermal.py ESC/POS thermal output
watch.py RSS polling, quiet hours, retry queue
letter.py Letter document model
journal.py Timestamped journal entries
illustrations.py DALL-E + vtracer illustration pipeline
pi/
webapp/ Flask web UI
setup.sh One-command Pi setup
appliance.py Pi-specific config
- Python 3.9+
- Windows, macOS, or Linux
- AxiDraw plotter (optional —
--dry-runworks without hardware) - ESC/POS thermal printer (optional)
- Microphone (optional)
GNU General Public License v3.0 — see LICENSE.


