Render finance dashboard
An Israeli Claude Finance Plugin
npx -y skills add ya5huk/findash --skill render-finance-dashboardAssembled from the repository path, not quoted from the project. Check it against their README if it does not work.
2 things to look at
- no licenseNo license file was found in the repository. Code published without one is not open source by default, so using it at work is a question for whoever answers licensing questions where you are.
- 20 stars20 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.
What its author says it does
Copied from the file, not written here
Use when the user says "render dashboard", "show my finances", "build the dashboard", or any morning-summary equivalent. Reads SQLite, fetches live prices/FX from Yahoo Finance, fills the HTML template, and writes a self-contained dashboard to `output/dashboard.html`.
SKILL.md
6.4 KB, as published. Nobody here has run it
render-finance-dashboard
You render the booky finance dashboard from the current state of data/finance.db. The visual design is fixed by the template; you only fill it with data. The mechanical part (SQL → HTML, live-price fetch, asset inlining) lives in scripts/render_dashboard.py — invoke it, don't re-derive it.
Where things live
- Canonical renderer:
scripts/render_dashboard.py - HTML template (placeholders in
{{NAME}}form):templates/dashboard.html.tpl - CSS:
templates/styles.css— inlined into the HTML at render time - Chart constructors:
templates/charts.js— inlined into the HTML - Vendored offline assets (gitignored, produced by
scripts/bundle-assets.py):templates/vendor/chart.umd.min.jstemplates/vendor/chartjs-adapter-date-fns.bundle.min.jstemplates/vendor/fonts-inline.css(EB Garamond + Cormorant Garamond, base64 woff2)
- Telegram credentials: the
[telegram]section of.secrets/findash(bot_token=…andchat_id=…) - Local DB:
data/finance.db - Output: a single self-contained file at
output/dashboard.html - SQL schema and example queries:
docs/sqlite-schema.md - Visual rules:
docs/design-system.md
Flow
-
Run the renderer. From the project root:
python3 scripts/render_dashboard.pyThe script handles everything mechanical:
- Live-fetches prices for currently-held securities and
USD/ILS,GBP/ILSFX rates from Yahoo Finance (query1.finance.yahoo.com/v8/finance/chart/{symbol}). User-Agent header required. - Yahoo symbol translation:
RR.LSE→RR.L. Quote units: USD direct; LSE pence (÷100→ GBP); TASE agorot (÷100→ ILS). - Persists fetched prices into
pricesand the new FX intofx_ratesso a history accumulates day-by-day. - Computes net worth in ILS, brokerage market value, unrealized P/L per position.
- Excludes accounts with
closed_on IS NOT NULLfrom Cash and from the headline (they still show in SQLite-data). - Sorts the positions table by ILS-equivalent market value, descending (so SPY ranks above RR.LSE despite fewer shares).
- Orders brokerage deposits newest first.
- Builds the SQLite-data debug tabs (first 50 rows + count per table).
- Inlines CSS, fonts, Chart.js, and the chart-app JS into a single HTML file.
- Writes
output/dashboard.htmland a small meta file at/tmp/dashboard_meta.json(used by the Telegram step).
If any vendor file is missing, the script stops with a clear message. Run
python3 scripts/bundle-assets.pyonce to fix. - Live-fetches prices for currently-held securities and
-
Send to Telegram. Delivery lives in one committed, allowlisted command so the unattended daily
claude -prun can run it without per-call approval (it can't build the read-secret +curlsend inline — the permission analyzer won't auto-approve a command that sources.secretsand expands${bot_token}, and theWritetool isn't granted unattended). The token is read at runtime and never printed.scripts/send_telegram.sh # add: --note "<line>" to append a caption lineWhat it does (= the old steps 2+3, now deterministic):
- Sends
output/dashboard.htmlas a document, captionFinance — <AS_OF_DATE> · <net worth>(literal·U+00B7), read from/tmp/dashboard_meta.json. - If
data/last_sync_summary.mdexists, sends it as a secondsendMessage(HTML parse mode; bold titleSync · <AS_OF_DATE>; split into ≤3900-char parts on\nboundaries;## Ingested/## Triagedheaders render as bold New/Filed, any other##header — e.g.## ⚠️ Warnings— passes through as its own bold line), then deletes it on success. The summary may lead with a⚠️ Warningsblock — that's expected on degraded runs, not an error. Absent → printsSync summary: Skipped (no summary). - Telegram not configured (no
[telegram]in.secrets/findash) → printsTelegram delivery skipped: …and exits 0 (local file still useful). Never deletes the local dashboard on a Telegram failure.
Pass
--note "<line>"to append a caption line — the morning flow uses this to surface a best-effort fetch failure. The script printsSent to chat <id>/Telegram delivery failed: <description>/ theSync summary: …line — relay them in step 3. - Sends
-
Report. Print:
- The absolute path of
output/dashboard.html. - The Telegram delivery status:
Sent to chat <chat_id>,Telegram delivery skipped: …, orTelegram delivery failed: <description>. - The sync summary delivery status:
Sync summary: Sent (<N> bullets),Sync summary: Skipped (no summary), orSync summary: Failed: <description>. - Any tickers Yahoo couldn't price (the script logs them on
FAILED:— flag them so the user knows which positions fell back to cost basis).
- The absolute path of
Where judgment still lives (not in the script)
- Deciding whether a fresh balance figure looks plausible or whether a sync mis-parsed something. If a number looks wrong, check the source doc and explain rather than rendering a broken figure (e.g. a closed Hapoalim sub-account showing an apparent negative balance from a parser artifact when the real closing balance was 0).
- Whether to mention a particular caveat in the Overview footnote (e.g. "no price for X" or "this account was just opened").
- The contents of the Telegram caption when the dashboard contains something unusual.
Principles
- Don't invent design. All visual choices are in
styles.cssand the template. Don't add inline styles, classes, or markup not already defined. - Be honest with empty states. If a section has no data yet, show a brief italic muted note ("No payslips yet"), not a fake placeholder row.
- Number formatting: group thousands; 2 decimals for amounts <10,000, 0 decimals for ≥10,000. Right-align money columns.
- Hebrew text passes through unchanged.
dir="auto"on table cells is already handled by the script. - The "SQLite data" tab is for debugging. Show raw rows truthfully. Don't reformat or hide columns.