+1 and a live sparkline page exists one second later.# count curl -d "+1" https://tally.legible.sh/my-agents-x7k2q/tasks-completed # {"metric":"tasks-completed","value":1} # now open the same URL in a browser → a live sparkline page # and /my-agents-x7k2q → a live dashboard of every metric in the topic
| POST /t/m | body +1 (default), -2, =42 gauge set → {"metric","value"}. First write creates topic + metric. |
| GET /t/m | curl: value + minute/hour/day series · browser: live sparkline page · Accept: text/plain: bare value |
| GET /t/m?wait=30 | long-poll — responds on the next change |
| GET /t | curl: metric list · browser: live dashboard |
| GET /t/sse | SSE — named update/delete events |
| DELETE /t/m | remove a metric |
Buckets of {t, sum, count, last}: minutes kept 24 h, hours 14 d, days 400 d. Unlike the countapi clones, there is a time series behind every number. Unlike the StatHat successors, there is no signup and no $20/mo.
Your hooks already curl ntfy for pings — now curl tally for numbers. A Claude Code Stop hook counts tasks-completed; a PostToolUse hook counts tool-errors; one line of CLAUDE.md teaches the agent to bump tests-fixed itself. The topic URL on a second monitor is the fleet, at a glance.
npx tally-sh serve # identical API on http://localhost:4189 tally serve --data-dir ./data # JSONL persistence, replayed on boot tally serve --token s3cret # writes require a Bearer token
Node ≥ 20, zero dependencies, MIT. The hosted instance sells retention, private topics, alerts, export, teams — never the verbs.
Topics are public-by-obscurity, like ntfy. Add entropy (-x7k2q), or self-host with --token.
sum / count / last per bucket. No percentiles, no labels. Need p99{region}? That's Prometheus, and that's fine.