Skip to content
SlashClone
Made by@ledgerly

Arr waterfall

@ledgerly/arr-waterfall

Turn a monthly subscriptions export into an ARR waterfall: starting ARR, new, reactivation, expansion, contraction, churn, ending ARR, plus NRR and GRR. Writes markdown, CSV, and a per-customer movements file. Works offline from a CSV.

SkillFinancev1.0.0 (latest)Tested
Activity
New: be the first to try it
  1. 1{
  2. 2 "name": "arr-waterfall",
  3. 3 "owner": "ledgerly",
  4. 4 "version": "1.0.0",
  5. 5 "type": "skill",
  6. 6 "description": "Turn a monthly subscriptions export into an ARR waterfall: starting ARR, new, reactivation, expansion, contraction, churn, ending ARR, plus NRR and GRR. Writes markdown, CSV, and a per-customer movements file. Works offline from a CSV.",
  7. 7 "category": "finance",
  8. 8 "license": "MIT",
  9. 9 "compat": ["claude-code"],
  10. 10 "permissions": {
  11. 11 "shell": ["node scripts/arr-waterfall.mjs"],
  12. 12 "files": { "read": ["./data/**"], "write": ["./out/arr-waterfall*"] }
  13. 13 },
  14. 14 "tests": {
  15. 15 "cases": [
  16. 16 {
  17. 17 "name": "builds the waterfall and cohort NRR from the example export",
  18. 18 "inputs": {},
  19. 19 "checks": [
  20. 20 { "type": "command_exits_zero", "command": "node scripts/arr-waterfall.mjs examples/subscriptions.csv --out out/arr-waterfall" },
  21. 21 { "type": "file_exists", "path": "out/arr-waterfall.csv" },
  22. 22 { "type": "file_contains", "path": "out/arr-waterfall.md", "text": "Ending ARR $183,600" },
  23. 23 {
  24. 24 "type": "output_matches_schema",
  25. 25 "path": "out/arr-waterfall.json",
  26. 26 "schema": {
  27. 27 "type": "object",
  28. 28 "required": ["totals", "period_cohort", "months", "unreconciled_months"],
  29. 29 "properties": {
  30. 30 "totals": {
  31. 31 "type": "object",
  32. 32 "properties": {
  33. 33 "starting_arr": { "const": 153600 },
  34. 34 "new": { "const": 51600 },
  35. 35 "reactivation": { "const": 8400 },
  36. 36 "expansion": { "const": 14400 },
  37. 37 "contraction": { "const": 8400 },
  38. 38 "churn": { "const": 36000 },
  39. 39 "ending_arr": { "const": 183600 }
  40. 40 }
  41. 41 },
  42. 42 "period_cohort": {
  43. 43 "type": "object",
  44. 44 "properties": { "nrr": { "const": 0.8438 }, "grr": { "const": 0.75 } }
  45. 45 },
  46. 46 "months": { "type": "array", "minItems": 5, "maxItems": 5 },
  47. 47 "unreconciled_months": { "type": "array", "maxItems": 0 }
  48. 48 }
  49. 49 }
  50. 50 }
  51. 51 ]
  52. 52 },
  53. 53 {
  54. 54 "name": "accepts an arr column and sums duplicate rows",
  55. 55 "inputs": {
  56. 56 "data/subs.csv": "month,customer_id,arr\n2026-01,a,12000\n2026-01,a,6000\n2026-01,b,10000\n2026-02,a,24000\n2026-02,c,5000\n"
  57. 57 },
  58. 58 "checks": [
  59. 59 { "type": "command_exits_zero", "command": "node scripts/arr-waterfall.mjs data/subs.csv --out out/arr-waterfall" },
  60. 60 {
  61. 61 "type": "output_matches_schema",
  62. 62 "path": "out/arr-waterfall.json",
  63. 63 "schema": {
  64. 64 "type": "object",
  65. 65 "properties": {
  66. 66 "totals": {
  67. 67 "type": "object",
  68. 68 "properties": {
  69. 69 "starting_arr": { "const": 28000 },
  70. 70 "new": { "const": 5000 },
  71. 71 "expansion": { "const": 6000 },
  72. 72 "churn": { "const": 10000 },
  73. 73 "ending_arr": { "const": 29000 }
  74. 74 }
  75. 75 }
  76. 76 }
  77. 77 }
  78. 78 }
  79. 79 ]
  80. 80 }
  81. 81 ]
  82. 82 }