A Bitcoin (BTC) and crypto portfolio tracker for the Omarchy bar: live cryptocurrency price, holdings, cost basis, portfolio value, profit and loss (PnL), candlestick charts, market sentiment, price alerts, chain stats and Bitcoin news — plus a plugin that will not stop telling you to HODL.
Every price widget shows you a number. None of them know what you paid.
This one does. Record what you bought, when, and at what price, and the panel answers the only question that matters when you look at bitcoin: am I up or down, and by how much — per position and in total, the way a broker shows you a stock. Your average cost is drawn straight across the candles, so the chart stops being decoration and starts being your position.
And because the correct action is almost always none, it keeps saying so.
- Price in the bar, refreshed every minute, in any of ten currencies.
- Your book — every buy with its date, size and entry price, its unrealized P/L in money and percent, and the totals: cost, current value, break-even, and how long you have held.
- Candles over 1D / 7D / 1M / 3M / 1Y, with your break-even as a dashed line and a link out to the full chart when a panel is not enough.
- Fear & greed, with yesterday's move and when the next reading lands.
- The chain — block height, fees, hashrate, difficulty, and the countdown to the next halving.
- A daily digest of bitcoin headlines, optionally with the article artwork, delivered as a notification and readable in the panel.
- Mantras matched to the market:
TO THE MOON 🚀on a green day,FUD! Do not panic sell.on a red one, andNot your keys, not your coins.whenever it feels like it. Over a hundred of them.
Fold any section away with a click or its key. Folding never hides the number
it exists for — a folded book still shows your P/L, a folded sentiment section
still shows 69 · Greed. z folds all three readouts at once, which is the
version worth leaving open all day. The chart is separate: c owns it, so
folding the text never puts your chart away or costs a fetch.
The screenshots use a sample portfolio. Yours never leaves your machine.
omarchy plugin add https://github.com/alvaroeds/omarchy-hodl.git --enable --yesThen bind it to a key — ~/.config/hypr/bindings.lua:
o.bind("SUPER + B", "Bitcoin (HODL)", "omarchy-shell hodl toggle")Requires Omarchy 4.x.
omarchy plugin remove io.github.alvaroeds.hodl --yesThat takes the widget out of the bar and deletes the checkout. Your book and the caches live outside the plugin, so removal never touches them — delete them yourself if you want them gone:
rm -rf ~/.local/share/omarchy-hodl ~/.local/state/omarchy-hodlIf you added the keybinding or the hodl symlink by hand, remove those too:
the line in ~/.config/hypr/bindings.lua and ~/.local/bin/hodl.
Nothing to install and no build step. At runtime it uses only what Omarchy already ships:
python3 (stdlib only) |
every fetch, cache and calculation in bin/hodl |
curl / bash |
not required — the CLI uses Python's own HTTP client |
ImageMagick (magick) |
optional; validates and normalizes new thumbnails. Without it, uncached article images are omitted |
xdg-open |
optional; opening a headline or the CoinGecko chart |
Public APIs, no keys and no accounts: CoinGecko (price and OHLC), alternative.me (fear & greed), mempool.space (chain stats), and the public RSS feeds of Cointelegraph, Bitcoin Magazine, Decrypt and Bitcoin.com. Article thumbnails are fetched from whatever CDN those feeds point at, unless you turn them off — see Article images.
| Key | |
|---|---|
a |
add a position |
j / k |
move between positions |
d d |
remove the selected one (twice, on purpose) |
1–6, h / l |
range — 6 is the ↗ chip: the full chart on CoinGecko |
c |
show / hide the chart |
b s w |
fold the book / sentiment / network section |
z |
fold those three at once, or unfold them — the chart is c's business |
n |
the digest — enter opens a headline in the browser |
t |
the digest in a floating terminal |
r |
refresh everything |
m |
next mantra |
esc |
close |
Left click the pill toggles the panel, right click refreshes, middle click opens the digest in a terminal, and the scroll wheel changes the range.
Press a and fill three fields:
- amount —
0.025(BTC),250k sats, or$500, converted at the entry price - entry price — blank means the current market price
- date —
YYYY-MM-DDor14/03/2025; blank means today
Both European and American number formats are understood: 78,417 is seventy
eight thousand, 0,05 is five hundredths, 1.234,56 and 1,234.56 are the
same number. A BTC amount never treats a dot as a thousands separator —
1.000 is one bitcoin, not a thousand.
The digest can show the artwork each publisher ships inside its own RSS feed.
Those images belong to the publisher, so the plugin treats them as borrowed:
fetched from the feed the publisher offers, cached only on your machine, never
uploaded or shared, always shown beside that publisher's name, and one click
opens their article. They are deleted after two weeks, and newsImages: false
— or hodl news --no-images — turns the whole thing off for a text-only
digest. That is the mode in the screenshot above, which is why no third-party
artwork ships in this repository either.
Publisher bytes are never handed directly to the panel. ImageMagick decodes only the first frame under strict width, height, area, memory, map, disk, thread and time limits, then writes a stripped static PNG no larger than 200x200. The PNG is checked again before publication. Missing ImageMagick, a decode error, a resource-limit failure or an oversized result simply omits that article's image.
bin/hodl is the same brain the panel uses, and it works on its own:
ln -s ~/.config/omarchy/plugins/io.github.alvaroeds.hodl/bin/hodl ~/.local/bin/hodlhodl price, your positions, P/L, and a mantra
hodl news today's digest
hodl add <amount> [price] [date]
hodl rm <id>
hodl list
hodl price one line, for scripts and status bars
hodl mantra one bitcoin truth
hodl fetch [--sources market,fng,network]
hodl candles --days 7
Every command takes --currency eur and --force.
Over IPC: omarchy-shell hodl toggle | add | news | chart 1Y | fold all | refresh | price | status | state.
Setup → Plugins → HODL, or the widget entry in ~/.config/omarchy/shell.json:
| Setting | Default | |
|---|---|---|
currency |
USD | USD EUR GBP CHF JPY CAD AUD MXN ARS BRL |
barDisplay |
Price + change | or Price, Change only, Profit / loss, Portfolio value |
colors |
Green / red | or Theme, to use the theme's accent and urgent colors |
refreshSeconds |
60 | price poll interval |
alertPercent |
5 | notify when the 24h move crosses this; 0 disables |
hodlReminderHours |
6 | how often the HODL reminder fires; 0 disables it |
newsletterHour |
9 | when the daily digest arrives |
newsImages |
true | article artwork in the digest; off gives a text-only list |
notifications |
true | master switch for all three |
- break-even — the average price you paid per bitcoin across the whole book (total cost ÷ total BTC). Above it you are in profit, below it at a loss. Drawn as a dashed line whenever it falls inside the range on screen; when it does not, the caption says which way it went.
7D $77.0k – $81.3k— low and high of the range you have selected, not a fixed 24 hours. It follows the chart, and stays put when you switch to the digest and back.-1.96% 7D— the headline percentage follows the selected range too. The dim line beside it keeps the standard windows for reference. The bar pill is always 24h, whatever the panel is showing.- ATH — the all-time high and how far below it the price is now. This one never changes with the range.
- P/L — unrealized: what a position is worth now minus what it cost. Money on the left, percent on the right. Nothing here is realized until you sell, which you are not going to do.
Each source moves at the speed of the thing it measures:
| Source | Automatically | |
|---|---|---|
| Price | every 60s, always | the one value the bar shows with the panel shut |
| Fear & greed | every hour | the index is published once a day |
| Chain stats | every 15 min, only while the panel is open | nothing outside the panel shows them |
| Candles | never on a timer | on open, on a range change, and on r |
| Digest | once a day | plus n / r on demand |
Hovering the pill refreshes a price that has gone cold. Nothing ever blanks while it reloads: values stay on screen, a small spinner marks what is in flight, and a source that fails keeps its last good reading.
QML never touches the network. bin/hodl owns every request and caches each
source on disk with its own TTL, so a one-minute poll only reaches an API that
has actually gone stale.
CoinGecko's free tier answers a throttled request with HTTP 200 and the 429
buried in the JSON body, so it is detected by content rather than status
code. When it trips, the plugin backs that host off (45s → 15min, respecting
Retry-After), keeps serving the last good values, and says so next to the
chart. Two requests to the same host are never fired within four seconds.
Every response is size-capped — 1MB for JSON, 4MB for a feed, 2.5MB for an image — so a broken or hostile endpoint cannot stream memory away. Complete commands have wall-clock budgets too (45 seconds normally, 90 for the multi-feed digest), rather than relying on a per-socket timeout that a slow trickle can repeatedly reset. The shell applies a second watchdog and terminates the helper's isolated process group with TERM then KILL. JSON/text written to stdout is schema-, cardinality- and byte-capped before emission, and the QML runner independently caps the chunks it accepts.
Where it will connect. Thumbnail URLs are written by the RSS feeds, not by
this plugin, so a feed could otherwise point your machine at
https://127.0.0.1:8443/…, your router, or a cloud metadata address and have
it fetched from inside your network. Every URL is resolved before connecting
and refused if any of its addresses is loopback, private, link-local,
multicast or reserved; the connection is pinned to the address that was
checked, so DNS cannot answer differently a moment later; redirects are never
followed blindly — each hop is vetted the same way, up to four of them.
https only — nothing is fetched in the clear. Image signatures select a
restricted raster decoder, but no downloaded file is published: only a
successfully decoded and bounded static PNG reaches the panel.
Headline links reach your browser only when they are http or https: a feed
cannot hand xdg-open a file:// path or a custom scheme that would launch
another application.
Files are opened relative to held directory descriptors. Reads use
O_NONBLOCK|O_NOFOLLOW, require a single-link regular file owned by the user,
and stop one byte past a per-file cap before parsing. Writes use an
unguessable O_EXCL temporary entry and descriptor-relative rename.
python3 tests/security.test.py covers these boundaries, the command deadline,
process-tree cleanup and image normalization.
~/.local/share/omarchy-hodl/positions.json your book — back this up
~/.local/state/omarchy-hodl/ caches, digest, thumbnails
Both directories are created 0700 and every file 0600 — the book records
how much bitcoin you hold and what you paid, which is nobody else's business
on a shared machine. Only bin/hodl ever writes it, including when the panel
adds a position, so there is one place that decides those permissions.
positions.json is plain JSON, watched for changes, and yours — it outlives
an uninstall on purpose. Nothing from your book is sent anywhere. The plugin
talks to CoinGecko, alternative.me, mempool.space and four RSS feeds; when
article images are enabled, it also contacts the public CDN hosts named by
those feeds. None of them are told what you own. There is no account, no key,
no telemetry.
It is a price display with a strong opinion. The opinion is HODL.
MIT — see LICENSE.



