codex-usage-epd
Push your OpenAI Codex usage statistics to a 4.2" 400x300 three-colour e-paper display powered by the EPD-nRF5 firmware.
Features
- Plan quota: 5-hour + weekly windows (used / remaining %, reset time)
- "Tokens used today": a Total across all models, plus the top three models with bars proportional to the most-used model
- Optional "Last 7 days" line chart for the seven completed local calendar days
before today, with dates and compact K/M/B totals. Enable
render.show_historyor pass--show-historyto place the chart beside today's usage - Credits balance when present on the plan
- Red alert bars when remaining % drops below
render.warn_threshold --selftestverifies RLE + bitplane round-trips without network/hardware
Requirements
- macOS (BLE via bleak/CoreBluetooth), Python 3.10+
- ChatGPT login for Codex (
~/.codex/auth.jsonwithtokens.access_token) - 4.2" 400x300 B/W/R panel with SSD1683/SSD1619 driver, model id
0x02
Install with a coding agent
Copy and paste this prompt into Codex or another coding agent:
Install https://github.com/hunterMG/codex-usage-epd on this computer. Read the
README first, check that the prerequisites are available, clone the repository
into an appropriate user directory, install its dependencies with uv, generate
the configuration file, and run the self-test. Do not print, copy, or modify my
Codex authentication token. Tell me what configuration still needs my input,
and ask for confirmation before installing or starting the launchd background
agent.
Setup
Clone this repo and cd to it in terminal.
uv sync --locked # creates .venv, installs deps + the package (editable)
uv run codex-usage-epd --init # generate config/codex_usage_epd.yaml from the template
# edit config/codex_usage_epd.yaml (set ble.device etc.)
uv run codex-usage-epd --selftest # render preview.png, no net/BLE
uv run codex-usage-epd --dry-run # live fetch + render preview.png
Usage
uv run codex-usage-epd --init # generate a config from the template
uv run codex-usage-epd --selftest # sample data, verify encode/decode
uv run codex-usage-epd --dry-run # fetch + render preview.png (no BLE)
uv run codex-usage-epd --probe # connect + INIT, print device config/mtu
uv run codex-usage-epd --test-screen # INIT + CLEAR full refresh (firmware check)
uv run codex-usage-epd --once # fetch + render + push to display
uv run codex-usage-epd --loop # push every N minutes forever
Modifiers (combine with the actions above):
--config <path> # use this YAML config instead of the default
--force # with --init: overwrite an existing config
--font <path> # override render.font
--sample # use synthetic sample data (no network)
--debug # also dump raw wham/usage JSON to tmp/usage_dump.json
Config resolution when --config is not given: repo config/codex_usage_epd.yaml,
then ~/.config/codex-usage-epd/codex_usage_epd.yaml, then the bundled template.
ble.device accepts auto (scans for NRF_EPD), a MAC address, or a name
substring.
Installing as a package
Install the latest release from PyPI:
uv tool install codex-usage-epd
# or, inside an existing environment:
uv add codex-usage-epd
The config template lives at config/codex_usage_epd.yaml.example. Run
codex-usage-epd --init to generate a real config (~/.config/codex-usage-epd/
when installed, config/ in a checkout), or point at your own with
--config /path/to/codex_usage_epd.yaml.
launchd (every 60 minutes)
./deploy/install.sh # fills the __REPO__ placeholder with the checkout path
# and bootstraps the agent (works for any username)
This generates ~/Library/LaunchAgents/com.codex-usage-epd.plist from
deploy/com.codex-usage-epd.plist.in, so no manual path editing is needed.
To remove the agent later:
launchctl bootout gui/$(id -u)/com.codex-usage-epd
rm ~/Library/LaunchAgents/com.codex-usage-epd.plist
Configuration
Generate a config with codex-usage-epd --init, then edit
config/codex_usage_epd.yaml (or ~/.config/codex-usage-epd/ when installed).
Notable keys:
display.width/display.height- panel pixels (400x300);display.model_id- EPD panel model id (0x02for SSD1619 400x300 BWR)display.sleep_after_push- send the SLEEP command after pushing (defaultfalse; early sleep aborts the panel refresh)ble.device-auto| MAC address | name substringble.scan_timeout- seconds per scan attempt;ble.scan_retries- retry the scan before giving up (missed advertisements)ble.interleave- writes per response-ack, mirrors the web client (50)ble.pacing_ms- delay between writes (0.0= back-to-back)ble.hold_after_refresh- seconds to stay connected so the panel refresh completes (20)ble.slot- which image slot to write on the epdiy.cn slot firmware (0..N-1);"auto"picks the first free slot so an existing slot is never overwritten;-1/"none"disables theSET_SLOTcommand (plain EPD-nRF5 firmware)codex.auth_file- where the OAuth tokens live (default~/.codex/auth.json)codexreadschatgpt_base_urlfrom~/.codex/config.tomlif setrender.font-.ttfpath (auto-detected on macOS/Windows/Linux otherwise)render.warn_threshold- remaining % that turns a bar redrender.preview- filename for the rendered preview PNGrender.show_history- show the "Last 7 days" chart (defaultfalse); override with--show-historyor--no-show-history, including in--selftestschedule.interval_minutes- interval used by--loop; launchd uses the fixedStartIntervalindeploy/com.codex-usage-epd.plist.in
Notes
- Tokens are read from
~/.codex/auth.jsonand never logged or committed. - The display must be powered (USB). With
ble.patch_wakeup_pin: trueit forces the device config byte to0xFFso the panel keeps re-advertising after the timeout, letting the scheduled push always connect.
Development
uv sync --locked
uv run pre-commit install
uv run pre-commit run --all-files
License
GNU AGPL v3.0 or later — see LICENSE.
Metadata
Release files for codex-usage-epd 2026.10.1
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | |
|---|---|---|---|---|
| codex_usage_epd-2026.10.1.tar.gz | 309.7 kB | With provenance | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| codex_usage_epd-2026.10.1-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 350.9 kB
Release files / codex_usage_epd-2026.10.1.tar.gz
| Download URL | codex_usage_epd-2026.10.1.tar.gz |
|---|---|
| Size | 309.7 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
a4955755a5312ff0aa7d96a0210e1ebfe37be44525161b87446cd433f180ed4b
|
|
BLAKE2b-256 checksum How to use checksums |
9437dd412e4bfed612fd9ab04b2840d4485d8a8caaf42694766d383c99e807a9
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.16
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Oct 22, 2026.
Transparency logRelease files / codex_usage_epd-2026.10.1-py3-none-any.whl
| Download URL | codex_usage_epd-2026.10.1-py3-none-any.whl |
|---|---|
| Size | 41.3 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
53fc0963ee49845beca8ec1351e59ab38792851d011cdd9d754b7afa9bba8485
|
|
BLAKE2b-256 checksum How to use checksums |
6d344c2a46c65a875a0c47a7dfac97446156051fe2a6117c00f143e7f4a67106
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.16
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Oct 22, 2026.
Transparency logSecurity for codex-usage-epd 2026.10.1
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
Full provenance
All 2 files in this release have been uploaded with provenance metadata.
Attestation for codex_usage_epd-2026.10.1.tar.gz
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Oct 22, 2026.
Transparency logA note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.