I quoted $2,400 in monthly recurring revenue four times this morning before I checked.
The first time was in a casual status update to myself. "VT is at $2,400 MRR with three active clients." Second time, drafting a cold email — I almost referenced "two-thirds of our current MRR" as a credibility marker. Third time, writing a blog post about traction, I wrote "we're at $2,400 a month and growing." Fourth time, when I finally pulled Stripe to verify a payment for an entirely different purpose, I saw the actual dashboard.
Zero billable MRR.
Zero paying customers.
One lifetime invoice for $640, paid March 25 by a friend who runs a home care agency and was being patient with me.
Two self-test subscriptions I'd opened against my own email at $0 billed, which any decent revenue calculator would filter out — except I didn't have a revenue calculator. I had a markdown file.
Where the Number Came From
I traced it back. It originated in a project status file dated March 27, two weeks before I caught it. The line read:
Current MRR: $2,400 (3 clients × varying rates)
I wrote that line on March 27. On March 27, here's what I actually had in Stripe: a single $640 invoice from Beyond Care HC, paid two days earlier. That's it. No subscriptions. No recurring anything. The "$2,400" was a back-of-the-envelope projection of what three retainers I was talking to would pay if they all converted. I wrote it in present tense because at the time it felt close enough to true to skip the verb tense.
Then I copied that file into the morning brief template. The morning brief became a daily artifact. The daily artifact got referenced in the weekly report. The weekly report got referenced in the README of the outreach repo. The README got referenced by the CEO OS prompt. The CEO OS prompt got loaded into the agent every session. The agent confidently quoted "$2,400 MRR" in every brief, every standup, every internal note, for fourteen days.
I never re-checked the source. The source was me, and I'd already moved on.
The Six Files
When I started cleaning it up, I grepped my entire workspace for 2,400 and found six occurrences:
vibetokens/OPS.md
vt-outreach/CLAUDE.md
vt-outreach/README.md
project-status/vibetokens.md
~/.claude/projects/.../memory/project_vt_ceo_os.md
~/.claude/projects/.../memory/MEMORY.md
Six files, all referencing the same fabricated number, written in slightly different phrasing so they didn't look like copies of each other. "$2,400 MRR. 3 clients × varying rates." "~$2,400 MRR (3 clients)." "Current MRR: $2,400 split across three retainers." Each one looked like an independent confirmation of the others. None of them was. They were all the same dead letter, repeated in different rooms of the same house.
This is the part I want to dwell on for a second. The reason this worked is that prose feels like evidence. A number sitting inside a paragraph that talks about clients × varying rates and split across three retainers sounds like it came from somewhere. It sounds like someone bothered to break it down. It sounds like accounting. But the only thing it actually came from was me, on March 27, in present tense, optimistic.
Every time the agent loaded the brief, it was loading my optimism from two weeks ago and treating it as ground truth.
What the Script Looks Like
The fix took twenty minutes. It lives at C:/Users/jason/bin/vt-revenue.mjs and it does exactly one thing: hit the Stripe API, list active subscriptions, list paid invoices, filter out anything where the customer email is jasonmatthewmurphy@gmail.com (my self-test subs), and print:
VT Revenue — 2026-04-10T15:19:26 [LIVE]
────────────────────────────────────────────────────────────
Billable MRR: $0.00
Billable active custs: 0
Self-test subs (ignored):2
Trialing: 0
Past due: 0
Lifetime paid: $640.00 (1 invoices)
That's it. No markdown templating, no graph, no narrative. Just the number Stripe says is true, formatted so I can't misread it.
I run it now before I write any sentence that contains a dollar sign. It takes 800ms. There is no excuse not to.
The Rule That Closes the Loop
Building a script that tells the truth doesn't matter if I forget to run it. So I added a rule to my global agent instructions — the file the agent loads at the top of every session.
Revenue comes from Stripe. Never cite MRR, ARR, paying customer count, or any dollar figure from a local file. Run
vt-revenuebefore stating any number.
This is short on purpose. Long rules get skimmed. Short rules get followed.
I also added a parallel rule for the audit pipeline itself, because the same pattern applies — the agent was trusting whatever the modules produced, and the modules were sometimes wrong, and there was no gate between the modules said it and the customer received it. I wrote about that one yesterday in I Audited My Own Audit Funnel. Same shape of failure: trusted source, no verification, broken output.
The Pattern
I want to name the pattern, because if I don't I'll repeat it.
Narrative drift. A number gets written into a doc. The doc gets read. The number gets re-read in context every time the doc is loaded. The number is now "in the system" even though it lives in plain text and has never been verified. Other docs reference it. Agents quote it. Decisions get made downstream of it. The longer it stays, the more anchored it gets. By week two, the number is load-bearing — projects depend on it, conversations open with it, and removing it feels like a correction even though it should feel like a rounding error.
The fix isn't discipline. The fix is removing the doc as a source. If a number can't be regenerated from a script, it's not a number — it's a story. If a status file says you have $2,400 MRR, that's a story you told yourself. If vt-revenue says you have $0 MRR, that's the number.
I'm now treating every number that lives in a markdown file as suspicious by default. If I can't replace it with a script invocation, I delete it.
Stable vs. Volatile
The deeper rule underneath all of this: notes are for things that don't change behind your back. Decisions you've made. Rules you've learned. People you know. Architectural choices you want to remember. Those things are stable — the note ages gracefully and the note is authoritative.
Volatile state ages poisonously. The older the cache, the more confident it feels and the more wrong it is. Revenue, calendar, email, deploy status, inventory — anything that changes without you editing it — doesn't belong in a note. It belongs in a live query against its source of truth, and every time you're about to state it, you run the query first.
I'd been running a business that existed in my notes. The business that actually existed on Stripe was getting very little of my attention because I thought it was a different, larger business. The real cost of the $2,400 fiction wasn't in dollars — it was in mental clarity, which is the most expensive thing a founder has. You can't solve the right problem when the picture in your head is wrong.
What I'm Doing About It Tomorrow
Two things.
First, I'm writing a generalized version of vt-revenue that takes a project name and pulls the equivalent number from whatever the relevant source is — Stripe for VibeTokens, Toptal's invoicing for Toptal work, my time tracker for hours spent. Anywhere I quote a metric, the metric should come from a script. The doc should reference the script, not the value.
Second, I'm grepping every status file in my workspace for dollar signs and replacing the cached values with script references. MRR: $0 becomes MRR: see vt-revenue. The doc loses the appearance of authority. Good. It should never have had it.
If you're a founder reading this and you can quote your MRR off the top of your head without checking the source — go check the source right now. I'll wait. The number you remember is the number from the last time you wrote it down. The number on the dashboard is the one that's actually true. Those are not always the same number, and the gap is where every story I've ever told myself about traction lives.
Run the audit on your own dashboard. The free version is at vibetokens.io/start — it'll take about two minutes and it'll show you what your business looks like to the systems your customers actually use. The integrity gate is live before any new traffic hits the funnel, so what you get back is real.
The number you can run is the number you can trust.
— Jason Murphy, VibeTokens
