You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: README.md
+12-12Lines changed: 12 additions & 12 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -73,7 +73,7 @@ Developer uses Cursor → API collects data hourly → Engine detects anomaly
73
73
| Someone's daily spend spikes |`Alice: daily spend spiked to $214 (4.2x her 7-day avg of $51)` → Slack alert |
74
74
| A user's cycle spend is far above the team |`Bob: cycle spend $957 is 5.1x the team median ($188)` → Slack alert |
75
75
| A user is statistically far from the team |`Bob: daily spend $214 is 3.2σ above team mean ($42)` → Slack alert |
76
-
| Someone switches to an expensive model |`Bob: cost/request spiked to $1.45 (4.2x his avg of $0.34) — using opus-max` → Slack alert |
76
+
| Someone switches to an expensive model |`Bob: cost/request spiked to $1.45 (4.2x his avg of $0.34), using opus-max` → Slack alert|
77
77
| A developer uses an expensive model when others don't |`Bob averaged $4.20/req on claude-opus-max (team median: $0.52 on sonnet)` → Model cost comparison table |
78
78
79
79
Every alert includes who, what model, how much, and a link to their dashboard page so you can investigate immediately.
@@ -117,7 +117,7 @@ You don't need to remember to check the dashboard. The system comes to you.
117
117
|**Plan exhaustion**| Daily, when users exceed plan | "65/151 active users have exceeded their included plan this cycle" |
118
118
|**Cycle summary**| 3 days before billing cycle ends | Total spend, unused seats, top spenders, adoption breakdown, cycle-over-cycle trend |
119
119
120
-
Anomaly alerts include severity, user, model, value vs threshold, and a direct link to the user's dashboard page. Cycle summaries tell you how many seats are going unused and who's driving cost — so you can act before the invoice, not after.
120
+
Anomaly alerts include severity, user, model, value vs threshold, and a direct link to the user's dashboard page. Cycle summaries tell you how many seats are going unused and who's driving cost, so you can act before the invoice lands.
121
121
122
122
Also supports **email alerts** via [Resend](https://resend.com) (one API key, no SMTP config).
123
123
@@ -143,7 +143,7 @@ Deploy your own instance in minutes. You'll need a [Cursor Enterprise](https://c
143
143
144
144
[](https://render.com/deploy?repo=https://github.com/ofershap/cursor-usage-tracker)
145
145
146
-
> **Railway and Docker** options below. Want help setting this up for your team — deployment, threshold tuning, first spend analysis, and ongoing support?[Let's talk](https://linkedin.com/in/ofershap).
146
+
> **Railway and Docker** options below. Want help setting this up for your team? Deployment, threshold tuning, first spend analysis, ongoing support.[Let's talk](https://linkedin.com/in/ofershap).
147
147
148
148
---
149
149
@@ -288,16 +288,16 @@ fly deploy
288
288
# Dashboard at https://your-app.fly.dev
289
289
```
290
290
291
-
Set up hourly collection by adding `DASHBOARD_URL` and `CRON_SECRET` as [GitHub Actions secrets](https://docs.github.com/en/actions/security-for-github-actions/security-guides/using-secrets-in-github-actions) — the included `.github/workflows/cron.yml` workflow triggers `/api/cron` every hour.
291
+
Set up hourly collection by adding `DASHBOARD_URL` and `CRON_SECRET` as [GitHub Actions secrets](https://docs.github.com/en/actions/security-for-github-actions/security-guides/using-secrets-in-github-actions). The included `.github/workflows/cron.yml` workflow triggers `/api/cron` every hour.
292
292
293
293
### Other cloud platforms
294
294
295
295
Any platform that supports Docker + persistent volumes works:
296
296
297
-
-**[Render](https://render.com)**— use the deploy button above, or `render.yaml` in this repo
298
-
-**[Railway](https://railway.app)**— create a project from this repo, attach a volume at `/app/data`
297
+
-**[Render](https://render.com)**- use the deploy button above, or `render.yaml` in this repo
298
+
-**[Railway](https://railway.app)**- create a project from this repo, attach a volume at `/app/data`
299
299
300
-
> **Serverless platforms** (Vercel, AWS Lambda, etc.) require replacing SQLite with an external database. The data layer is abstracted behind `src/lib/data/` — swap the implementation to use Postgres, Supabase, PlanetScale, or any other database. See [Architecture](#architecture) for details.
300
+
> **Serverless platforms** (Vercel, AWS Lambda, etc.) require replacing SQLite with an external database. The data layer is abstracted behind `src/lib/data/`. Swap the implementation to use Postgres, Supabase, PlanetScale, or any other database. See [Architecture](#architecture) for details.
301
301
302
302
---
303
303
@@ -317,7 +317,7 @@ flowchart TB
317
317
D --> AL
318
318
```
319
319
320
-
The data layer is abstracted behind `src/lib/data/` — SQLite is the default (zero-config), but you can swap the implementation for Postgres, Supabase, or any database that fits your infrastructure.
320
+
The data layer is abstracted behind `src/lib/data/`. SQLite is the default (zero-config), but you can swap the implementation for Postgres, Supabase, or any database that fits your infrastructure.
321
321
322
322
---
323
323
@@ -346,11 +346,11 @@ The Settings page (`/settings`) is where you configure detection behavior and ma
346
346
347
347
### Detection Thresholds
348
348
349
-
All anomaly detection parameters listed in [Configuration](#configuration) above are editable from the Settings page — static thresholds, z-score sensitivity, spend spike multipliers, and the expensive model detector. Set any value to 0 to disable that specific check.
349
+
All anomaly detection parameters listed in [Configuration](#configuration) above are editable from the Settings page. Static thresholds, z-score sensitivity, spend spike multipliers, the expensive model detector. Set any value to 0 to disable that check.
350
350
351
351
### Billing Groups
352
352
353
-
Billing groups let you organize team members by department, team, or any structure that fits your org. The Team Overview page includes a group filter dropdown — select a group to instantly scope all stats, charts, and the members table to that subset.
353
+
Billing groups let you organize team members by department, team, or any structure that fits your org. The Team Overview page has a group filter dropdown. Select a group to scope all stats, charts, and the members table to that subset.
354
354
355
355
From the Settings page you can:
356
356
@@ -368,7 +368,7 @@ For teams using [HiBob](https://www.hibob.com/) as their HR platform, the Settin
368
368
369
369
1. Export a CSV from HiBob's People Directory (include Email, Department, Group, and Team columns)
370
370
2. Upload it to the import modal
371
-
3. Review the preview — see which members will be moved, which groups will be created, and who wasn't matched
371
+
3. Review the preview: which members move, which groups get created, who wasn't matched
372
372
4. Selectively approve or reject individual changes before applying
373
373
374
374
The import builds a `Group > Team` hierarchy automatically. Small teams (fewer than 3 members) are merged into their parent group. Members not found in the CSV keep their current assignment.
@@ -408,7 +408,7 @@ When both are set, either match grants access. When neither is set, any Google a
408
408
409
409
### How It Works
410
410
411
-
- Sessions use encrypted JWT cookies — no database tables needed
411
+
- Sessions use encrypted JWT cookies, no database tables needed
412
412
- The `/api/cron` endpoint is excluded from auth (it uses its own `CRON_SECRET`)
413
413
- Sign-in page appears automatically when auth is enabled
414
414
- User avatar and sign-out menu appear in the nav bar
Copy file name to clipboardExpand all lines: src/lib/anomaly/trends.ts
+3-3Lines changed: 3 additions & 3 deletions
Original file line number
Diff line number
Diff line change
@@ -63,7 +63,7 @@ function detectSpendSpikes(
63
63
metric: "spend",
64
64
value: user.spend_cents,
65
65
threshold: history.avg_spend*spikeMultiplier,
66
-
message: `${user.name}: daily spend spiked to $${todayDollars} (${ratio.toFixed(1)}x their ${lookbackDays}-day avg of $${avgDollars}) — model: ${user.most_used_model||"unknown"}`,
66
+
message: `${user.name}: daily spend spiked to $${todayDollars} (${ratio.toFixed(1)}x their ${lookbackDays}-day avg of $${avgDollars}), model: ${user.most_used_model||"unknown"}`,
67
67
detectedAt: now,
68
68
resolvedAt: null,
69
69
alertedAt: null,
@@ -98,7 +98,7 @@ function detectCycleOutliers(anomalies: Anomaly[], now: string, outlierMultiplie
98
98
metric: "spend",
99
99
value: user.spend_cents,
100
100
threshold: median*outlierMultiplier,
101
-
message: `${user.name}: cycle spend $${userDollars} is ${ratio.toFixed(1)}x the team median ($${medianDollars}) — model: ${user.most_used_model||"unknown"}, ${user.fast_premium_requests} premium reqs`,
101
+
message: `${user.name}: cycle spend $${userDollars} is ${ratio.toFixed(1)}x the team median ($${medianDollars}), model: ${user.most_used_model||"unknown"}, ${user.fast_premium_requests} premium reqs`,
102
102
detectedAt: now,
103
103
resolvedAt: null,
104
104
alertedAt: null,
@@ -140,7 +140,7 @@ function detectCostPerReqSpikes(
message: `${user.name}: cost/request spiked to $${todayCpr} (${ratio.toFixed(1)}x their avg of $${histCpr}) — using ${user.today_top_model||"unknown"}, $${todaySpend} total today across ${user.today_reqs} reqs`,
143
+
message: `${user.name}: cost/request spiked to $${todayCpr} (${ratio.toFixed(1)}x their avg of $${histCpr}), using ${user.today_top_model||"unknown"}, $${todaySpend} total today across ${user.today_reqs} reqs`,
0 commit comments