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
endParse existing text
bean = Beancount.render(ledger)
{:ok, parsed} = Beancount.parse_text(bean)
Beancount.render(parsed) == beanReports preview
Application.put_env(:beancount_ex, :engine, Beancount.Engine.Elixir)
{:ok, result} = Beancount.balances(ledger)
Beancount.Query.Result.to_maps(result)Next notebooks
- Accounting cookbook - cash, salary, trading patterns
- Parsing and validation - import, round-trip, errors
- Reporting with Explorer - DataFrames and dashboards