Prompt: month-by-month spend report from the credits ledger
Have an agent turn the ird credits ledger into a month-by-month report —
charges grouped per service, top-ups, refunds, adjustments and expiries
on their own lines — reconciled against what is actually running on the
account today, so charges for resources that no longer exist, credits
about to expire and your remaining runway are visible. Nothing is
changed — unlike account-audit (inventory plus approved cleanup) and
plan-and-price-stack (pricing what you intend to run), this one only
looks back.
Needs: the ird CLI, logged in (ird credits ledger is CLI-only); ird MCP or CLI for the inventory reads
Costs: none — the ledger, credits_balance, credits_prices, the *_list and *_usage tools are reads; dns_claim_list is a dns.manage request (check credits_prices)
Group: housekeeping
Paste everything below the line into a fresh conversation. Fill in the
FILL IN block first.
Task
Report what the account spent, per month and per service, over MONTHS,
reconcile it with the live inventory, and state the runway. Nothing is
unpinned, deleted, renewed or changed.
FILL IN
MONTHS: 3 # full calendar months to report, newest first
CURRENCY: credits # credits, or a currency to add as a second column with the rate you give below
RATE: # credits per unit of CURRENCY, blank = credits only
OUT_FILE: ./ird-spend.csv # one row per month × service; blank = table in chat only
Non-negotiable rules
- Read-only. No
ipfs_unpin, delete_tunnel, vps_destroy,
apps_destroy, p2p_delete_app, renew_domain, no record change.
A wrong-looking charge goes in the report, not a fix.
- Numbers come from the ledger, never from memory. Every figure is
a ledger entry or a sum of them; rates for context come from
credits_prices read now, with their key.
- Say what you couldn't see.
--limit caps at 200 with no paging
flag: a kind returning 200 rows may lose its oldest month — mark it.
If ird credits ledger fails (0.20.0 does: an unmarshal error on
next_cursor), report the error verbatim plus ird version, run
ird update --check, ird update if newer, retry once; still
failing, stop — the way out is a support ticket
(support_create_ticket, only if I say so). Never reconstruct
figures from usage tools.
- Don't assume field names. Read the JSON before parsing: expect a
kind, an amount, a timestamp and a description in some form, use the
names the output actually has, and say if one is missing.
Steps
A. Pull the ledger. One call per kind, all with --json --limit 200:
ird credits ledger --kind charge, then grant, purchase,
adjustment, refund, expiry. Save the raw JSON under OUT_FILE's
folder as ledger-<kind>.json. Note the oldest timestamp per kind.
B. Bucket by month. Assign every entry to its calendar month (UTC
as printed). Charges are the spend; purchase and grant are inflow;
refund and adjustment are corrections; expiry is credit lost.
Keep the last MONTHS full months plus the current partial month,
marked partial.
C. Group charges per service. Match each charge's description to a
service family from credits_prices: domains (domains.register,
domains.renew, domains.trade, domains.transfer), DNS zones
(recurring.dns-zone-hourly), IPFS storage and traffic
(recurring.ipfs-pin-hourly), tunnels (recurring.tunnel-hourly),
servers (recurring.vps-hourly.<tier>), snapshots and volumes
(recurring.image-hourly, recurring.volume-hourly), p2p apps and
mailbox (recurring.p2p-app-hourly), jobs (jobs.*), per-request
lines (domains.dns-snapshot, domains.info, p2p.credentials,
dns.provision). Unmatched charges go into "other" with their
description verbatim. Keep any resource the description names
(hostname, CID, server, app) — step E needs it.
D. Inventory today. credits_balance; list_domains;
dns_list_zones; ipfs_pins(limit=100, offset=…) over every page
(total says how many; CLI: ird ipfs pins --all --json); ipns_list;
ipfs_domains; dns_claim_list (a dns.manage request — read its
price first); list_tunnels; vps_list; apps_list;
p2p_list_apps; ird vps snapshot images --json; ird vps volumes
--json; grants_list (payer explains charges for work on domains
shared with me, and my work another account paid). ipfs_usage and
p2p_usage give this period's running rate.
E. Reconcile. For each resource named in a charge: in D, or not.
Absent ones are "stopped mid-month" (last charge well before today —
normal) or "charged this month yet not listed" — flag those with last
charge date and amount (a support ticket only if I ask). Then compare
last full month's total with the running rate (*_usage monthly plus
hourly rates × 730 for servers, tunnels, p2p apps, snapshots,
volumes): a big gap means something was added or removed — say which.
F. Expiry and runway. From grant and expiry entries, list
credits that expired and grants whose description carries a future
expiry date. Runway = credits_balance ÷ average charges over the
last MONTHS full months; also at E's running rate, if different.
Months, one decimal.
G. Write it. OUT_FILE with columns: month, service, credits,
CURRENCY (if RATE), entries, resources, note.
Deliverable
A table per month: service, credits spent, share of the month; a totals
row; inflow, refunds, adjustments and expiries per month underneath.
The reconciliation list (resource, service, last charge date, amount,
status in inventory). Runway both ways. Truncation notes from rule 3.
One line on what this is not: forward pricing is plan-and-price-stack,
cleanup with approvals is account-audit (both at
https://ird.cod-sursa.ro/prompts/).