What is declarative accounting software?
This is a short intro — a seed post while the fuller write-up takes shape. It exists to put one idea plainly.
Most accounting software is imperative: someone posts each journal entry by hand, and the ledger is those stored rows. The source of truth is a pile of rows you mutate.
Declarative accounting flips that. You declare the inputs and the rules — the way you declare infrastructure in Terraform, or a UI in React — and the ledger is derived from them. You never hand-edit a ledger row; you change an input or a rule and regenerate the whole thing.
The piece that does the deriving is a generator: a pure function from immutable inputs to a full double-entry ledger.
function generateLedger(inputs: Input[]): LedgerRow[] {
const rows: LedgerRow[] = []
for (const input of inputs) {
rows.push(...rulesFor(input).map((rule) => rule.apply(input)))
}
return rows
}Because the ledger is derived, it is reproducible (same inputs + same rules → the same ledger, every time), every row keeps its provenance (which input and rule produced it), and the whole history is versionable.
Here is the shape in one domain — crypto, where the inputs are raw on-chain events:
| On-chain event | Debit | Credit |
|---|---|---|
| deposit 2 ETH | ETH (asset) | Capital |
| buy 1 ETH @ $3,000 | ETH (asset) | USD (asset) |
| sell 1 ETH @ $3,400 | USD (asset) | ETH + Gain |
The longer version — FIFO lots, multi-entity consolidation, what happens when an exchange collapses under you — is still to come.