Getting started with beancount_ex

Copy Markdown View Source
Mix.install([
  {:beancount_ex, "~> 0.6"},
  {:kino, "~> 0.13"}
])

Build a ledger

Constructors live on Beancount. You build a list of typed directive structs.

ledger = [
  Beancount.open(~D[2026-01-01], "Assets:Bank", ["USD"]),
  Beancount.open(~D[2026-01-01], "Income:Salary", ["USD"]),
  Beancount.open(~D[2026-01-01], "Equity:Opening", ["USD"]),
  Beancount.transaction(~D[2026-01-31], "*", "Employer", "Salary", [
    Beancount.posting("Assets:Bank", Decimal.new("5000"), "USD"),
    Beancount.posting("Income:Salary", Decimal.new("-5000"), "USD")
  ])
]

Render to Beancount text

IO.puts(Beancount.render(ledger))

Check the ledger

With the default CLI engine you need pip install beancount beanquery (the latter provides bean-query for reports). The native engine works without Python tooling:

# Optional: use native validation (booking, balance assertions, pad)
Application.put_env(:beancount_ex, :engine, Beancount.Engine.Elixir)

case Beancount.check(ledger) do
  {:ok, result} -> result.status
  {:error, result} -> result.normalized.errors
end

Parse existing text

bean = Beancount.render(ledger)
{:ok, parsed} = Beancount.parse_text(bean)
Beancount.render(parsed) == bean

Reports preview

Application.put_env(:beancount_ex, :engine, Beancount.Engine.Elixir)

{:ok, result} = Beancount.balances(ledger)
Beancount.Query.Result.to_maps(result)

Next notebooks