Four dashboards. Zero extra instrumentation.
Four reports that live under /reports, all aggregated from data the platform already collects: AI logs, task events, time entries. Nothing is instrumented separately — if someone used the chat, generated a content or logged minutes, it's already in the report.
Where is my token budget going?
Every LLM call writes an AIUsageLog. The report pivots that log across four breakdowns.
GET /ai-logs/token-usageprovider—claude_code/anthropic/openaimodel—claude-sonnet-4,gpt-4o, etc.user_iddate_range
- Daily time series —
input_tokens,output_tokens,cost_estimate. - Breakdown by model
- Breakdown by user
- Breakdown by function —
chat.send,content.generate,learnings.extract,chat.title…
The AIUsageLog stores function, provider, model, tokens_in, tokens_out, duration_ms, user_id — the report is a pivot over that record, nothing instrumented on the side.
Who's pulling the team forward?
GET /ai-logs/leaderboardscore = messages_sent × 2
+ ai_calls × 1
+ content_generated × 5
+ chat_interactions × 1champion— rank 1.top3— ranks 2 and 3.power_user— score > 50 (independent of rank).
Each badge has its own color in light and dark themes (see BADGE_CONFIG), with a gold / silver / bronze podium for the top 3.
Who worked on what, and how much is billable?
Entries arrive in two ways: automatic timer on the Kanban task card, or manual CRUD. The report aggregates by user, client, project and date, with native split between billable and non-billable.
user_id, task_id, client_id, project_idstarted_at, ended_at, minutesbillable—booldescriptionsource—timer/manual
GET /timesheets/report- Total minutes
- Billable vs non-billable (split)
- Daily chart
- Entry list with drill-down
- Automatic timer — Play/Stop on the Kanban task card creates the entry on stop.
- Manual — CRUD directly via
/timesheets/entries.
Where does the team slip, and on which column?
GET /tasks/productivity-reportcompletion_rate— % of tasks closed in the period.on_time_rate— % of completed tasks done before or ondue_date.variance_pct— average difference betweenestimated_minutesandactual_minutes.daily_completed— time series of tasks completed per day.
- By priority —
urgent/high/medium/low. - By user (assignee) — Who closes on time, who carries the delay.
- By column — Kanban bottlenecks — which column holds things the longest. Not just knowing it's late, but knowing where it stalled.
Where each number is collected.
- Source — Token Usage
AIUsageLogwritten on every LLM call, across every route.- Source — Leaderboard
- Same AIUsageLog + content.generate events; score computed on-the-fly, no parallel table.
- Source — Timesheet
- Model
TimeEntry— Kanban timer + manual CRUD via/timesheets/entries. - Source — Productivity
- Task events (creation, column moves, closure) + due_date + estimated/actual minutes.
Why these four reports, and not twenty.
Zero configuration
The numbers already exist because the platform records everything. You don't 'turn on' the report — it exists because the data does.
Native billable split
Billable vs non-billable comes from TimeEntry itself. Not an add-on, not computed after — it's in the schema.
Bottleneck per column
Productivity broken down by column reveals the real Kanban bottleneck, not just ticket delay. Where work stalls shows up.
Want to see this running on your own pipeline?
We'll show you in a quick demo, using data you already work with.