phomemo
by s04
README.md
# phomemo
Print on a **Phomemo M02 Pro** pocket thermal printer from your computer, without the
phone app. Includes a command-line tool and an **MCP server**, so Claude and other
AI agents can print cards, checklists and pictures for you.
- Markdown in, neat cards out: titles, bullets, checkboxes, numbered lists.
- Pictures are scaled to the paper and dithered for thermal printing.
- Print jobs you can list, cancel (cleanly, between blocks) and reprint.
- Waits for the printer to confirm that each card actually printed.
- Reads battery, paper, lid and temperature.
- Runs locally over Bluetooth LE on macOS and Linux (and in principle Windows,
via [bleak](https://github.com/hbldh/bleak)).
## Supported printers
| Model | Status |
|---|---|
| **M02 Pro** | Tested: printing, cancel, print-complete signal, status |
| M02S | Same protocol and resolution as the M02 Pro; untested |
| M02, T02 | Same protocol at 203 dpi; untested |
Other Phomemo families (M110, M04, D30, …) use different protocols and aren't
supported yet. See [Contributing](#contributing).
**Paper:** 53mm-wide continuous rolls (e.g. 53mm × 6.5m). The print head
covers the middle 48mm (576 dots at 300 dpi).
> The M02 Pro's USB-C port only charges. It carries no data, so Bluetooth is
> the only way to print.
## Install
```sh
uv tool install git+https://github.com/s04/phomemo
# or: pipx install git+https://github.com/s04/phomemo
```
Requires Python 3.11+.
## Use
Turn the printer on and close the Phomemo phone app, because the printer accepts
only one connection at a time.
```sh
phomemo scan # find printers nearby
phomemo "# Groceries" "- [ ] oat milk" "- [ ] bread"
echo "# Idea" | phomemo # from stdin
phomemo -f notes.md # from a file
phomemo --preview -f notes.md # save a PNG instead of printing
phomemo image photo.jpg # print a picture
phomemo status # battery, paper, lid, temperature
```
### Card format
```markdown
# Title ← every "# " starts a new card
## Heading
A paragraph of text.
- bullet
1. numbered
- [ ] todo
- [x] done
> aside
--- ← also starts a new card
```
The printable width is 48mm (about 25 characters per line), so short cards
work best.
### Jobs
```sh
phomemo jobs # recent jobs, status and progress
phomemo cancel # stop everything queued or printing
phomemo cancel 0923-1651 # stop one job (any unique id prefix)
phomemo reprint # print the last job again
```
- **Ctrl-C** cancels cleanly; press it twice to force quit.
- Cancelling stops between image blocks (at most about 2cm of paper) and feeds
the paper out. The printer is left ready for the next job.
- Cancelling works across processes: `phomemo cancel` stops a print an AI agent
started.
- Only one job talks to a printer at a time. The others wait as `queued`.
- Job statuses:
- `done`: the printer confirmed every card printed.
- `unconfirmed`: all data was sent but the printer never confirmed. Check the
output; a low battery is the usual cause.
- `failed`, `cancelled`.
Job history lives in `~/.local/state/phomemo/jobs` (override with
`PHOMEMO_STATE`).
## MCP server (Claude and other agents)
```sh
phomemo mcp # stdio
phomemo mcp --http 127.0.0.1:8765 # streamable HTTP at /mcp
```
Tools: `print_cards`, `preview_cards` (returns images, so the agent can check
the layout first), `print_picture`, `printer_status`, `list_print_jobs`,
`cancel_print`, `reprint`, `list_printers`. The print tools wait up to 15
seconds. A longer print keeps running in the background and the tool returns
its job id.
**Claude Code**
```sh
claude mcp add phomemo -s user -- phomemo mcp
```
**Claude Desktop** (`claude_desktop_config.json`):
```json
{ "mcpServers": { "phomemo": { "command": "phomemo", "args": ["mcp"] } } }
```
Use the full path from `which phomemo` if the app can't find the command.
## Configuration
Optional. Without a config file you get one printer, `m02pro`, found
automatically. `phomemo config` shows where the file goes, with an example:
```toml
default = "desk"
[printers.desk]
model = "m02pro"
# address = "…" # from `phomemo scan`; skips discovery, picks one of several printers
# feed = 3 # blank lines after each card
```
Driver options are listed in `src/phomemo/drivers/m02.py`.
## Troubleshooting
- **"not found over Bluetooth"**: turn the printer on and close the Phomemo
app. On macOS, the app running `phomemo` (Terminal, iTerm, Claude…) needs
Bluetooth access under System Settings → Privacy & Security → Bluetooth.
- **The light blinks fast**: the paper is out, the printer is too hot, or the
battery is low. `phomemo status` tells you which.
- **It won't charge from a USB-C charger**: use a 5V USB-A charger with an
A-to-C cable. Some USB-C chargers never switch on power for this printer.
Phomemo warns that chargers above 5V can damage it.
- **Photos look muddy**: pictures are contrast-stretched and brightened before
dithering, but thermal paper suits strong contrast. Bold images print best.
## Thermal paper
Most thermal paper contains BPA or BPS, and both are absorbed through the skin.
"BPA-free" usually means BPS. If you'll handle the prints a lot, look for
**phenol-free** paper.
## How it works
The protocol was reverse-engineered by others (see Credits). What this project
verified on a real M02 Pro, including the print-complete signal and the status
replies, is in [PROTOCOL.md](PROTOCOL.md).
```
src/phomemo/
cards.py Markdown → cards
render.py cards / pictures → grayscale images at printer width
drivers/m02.py M02 family: raster encoding, Bluetooth transport, status
jobs.py job records, per-printer queue, cancel, reprint
api.py shared by the CLI and the MCP server
cli.py `phomemo`
mcp_server.py `phomemo mcp`
```
## Contributing
Issues and pull requests are welcome, especially reports from **M02S, M02 and
T02** owners (does printing work, and does `phomemo status` answer?).
```sh
uv sync
uv run pytest
```
⚠️ **Don't probe unknown `1F 11 NN` commands.** Sweeping opcodes above `0x14`
[bricked an M02X](https://github.com/sgrankin/phomemo/blob/HEAD/PROTOCOL.md).
Stick to documented commands.
## Credits
The protocol knowledge comes from
[vivier/phomemo-tools](https://github.com/vivier/phomemo-tools),
[ryo-endo/phomemo-printer](https://github.com/ryo-endo/phomemo-printer),
[theacodes/phomemo_m02s](https://github.com/theacodes/phomemo_m02s) and
[sgrankin/phomemo](https://github.com/sgrankin/phomemo). This project
re-implements it and contains no code from those projects.
Not affiliated with Phomemo.
## License
MIT
This server cannot be deployed
Maintenance
ActivityMaintained
ResponsivenessNo issues