Skip to main content

CLI and library for mini Bluetooth thermal printers

Project description

Thermal Printer CLI (thermy.py)

thermy.py is a command-line interface for ultra-cheap mini thermal printers, commonly found on platforms like AliExpress. These compact printers — often shaped like cute animals such as cats — are inexpensive, highly portable, and surprisingly useful for everyday tasks such as printing receipts, notes, labels, QR codes, and more.

This tool brings full printing capability to the Linux terminal, allowing you to send both text and image files to supported Bluetooth-enabled thermal printers without needing a graphical interface or browser. Whether you’re working with a headless device like an Orange Pi or simply prefer the CLI, this script makes thermal printing accessible and powerful.

It is built upon the core protocol and communication logic of the kitty-printer web project and reuses its reliable Python-based Bluetooth communication module. Ideal for makers, POS experiments, DIY logging stations, or lightweight print automation projects.

Printout Result

Features

  • Text Printing: Print text with configurable font size
  • Image Printing: Print PNG, JPG, and other image formats
  • QR Code Printing: Generate and print QR codes from text or URLs
  • File Support: Print from text files
  • Bluetooth Discovery: Scan for compatible thermal printers
  • Compatible Protocol: Uses the same protocol as kitty-printer web project
  • Proven Bluetooth: Reuses reliable Bluetooth communication from thermal_printer.py

Supported Printer Models

The same models supported by the original projects:

  • XW Series: XW001, XW002, XW003, XW004, XW005, XW006, XW007, XW008, XW009
  • JX Series: JX001, JX002, JX003, JX004, JX005, JX006
  • Other Models: M01, PR02, PR07, GB01, GB02, GB03, GB04, LY01, LY02, LY03, LY10, AI01, GT01, MX10

Requirements

  • Linux System: Debian 12 (Orange Pi) or compatible
  • Python: 3.11 or higher
  • Bluetooth: Built-in or USB Bluetooth adapter
  • Thermal Printer: One of the supported models

Quick Install (pip)

pip install thermy           # Core library + CLI
pip install 'thermy[qr]'     # + QR code support
pip install 'thermy[mcp]'    # + MCP server for AI agents
pip install 'thermy[all]'    # Everything

After installing, the thermy command is available:

thermy --scan
thermy --text "Hello" --device AA:BB:CC:DD:EE:FF
thermy --qr "https://example.com" --device AA:BB:CC:DD:EE:FF

AI Agent Integration (MCP Server)

Thermy includes an MCP server so AI agents can print directly. Replace AA:BB:CC:DD:EE:FF with your printer's Bluetooth address (find it with thermy --scan).

Claude Code

claude mcp add thermy -e THERMY_DEVICE=AA:BB:CC:DD:EE:FF -- python3 -m thermy_mcp

Then ask Claude: "print a QR code for https://example.com"

Claude Desktop / Cowork

Option A: One-click install Download thermy.mcpb from Releases and double-click to install.

Option B: Manual config Edit your Claude Desktop config (Settings > Developer > Edit Config):

{
  "mcpServers": {
    "thermy": {
      "command": "python3",
      "args": ["-m", "thermy_mcp"],
      "env": {
        "THERMY_DEVICE": "AA:BB:CC:DD:EE:FF"
      }
    }
  }
}

MetaMCP / uvx

Add a STDIO server in MetaMCP with:

  • Command: uvx
  • Args (4 separate entries): --from thermy[all] thermy-mcp
  • Env: THERMY_DEVICE = AA:BB:CC:DD:EE:FF

JSON config for import:

{
  "mcpServers": {
    "thermy": {
      "command": "uvx",
      "args": ["--from", "thermy[all]", "thermy-mcp"],
      "env": {
        "THERMY_DEVICE": "AA:BB:CC:DD:EE:FF"
      }
    }
  }
}

Note: Use thermy[all] (not thermy[mcp]) to include QR code support. If the cached environment is stale, add --refresh as the first arg.

Available MCP Tools

Tool Description
scan Discover nearby Bluetooth thermal printers
connect Connect to a printer (uses THERMY_DEVICE env var if set)
disconnect Disconnect from the printer
print_text Print text with font size, alignment, borders, invert
print_image Print an image file (PNG, JPG, etc.)
print_qr Generate and print a QR code from text/URL

Manual Installation (from source)

1. System Dependencies

Install required system packages on Debian 12:

sudo apt update
sudo apt install python3 python3-pip python3-venv bluetooth bluez

2. Bluetooth Setup

Add your user to the Bluetooth group:

sudo usermod -a -G bluetooth $USER
# Log out and log back in, or use: newgrp bluetooth

Enable and start Bluetooth service:

# Start Bluetooth service
sudo systemctl start bluetooth

# Enable Bluetooth to start automatically
sudo systemctl enable bluetooth

# Check Bluetooth status
sudo systemctl status bluetooth

3. Python Environment

Create and activate a virtual environment:

python3 -m venv tp_env
source tp_env/bin/activate

4. Python Dependencies

Install Python packages:

pip install -r requirements.txt

5. Make Script Executable

chmod +x thermy.py

6. Verify Installation

Check if everything is working:

python3 thermy.py --check-requirements

Usage

System Check

Always run this first if you encounter issues:

python3 thermy.py --check-requirements

Scan for Printers

Find available thermal printers:

python3 thermy.py --scan

This will show compatible printers with their Bluetooth addresses:

Found compatible printer: GB01: AA:BB:CC:DD:EE:FF
Found compatible printer: MX10: 28:03:08:58:C5:65

Print Text

Print text directly:

python3 thermy.py --text "Hello, World!" --device AA:BB:CC:DD:EE:FF

Print text with custom font size:

python3 thermy.py --text "Large Text" --font-size 24 --device AA:BB:CC:DD:EE:FF

Print text with different alignments:

# Left-aligned text
python3 thermy.py --text "Left\nAligned\nText" --align left --device AA:BB:CC:DD:EE:FF

# Center-aligned text (default)
python3 thermy.py --text "Center\nAligned\nText" --align center --device AA:BB:CC:DD:EE:FF

# Right-aligned text
python3 thermy.py --text "Right\nAligned\nText" --align right --device AA:BB:CC:DD:EE:FF

Print text with inverted colors (white text on black background):

# Normal text: black text on white background
python3 thermy.py --text "Normal Text" --device AA:BB:CC:DD:EE:FF

# Inverted text: white text on black background
python3 thermy.py --text "HIGHLIGHTED\nTEXT" --invert --device AA:BB:CC:DD:EE:FF

# Large inverted label
python3 thermy.py --text "WARNING" --invert --font-size 32 --align center --device AA:BB:CC:DD:EE:FF

Print text with borders/frames:

# Thin border (1px)
python3 thermy.py --text "Thin\nBorder" --border 1 --device AA:BB:CC:DD:EE:FF

# Medium border (3px)
python3 thermy.py --text "Medium\nBorder" --border 3 --device AA:BB:CC:DD:EE:FF

# Thick border (5px)
python3 thermy.py --text "Thick\nBorder" --border 5 --device AA:BB:CC:DD:EE:FF

# Extra thick border (10px)
python3 thermy.py --text "VERY\nTHICK" --border 10 --device AA:BB:CC:DD:EE:FF

# Inverted text with border
python3 thermy.py --text "DANGER" --invert --border 5 --font-size 24 --device AA:BB:CC:DD:EE:FF

Print Text File

Print contents of a text file:

python3 thermy.py --file document.txt --device AA:BB:CC:DD:EE:FF

Print QR Code

Generate and print a QR code from text or a URL:

# Print a QR code for a URL
python3 thermy.py --qr "https://example.com" --device AA:BB:CC:DD:EE:FF

# Print a QR code for plain text
python3 thermy.py --qr "Hello, scan me!" --device AA:BB:CC:DD:EE:FF

Print Image

Print an image file (PNG, JPG, etc.):

python3 thermy.py --image photo.jpg --device AA:BB:CC:DD:EE:FF

Advanced Options

Print with custom speed and energy settings:

python3 thermy.py --text "High Quality" --speed 20 --energy 10000 --device AA:BB:CC:DD:EE:FF
  • --speed: Print speed (10-90, lower = better quality, default: 35)
  • --energy: Energy level (default: 8000)
  • --font-size: Font size for text (default: 16)
  • --align: Text alignment - left, center, or right (default: center)
  • --invert: Invert colors - white text on black background
  • --border: Add border frame around text - 1-10 pixels thick

Command Reference

python3 thermy.py [OPTIONS]

Options:
  --scan, -s                    Scan for available printers
  --text TEXT, -t TEXT          Text to print
  --file FILE, -f FILE          Text file to print
  --image IMAGE, -i IMAGE       Image file to print
  --qr TEXT                     Generate and print a QR code from text/URL
  --device ADDRESS, -d ADDRESS  Bluetooth device address
  --font-size SIZE             Font size for text (default: 16)
  --align {left,center,right}  Text alignment (default: center)
  --invert                     Invert colors: white text on black background
  --border {1-10}              Add border frame (1-10 pixels thick)
  --speed SPEED                Print speed 10-90 (default: 35)
  --energy ENERGY              Energy level (default: 8000)
  --check-requirements         Check system requirements
  --help, -h                   Show help message

Examples

Basic Usage

# Find your printer
python3 thermy.py --scan

# Print simple text
python3 thermy.py --text "Receipt #12345" --device AA:BB:CC:DD:EE:FF

# Print a file
python3 thermy.py --file receipt.txt --device AA:BB:CC:DD:EE:FF

# Print an image
python3 thermy.py --image logo.png --device AA:BB:CC:DD:EE:FF

# Print a QR code
python3 thermy.py --qr "https://example.com" --device AA:BB:CC:DD:EE:FF

Advanced Usage

# Large bold text
python3 thermy.py --text "IMPORTANT NOTICE" --font-size 32 --device AA:BB:CC:DD:EE:FF

# Left-aligned multiline text
python3 thermy.py --text "HELLO\nWORLD\n!" --font-size 72 --align left --device AA:BB:CC:DD:EE:FF

# Right-aligned receipt header
python3 thermy.py --text "Receipt #12345\nDate: 2024-01-01" --align right --device AA:BB:CC:DD:EE:FF

# Inverted text for highlights and labels
python3 thermy.py --text "WARNING\nHOT SURFACE" --invert --font-size 32 --align center --device AA:BB:CC:DD:EE:FF

# Bordered warning label
python3 thermy.py --text "DANGER\nHIGH VOLTAGE" --border 5 --invert --font-size 24 --device AA:BB:CC:DD:EE:FF

# Simple framed receipt header
python3 thermy.py --text "RECEIPT" --border 3 --align center --font-size 20 --device AA:BB:CC:DD:EE:FF

# QR code for WiFi sharing
python3 thermy.py --qr "WIFI:T:WPA;S:MyNetwork;P:MyPassword;;" --device AA:BB:CC:DD:EE:FF

# High quality image (slower)
python3 thermy.py --image photo.jpg --speed 20 --energy 10000 --device AA:BB:CC:DD:EE:FF

# Receipt with mixed styles (bordered header, normal items)
python3 thermy.py --text "STORE NAME" --font-size 24 --align center --border 3 --device AA:BB:CC:DD:EE:FF
python3 thermy.py --text "Item 1: $10\nItem 2: $15\nTotal: $25" --align left --device AA:BB:CC:DD:EE:FF

Testing on Orange Pi

Since development and testing will be performed only on the Orange Pi (the only device with Bluetooth), here's how to test the functionality:

1. System Test

# Check all requirements
python3 thermy.py --check-requirements

# Test Bluetooth scanning
python3 thermy.py --scan

2. Printer Connection Test

# Test connection (replace with your printer's address)
python3 thermy.py --text "Connection Test" --device AA:BB:CC:DD:EE:FF

3. Feature Tests

# Test text printing
python3 thermy.py --text "Text Test - Hello World!" --device AA:BB:CC:DD:EE:FF

# Test file printing
echo "File test content" > test.txt
python3 thermy.py --file test.txt --device AA:BB:CC:DD:EE:FF

# Test QR code printing
python3 thermy.py --qr "https://example.com" --device AA:BB:CC:DD:EE:FF

# Test image printing (create a small test image first)
python3 thermy.py --image test_image.png --device AA:BB:CC:DD:EE:FF

# Test different font sizes
python3 thermy.py --text "Small" --font-size 12 --device AA:BB:CC:DD:EE:FF
python3 thermy.py --text "Large" --font-size 24 --device AA:BB:CC:DD:EE:FF

# Test print quality settings
python3 thermy.py --text "High Quality" --speed 20 --energy 10000 --device AA:BB:CC:DD:EE:FF

4. Error Handling Tests

# Test with invalid device address
python3 thermy.py --text "Test" --device 00:00:00:00:00:00

# Test with non-existent file
python3 thermy.py --file nonexistent.txt --device AA:BB:CC:DD:EE:FF

# Test with invalid image
python3 thermy.py --image nonexistent.jpg --device AA:BB:CC:DD:EE:FF

Troubleshooting

Bluetooth Issues

"Bluetooth support not available" Error:

pip install bleak

Useful Bluetooth utilities

bluetoothctl list    # List local bluetooth interfaces
bluetoothctl         # Enter the bluetooth client - or use inline commands
power on             # Turn bluetooth interface on - or inline "bluetoothctl power on"
scan on              # Scan devices around - or inline "bluetoothctl scan on"
scan off             # Turn off the scan after get the device add ("bluetoothctl scan off")
info <mac add>       # Show specific device information "bluetoothctl info <mac add>"
pair <mac add>       # Pair with the device
trust <mac add>      # Trust the device
connect <mac add>    # Connect to the device
exit                 # Exit cli

# Example in a bash script:
  #!/usr/bin/bash
  bluetoothctl power on
  bluetoothctl trust <mac add>
  bluetoothctl disconnect <mac add>
  bluetoothctl connect <mac add> 

"No compatible thermal printers found" during scan:

  • Make sure your printer is powered on
  • Put the printer in pairing/discoverable mode
  • Move closer to the printer
  • Check if the printer model is supported

Connection failures:

  • Verify the device address is correct
  • Try restarting the Bluetooth service: sudo systemctl restart bluetooth
  • Make sure you're in the bluetooth group: groups $USER

Permission Issues

"Permission denied" errors:

sudo usermod -a -G bluetooth $USER
newgrp bluetooth  # Or log out and log back in

Print Quality Issues

Faded or unclear prints:

  • Increase energy level: --energy 10000
  • Decrease speed: --speed 20
  • Check if printer paper is fresh

Image not printing correctly:

  • Make sure image file exists and is readable
  • Try converting image to PNG first
  • Check image resolution (too high resolution may cause issues)

Technical Details

Protocol Compatibility

This CLI script uses the CRC8 Calculation based on cat-protocol.ts:

Bluetooth Implementation

The Bluetooth communication reuses the proven implementation from several projects for bluetooth thermal printers:

  • Service Discovery: Automatic discovery of compatible printers
  • Characteristic Detection: Automatic detection of write characteristics
  • Error Handling: Comprehensive error handling for connection issues
  • UUID Support: Multiple UUID variants for different printer models

Image Processing

  • Automatic Resizing: Images are automatically resized to fit paper width
  • Aspect Ratio: Maintained during resizing
  • Centering: Smaller images are centered on the paper
  • Format Support: PNG, JPG, and other PIL-supported formats

Library Versions

The script is designed for compatibility with:

  • Python: 3.11+ (as available on Debian 12)
  • bleak: 0.21.1+ (Bluetooth Low Energy)
  • Pillow: 10.0.0+ (Image processing)
  • qrcode: 7.4+ (QR code generation)

These versions are tested to work reliably on Debian 12 (Orange Pi) systems.

Python License

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

thermy-0.4.4.tar.gz (27.0 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

thermy-0.4.4-py3-none-any.whl (23.4 kB view details)

Uploaded Python 3

File details

Details for the file thermy-0.4.4.tar.gz.

File metadata

  • Download URL: thermy-0.4.4.tar.gz
  • Upload date:
  • Size: 27.0 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for thermy-0.4.4.tar.gz
Algorithm Hash digest
SHA256 3a01eb2f8e68e79f9652acd6193afcb93ef70f1a470aefbeae5ba9bbb1bd9878
MD5 a87347e5ff0f9f2e163a59e79ea64728
BLAKE2b-256 7230c3b8d811c5bd172fc8a612bb76712eb7e774b489c3e1bd139f6f55513f7e

See more details on using hashes here.

Provenance

The following attestation bundles were made for thermy-0.4.4.tar.gz:

Publisher: publish.yml on tentje/thermy

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file thermy-0.4.4-py3-none-any.whl.

File metadata

  • Download URL: thermy-0.4.4-py3-none-any.whl
  • Upload date:
  • Size: 23.4 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for thermy-0.4.4-py3-none-any.whl
Algorithm Hash digest
SHA256 ef660b3dea43d056f222932249f90071b502712248880265aed3b695193e4aae
MD5 62a3ff38eb1a316e371c1dc85c477c12
BLAKE2b-256 8d02dc12d51dfe03a69d57653d5721e2cc4bdd7f5ddbb0c5c3af152331855f92

See more details on using hashes here.

Provenance

The following attestation bundles were made for thermy-0.4.4-py3-none-any.whl:

Publisher: publish.yml on tentje/thermy

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page