Customer health score
@usagemetrics/customer-health-score
Score customer health from usage, support, and billing signals with weights you can read and edit. Bands every account green, yellow, or red, names the top drivers, tracks change since the last score, and flags at-risk accounts renewing soon. Works from one CSV.
- Activity
- New: be the first to try it
- Installs
- 0 installs
- Likes
- 0 likes
- Clones
- 0 clones
- 1{
- 2 "name": "customer-health-score",
- 3 "owner": "usagemetrics",
- 4 "version": "1.0.0",
- 5 "type": "skill",
- 6 "description": "Score customer health from usage, support, and billing signals with weights you can read and edit. Bands every account green, yellow, or red, names the top drivers, tracks change since the last score, and flags at-risk accounts renewing soon. Works from one CSV.",
- 7 "category": "data",
- 8 "license": "MIT",
- 9 "compat": ["claude-code"],
- 10 "permissions": {
- 11 "shell": ["node scripts/health.mjs"],
- 12 "files": { "read": ["./data/**"], "write": ["./data/health-weights.json", "./out/health*"] }
- 13 },
- 14 "tests": {
- 15 "cases": [
- 16 {
- 17 "name": "scores and bands the example accounts",
- 18 "inputs": {},
- 19 "checks": [
- 20 { "type": "command_exits_zero", "command": "node scripts/health.mjs examples/accounts.csv --weights examples/weights.json --as-of 2026-11-01 --out out/health" },
- 21 { "type": "file_exists", "path": "out/health.csv" },
- 22 { "type": "file_contains", "path": "out/health.md", "text": "| **Bluebird Labs** | 25 red | -39 |" },
- 23 {
- 24 "type": "output_matches_schema",
- 25 "path": "out/health.json",
- 26 "schema": {
- 27 "type": "object",
- 28 "required": ["bands", "priority", "accounts"],
- 29 "properties": {
- 30 "bands": {
- 31 "type": "object",
- 32 "properties": {
- 33 "green": { "type": "object", "properties": { "accounts": { "const": 5 } } },
- 34 "yellow": { "type": "object", "properties": { "accounts": { "const": 3 } } },
- 35 "red": { "type": "object", "properties": { "accounts": { "const": 2 }, "arr": { "const": 50400 } } },
- 36 "unknown": { "type": "object", "properties": { "accounts": { "const": 1 } } }
- 37 }
- 38 },
- 39 "priority": { "const": ["acct-002", "acct-006", "acct-008"] },
- 40 "low_coverage": { "const": ["acct-011"] }
- 41 }
- 42 }
- 43 }
- 44 ]
- 45 },
- 46 {
- 47 "name": "scales each signal between bad and good and clamps",
- 48 "inputs": {
- 49 "data/accounts.csv": "account_id,seat_utilization,days_past_due\na,0.55,0\nb,1.2,90\n",
- 50 "data/health-weights.json": "{\"signals\":[{\"column\":\"seat_utilization\",\"weight\":50,\"bad\":0.3,\"good\":0.8},{\"column\":\"days_past_due\",\"weight\":50,\"bad\":45,\"good\":0}]}"
- 51 },
- 52 "checks": [
- 53 { "type": "command_exits_zero", "command": "node scripts/health.mjs data/accounts.csv --weights data/health-weights.json --as-of 2026-11-01 --out out/health" },
- 54 {
- 55 "type": "output_matches_schema",
- 56 "path": "out/health.json",
- 57 "schema": {
- 58 "type": "object",
- 59 "properties": {
- 60 "accounts": {
- 61 "type": "array",
- 62 "minItems": 2,
- 63 "maxItems": 2,
- 64 "items": { "type": "object", "properties": { "score": { "enum": [75, 50] }, "band": { "enum": ["green", "yellow"] } } }
- 65 }
- 66 }
- 67 }
- 68 }
- 69 ]
- 70 }
- 71 ]
- 72 }
- 73}
