A local-first monitor for a self-hosted Monero P2Pool mining stack: a macOS
menu-bar app and a web dashboard that read straight from your own monerod,
XMRig, and P2Pool — no pool website, no account, no third party holding your
numbers.
Your wallet address is read at runtime from the P2Pool API and never stored in this repo. The only outbound request is an optional XMR/USD price lookup, which carries no address.
P2Pool is decentralized, which is the point — but it also means there is no
supportxmr.com-style page to glance at. Your stats live in files and local
HTTP endpoints on your own machine. This surfaces them two ways:
- Menu bar — live hashrate in the title, full miner/P2Pool/node stats in the dropdown, one-click stop/restart, and a notification the moment P2Pool finds a block you shared in.
- Dashboard — a browser view at
127.0.0.1:8800with the hashrate history, performance cards, and a running log of wins.
P2Pool pays you directly, per block, whenever the sidechain finds one and you held shares in the PPLNS window. The monitor captures two events as they land:
- block — the sidechain found a Monero block. Fires a notification with the height and your current reward share.
- share — you found a PPLNS share on the sidechain. Logged quietly, no popup.
A note on what "block" means: a P2Pool-mini block is found by the whole
sidechain, roughly every few hours, so this notification fires several times a
day — not weekly. You earn from a block only if you held shares in its PPLNS
window; reward_share is your current share, a proxy. Confirmed "money hit the
wallet" would need a wallet-RPC check, which is intentionally out of scope here.
The always-on menu-bar app is the sole writer of this history; the dashboard only reads it, so the two never race on the same file.
Requires a running local stack — monerod, P2Pool (with --data-api /
--local-api), and XMRig with its HTTP API enabled — plus Python 3.11+.
git clone https://github.com/JeremyGracey-AI/p2pool-monitor
cd p2pool-monitor
cp config.example.toml config.toml # then edit — see below
bash scripts/install.sh # installs two launchd agents, starts bothOpen http://127.0.0.1:8800. The menu-bar icon appears immediately.
Everything lives in config.toml (each key also has an env override). The values
you will actually touch:
| Key | What |
|---|---|
sources.p2pool_api_dir |
where P2Pool writes its API files (default ~/p2pool/api) |
sources.xmrig_api |
XMRig HTTP API (default 127.0.0.1:18088) |
miner.launchd_label |
your XMRig launchd label, for the Stop/Restart buttons |
display.wallet |
masked (default, shows 42vP…5RA) or full |
privacy.price |
fetch XMR/USD (default on) — set false for zero outbound |
privacy.observer |
link stats to p2pool.observer (off; sends your address) |
- Wallet address read from the local P2Pool API at runtime, never committed.
- Dashboard binds to loopback only.
- One optional outbound call (price). P2Pool Observer integration is off by default because it necessarily sends your address off-machine.
mining_stats.py one source of truth — reads XMRig / monerod / P2Pool, all local
wins.py pure detect() + a small on-disk history (unit-tested)
menubar.py rumps menu-bar app — producer of win history + notifications
dashboard/ stdlib HTTP server + a single static page (reader of history)
config.py defaults <- config.toml <- env
Run the tests:
python -m pytest tests/ -q # or: python -m unittest discover testsBuilt by Jeremy Gracey. BSD-3-Clause.
Not affiliated with the Monero Project, P2Pool, or XMRig.
