# Budget Variance Commentary

> Compare actual to budget by department and account, apply absolute and percentage materiality thresholds, classify each material variance as volume, timing, or permanent where the data supports it, and draft reviewable commentary for the…

Budget Variance Commentary is an AI skill that you can use in Claude Code, Codex, or type.com.

- Skill page: https://typestaging.com/library/skills/budget-variance-commentary
- Raw SKILL.md: https://typestaging.com/library/skills/budget-variance-commentary/SKILL.md
- Created by the type.com team
- Updated: September 24, 2026
- Package: 7 files

## How to use Budget Variance Commentary

1. **type.com:** Choose Use Skill to add Budget Variance Commentary to your type.com workspace.
2. **Claude Code:** Download the skill and extract it into ~/.claude/skills/budget-variance-commentary/ (or .claude/skills/budget-variance-commentary/ in a project). Then ask Claude to use Budget Variance Commentary.
3. **Codex:** Download the skill and extract it into ~/.agents/skills/budget-variance-commentary/ (or .agents/skills/budget-variance-commentary/ in a repository). Then ask Codex to use Budget Variance Commentary.

## Frequently asked questions

### What is Budget Variance Commentary?

Budget Variance Commentary is an AI skill that you can use in Claude Code, Codex, or type.com.

### What does Budget Variance Commentary do?

Compare actual to budget by department and account, apply absolute and percentage materiality thresholds, classify each material variance as volume, timing, or permanent where the data supports it, and draft reviewable commentary for the…

### Can I use Budget Variance Commentary in Claude Code or Codex?

Yes. Budget Variance Commentary is a standard Agent Skills folder with a SKILL.md file. Download it and extract it into ~/.claude/skills/ for Claude Code or ~/.agents/skills/ for Codex.

### Who created Budget Variance Commentary?

The type.com team created Budget Variance Commentary. The type.com team reviews every skill before it is published in the Skills Library.

## Example output

Example output from a sample run. Company names and figures are sample data.

```markdown
## Budget variance and commentary: August 2026, as of 2026-08-31

**Verdict: ties to the P&L.** Operating income is -93,420.00 against budget (-17.1%). 11 material lines drive -122,800.00 of that, offset by 29,380.00 from immaterial lines, and both reconciliation residuals are 0.00.

| P&L line | Actual | Budget | Variance | Var % |
| --- | ---: | ---: | ---: | ---: |
| Revenue | 524,800.00 | 522,000.00 | 2,800.00 | 0.5% |
| Cost of revenue | 95,320.00 | 81,100.00 | 14,220.00 | 17.5% |
| Operating expenses | 1,069,000.00 | 987,000.00 | 82,000.00 | 8.3% |
| Operating income | -639,520.00 | -546,100.00 | -93,420.00 | -17.1% |

| Material line | Variance | Var % | F/U | Class | To confirm |
| --- | ---: | ---: | --- | --- | --- |
| Marketing 6200 Paid media | 33,400.00 | 35.2% | U | volume | R. Okafor |
| Marketing 6210 Events and sponsorships | -33,000.00 | -73.3% | F | timing | R. Okafor |
| G&A 6810 Professional fees | 23,000.00 | 127.8% | U | timing | P. Raman |
| Sales 6000 Salaries and commissions | 17,400.00 | 10.5% | U | volume | S. Marchetti |
| Engineering 6410 Contractors | 16,500.00 | 58.9% | U | timing | T. Weber |
| Revenue 4100 Professional services revenue | -13,500.00 | -26.0% | U | unclassified | D. Alvarez |
| Cost of Revenue 5000 Hosting and infrastructure | 13,400.00 | 23.1% | U | permanent | M. Lin |
| G&A 6840 Bad debt expense | 12,400.00 | n/m | U | permanent | P. Raman |

…plus 3 more material lines in the full report. Classification mix: volume 2, timing 4, permanent 3, unclassified 2.

**Draft commentary, Paid media:** volume-driven. Marketing qualified leads were 4,280 vs 3,100 plan (38.1%). At plan rate that is 36,161.29 of the variance, leaving -2,761.29 of rate/mix.

**Next actions**
- **Hosting and infrastructure, Bad debt expense:** reforecast the remaining periods at the new level.
- **Professional services revenue, Customer education:** don't assert timing or run rate in the pack until the cause is confirmed.
- **Paid media, Sales salaries and commissions:** hold the plan rate and flex the forecast with volume.
- **Timing lines:** confirm the phasing with each budget owner. No change to the full-year expectation is implied.
- A P&L control total that disagrees with the detail fails the check: "DOES NOT TIE: control residual -13,420.00", exit status 1.

**Inputs:** 22 lines across 7 departments. Material means |variance| >= 5,000.00 and |variance %| >= 10.0%, with a control operating variance of -93,420.00.

_Produced by running `bash examples/run.sh` on the sample data bundled with this skill._
```

## Package files

- DATA_CONTRACT.md
- SKILL.md
- examples/august_actuals.csv
- examples/broken_actuals.csv
- examples/expected_output.txt
- examples/run.sh
- scripts/variance_commentary.py

## SKILL.md

````markdown
---
name: budget-variance-commentary
description: Compare actual to budget by department and account, apply absolute and percentage materiality thresholds, classify each material variance as volume, timing, or permanent where the data supports it, and draft reviewable commentary for the material lines only.
---

# Budget variance commentary

The monthly "why is marketing over?" exercise, done consistently. It applies
your materiality policy rather than eyeballing the big numbers, classifies each
material variance from evidence in the file, and drafts the sentence a budget
owner will edit rather than a blank box they will ignore.

## Before you run

This skill ships scripts and sample data alongside this SKILL.md. Before running any command:

1. **Get the files.** Make sure the skill's other files (`scripts/`, `examples/` and anything else listed with this skill) are in your working folder at the same relative paths. Some environments load only SKILL.md; if yours did, fetch each file from this skill's published files and write it to the matching path. In Type, read them with the skill-file tools. Anywhere else, the Type Skills Library API lists every file with its path, content and `sha256`: GET `https://api.type.com/api/public/library/skills` and take the entry with slug `budget-variance-commentary`.
2. **Check the copies are exact.** Compare each file's size in bytes, not characters (and its hash, where your tools report one), with the published version before running. A copy written out from the published file is fine once its byte size and hash match; never run a script you summarised or reconstructed from memory.
3. **Run from the skill's folder**, calling interpreters explicitly: `python3 scripts/…` and `bash examples/run.sh`.
4. **Try the sample first.** If the skill ships `examples/run.sh` and `examples/expected_output.txt`, run `bash examples/run.sh`; its output should match the expected file exactly. If it doesn't, stop and report the first differing line rather than running on real data.

## When to use this

- Monthly or quarterly management accounts: the variance section of the pack.
- Budget-owner review meetings: one page per department, with the immaterial
  noise aggregated instead of debated.
- Reforecasting: the timing vs permanent split is what tells you which
  variances to roll forward.
- Board reporting, where every commented number has to trace to a line.

## Inputs

One CSV, one row per department and account for the period. Required columns:
`department`, `account_code`, `account_name`, `account_type`, `actual`,
`budget`. The optional columns are what make classification possible:
`ytd_actual`, `ytd_budget`, `prior_actual`, `prior_budget`, `actual_units`,
`budget_units`, `unit_name`, `owner`, `classification`, `note`. Full
specification in `DATA_CONTRACT.md`.

### Gathering the inputs through Type integrations

- **Actuals**: export the period P&L by class/department from QuickBooks, Xero,
  or NetSuite at account level. Do not use a summarised report — the commentary
  is only as granular as the export.
- **Budget**: the budget-vs-actual report from the same system if budgets are
  loaded there, otherwise the planning sheet from the connected Google Sheets
  or Excel source. Match on `department` + `account_code`.
- **Year to date and prior period**: the same reports run for the wider range
  and the preceding period. These two pairs of columns are what separate a
  timing variance from a run-rate change; without them most lines come back
  `unclassified`, which is the honest answer.
- **Units**: headcount from the HRIS or payroll provider, customers from the
  billing system, MQLs from the marketing platform, orders from the commerce
  platform. Whatever genuinely drives the account.
- **Owner**: the budget owner. It goes into the drafted sentence so the review
  request has a name on it.

## Running it

```bash
python3 scripts/variance_commentary.py \
  --actuals examples/august_actuals.csv \
  --as-of 2026-08-31 \
  --materiality-abs 5000 \
  --materiality-pct 10 \
  --control-operating-variance -93420.00
```

- `--materiality-abs` and `--materiality-pct` set the thresholds;
  `--materiality-rule and` (default) requires both, `or` requires either. Use
  `and` for a short, senior-audience pack; `or` for a controller's working
  review. A line with a zero budget is judged on the absolute test alone.
- `--volume-share` (default 60) is how much of a variance the volume effect
  must explain before the line is called volume-driven.
- `--timing-share` (default 50) is how small the year-to-date variance must be,
  relative to the period variance, to read as phasing.
- `--control-operating-variance` is the operating income variance from the P&L.
  Supply it: it is the only external check in this skill.
- `--as-of` is required and sets the period label; nothing reads the clock.
- `--json` emits every material line with its evidence and drafted commentary.

Exit codes: `0` ties, `1` the detail does not reconcile to the control total,
`2` bad input naming the line and column. `examples/run.sh` runs four scenarios.

## How classification works

Evaluated in this order; the first rule that fits wins:

1. **Stated** — a `classification` value in the file always wins, and the
   report labels the basis `stated in the file`.
2. **Volume** — needs `actual_units` and `budget_units`. The volume effect is
   `(actual units - budget units) x budget rate`; the rate/mix effect is the
   residual, so the two always sum to the variance exactly. If the volume
   effect explains at least `--volume-share` of the variance, the line is
   volume-driven.
3. **Timing** — needs YTD columns. If the YTD variance runs the other way, or
   is smaller than `--timing-share` of the period variance, the swing is not
   carrying through: phasing.
4. **Permanent** — the YTD variance is at least as large and in the same
   direction as the period variance (optionally confirmed by the prior period),
   or, with no YTD data, the prior period ran the same way.
5. **Unclassified** — the file does not support a claim. The drafted sentence
   says so and asks the owner, rather than inventing a cause. This includes a
   line whose YTD variance runs the same way at between `--timing-share` and
   100% of the period variance: part of the swing is carrying through and part
   is not, so it is neither clean phasing nor a clean run-rate change. The
   prior-period fallback in rule 4 is never used when YTD data is present.

## Reading the output

- **P&L summary and by-department** — where the operating income variance came
  from. `op income effect` flips the sign for cost lines, so a positive number
  always means "good for profit".
- **Material variances** — sorted by effect on operating income, with the
  classification and the basis it rests on.
- **Immaterial lines** — count, net variance, and the three biggest, so nobody
  can say a line was quietly dropped. Watch this block: under the `and` rule a
  large variance on a large budget can sit here. That is the rule working, but
  check it before the meeting.
- **Reconciliation** — material effect plus immaterial effect equals the
  operating income variance, and equals your control total.
- **Draft commentary** — one paragraph per material line. It is a draft. Edit
  it, and never issue the `unclassified` ones without an answer from the owner.

## Limits

- It explains variances arithmetically; it does not know *why* anything
  happened. Classification is an inference from the columns you supplied, and
  the report always states which column drove it.
- Volume analysis is a two-factor split (volume and rate/mix) against a single
  driver per line. It is not a full price-volume-mix bridge across a product
  portfolio.
- Timing vs permanent uses year-to-date and prior-period comparisons only.
  There is no forecast, no seasonality model, and no full-year projection.
- One period per run, one currency, and no consolidation or intercompany
  elimination.
- Materiality here is a variance-size rule, not an audit materiality framework,
  and it is applied per line, not to aggregated risk.
- Rows must be pre-aggregated to one line per department and account —
  duplicates are rejected rather than summed, so that nothing is combined
  behind your back.
- The internal reconciliation is an invariant check on the script's own
  aggregation. Only `--control-operating-variance` tests the data against
  something outside the file, so supply it.
- Draft commentary is not approved commentary. Nothing here should reach a
  board pack without a named human reviewing it.
````
