company-cfo
Monthly CFO workflow for a company or agency — pull raw data from bank + payment processor + payroll + expense management, categorize and reconcile, compute end-of-month cash via transaction-sum method, update a scenario projector for forward forecasting, write the monthly snapsh
Install
npx skills add https://github.com/coreyhaines31/makerskills/tree/main/skills/company-cfo
claude plugin marketplace add https://llmmart.ai/marketplace.json && claude plugin install coreyhaines31-makerskills@llmmart
git clone https://github.com/coreyhaines31/makerskills.git
The skills CLI installs just this skill, for any of its supported agents. Claude Code installs the whole coreyhaines31/makerskills collection as a plugin from our marketplace. Git is the plain clone.
Skill manifest
/company-cfo — Monthly company CFO workflow
The standing analysis leadership uses to make distribution / cuts / hiring / runway decisions. Primary cadence is monthly (run on the 1st for the closed prior month). Weekly and scenario modes cover the in-between.
Anonymized team-scope sibling to personal-cfo (households). Same discipline (transaction-sum EOM, categorization traps, scenario modeling) applied to company books.
Step 0 — Load company config + prior run
Before starting work, read these in order:
${COMPANY_CFO_ROOT:-$HOME/code/company-cfo}/CLAUDE.md— your company's specific methodology, data source map, categorization rules, distribution mechanics. This is the source of truth for HOW your company computes things. Don't invent your own methodology.- The most recent report in
${COMPANY_CFO_ROOT}/reports/monthly/— last month's snapshot. Tells you what leadership decided + what was open. - The most recent
*-followup.mdin that folder (if one exists) — supplementary decisions, scenario analysis. - Any relevant memory notes in
~/.claude/memory/— running context: known anomalies, leadership constraints, current churn state. git log --oneline -10in${COMPANY_CFO_ROOT}— what's shipped since the last run.
If the COMPANY_CFO_ROOT dir doesn't exist yet: first-run walkthrough asks the user to mkdir it, seed a CLAUDE.md from references/company-config-template.md, and set the env var.
Step 1 — Parse mode
| Invocation | Mode | Cadence |
|---|---|---|
/company-cfo monthly (default) |
monthly | Once per month on the 1st for the closed prior month |
/company-cfo weekly |
weekly | Thin cash pulse — current cash + next 2 weeks of expected flows |
/company-cfo scenario <question> |
scenario | Ad-hoc modeling in the projector |
/company-cfo pickup |
pickup | Resume where the prior run left off (checks git log + last report + open items) |
Below sections walk through monthly in detail. Weekly + scenario are summarized at the end.
Monthly workflow
Ask the user: Which month are we reporting on? (Default: prior calendar month.)
Then walk through these phases. Pause and confirm before moving to the next.
Phase 1 — Pull raw data
For the target month, pull raw data from each source. Standard source categories (each company's actual tools live in their CLAUDE.md):
| Source category | What it gives | Common tools |
|---|---|---|
| Bank / cash accounts | Cash truth, internal vs external transfers, distribution recipients | Mercury CLI, Plaid, direct bank export |
| Payment processor | Revenue, subscriptions, churn, payout timing | Stripe API, Paddle, LemonSqueezy |
| Payroll / contractors | W-2 payroll, contractor pay | Plane, Deel, Gusto, Rippling |
| Expense management | Reimbursements, corporate cards | Ramp, Brex, Divvy |
| Alternative revenue | Non-primary billing sources | Direct invoice tools, alternative payment platforms |
Save all pulls to ${COMPANY_CFO_ROOT}/data/YYYY-MM/<source>-*.json[l] (gitignored — raw data doesn't get committed).
Also pull the current cash balance from the bank source for the "today" starting-cash figure.
If a source isn't wired yet: use /toolify <source> to wire it up before running the CFO workflow. First-time integration is a one-time cost.
Phase 2 — Categorize and reconcile
Bucket all cash-account outflows into the categories your company uses. See references/categorization.md for a starter category set and the discipline of maintaining categorization.
Universal traps to check (see references/traps.md for full list):
- Cash-vs-credit double-count — if the bank shows a "credit card autopay" outflow AND the credit card account shows individual charges, don't count both. Filter to cash accounts only OR treat the CC as a debt account.
- Internal transfers — Checking ↔ Savings transfers net to zero. Exclude them (usually via a
kind=internalTransferfilter or account-pair match). - Currency mismatches — contractor payment tools often return
destination_amountin the worker's payout currency. Always usesource_amount(or equivalent) for USD/base-currency cost analysis. - Distribution counting — if leadership has N partners who should get a monthly distribution, verify N distributions exist. If N-1, flag the missing partner — often one is deferring their draw to balance cash.
Cross-checks before writing the report:
- Total payroll debits in bank ≈ payroll-tool API total + fees (within a small residual for held deductions)
- Payment processor payouts arriving in the month ≈ bank inflows from that processor (within timing lag)
- Expense-management outflows in bank ≈ approved expenses in expense-mgmt tool (with cash-basis lag)
Phase 3 — Compute EOM cash (the transaction-sum method)
Use transaction sums, not the walkback-from-current-balance method. Walkback has bitten CFO workflows repeatedly — a bank API balance snapshot at pull time can be off by tens of thousands, and that error propagates into every historical EOM value.
Correct method (see references/eom-cash-methodology.md for the full recipe):
# 1. Pull ALL transactions for each cash account (Checking + Savings + any other cash-holding):
# <bank-tool> transactions list --account-id <id> --format jsonl --max-items 100000
# 2. Sum the amount field across all transactions in each account.
# 3. The sum should equal that account's CURRENT available_balance exactly.
# (Sanity check — if not, missing data or a pre-history baseline deposit exists.)
# 4. For any past date T: balance_at_T = sum of all transactions posted on or before T
# (plus any pre-history baseline, which should be ~$0 if the sanity check passes).
Cross-check EOM: last month's EOM + this month's net cash change should equal this month's EOM, to the dollar.
If transaction sums don't reconcile with current balance, do not proceed with walkback as fallback. Investigate the gap first — missing pulls (timeout, paging), an unknown account, or a legitimate pre-history baseline.
Phase 4 — Update the scenario projector
Most CFO workflows benefit from a scenario projector — an interactive forecast that projects EOM cash forward N months under adjustable assumptions (revenue growth, expense scenarios, hiring plans, distribution changes).
Common structure (see references/scenario-projector.md for the reference implementation):
- HISTORICAL (trailing 3 closed months) — provides context before TODAY
- TODAY — actual current cash balance (calendar-positioned within current month)
- Mo 1 — current calendar month EOM (partial — remaining-month activity)
- Mo 2-7 — next 6 full calendar month EOMs (scenario settings apply from here)
Each month: starting + revenue − expenses = profit → ending
Intramonth cycle low (for weekly cash pulse relevance): most CFO systems care about the low point of the month (when you might hit a cash floor), not just the high (EOM). Formula depends on payout cadence — see references/scenario-projector.md.
Update the projector each monthly run:
- Append the just-closed month to HISTORICAL with all category fields; drop the oldest.
- Update
startingCashto today's actual bank balance. - Update expense baselines for any category that materially shifted.
- Update
baselineMrr(net of processing fees). - Verify presets still make sense (scenarios may need updating if comp structure or hiring plans changed).
Phase 5 — Write the snapshot report
Create ${COMPANY_CFO_ROOT}/reports/monthly/YYYY-MM.md following the template in references/report-template.md. Sections (adapt as needed):
- TL;DR — headline + status table (net cash, ending balance, current MRR, trailing-N-month, recommendation)
- Cash In — by source (payment processor, alt revenue, one-times)
- Cash Out — by category (matches the projector's category structure)
- Payroll breakdown — verified contractor + W-2 split
- Distributions — who got paid, who didn't (flag anomalies)
- Revenue metrics — active subs, MRR delta, recent cancels with $ and customer
- Forward projection — 1-3 scenarios from the projector (link the projector state)
- Recommended actions — concrete for leadership to decide on
- Open items — questions to resolve next month
Write the why-paragraph in plain English: what happened and why. Reference the previous month if there's continuity ("Vendor X churn from last month finished hitting June payouts").
Phase 6 — Update memory
Update ~/.claude/memory/company_cfo_<company-slug>.md (or wherever your memory system lives) if any of:
- Distribution/comp structure changed
- Active sub count or MRR shifted materially
- New revenue stream (new billing platform)
- New partner / contractor decision
- New cash floor or distribution constraint
Don't bloat the note. Replace stale facts; don't append indefinitely.
Phase 7 — Review and ship
Follow your company's git workflow:
Before the first-ever run, verify .gitignore at the repo root excludes raw exports — Phase 1 dumps sensitive bank / payroll / payment-processor data to data/ and that MUST NOT be committed. If missing, seed it:
cd ${COMPANY_CFO_ROOT}
# Verify .gitignore excludes raw data + secrets
if ! grep -q '^data/' .gitignore 2>/dev/null; then
cat >> .gitignore <<'GITIGNORE'
# Raw financial data — never commit
data/
*.jsonl
*.env
*.env.local
.mcp.json
GITIGNORE
git add .gitignore
git commit -m "Seed .gitignore for raw financial data"
fi
Then ship the report + projector changes ONLY (never git add -A in this repo — targeted adds only, so a stray data/ file can't slip in):
cd ${COMPANY_CFO_ROOT}
git checkout -b feature/YYYY-MM-snapshot
git add reports/monthly/YYYY-MM.md scenarios/index.html CLAUDE.md # targeted
git status --short # verify no data/ or .env files staged
git commit -m "YYYY-MM monthly snapshot"
git push -u origin feature/YYYY-MM-snapshot
gh pr create --base main --title "YYYY-MM monthly snapshot"
Never git add -A in ${COMPANY_CFO_ROOT}. A silent data/ file leak would push bank transaction history + partner distribution ACHs to a git remote. Targeted adds only.
Before merging: run a code review (if applicable) or manually review the diff. Then merge + delete branch.
Weekly cash pulse mode
Thin — designed to fit into a 15-minute weekly sync.
- Pull current cash balance (bank API
accounts list) - Pull last 7 days of transactions + next 7 days of scheduled outflows (payroll, known bills)
- Compute: current cash, next-payroll date + amount, next-Stripe-payout date + amount
- Flag if cash < next 2 weeks of outflows (below cash floor)
- One-line status:
Cash $X | Next payroll $Y on <date> | Next inflow $Z on <date> | Floor status: OK|WATCH|BREACH
Save to ${COMPANY_CFO_ROOT}/reports/weekly/YYYY-WW.md.
Pair with /loopify to schedule the weekly run (typically Monday 9am).
Scenario mode
Ad-hoc — for "what if we hire a $150K/yr engineer in September" or "what if churn ticks up 2%".
Open the scenario projector, adjust the relevant knobs, screenshot or export the resulting cash projection. Save the analysis to ${COMPANY_CFO_ROOT}/reports/scenarios/YYYY-MM-DD-<question-slug>.md.
If the scenario decision is material (new hire, distribution change, big expense), also run /decide to formalize.
Pickup mode
Resume from the prior run. Surface:
- Most recent monthly report (
ls -t ${COMPANY_CFO_ROOT}/reports/monthly/*.md | head -1) - Most recent weekly pulse
- Latest
git logon${COMPANY_CFO_ROOT}(what's shipped since last snapshot) - Memory note for current narrative
- Open items from the last report's §9
Don't assume continuity from training data. Always check the reports + memory + git log first.
Composes with
personal-cfo— sibling. Personal-cfo handles household finances (house math, monthly cash flow, big purchases). Same discipline (transaction-sum method, scenario modeling) applied to different scope.company-brain— the CFO reports get stored + wiki-indexed there.outputs/in the company brain accumulates monthly reports; wiki pages compile trends across months.toolify— wire company-specific data sources (Mercury API, Stripe, Plane, Ramp, or equivalents). First-run integration setup.loopify— schedule the monthly run (1st of month) + weekly cash pulse (Monday 9am).decide— for material decisions surfaced by the report (distribution changes, hiring, cash floor breach response). Formalize with the 37signals framework.deep-research— for benchmark questions ("what's a typical SaaS marketing budget as % of ARR?") that inform scenario inputs.
Notes on quality
- Never invent methodology. Every company computes cash differently — trust the company's
CLAUDE.mdin${COMPANY_CFO_ROOT}. If it's not documented, ask; don't guess. - Transaction-sum method is non-negotiable. Walkback from a balance snapshot has burned CFO workflows repeatedly. Use raw transaction sums, verify against current balance.
- Categorization discipline matters more than accuracy. Same categories every month = trend-readable. Changing categories mid-year = trends become noise.
- Baseline expenses to actuals, not to "safe" estimates. A software line modeled at $8K when actuals run $12K creates optimistic projections that break the model.
- Revenue is net of processing fees, not gross. ~3% Stripe/similar processor fees materially change monthly cash inflow.
- The intramonth cycle low matters more than EOM. With monthly payout cadences, cash dips deep mid-month. Cash floor applies to the LOW, not the EOM HIGH.
- Weekly payouts smooth the cycle dramatically — if your payment processor supports it, switching from monthly to weekly payouts is one of the highest-leverage cash-management moves available. See
references/eom-cash-methodology.md. - When numbers don't reconcile, stop. Don't ship a report with unexplained gaps. Investigate first — a $42K reconciliation gap once propagated silently for weeks before being caught.
When NOT to use this skill
- Ad-hoc single-number lookups ("what's our current cash?") — just query the bank source directly, don't run the full workflow.
- Tax / accounting questions — out of scope; refer to your CPA.
- Personal finance — use
personal-cfoinstead. - Investor pitch financials — different discipline (multi-year projections, unit economics deep dives). This skill covers operational CFO cadence, not fundraising narrative.
Files (makerskills)
-
references
-
categorization.md 4.1 KB
# Categorization discipline Same categories every month = trend-readable. Changing categories mid-year = trends become noise. This file documents a starter category set + the discipline of maintaining it. ## Starter categories for a services or SaaS company Bucket all cash outflows into these categories (adjust once per year, not mid-year): | Category | What counts | |---|---| | **distributions** | ACHs to founder/partner accounts (owner draws, member distributions, W-2 salary if paid through payroll instead of ACH) | | **team** | Payroll debits (contractor + W-2) + payroll platform fees | | **software** | Corporate card autopay (usually dominated by SaaS subscriptions — CRM, dev tools, comms, hosting, analytics) | | **reimbursements** | Expense-management-tool outflows actually paid to team members | | **benefits** | Healthcare, retirement (401k custodian, Vestwell / Guideline / Human Interest), dental, vision, HSA | | **other** | Everything else: rent, professional services (CPA, lawyer, contractor accountant), insurance, events, one-times | Companies with distinct revenue models may need additional categories: | Category (add if relevant) | What counts | |---|---| | **cogs** | Cost of goods sold — for physical or fulfilled products | | **advertising** | Paid channel spend (Meta, Google, LinkedIn, etc.) — separate line item because it varies wildly | | **inventory** | Inventory purchases (physical goods) | | **client-pass-through** | Money that flows through to third parties on client's behalf (freelancer platforms, ad spend billed to client) | ## The discipline **Lock categories for the fiscal year.** Every month uses the same categories, in the same order, with the same definitions. Deviations get flagged in the report's "why" paragraph, not silently moved into a different bucket. **When a new expense type appears**, ask: does it fit an existing category? If yes, bucket it. If no, add a new category — but only at the start of a new fiscal year, or with a documented rationale in the memory note. **Don't over-split.** More categories = more moving lines = harder to read the trend. 6-8 categories is the sweet spot; >12 becomes noise. **Don't over-lump.** If two very different expense types share a bucket, the trend hides real signal. Advertising bucketed into "other" is the classic mistake — ad spend can swing $20-100K month-to-month; hiding it in "other" makes "other" unreadable. ## Cross-checking categorization each month At Phase 2 (categorize and reconcile), run these cross-checks: 1. **Payroll cross-check**: Total payroll debits in bank ≈ payroll-tool API total + platform fees. Should be within ~$1K residual (held deductions, timing lags). 2. **Distribution count**: N partners → N distributions. If N-1, flag the missing partner. Common cause: one partner deferring their draw to preserve cash. 3. **Software vs actuals**: Corporate card autopay total should roughly match your subscribed SaaS bills (from receipts or the card statement). Big deltas mean either a new subscription or a canceled one worth noting. 4. **Category vs prior 3 months**: Is any category materially different from the trailing average? If yes, is there a documented reason? If no, investigate before writing the report. ## The "why" paragraph Every monthly report includes a "why" paragraph explaining what happened this month vs last: > Team costs were up $12K m/m because we onboarded [Role] on the 15th (prorated payroll). Software was flat. Advertising was down $8K because [Campaign] wrapped end of month. Other was up $4K due to Q3 CPA fees hitting. This paragraph is the trend-narrative. Without it, category numbers are just numbers. ## Category evolution Once per year (at fiscal year-end), review: - Are all categories still meaningful? (Merge any that consistently run <$1K/mo into "other") - Are any hidden categories worth surfacing? (Grep "other" for line items >$5K/mo — those may deserve their own category) - Does the ordering still match how leadership reads the report? (Reorder if needed for readability) Document the changes in the memory note + call them out in the first monthly report of the new fiscal year. -
company-config-template.md 4.7 KB
# Company config template Copy this to `${COMPANY_CFO_ROOT}/CLAUDE.md` when seeding a new company's CFO workflow. Fill in placeholders with your actuals. The file becomes the source of truth for HOW your company computes its financials. The `company-cfo` skill reads this first before every run. ## Also seed a `.gitignore` in the repo root Raw financial data (bank transaction dumps, payroll payloads, expense-manager exports) MUST NOT be committed. Before running the CFO workflow for the first time, verify the repo has a `.gitignore` with at minimum: ``` # Raw financial data — never commit data/ *.jsonl *.env *.env.local .mcp.json ``` The `company-cfo` skill's Phase 7 seeds this automatically if missing, but doing it manually at repo setup is safer. --- ```markdown # <Company Name> CFO — methodology + config ## Structure - **Legal form**: <LLC / C-Corp / S-Corp / other> - **Fiscal year**: <calendar / July-June / other> - **Owners / partners / leadership**: <names + roles> - **Number of monthly distributions expected**: <N> - **Cash floor**: $<X>K (below this, defer distributions + review expenses) ## Data sources | Source | Tool | Access | Notes | |---|---|---|---| | Bank / cash | <e.g. Mercury CLI> | `<install> ; <auth>` | Cash accounts to include: <list account labels> | | Payment processor | <e.g. Stripe> | `<key location>` | MRR source of truth | | Alt revenue | <e.g. Paddle, direct invoicing> | <access> | Note: not visible in payment processor | | Payroll (contractors) | <e.g. Plane, Deel> | `<key location>` | Currency: use `source_amount` for base-currency cost | | Payroll (W-2) | <e.g. Gusto, Rippling> | <access> | Includes employer taxes + benefits | | Expense management | <e.g. Ramp, Brex> | `<CLI or API>` | Cash-out timing lives in bank (RMPR / equivalent debits) | ## Cash accounts Filter transactions to these accounts only (exclude credit card / debt / escrow): - Checking ••<last 4> (primary operating) - Savings ••<last 4> (reserves) - <any other cash-holding accounts> Exclude: internal transfers (Checking ↔ Savings), credit card account (debt-side, double-counts autopay flows). ## Categorization | Category | What counts here | |---|---| | **distributions** | ACHs to partner accounts <account digits or names> | | **team** | All payroll debits + payroll platform fees | | **software** | Corporate card autopay (dominated by SaaS) | | **reimbursements** | Expense-management outflows paid to team | | **benefits** | Healthcare, retirement, dental, vision | | **other** | Rent, CPA, insurance, professional services, one-times | Add categories only at fiscal year-end (see `references/categorization.md`). ## Distribution mechanics - **Frequency**: <monthly / quarterly / ad-hoc> - **Formula**: <fixed amount / % of profit / other> - **Recipients**: <named partners + account digits> - **Constraints**: <cash floor, retention buffer, deferrals> ## MRR + revenue - **Primary source**: <Stripe / other> - **Secondary sources**: <alt billing platforms — always include, they're invisible in the primary> - **Processing fee assumption**: ~<X>% (default 3% for Stripe). Report MRR NET of fees, not gross. - **Churn tracking**: <how you track — Stripe events, manual log, other> ## Payroll notes - **Contractor tool**: <tool>. Currency: use `source_amount` for base-currency cost. `destination_amount` is in worker's payout currency (e.g. JPY, EUR, GBP). - **W-2 tool**: <tool>. Includes employer taxes + benefits in the total. - **Held deductions**: expect ~$<X> residual between bank total and payroll tool total. ## Traps documented for this company Add as they're discovered — this list is company-specific muscle memory: - <e.g. "The IO autopay double-counts if we include the credit card account. Cash accounts only."> - <e.g. "Contractor <Name>'s payments come through in JPY. Use source_amount."> - <e.g. "Vendor <Name> revenue is invisible in Stripe. Add from bank inflows manually."> ## Reports - **Monthly**: `reports/monthly/YYYY-MM.md` - **Weekly cash pulse**: `reports/weekly/YYYY-WW.md` - **Scenarios**: `reports/scenarios/YYYY-MM-DD-<question>.md` ## Scenario projector - **Location**: `scenarios/index.html` (served via `scenarios/serve.sh` on port <port>) - **Structure**: 3 historical months + TODAY + 7 forward months - **Update cadence**: end of each monthly run ## Git workflow - Branch pattern: `feature/YYYY-MM-snapshot` - Review: <auto / manual / codex review / other> - Merge: `gh pr merge --squash --delete-branch` ## Memory note Running context lives at `~/.claude/memory/company_cfo_<slug>.md`. Update if: - Distribution/comp structure changes - Active sub count or MRR shifts materially - New revenue stream or new payroll tool - Cash floor changes ``` -
eom-cash-methodology.md 5.2 KB
# End-of-month cash methodology The single most important discipline in the CFO workflow. Getting this wrong once has propagated errors into every downstream chart, forecast, and partner decision. ## The rule **Compute EOM cash by summing raw transactions, not by walking back from a current balance snapshot.** ## Why walkback fails A bank API balance snapshot at pull time reflects a specific instant. That instant might include: - Transactions in-flight but not yet posted (ACH holds, wire receipts pending) - API-cache staleness (some banks serve a 5-15 minute cached value) - Pending-vs-posted delta (Stripe payouts marked available but not yet in the checking account) If your snapshot is off by $X and you walk backward through transactions to reconstruct historical EOMs, every historical EOM is off by exactly $X — silently — and no downstream chart can catch it. This has happened multiple times in production CFO workflows; one incident carried a ~$42K error for weeks before the reconciliation caught it. ## The correct method ```python # 1. Pull ALL transactions for each cash-holding account: # (Checking + Savings + any other bank account that actually holds cash) transactions = fetch_all_transactions(account_id, limit=100000) # 2. Sum the signed amount field across all transactions: transaction_sum = sum(t["amount"] for t in transactions) # 3. Sanity check: transaction_sum should equal the account's CURRENT available_balance # to the cent. If not, one of: # - Missing transactions (paging error, API timeout, filter mistake) # - Pre-history baseline deposit (opening deposit that predates the transaction history) # - Data-source bug (rare but real — file an issue) current_balance = fetch_current_balance(account_id) assert abs(transaction_sum - current_balance) < 0.01, \ f"Transaction sum {transaction_sum} != current balance {current_balance}" # 4. For any past date T: # balance_at_T = sum of all transactions with posted_date <= T # + any pre-history baseline (should be ~$0 if step 3 passes) def balance_at(date, transactions): return sum(t["amount"] for t in transactions if t["posted_date"] <= date) ``` ## Cross-checks Every monthly run: 1. **Sanity check per account** — transaction sum == current balance (to the cent) 2. **Month-over-month reconciliation** — last month's EOM + this month's net cash change == this month's EOM (to the dollar) 3. **Cash accounts only** — filter out credit card / debt accounts. Including a credit card account double-counts autopay flows (charges on the card show, AND the autopay debit from checking shows). 4. **Internal transfers excluded** — Checking ↔ Savings transfers net to zero within the company. Exclude via `kind=internal_transfer` filter or account-pair matching. ## What to do when reconciliation fails **Stop.** Do not proceed with walkback as a fallback. Investigate: 1. **Re-pull transactions with a larger `--max-items`** — pagination silently truncated at a lower limit? 2. **Check for accounts you didn't know about** — a treasury account, a savings bucket, an escrow account? 3. **Look for a pre-history baseline** — the transaction history may not go back to account opening. If the oldest transaction is a $50K "initial deposit," that's your baseline. 4. **Timeout during pull?** — API returned partial data. Retry with a longer timeout or smaller date range. Never silently ship a report with an unreconciled gap. The gap will grow. ## Intramonth cycle low The EOM cash is often the *high* point of the month, not what you have most of the month. Payment processors on monthly payout cadences deposit the entire month's revenue at end-of-month, so mid-month your cash is at the low. Formula depends on payout cadence: - **Monthly payouts (legacy)**: `intramonth_low ≈ EOM − month_revenue` — whole month's inflow lands at EOM, so trough is everything except that lump - **Weekly payouts**: `intramonth_low ≈ EOM − (month_revenue / 4)` — only one week of inflow is "lumpy," rest is smoothed across the month - **Daily payouts** (rare): `intramonth_low ≈ EOM − (month_revenue / 30)` — negligible dip **Switching from monthly to weekly payouts** is one of the highest-leverage cash-management moves available. It cuts the intramonth dip by ~75% and dramatically reduces cash-floor pressure. If your payment processor supports it (Stripe does), the switch takes ~5 minutes in the dashboard. ## The $50K floor (or whatever your floor is) Every company should have a documented cash floor — the minimum cash balance below which leadership takes action (defer distributions, cut expenses, accelerate collections). **The floor applies to the intramonth LOW, not the EOM HIGH.** A company that says "we'll never go below $50K" and only checks EOM is guaranteed to breach mid-month at some point. Weekly cash pulse mode (see main SKILL.md) is designed to catch floor risk before it becomes a floor breach. ## Historical incidents (add yours here) - **The $42K walkback error** — snapshot-based reconstruction was silently off by ~$42K for weeks. Now all EOM computation uses transaction-sum only. Discovered via a month-over-month reconciliation failure. - (Add your own incidents as they happen — the log is the discipline.) -
report-template.md 5.2 KB
# Monthly snapshot report template Copy this template and fill in placeholders. Adapt sections as needed — this is a starting point, not a rigid form. Save to `${COMPANY_CFO_ROOT}/reports/monthly/YYYY-MM.md`. Commit only this file (not the raw data used to generate it). --- ```markdown # <YYYY-MM> Monthly Snapshot **Report date**: <YYYY-MM-DD> **Prepared by**: <who ran the workflow> **Data through**: last day of <MMMM YYYY> --- ## TL;DR | Metric | Value | vs prior month | Status | |---|---|---|---| | Net cash change | ±$X | ±$Y m/m | 🟢 / 🟡 / 🔴 | | Ending balance | $X | ±$Y m/m | (vs floor) | | Current MRR | $X | ±$Y m/m | 🟢 / 🟡 / 🔴 | | Trailing 3-mo avg | $X | | | | Runway (at current burn) | N months | | | **Recommendation**: <1-2 sentences — what leadership should do next month> --- ## Cash In ### By source | Source | Amount | Notes | |---|---|---| | <Payment processor> | $X | <N transactions, avg $Y> | | <Alt revenue source> | $X | <notes> | | One-time inflows | $X | <describe> | | Refunds / chargebacks | -$X | <notes> | | **Total in** | $X | | ### Notable inflows - <one-line item + $X + why it matters> - <another item> --- ## Cash Out ### By category Match the categories defined in your `CLAUDE.md`: | Category | Amount | vs prior month | Notes | |---|---|---|---| | Distributions | $X | ±$Y | <N of N expected partners> | | Team (payroll) | $X | ±$Y | <contractor + W-2 split> | | Software | $X | ±$Y | <corporate card autopay> | | Reimbursements | $X | ±$Y | <expense-mgmt outflows actually paid> | | Benefits | $X | ±$Y | <healthcare + retirement + custodian> | | Other | $X | ±$Y | <rent + CPA + insurance + one-times> | | **Total out** | $X | ±$Y | | ### Notable outflows - <one-line item + $X + why it matters> --- ## Payroll breakdown **Verified against `<payroll tool>` API totals + bank debits.** | Line | Bank total | Payroll API total | Residual | |---|---|---|---| | Contractors (Plane / Deel / etc.) | $X | $X | $X (held deductions) | | W-2 payroll (Gusto / Rippling / etc.) | $X | $X | $X (employer taxes + benefits) | | Payroll platform fees | $X | | | | **Combined** | $X | $X | $X | Currency notes: <e.g., contractor N is JPY, converted at ~150 JPY/USD> --- ## Distributions Expected: <N> partners × 1 distribution each | Partner | Amount | Sent | Received | Notes | |---|---|---|---|---| | <Name> | $X | ✅ | ✅ | | | <Name> | $X | ✅ | ✅ | | | <Name> | $0 | ⏸ | | Deferred to preserve cash (see notes) | Flag anomalies: <e.g., partner N deferred, or partner M received a larger draw as catch-up> --- ## Revenue metrics ### MRR - Current: $X (net of processing fees) - Prior month: $Y - Delta: ±$Z (±W%) ### Active subscriptions - Count: N - Delta: ±M m/m - Avg revenue per customer: $X ### Churn (recent cancels) | Customer | MRR lost | Reason (if known) | Cancel date | |---|---|---|---| | <Name> | $X | <reason> | <YYYY-MM-DD> | | <Name> | $X | | | Churn rate this month: X% (lost / start-of-month active) ### New subs | Customer | MRR added | Sign-up date | Source | |---|---|---|---| | <Name> | $X | <YYYY-MM-DD> | <channel> | --- ## Forward projection Scenarios from `${COMPANY_CFO_ROOT}/scenarios/index.html`: ### Scenario A: Status quo - Mo 3 EOM: $X, low: $Y - Mo 6 EOM: $X, low: $Y - Runway assumption: N months ### Scenario B: <name — e.g., aggressive hire> - Mo 3 EOM: $X, low: $Y - Mo 6 EOM: $X, low: $Y - Trigger: <when to commit to this> ### Scenario C: <name — e.g., churn pessimism> - Mo 3 EOM: $X, low: $Y - Mo 6 EOM: $X, low: $Y - Trigger: <when to worry> --- ## Recommended actions Concrete, tactical, decidable by leadership: 1. <action + owner + deadline> 2. <action + owner + deadline> 3. <action + owner + deadline> --- ## Open items - [ ] <question to resolve next month> - [ ] <data to verify — e.g., reconcile alt revenue source X> - [ ] <categorization to revisit — e.g., how to bucket new AI subscriptions> --- ## Why paragraph (plain English) Explain what happened this month vs last, in continuous prose. Reference prior months when there's continuity ("The <Vendor X> churn from last month finished hitting <this month>'s payouts; hence the MRR dip"). Note anomalies + the story behind them. 2-4 paragraphs is the sweet spot. This is the section leadership actually reads first. ``` --- ## Section adaptations Trim / expand based on your business shape: - **Services company (agency)**: expand "Distributions" — often the largest cash outflow. Add sub-categories for retainer vs one-off vs pass-through. - **SaaS**: expand "Revenue metrics" with cohort retention, LTV, CAC payback if you track those. - **Ecommerce**: add COGS + inventory + advertising as top-level categories (they'll dominate). - **Marketplace**: separate GMV (through your platform) from your take-rate revenue. ## What NOT to include - **Raw bank transaction dumps.** Sensitive. Belongs in `data/` (gitignored), not the report. - **Customer names for churn if the report will be shared broadly.** Anonymize as needed. - **Employee comp specifics.** If the report is shared with a broader team, aggregate to category level; keep individual comp in leadership-sensitivity-tagged sections. - **Forward-looking guarantees.** Projections are estimates, not commitments. Frame accordingly. -
scenario-projector.md 6.7 KB
# Scenario projector — reference implementation An interactive forecast that projects EOM cash forward N months under adjustable assumptions (revenue growth, expense scenarios, hiring plans, distribution changes). Updated monthly during Phase 4 of the standing workflow. Most CFO workflows benefit from having a projector — leadership decisions (hire, distribute, cut) get made against projected scenarios, not just the current month's snapshot. ## Structure Standard chart layout (adopt as-is or adapt to your team's preferences): - **HISTORICAL** — trailing 3 closed months. Provides context before TODAY. - **TODAY** — today's actual cash balance, calendar-positioned within the current month. - **Mo 1** — current calendar month EOM (partial — only remaining-month activity, dominated by the upcoming payment-processor payout). - **Mo 2–7** — next 6 full calendar month EOMs. Scenario settings apply from Mo 2 onward. Rationale: 3 months of history is enough to see trend + spot anomalies; more than 3 crowds the chart. 6-7 months forward is the right forecast horizon for most operational decisions — long enough to catch cliffs, short enough to be reliable. ## Per-month computation For each future month: ``` starting + revenue − expenses = profit ± → ending ``` Where: - `starting` for Mo 1 = TODAY's actual cash (Mo 1's projection starts from today, not from the prior closed-month EOM) - `starting` for Mo 2+ = prior month's EOM (chained forward) - `revenue` = `baselineMrr` * (growth multiplier if applicable) + one-times - `expenses` = sum of per-category baselines under the active scenario ## Intramonth cycle low The EOM cash is often the *high* of the month (payment processor payout just landed). Cash floor checks apply to the LOW, not the HIGH. Formulas by payout cadence (see `eom-cash-methodology.md` for the full derivation): - **Monthly payouts** (legacy): `low ≈ EOM − month_revenue` (whole month's inflow lands at EOM, trough is everything except that lump) - **Weekly payouts**: `low ≈ EOM − (month_revenue / 4)` (one week of inflow is lumpy, rest smoothed) - **Daily payouts** (rare): `low ≈ EOM − (month_revenue / 30)` (negligible dip) Weekly payouts smooth the cycle dramatically. If your processor supports it (Stripe does), switching from monthly to weekly is one of the highest-leverage cash-management moves available. **Mo 1 (current month, partial)** uses a different formula since most outflows may already have fired MTD: ``` mo1_low = starting_cash − mo1_outflow ``` Where `mo1_outflow` is calibrated by run-date: - **Late-month run** (25th+): `mo1_outflow ≈ small drip` — today's cash IS approximately the low - **Early-month run** (1st-3rd): `mo1_outflow ≈ full month's expenses` — significant drop coming - **Mid-month run**: `mo1_outflow ≈ remaining outflows` — pro-rata estimate ## Chart implementation options Three common approaches: ### Option A: Static HTML with hardcoded arrays Simplest. Serve via a lightweight `serve.sh` script (`python3 -m http.server 8765` or similar). Each monthly run edits the `HISTORICAL` array + `startingCash` HTML input default. Scenario adjustments happen via HTML input fields that trigger JS recomputation. Pros: no build step, no framework, no dependencies. Anyone can open the file and tweak numbers in the browser. Cons: no version control on scenario state (you're editing HTML), can drift. ### Option B: React app (Next.js / Vite) More sophisticated. Scenario state in URL params, share links for specific what-if analyses. Pros: version-controllable scenarios, shareable URLs, easier to add features. Cons: build step + deps. ### Option C: Google Sheet For teams that live in spreadsheets already. Sheets → CSV export → chart in the report. Pros: familiar tool, easy for non-technical leadership to interact with. Cons: sync friction, chart quality is lower than custom HTML/React. Most companies land on Option A first + graduate to Option B once the projector becomes a decision-making tool used weekly. ## Monthly projector updates (Phase 4 checklist) 1. **Append the just-closed month** to `HISTORICAL` with ALL category fields: `label`, `cash`, `revenue`, `distributions`, `team`, `software`, `reimbursements`, `benefits`, `other`, `total_out`, `net`. Use `"MMM 'YY EOM"` label format (e.g., `"Jun '26 EOM"`). 2. **Drop the oldest** so `HISTORICAL` stays at 3 entries. 3. **Update `startingCash`** default to today's actual bank balance (cash accounts only, excluding credit card debt). 4. **Update `mo1Inflow`** based on run date: - **Late-month run**: current processor balance + pending (upcoming EOM payout). Divide by 100 if the API returns cents. - **Early-month run**: estimate based on full month's expected MRR + alt revenue. - **Mid-month run**: what's in processor now + pro-rata for remaining days. 5. **Update `mo1Outflow`** based on run date (see intramonth cycle low above). 6. **Update `OPEX_DEFAULTS`** AND matching HTML `value=` attributes for any category that materially shifted from the trailing baseline. 7. **Update `baselineMrr`** — current MRR NET of processing fees (typically ~3%). 8. **Verify presets still make sense**. If comp structure or hiring plans changed, the scenario descriptions and `apply()` handlers may need updating. ## Scenarios worth having Common presets to seed the projector with: - **Status quo** — trailing 3-month averages carry forward. Baseline. - **Aggressive hire** — add a $X/mo team cost starting Mo N. See what runway looks like. - **Distribution cut** — reduce partner distributions by X% for M months. - **Revenue optimism** — MRR grows Y% m/m. - **Revenue pessimism** — Z% churn spike concentrated in Mo 2-3. - **Big client win** — one-time $X inflow in Mo N. - **Big client loss** — MRR drops $X starting Mo N. Every preset should call `resetBaseline()` (or equivalent) first to clear prior state cleanly. ## Tooltip framing per EOM point Use the explicit equation format, not raw "net": ``` starting $X + revenue $Y − expenses $Z = profit ±$P → ending $E ``` For historical months (already happened), drop `starting` (just `revenue − expenses = profit → ending`) since we're showing what landed in the bank that month, not chaining from a prior position. For future months, show the full equation — including which month's ending balance feeds this month's starting. ## Rebuilding after data changes When a monthly close changes (e.g., a late-arriving corrective transaction), the whole HISTORICAL chain needs updating downstream. Rerun Phase 3 (transaction-sum EOM) for the affected months, update HISTORICAL, re-verify month-over-month reconciliation. **Don't patch a single EOM value manually.** Always rerun the transaction sum. Manual patches introduce reconciliation gaps that will silently propagate. -
traps.md 6.5 KB
# CFO workflow traps Universal categorization + reconciliation traps that recur across CFO workflows. Check each every monthly run. ## Cash-vs-credit double-count If your bank shows a monthly "credit card autopay" outflow AND the credit card account shows individual charges, counting both double-counts every SaaS bill. **Fix**: Filter to cash accounts only when computing outflows. Treat the credit card as a debt account (individual charges are visible on the CC statement, but the CC autopay from checking is what actually leaves cash). Alternative: treat the CC individual charges as your source of truth and exclude the autopay from cash outflow analysis. Both work — pick one and lock it. ## Internal transfers Transfers between your own accounts (Checking ↔ Savings, brokerage ↔ checking, subsidiary ↔ parent) net to zero within the company but appear as separate transactions. **Fix**: Filter out `kind=internalTransfer` (or equivalent) OR match by account-pair-and-timestamp OR sum only OUTGOING transactions to accounts you don't own. Common gotcha: sweep accounts (auto-move idle cash to savings for yield) generate internal transfers daily. Include them in the exclusion filter. ## Currency mismatches Contractor payment tools often return `destination_amount` in the worker's payout currency (JPY, EUR, GBP, INR, etc.) — not USD. **Fix**: Always use `source_amount` (or equivalent — different tools name it differently) for base-currency cost analysis. Common tools + right field: - **Plane**: `funding.amount` (USD funding) vs `destination_amount` (worker's local currency) → use `funding.amount` - **Deel**: `source_amount` vs `destination_amount` → use `source_amount` - **Gusto** (US-only): USD everywhere, no ambiguity - **Wise Business**: check the API docs — the naming varies by endpoint ## Distribution count mismatch If N partners should get a monthly distribution and only N-1 appear in the bank data, flag the missing partner. **Common causes**: - One partner is deferring their draw to preserve cash - One partner's ACH bounced or was rejected (rare, but worth catching) - Distribution was routed to a different account than usual (e.g., moving from personal checking to an LLC-owned brokerage) - The payroll platform processed the distribution as a W-2 payment instead of an owner draw (common when there's a comp-structure change mid-month) **Fix**: Ask leadership to confirm — don't guess. The report should note which N-1 distributions occurred + flag the missing one. ## Held deductions residual Total payroll debits in the bank rarely EXACTLY match payroll-tool API totals — there's usually a small residual ($100-$2K) from held deductions: - Retirement contributions held for the 401k custodian - Benefits held for insurance carriers - Tax withholdings held for quarterly payment - Garnishments (rare but real) - Corrections + adjustments applied later **Fix**: Allow ~$1K-$2K residual as normal. Flag anything bigger — that's usually a missed transaction or a categorization bug. ## Cash-basis vs accrual lag (expense management) Expense management tools (Ramp / Brex / Divvy) show WHEN expenses were submitted / approved. Bank shows WHEN reimbursement was PAID OUT. These can lag 1-4 weeks. Reconciliation between expense-mgmt total and bank total will always show a delta. **Fix**: Use **bank** as the source of truth for cash-basis reporting (matches what actually left the account). Use expense-mgmt for spend-by-category reporting (matches spend by category). Note the two in the report — they're different lenses on different questions. ## Payment processor lag Payment processors (Stripe, etc.) charge customers on day X but payout to your bank on day X+2 or later. Monthly Stripe payout cadence lands the whole month's revenue at EOM. **Fix**: For MRR + revenue reporting, use processor API (charges) as source of truth. For cash-in-bank reporting, use bank inflows. They will not match — that's expected — but they should be reconcilable via known payout schedules. ## Missing revenue sources (invisible in primary processor) If you bill through multiple platforms (Stripe + Paddle, Stripe + direct invoicing, Stripe + a marketplace's payment intermediary), the primary processor's MRR is an undercount. **Fix**: Add all revenue sources to your `CLAUDE.md` methodology. Query each independently. Reconcile against bank inflows. Common example: SaaS with a primary Stripe subscription AND a "Mallow-style" secondary invoicing platform. Stripe MRR shows $80K; total revenue from all sources is $95K. Reporting Stripe MRR only understates cash generation. ## Software baseline drift The monthly SaaS bill (dominated by autopay from corporate cards) shifts as tools are added / removed. Model the current baseline, not last year's — a stale baseline creates optimistic cash projections. **Fix**: Every quarter, review the actual last-3-month software autopay average. Update `baselineMrr` and `OPEX_DEFAULTS` in the projector to match. Don't project with a lower software baseline "to be conservative" — the projection is inaccurate. ## Categorization drift mid-year Changing how a category is defined mid-year makes trends unreadable. If June's "software" category includes AI subscriptions but May's didn't, month-over-month software growth is noise. **Fix**: Lock categories at the start of the fiscal year. If a new expense type appears that doesn't fit, add a new category at year-end + document in the memory note. See `categorization.md`. ## Partner comp-structure changes If a partner's W-2 salary decreases by $X and their monthly distribution increases by $X, total comp is unchanged. But the "team" (payroll) line drops and the "distributions" line rises — this WILL show up as a trend break in your monthly charts. **Fix**: Note comp-structure changes in the "why" paragraph. Don't read the team-line drop as a real cost decrease. ## The cash floor applies to the LOW, not the EOM HIGH EOM cash is the cycle HIGH (Stripe payout just landed). Most of the month you're at the intramonth LOW. **Fix**: Weekly cash pulse (weekly mode of this skill) monitors the low. Cash floor checks apply to the low. See `eom-cash-methodology.md` for the intramonth-low formulas by payout cadence. ## Add your own Every CFO workflow discovers company-specific traps over time. Document them in your `${COMPANY_CFO_ROOT}/CLAUDE.md` under a "Traps documented for this company" section. This file is the universal starter; your company's `CLAUDE.md` is where the specific muscle memory lives.
-
-
SKILL.md 15.5 KB
--- name: company-cfo description: Monthly CFO workflow for a company or agency — pull raw data from bank + payment processor + payroll + expense management, categorize and reconcile, compute end-of-month cash via transaction-sum method, update a scenario projector for forward forecasting, write the monthly snapshot report, surface decisions to leadership. Modes — monthly (default; the standing report), weekly (thin cash pulse), scenario (ad-hoc modeling in the projector), pickup (resume where the prior run left off). Anonymized team-scope sibling to personal-cfo (which handles personal household finances). Composes with company-brain (report gets stored + wiki-indexed there), toolify (wire company-specific data sources), loopify (schedule the monthly + weekly runs). Triggers on "/company-cfo," "/cfo," "monthly cash report," "do the CFO snapshot," "CFO monthly," "let's run CFO," "cash projection," "runway forecast," "monthly financials," "cash pulse." metadata: version: 0.1.1 --- # /company-cfo — Monthly company CFO workflow The standing analysis leadership uses to make distribution / cuts / hiring / runway decisions. Primary cadence is **monthly** (run on the 1st for the closed prior month). Weekly and scenario modes cover the in-between. Anonymized team-scope sibling to `personal-cfo` (households). Same discipline (transaction-sum EOM, categorization traps, scenario modeling) applied to company books. ## Step 0 — Load company config + prior run Before starting work, read these in order: 1. **`${COMPANY_CFO_ROOT:-$HOME/code/company-cfo}/CLAUDE.md`** — your company's specific methodology, data source map, categorization rules, distribution mechanics. **This is the source of truth for HOW your company computes things.** Don't invent your own methodology. 2. **The most recent report** in `${COMPANY_CFO_ROOT}/reports/monthly/` — last month's snapshot. Tells you what leadership decided + what was open. 3. **The most recent `*-followup.md`** in that folder (if one exists) — supplementary decisions, scenario analysis. 4. **Any relevant memory notes** in `~/.claude/memory/` — running context: known anomalies, leadership constraints, current churn state. 5. **`git log --oneline -10`** in `${COMPANY_CFO_ROOT}` — what's shipped since the last run. If the `COMPANY_CFO_ROOT` dir doesn't exist yet: first-run walkthrough asks the user to `mkdir` it, seed a `CLAUDE.md` from `references/company-config-template.md`, and set the env var. ## Step 1 — Parse mode | Invocation | Mode | Cadence | |---|---|---| | `/company-cfo monthly` (default) | **monthly** | Once per month on the 1st for the closed prior month | | `/company-cfo weekly` | **weekly** | Thin cash pulse — current cash + next 2 weeks of expected flows | | `/company-cfo scenario <question>` | **scenario** | Ad-hoc modeling in the projector | | `/company-cfo pickup` | **pickup** | Resume where the prior run left off (checks git log + last report + open items) | Below sections walk through **monthly** in detail. Weekly + scenario are summarized at the end. --- ## Monthly workflow Ask the user: **Which month are we reporting on?** (Default: prior calendar month.) Then walk through these phases. Pause and confirm before moving to the next. ### Phase 1 — Pull raw data For the target month, pull raw data from each source. Standard source categories (each company's actual tools live in their `CLAUDE.md`): | Source category | What it gives | Common tools | |---|---|---| | **Bank / cash accounts** | Cash truth, internal vs external transfers, distribution recipients | Mercury CLI, Plaid, direct bank export | | **Payment processor** | Revenue, subscriptions, churn, payout timing | Stripe API, Paddle, LemonSqueezy | | **Payroll / contractors** | W-2 payroll, contractor pay | Plane, Deel, Gusto, Rippling | | **Expense management** | Reimbursements, corporate cards | Ramp, Brex, Divvy | | **Alternative revenue** | Non-primary billing sources | Direct invoice tools, alternative payment platforms | Save all pulls to `${COMPANY_CFO_ROOT}/data/YYYY-MM/<source>-*.json[l]` (gitignored — raw data doesn't get committed). Also pull the **current cash balance** from the bank source for the "today" starting-cash figure. **If a source isn't wired yet:** use `/toolify <source>` to wire it up before running the CFO workflow. First-time integration is a one-time cost. ### Phase 2 — Categorize and reconcile Bucket all cash-account outflows into the categories your company uses. See `references/categorization.md` for a starter category set and the discipline of maintaining categorization. **Universal traps to check** (see `references/traps.md` for full list): - **Cash-vs-credit double-count** — if the bank shows a "credit card autopay" outflow AND the credit card account shows individual charges, don't count both. Filter to cash accounts only OR treat the CC as a debt account. - **Internal transfers** — Checking ↔ Savings transfers net to zero. Exclude them (usually via a `kind=internalTransfer` filter or account-pair match). - **Currency mismatches** — contractor payment tools often return `destination_amount` in the worker's payout currency. Always use `source_amount` (or equivalent) for USD/base-currency cost analysis. - **Distribution counting** — if leadership has N partners who should get a monthly distribution, verify N distributions exist. If N-1, flag the missing partner — often one is deferring their draw to balance cash. Cross-checks before writing the report: - Total payroll debits in bank ≈ payroll-tool API total + fees (within a small residual for held deductions) - Payment processor payouts arriving in the month ≈ bank inflows from that processor (within timing lag) - Expense-management outflows in bank ≈ approved expenses in expense-mgmt tool (with cash-basis lag) ### Phase 3 — Compute EOM cash (the transaction-sum method) **Use transaction sums, not the walkback-from-current-balance method.** Walkback has bitten CFO workflows repeatedly — a bank API balance snapshot at pull time can be off by tens of thousands, and that error propagates into every historical EOM value. Correct method (see `references/eom-cash-methodology.md` for the full recipe): ```python # 1. Pull ALL transactions for each cash account (Checking + Savings + any other cash-holding): # <bank-tool> transactions list --account-id <id> --format jsonl --max-items 100000 # 2. Sum the amount field across all transactions in each account. # 3. The sum should equal that account's CURRENT available_balance exactly. # (Sanity check — if not, missing data or a pre-history baseline deposit exists.) # 4. For any past date T: balance_at_T = sum of all transactions posted on or before T # (plus any pre-history baseline, which should be ~$0 if the sanity check passes). ``` Cross-check EOM: last month's EOM + this month's net cash change should equal this month's EOM, to the dollar. If transaction sums don't reconcile with current balance, **do not proceed** with walkback as fallback. Investigate the gap first — missing pulls (timeout, paging), an unknown account, or a legitimate pre-history baseline. ### Phase 4 — Update the scenario projector Most CFO workflows benefit from a scenario projector — an interactive forecast that projects EOM cash forward N months under adjustable assumptions (revenue growth, expense scenarios, hiring plans, distribution changes). Common structure (see `references/scenario-projector.md` for the reference implementation): - **HISTORICAL** (trailing 3 closed months) — provides context before TODAY - **TODAY** — actual current cash balance (calendar-positioned within current month) - **Mo 1** — current calendar month EOM (partial — remaining-month activity) - **Mo 2-7** — next 6 full calendar month EOMs (scenario settings apply from here) Each month: `starting + revenue − expenses = profit → ending` **Intramonth cycle low** (for weekly cash pulse relevance): most CFO systems care about the *low* point of the month (when you might hit a cash floor), not just the high (EOM). Formula depends on payout cadence — see `references/scenario-projector.md`. **Update the projector each monthly run:** 1. Append the just-closed month to HISTORICAL with all category fields; drop the oldest. 2. Update `startingCash` to today's actual bank balance. 3. Update expense baselines for any category that materially shifted. 4. Update `baselineMrr` (net of processing fees). 5. Verify presets still make sense (scenarios may need updating if comp structure or hiring plans changed). ### Phase 5 — Write the snapshot report Create `${COMPANY_CFO_ROOT}/reports/monthly/YYYY-MM.md` following the template in `references/report-template.md`. Sections (adapt as needed): 1. **TL;DR** — headline + status table (net cash, ending balance, current MRR, trailing-N-month, recommendation) 2. **Cash In** — by source (payment processor, alt revenue, one-times) 3. **Cash Out** — by category (matches the projector's category structure) 4. **Payroll breakdown** — verified contractor + W-2 split 5. **Distributions** — who got paid, who didn't (flag anomalies) 6. **Revenue metrics** — active subs, MRR delta, recent cancels with $ and customer 7. **Forward projection** — 1-3 scenarios from the projector (link the projector state) 8. **Recommended actions** — concrete for leadership to decide on 9. **Open items** — questions to resolve next month Write the why-paragraph in plain English: what happened and why. Reference the previous month if there's continuity ("Vendor X churn from last month finished hitting June payouts"). ### Phase 6 — Update memory Update `~/.claude/memory/company_cfo_<company-slug>.md` (or wherever your memory system lives) if any of: - Distribution/comp structure changed - Active sub count or MRR shifted materially - New revenue stream (new billing platform) - New partner / contractor decision - New cash floor or distribution constraint Don't bloat the note. Replace stale facts; don't append indefinitely. ### Phase 7 — Review and ship Follow your company's git workflow: Before the first-ever run, verify `.gitignore` at the repo root excludes raw exports — Phase 1 dumps sensitive bank / payroll / payment-processor data to `data/` and that MUST NOT be committed. If missing, seed it: ```bash cd ${COMPANY_CFO_ROOT} # Verify .gitignore excludes raw data + secrets if ! grep -q '^data/' .gitignore 2>/dev/null; then cat >> .gitignore <<'GITIGNORE' # Raw financial data — never commit data/ *.jsonl *.env *.env.local .mcp.json GITIGNORE git add .gitignore git commit -m "Seed .gitignore for raw financial data" fi ``` Then ship the report + projector changes ONLY (never `git add -A` in this repo — targeted adds only, so a stray `data/` file can't slip in): ```bash cd ${COMPANY_CFO_ROOT} git checkout -b feature/YYYY-MM-snapshot git add reports/monthly/YYYY-MM.md scenarios/index.html CLAUDE.md # targeted git status --short # verify no data/ or .env files staged git commit -m "YYYY-MM monthly snapshot" git push -u origin feature/YYYY-MM-snapshot gh pr create --base main --title "YYYY-MM monthly snapshot" ``` **Never `git add -A` in `${COMPANY_CFO_ROOT}`.** A silent `data/` file leak would push bank transaction history + partner distribution ACHs to a git remote. Targeted adds only. Before merging: run a code review (if applicable) or manually review the diff. Then merge + delete branch. --- ## Weekly cash pulse mode Thin — designed to fit into a 15-minute weekly sync. 1. Pull current cash balance (bank API `accounts list`) 2. Pull last 7 days of transactions + next 7 days of scheduled outflows (payroll, known bills) 3. Compute: current cash, next-payroll date + amount, next-Stripe-payout date + amount 4. Flag if cash < next 2 weeks of outflows (below cash floor) 5. One-line status: `Cash $X | Next payroll $Y on <date> | Next inflow $Z on <date> | Floor status: OK|WATCH|BREACH` Save to `${COMPANY_CFO_ROOT}/reports/weekly/YYYY-WW.md`. Pair with `/loopify` to schedule the weekly run (typically Monday 9am). ## Scenario mode Ad-hoc — for "what if we hire a $150K/yr engineer in September" or "what if churn ticks up 2%". Open the scenario projector, adjust the relevant knobs, screenshot or export the resulting cash projection. Save the analysis to `${COMPANY_CFO_ROOT}/reports/scenarios/YYYY-MM-DD-<question-slug>.md`. If the scenario decision is material (new hire, distribution change, big expense), also run `/decide` to formalize. ## Pickup mode Resume from the prior run. Surface: 1. Most recent monthly report (`ls -t ${COMPANY_CFO_ROOT}/reports/monthly/*.md | head -1`) 2. Most recent weekly pulse 3. Latest `git log` on `${COMPANY_CFO_ROOT}` (what's shipped since last snapshot) 4. Memory note for current narrative 5. Open items from the last report's §9 **Don't assume continuity from training data.** Always check the reports + memory + git log first. ## Composes with - **`personal-cfo`** — sibling. Personal-cfo handles household finances (house math, monthly cash flow, big purchases). Same discipline (transaction-sum method, scenario modeling) applied to different scope. - **`company-brain`** — the CFO reports get stored + wiki-indexed there. `outputs/` in the company brain accumulates monthly reports; wiki pages compile trends across months. - **`toolify`** — wire company-specific data sources (Mercury API, Stripe, Plane, Ramp, or equivalents). First-run integration setup. - **`loopify`** — schedule the monthly run (1st of month) + weekly cash pulse (Monday 9am). - **`decide`** — for material decisions surfaced by the report (distribution changes, hiring, cash floor breach response). Formalize with the 37signals framework. - **`deep-research`** — for benchmark questions ("what's a typical SaaS marketing budget as % of ARR?") that inform scenario inputs. ## Notes on quality - **Never invent methodology.** Every company computes cash differently — trust the company's `CLAUDE.md` in `${COMPANY_CFO_ROOT}`. If it's not documented, ask; don't guess. - **Transaction-sum method is non-negotiable.** Walkback from a balance snapshot has burned CFO workflows repeatedly. Use raw transaction sums, verify against current balance. - **Categorization discipline matters more than accuracy.** Same categories every month = trend-readable. Changing categories mid-year = trends become noise. - **Baseline expenses to actuals, not to "safe" estimates.** A software line modeled at $8K when actuals run $12K creates optimistic projections that break the model. - **Revenue is net of processing fees, not gross.** ~3% Stripe/similar processor fees materially change monthly cash inflow. - **The intramonth cycle low matters more than EOM.** With monthly payout cadences, cash dips deep mid-month. Cash floor applies to the LOW, not the EOM HIGH. - **Weekly payouts smooth the cycle dramatically** — if your payment processor supports it, switching from monthly to weekly payouts is one of the highest-leverage cash-management moves available. See `references/eom-cash-methodology.md`. - **When numbers don't reconcile, stop.** Don't ship a report with unexplained gaps. Investigate first — a $42K reconciliation gap once propagated silently for weeks before being caught. ## When NOT to use this skill - **Ad-hoc single-number lookups** ("what's our current cash?") — just query the bank source directly, don't run the full workflow. - **Tax / accounting questions** — out of scope; refer to your CPA. - **Personal finance** — use `personal-cfo` instead. - **Investor pitch financials** — different discipline (multi-year projections, unit economics deep dives). This skill covers operational CFO cadence, not fundraising narrative.
Comments (0)
Sign in to join the conversation.
Reviews (0)
No reviews yet.
No comments yet.