Skip to main content

45 posts tagged with "accounting"

View All Tags

Beancount Cheat Sheet

· 2 min read
Mike Thrift
Mike Thrift
Marketing Manager

Example Account Name

Assets:US:BofA:Checking

cheatsheet-en

Account Types

Assets          +
Liabilities -
Income -
Expenses +
Equity -

Commodities

CNY, EUR, CAD, AUD
GOOG, AAPL, RBF1005
HOME_MAYST, AIRMILES
HOURS

Directives

General syntax

YYYY-MM-DD <Directive> <Parameters...>

Opening & Closing Accounts

2001-05-29 open Expenses:Restaurant
2001-05-29 open Assets:Checking USD,EUR ; Currency constraints

2015-04-23 close Assets:Checking

Declaring Commodities (Optional)

1998-07-22 commodity AAPL
name: "Apple Computer Inc."

Prices

2015-04-30 price AAPL   125.15 CNY
2015-05-30 price AAPL 130.28 CNY

Notes

2013-03-20 note Assets:Checking "Called to ask about rebate"

Documents

2013-03-20 document Assets:Checking "path/to/statement.pdf"

Transactions

2015-05-30 * "Some narration about this transaction"
Liabilities:CreditCard -101.23 CNY
Expenses:Restaurant 101.23 CNY

2015-05-30 ! "Cable Co" "Phone Bill" #tag ˆlink
id: "TW378743437" ; Meta-data
Expenses:Home:Phone 87.45 CNY
Assets:Checking ; You may leave one amount out

Postings

  ...    123.45 USD                             Simple
... 10 GOOG {502.12 USD} With per-unit cost
... 10 GOOG {{5021.20 USD}} With total cost
... 10 GOOG {502.12 # 9.95 USD} With both costs
... 1000.00 USD @ 1.10 CAD With per-unit price
... 10 GOOG {502.12 USD} @ 1.10 CAD With cost & price
... 10 GOOG {502.12 USD, 2014-05-12} With date
! ... 123.45 USD ... With flag

Balance Assertions and Padding

; Asserts the amount for only the given currency:
2015-06-01 balance Liabilities:CreditCard -634.30 CNY

; Automatic insertion of transaction to fulfill the following assertion:
2015-06-01pad Assets:Checking Equity:Opening-Balances

Events

2015-06-01 event "location" "New York, USA"
2015-06-30 event "address" "123 May Street"

Options

option "title" "My Personal Ledger"

Other

pushtag #trip-to-peru
...
poptag #trip-to-peru
; Comments begin with a semi-colon

The Magic of Plain Text Accounting with Beancount

· 5 min read
Mike Thrift
Mike Thrift
Marketing Manager

Discover the Magic of Plain Text Accounting with Beancount

Beancount.io banner

Introduction

2023-04-18-introduction-to-beancount

Welcome to a world where accounting is no longer a daunting task. Today, we introduce you to Beancount, a powerful, flexible, and intuitive plain text accounting tool. Beancount empowers you to take control of your finances by providing a transparent and straightforward approach to managing your money.

In this comprehensive guide, we will delve into the basics of Beancount, explain its core concepts, and walk you through its simple yet powerful features. By the end of this blog, you'll have a solid understanding of Beancount and be ready to start using it to organize and analyze your financial life.

What is Beancount?

Beancount is an open-source, plain text accounting system created by Martin Blais. Inspired by John Wiegley's Ledger system, Beancount aims to provide a robust and reliable method to manage personal and small business finances using plain text files. With Beancount, you can track your income, expenses, investments, and much more with ease.

Why Beancount?

Plain text accounting offers several advantages over traditional spreadsheet-based or software-based accounting systems:

  • Transparency: Beancount files are human-readable, making it easy to understand and audit your financial data.
  • Flexibility: Beancount can be easily customized to fit your specific needs, and you can use your favorite text editor and version control system to manage your financial data.
  • Portability: Your financial data can be accessed on any device, and it's easy to transfer between systems or share with others.
  • Future-proof: Plain text files are universally compatible, ensuring that your financial data will remain accessible, even as technology evolves.

Beancount's Core Concepts

To use Beancount effectively, it's crucial to understand its core concepts:

  • Transactions: Financial events, such as income, expenses, or transfers between accounts, are recorded as transactions.
  • Accounts: Transactions involve one or more accounts, such as assets, liabilities, income, or expenses.
  • Double-entry bookkeeping: Beancount enforces double-entry bookkeeping, ensuring that every transaction has balanced debits and credits.
  • Directives: Beancount uses a set of directives to define transactions, account openings, and other financial events.

Getting Started with Beancount

To start using Beancount, follow these simple steps:

  • Install Beancount: Install Beancount on your system using the provided installation instructions for your operating system.
  • Create your Beancount file: Create a new plain text file with the .beancount extension (e.g., my_finances.beancount).
  • Define your accounts: Use the "open" directive to define the accounts you'll use in your transactions.
  • Record transactions: Use the "txn" directive to record your financial transactions.

Or simply sign up at https://beancount.io. Here are some plain text accounting examples -

Example 1: Basic Transaction

2023-04-01 open Assets:Checking
2023-04-01 open Expenses:Groceries

2023-04-10 txn "Grocery Store" "Buying groceries"
Assets:Checking -50.00 USD
Expenses:Groceries 50.00 USD

In this example, we open two accounts, Assets:Checking and Expenses:Groceries. On April 10, 2023, we record a transaction for buying groceries worth 50.ThetransactionreducesthebalanceofAssets:Checkingby50. The transaction reduces the balance of Assets:Checking by 50 (debit) and increases the balance of Expenses:Groceries by $50 (credit).

Example 2: Income and Expense Transaction

2023-04-01 open Assets:Checking
2023-04-01 open Income:Salary
2023-04-01 open Expenses:Rent

2023-04-05 txn "Employer" "Salary payment"
Assets:Checking 2000.00 USD
Income:Salary -2000.00 USD

2023-04-06 txn "Landlord" "Monthly rent payment"
Assets:Checking -1000.00 USD
Expenses:Rent 1000.00 USD

In this example, we open three accounts: Assets:Checking, Income:Salary, and Expenses:Rent. On April 5, 2023, we record a salary payment transaction of 2000.ThetransactionincreasesthebalanceofAssets:Checkingby2000. The transaction increases the balance of Assets:Checking by 2000 (credit) and decreases the balance of Income:Salary by 2000(debit).OnApril6,2023,werecordarentpaymenttransactionof2000 (debit). On April 6, 2023, we record a rent payment transaction of 1000. The transaction reduces the balance of Assets:Checking by 1000(debit)andincreasesthebalanceofExpenses:Rentby1000 (debit) and increases the balance of Expenses:Rent by 1000 (credit).

Example 3: Transfer Between Accounts

2023-04-01 open Assets:Checking
2023-04-01 open Assets:Savings

2023-04-15 txn "Bank" "Transfer from Checking to Savings"
Assets:Checking -500.00 USD
Assets:Savings 500.00 USD

In this example, we open two accounts: Assets:Checking and Assets:Savings. On April 15, 2023, we record a transaction to transfer 500fromthecheckingaccounttothesavingsaccount.ThetransactionreducesthebalanceofAssets:Checkingby500 from the checking account to the savings account. The transaction reduces the balance of Assets:Checking by 500 (debit) and increases the balance of Assets:Savings by $500 (credit).

These examples illustrate the basic concepts of Beancount's double-entry bookkeeping system. By properly recording transactions, users can maintain accurate records of their financial activities and generate reports to gain insights into their financial situation.

Generating Reports and Analyzing Data

Beancount comes with a set of powerful tools for generating financial reports, including balance sheets, income statements, and more. You can also use Fava, a web-based user interface for Beancount, to visualize and interact with your financial data. https://beancount.io is built upon Fava with MIT license.

Conclusion

Embrace the power and simplicity of plain text accounting with Beancount. By understanding its core concepts and following the steps outlined in this guide, you'll be well on your way to managing your personal or small business finances with ease and precision. As you grow more comfortable with Beancount, you can explore advanced features and customizations to tailor the system to your unique needs.

Whether you're looking to track your spending, plan for the future, or gain insights into your financial habits, Beancount offers the flexibility and transparency needed to achieve your goals. With its user-friendly approach, Beancount has the potential to revolutionize the way you manage your finances and empower you to take control of your financial future.

Now that you have a solid foundation in Beancount, it's time to embark on your plain text accounting journey. Say goodbye to cumbersome spreadsheets and convoluted software, and welcome the world of Beancount. Happy accounting!

Enhancing Your Beancount Experience with Custom Links and Queries

· 3 min read
Mike Thrift
Mike Thrift
Marketing Manager

Beancount, the double-entry accounting system beloved by developers and finance nerds alike, is powerful in its simplicity. But for those who want more control and faster navigation inside Fava, Beancount’s web interface, custom sidebar links and SQL queries can take your workflow to the next level.

In this guide, we’ll show you how to:

  • Add quick-access links to Fava’s sidebar
  • Use SQL queries for advanced filtering and analysis
  • Customize your workflow for monthly reviews or anomaly detection

Why Customize Fava?

Fava is already a beautiful interface for viewing your Beancount ledger, but as your journal grows, so does the need for better shortcuts and smarter queries.

Pain points this solves:

  • Navigating through time ranges repeatedly
  • Filtering transactions across nested accounts
  • Spotting negative balances or anomalies faster

Let’s start with improving your daily workflow with simple sidebar shortcuts. These links appear in Fava’s left sidebar and can take you directly to filtered views like this month’s transactions or last month’s income.

Add these lines to your Beancount file:

2021-01-01 custom "fava-sidebar-link" "Current Month" "/jump?time=month"
2021-01-01 custom "fava-sidebar-link" "Last Month" "/jump?time=month-1"
2021-01-01 custom "fava-sidebar-link" "Clear All" "/jump?account=&time=&filter="

What They Do:

  • Current Month: Opens the transaction view filtered to the current month.
  • Last Month: Instantly jumps to the previous month—great for end-of-month reviews.
  • Clear All: Resets filters, showing all entries again.

These shortcuts eliminate manual time input and make your Fava experience feel more fluid and personalized.

🔍 Custom SQL Queries

For deeper insight, Fava’s SQL interface is incredibly powerful. Here’s a query that finds all negative balances in accounts that match a pattern—perfect for flagging unusual or problematic transactions.

SELECT account, units(sum(position)), sum(position)
WHERE number(units(position)) < 0
AND account ~ '.*:BCM:.*'
AND date >= DATE(2021,12,9)
AND date < DATE(2022,1,9)

Breakdown:

  • account ~ '.*:BCM:.*': Filters accounts containing :BCM: in their name.
  • number(units(position)) < 0: Flags negative balances (e.g. overspent budgets).
  • Date filters narrow the result to a specific 1-month window.

Use cases:

  • Spot errors like duplicate expenses or incorrect postings
  • Audit a specific vendor or category
  • Quickly extract actionable insights for budgeting

While Fava doesn’t allow direct links to custom queries, you can create a monthly review habit by:

  • Using the “Current Month” link to start your review
  • Opening your saved queries tab in another pane
  • Reviewing both simultaneously—filter first, then dig deep

This combo helps you catch anomalies before they spiral and ensure your ledger stays clean.

Final Thoughts

Beancount is minimal by design, but small enhancements like these bring huge gains in efficiency. Whether you’re reviewing your budget, debugging strange balances, or simply saving clicks, custom links and SQL queries give you more power and less friction.

Bonus: If you're using Fava’s custom reports, you can even build full dashboards tailored to your personal finance rituals.

Ready to take control?

Start small: add the “Current Month” link. Then build your own queries. Your future self will thank you.

Want more tips like this? Subscribe to our newsletter or explore more Beancount recipes at Beancount.io.

Forecasting Future Transactions in Beancount

· One min read
Mike Thrift
Mike Thrift
Marketing Manager

There is a plugin for beancount to forecast future recurring transactions. How to apply it in beancount.io? Put the following content into your ledger file.

; import the plugin
plugin "fava.plugins.forecast"

; add a monthly HOA fee
2022-05-30 # "HOA fee [MONTHLY]"
Expenses:Hoa 1024.00 USD
Assets:Checking -1024.00 USD

Forecast plugin screenshot

2022-05-30-forecast-plugin

And then, you will see the forecast in Net Profit chart.

Forecast Plugin

The tag [MONTHLY] above means it will recur forever. If you have more conditions to apply, try [MONTHLY UNTIL 2022-06-01], [MONTHLY REPEAT 5 TIMES], [YEARLY REPEAT 5 TIMES], or [WEEKLY SKIP 1 TIME REPEAT 5 TIMES].

Crafting & Tracking Invoices with Beancount

· 6 min read
Mike Thrift
Mike Thrift
Marketing Manager

A plain‑text template, a repeatable workflow, and a single query for “Who still owes me?”


2022-02-12-crafting-tracking-invoices-with-beancount

Invoicing can feel like a chore, stuck between the work you've finished and the payment you're waiting for. But a good invoice process is the backbone of healthy cash flow. It pulls double duty: it clearly tells your clients what they owe and when, and it feeds your accounting system the unassailable facts it needs.

While dedicated SaaS apps can send slick, automated PDFs, they often come with monthly fees and lock your data in a proprietary silo. A lightweight, plain-text approach using Beancount offers a powerful alternative. You can turn each invoice into a clear set of accounting entries, giving you all the benefits of version control, powerful metadata, and instant querying—no subscription required.


The Minimum Viable Invoice (Fields You Should Never Skip)

Before you touch your ledger, you need a professional invoice. The format can be simple, but the contents must be precise. These fields, borrowed from time-tested small-business practice, are non-negotiable.

  • Seller details: Your business name and physical address.
  • Client details: Your client’s name and (ideally) their address.
  • Invoice number: A unique, sequential ID that is never reused. INV-045 follows INV-044.
  • Issue & due dates: Clearly state when the invoice was issued and when payment is expected.
  • Line items: A clear description of services or products, along with quantity, rate, and the line total.
  • Subtotal, tax, and total: Show the math so the client can follow it easily.
  • Optional notes: A place for a thank you, wiring instructions, or a client-provided purchase order number.

To get you started, we've created a set of ready-to-edit templates that include all these fields. The spreadsheet versions even pre-calculate the totals for you.

Grab our templates here: beancount.io/invoice‑templates (Available in Google Docs, Word, Sheets, Excel, and PDF formats)


Record the Invoice in Your Ledger

Once you've sent the invoice PDF to your client, you must record it in Beancount. This is a crucial step that recognizes the revenue when it's earned, not just when it's paid. The process involves two distinct transactions.

1. When you issue the invoice:

You create a transaction that moves the total amount from your Income account into Assets:AccountsReceivable. This creates a digital IOU in your books.

; 2025‑07‑21 Invoice #045  Web design sprint for Acme Corp.
2025-07-21 * "Acme Corp" "INV-045 Web design sprint"
Assets:AccountsReceivable 3500.00 USD ; due:2025-08-04
Income:Design:Web
invoice_id: "INV-045"
contact_email: "ap@acme.example"
link: "docs/invoices/2025-07-21_Acme_INV-045.pdf"

Here, you debit AccountsReceivable and credit your Income account. Notice the rich metadata: the due date, a unique invoice_id, and even a direct link: to the PDF you sent.

2. When the client pays:

When the cash hits your bank account, you record a second transaction to "close out" the IOU. This moves the balance from AccountsReceivable to your checking account.

2025-08-01 * "Acme Corp" "Payment INV-045"
Assets:Bank:Checking 3500.00 USD
Assets:AccountsReceivable
invoice_id: "INV-045"

The balance for INV-045 in Assets:AccountsReceivable is now zero, and your books are perfectly balanced.

Attach the PDF: The link: metadata key is especially powerful when used with Fava, Beancount's web interface. Fava will render a clickable link directly in the transaction view, so the source document is never more than a click away. This workflow was envisioned as early as 2016 in a feature request (GitHub).


One Query to List All Open Invoices

So, who still owes you money? With this system, you don't need to hunt through emails or spreadsheets. You just need one simple query.

Save the following as a file named open-invoices.sql:

SELECT
meta('invoice_id') AS id,
payee,
narration,
date,
number(balance) AS outstanding
WHERE
account = "Assets:AccountsReceivable"
AND balance != 0
ORDER BY
date;

Now, run it from your command line:

bean-query books.beancount open-invoices.sql

In seconds, you'll get a clean, up-to-the-minute aging report of all outstanding invoices, showing the invoice ID, client, date issued, and amount owed. No extra software required.


Automate the Busywork

The beauty of plain text is scriptability. You can automate the tedious parts of this workflow.

  • Template + Pandoc = PDF: Maintain your invoice template in Markdown. A tiny Python script can populate the variables (client name, line items, invoice number), and the command-line tool Pandoc can instantly convert it to a professional PDF.
  • Git Pre-commit Hook: If you store your ledger in Git, a simple pre-commit hook can run checks before you save your work. It can verify that every new invoice_id is unique, that the transaction postings balance to zero, and that the file referenced in the link: metadata actually exists.
  • Cron Job: Set up a scheduled task (a cron job) to run your open-invoices.sql query every night and email you the summary. You'll start each day knowing exactly who needs a friendly nudge.

A Realistic Caveat

Beancount is an accounting tool, not an invoicing service. It will not automatically send payment reminders to your clients or process their credit card payments. The workflow is: you create and send the invoice using your chosen method (like the templates above), and then you book the accounting entries in your ledger.

For most freelancers and small shops, this manual step is a small price to pay for a bulletproof, auditable, and free accounting system that you completely own and control (beancount.io).


Next Steps

Ready to take control of your invoicing? Here’s how to start.

  1. Download a template and use it to create your next real invoice, making sure to use a sequential invoice number.
  2. Store your sent PDFs in a dedicated folder like docs/invoices/ and use the link: metadata key in your Beancount transaction to reference them.
  3. Save the open-invoices.sql query and make running it a part of your weekly financial review.

Plain-text accounting doesn’t mean giving up polish or control—it just means the database is grep-able. With a simple template and the snippets above, you’ll get paid faster and keep your books immaculate.

Adjusting Entries in Beancount: Your Month-End Tune-Up

· 4 min read
Mike Thrift
Mike Thrift
Marketing Manager

Accounting isn’t finished when the last sale hits the bank. To get a true picture of your business's health, you need to perform a month-end tune-up. At every period close, you'll make adjusting entries—journal tweaks that correctly place revenues and expenses in the proper time window and keep your balance sheet honest.

In a plain‑text Beancount ledger, these crucial entries are transparent, version‑controlled, and easy to audit, turning a tedious task into a clear and repeatable process.

2022-01-25-adjusting-entries-in-beancount-your-month-end-tune-up


Why Adjusting Entries Matter

Making these adjustments is fundamental to sound accounting. They ensure your financial statements are accurate and reliable.

  • Accrual Accuracy: Adjusting entries are the engine of accrual accounting. They move income and costs into the period they were actually earned or incurred, regardless of when cash changed hands. This satisfies the core revenue-recognition and matching principles that form the foundation of modern accounting (AccountingCoach.com).

  • Reliable KPIs: Key performance indicators are only as good as the data behind them. Metrics like gross margin, net income, and cash-flow forecasts only tell the truth once deferrals, accruals, and estimates are properly posted (Corporate Finance Institute).

  • Clean Audit Trail: Explicit month‑end adjustments create a clear record of your financial reasoning. This helps auditors (and your future self) easily trace what changed and why, building confidence in your numbers (Accountingverse).


Six Common Categories (with Beancount Snippets)

Here are the six most common types of adjusting entries, with examples of how to record them in your Beancount ledger. Notice the use of metadata like adj:"accrual" to make these entries easy to find and analyze later.

1. Accrued Revenue

This is for revenue you've earned but haven't yet billed or received payment for.

2025-07-31 * "Consulting—July hours"
Assets:AccountsReceivable 12000.00 USD
Income:Consulting
; adj:"accrual" period:"Jul-25"

2. Accrued Expense

An expense you've incurred but haven't yet paid, like a utility bill that will arrive next month.

2025-07-31 * "Attorney—July retainer"
Expenses:Legal 2500.00 USD
Liabilities:AccruedPayables
; adj:"accrual"

3. Deferred (Unearned) Revenue

This applies when a client pays you in advance. You recognize a portion of that revenue as it's earned over time.

2025-07-31 * "Annual SaaS prepayment (recognize 1/12)"
Liabilities:UnearnedRevenue 833.33 USD
Income:SaaS
; adj:"deferral"

4. Prepaid (Deferred) Expense

When you pay for an expense upfront (like an annual insurance policy), you expense a portion of it each month.

2025-07-31 * "Insurance—1 mo. expense from prepaid"
Expenses:Insurance 400.00 USD
Assets:PrepaidInsurance
; adj:"deferral"

5. Depreciation & Amortization

This entry allocates the cost of a long-term asset (like a computer or vehicle) over its useful life.

2025-07-31 * "Mac Studio depreciation"
Expenses:Depreciation 1250.00 USD
Assets:Computers:AccumDepr
; asset_id:"MAC-03" adj:"estimate"

6. Allowance for Doubtful Accounts

An estimate of accounts receivable that you don't expect to collect, which is recorded as a bad debt expense.

2025-07-31 * "Bad-debt provision (2% of A/R)"
Expenses:BadDebt 700.00 USD
Assets:AllowanceForBadDebt
; basis:"A/R" rate:0.02 adj:"estimate"

A Repeatable Workflow

To keep your month-end close efficient and error-free, adopt a consistent workflow.

  • Use a separate file. Keep all adjustments for a period in one place, like adjustments-2025-07.bean. In your main ledger file, use an include directive to import it last. This ensures adjustments are applied just before you generate final reports.

  • Standardize your metadata. Always use consistent metadata keys and values, like adj:"accrual|deferral|estimate" and period:"Jul-25". This makes querying and reviewing specific types of adjustments a breeze.

  • Run a pre-flight check. Before committing your changes to Git, run bean-check on your adjustments file to catch any typos or unbalanced postings.

  • Perform a one-line sanity check. This query confirms that all your adjustments for the period balance out, giving you confidence that you haven't introduced errors.

    bean-query main.bean "SELECT account, SUM(number) WHERE meta('adj') AND meta('period') = 'Jul-25' GROUP BY account"

Quick Troubleshooting Tips 🤔

  • Is your Liabilities:UnearnedRevenue balance climbing? Review your contract milestones. You might be recognizing revenue too slowly compared to the work you're delivering.

  • Is your Assets:PrepaidInsurance balance negative? You're likely expensing it faster than the asset's schedule allows. Double-check your amortization schedule.

  • Is your Days Sales Outstanding (DSO) getting worse after accruals? Your accrued revenue might be masking underlying collection issues. Pair this KPI with an A/R aging report to spot late-paying clients before it becomes a cash-flow problem.


Closing Thoughts

Adjusting entries can feel tedious, but their value becomes crystal clear when you compare your "before" and "after" income statements—the difference is often material. With Beancount, these adjustments become small, searchable patches that you can automate and review just like code.

Build the month-end habit, and your numbers will stay as accurate as your engineering.

Happy balancing!

Revolutionizing Personal Finance Management with Beancount.io

· 4 min read
Mike Thrift
Mike Thrift
Marketing Manager

Beancounters traditionally use command-line tools or self-host servers with private networks, where they have to operate through a computer or a general-purpose text editor on mobile. Beancount.io reduces hassles by bringing open-sourced Android and iOS mobile apps and a secured cloud so that your ledger is now a few taps away from your fingerprint.

Beancount is a computer language that enables double-entry bookkeeping in text files. Once you define financial transactions in the file, it will generate various reports. Martin Blais, the designer of this language, argues that command-line bookkeeping has many advantages - It is fast, portable, open, and customized.

We strongly agree with the argument and share the feeling of empowerment brought by beancount language. And we wanted to do more - introducing the technology to more people. It means that we have to improve the usability and make it more accessible to a broader audience.

2022-01-08-instant-access-to-your-beancount-cloud-ledger-anytime-anywhere

Not everyone is a command-line enthusiast, and this is why we build Beancount.io - the personal finance manager for everyone. Here is how it works:

For heavy-duty work, beancounters could still use their computers to edit or view the ledger with their browsers visiting https://beancount.io or syncing with Dropbox. This keeps the flexibility of the command-line tools, while not losing the cross-device access of the cloud-based solution.

For daily light-weight operations, such as instantly adding an entry, beancounters could use the mobile app to connect to the secured cloud.

Mike Thrift, a backend engineering working on this product, says

I used to set up a reminder every day for myself to open my laptop and input records to my bean files. Now, with beancount.io, it is way easier for me to modify my ledger whenever I need it, even when I am outdoors purchasing something in the store.

Zhi Li, a software engineer from Facebook, tells us

I have migrated all my beancount files to beancount.io, and now it works perfectly for my day-to-day usage. I have paid for Pro features like automatic data backup, but I feel there are more things you guys could do to improve the service.

You could sign up now at https://beancount.io/sign-up/ or download iOS or Android App. We streamlined the registration to collect as minimal information as we can from you to bootstrap the service. Then you will get a preset empty ledger that is ready for you to add an entry right away.

FAQs

Would beancount.io sell my ledger data to any third party?

  • No. We are committed to keeping your data secured and private, and we will never sell your ledger data.

Is my data secured?

  • Yes. We protect your email and ledger with AES256, your password with BCrypt, and your network requests with SSL.

Is my ledger data end-to-end encrypted?

  • No. Due to technical constraints, we still have to decrypt your data into memory when indexing the ledger file in production servers. Therefore, we restrict direct access from any of our team members. Unfortunately, we cannot do this in Intel's SGX or any security vault due to high costs.

Is this a reliable service I could trust for the incoming few years?

  • Yes. We initially launched Beancount.io on July 4th, 2019, and it has been more than two years that we have operated the service securely and reliably. Therefore, we have no reason not to continue the service in the future.

Can I request new features and sponsor the project?

QuickBooks to Beancount Migration Playbook

· 30 min read
Mike Thrift
Mike Thrift
Marketing Manager

Stage 1: Exporting Data from QuickBooks

Migrating five years of data starts with getting all QuickBooks records out in a usable format. QuickBooks Desktop and QuickBooks Online have different export options:

2021-12-01-from-quickbooks-to-plain-text-a-migration-playbook

1.1 QuickBooks Desktop – Export Options

IIF (Intuit Interchange Format): QuickBooks Desktop can export lists (like chart of accounts, customers, vendors) to .IIF text files. In QuickBooks Desktop, go to File → Utilities → Export → Lists to IIF, then select the lists you need (e.g. Chart of Accounts, Customers, Vendors). This yields a text file that includes account names, types, and list data. IIF is a proprietary but plain-text format that’s relatively easy to parse. Use it to capture your Chart of Accounts and contact lists for reference in Beancount.

General Ledger/Journal via CSV: For transaction data, QuickBooks Desktop doesn’t provide a one-click full export, but you can use reports. The recommended method is to export the General Journal (all transactions) over the desired date range. In QuickBooks Desktop, open Reports → Accountant & Taxes → Journal, set the Dates from the earliest transaction to today, and click Export → Excel. Save the result as CSV after removing any report headers/footers and empty columns. Make sure the numeric data is clean: include cents (e.g. 3.00 not 3), no extra quotes, and no currency symbols or double negatives in the CSV. The CSV should have columns like Date, Trans #, Name, Account, Memo, Debit, Credit, Balance (or a single Amount column depending on the report format).

Tip: QuickBooks Desktop 2015+ can also export transactions via the Find dialog. Use Edit → Find → Advanced, set the date range for five years, then export results to CSV. Warning: Some versions cap the export at 32,768 lines. If you have very large data, export year by year (or smaller chunks) to avoid truncation, then later combine them. Ensure date ranges don’t overlap to prevent duplicates.

Other Formats (QBO/QFX/QIF): QuickBooks Desktop can import bank transactions via .QBO (Web Connect) or .QFX/.OFX files, but for exporting from QuickBooks, these aren’t typical. If your goal is to extract bank transactions only, you might already have them in QBO/OFX from your bank. However, for a full ledger export, stick to IIF and CSV. QuickBooks Desktop cannot directly export to QIF (Quicken Interchange Format) without third-party tools. If you do find a way to get QIF, note that some ledger tools (older Ledger 2.x) could read QIF, but it’s better to work with CSV in our pipeline.

1.2 QuickBooks Online – Export Options

Built-in Excel/CSV Export: QuickBooks Online (QBO) provides an Export Data tool. Go to Settings ⚙ → Tools → Export Data. In the export dialog, use the Reports tab to select data (e.g. General Ledger or Transaction List) and the Lists tab for lists (chart of accounts, etc.), choose All dates, and export to Excel. QuickBooks Online will download a ZIP containing multiple Excel files for the selected reports and lists (for example, Profit and Loss, Balance Sheet, General Ledger, Customers, Vendors, Chart of Accounts, etc.). You can then convert these Excel files to CSV for processing.

Transaction Detail Report: If QBO’s default export doesn’t include a single General Ledger file, you can manually run a detailed report:

  1. Navigate to Reports and find Transaction Detail by Account (or General Ledger in some QBO versions).
  2. Set Report period to the full five-year range.
  3. Under Report options, set Group by = None (to list individual transactions without subtotals).
  4. Customize columns to include at least: Date, Transaction Type, Number, Name (Payee/Customer), Memo/Description, Account, Debit, Credit (or single Amount column), and Balance. Include any class or location if used.
  5. Run the report and then Export to Excel.

This yields a detailed ledger of all transactions. Save it as CSV. Each line will represent one split (posting) of a transaction. You’ll later need to group lines by transaction for conversion.

Chart of Accounts and Other Lists: QuickBooks Online can export the chart of accounts via Accounting → Chart of Accounts → Batch Actions → Export to Excel. Do this to get account names and types. Likewise, export Customers, Vendors, etc., if you want to carry over names for metadata.

QuickBooks Online API (Optional): For a programmatic approach, Intuit provides a REST API for QBO data. Advanced users can create a QuickBooks Online app (requires a developer account) and use the API to fetch data in JSON. For example, you could query the Account endpoint for the chart of accounts and the JournalEntry or GeneralLedger report endpoints for transactions. There are Python SDKs like python-quickbooks that wrap the API. However, using the API involves OAuth authentication and is overkill for a one-time migration unless you prefer automation. For most cases, the manual export to CSV/Excel is simpler and less error-prone.

Stage 2: Transforming and Cleaning Data

Once you have QuickBooks data in CSV (and/or IIF), the next step is to convert it into Beancount’s plain-text ledger format. This involves parsing the exports, mapping QuickBooks accounts to a Beancount chart of accounts, and formatting transactions in Beancount syntax.

2.1 Parsing QuickBooks Exports with Python

Using Python will ensure accuracy and reproducibility for the transformation. We’ll outline scripts for two key tasks: importing the chart of accounts and converting transactions.

Accounts Import and Mapping: It’s crucial to set up your accounts in Beancount before adding transactions. QuickBooks accounts have types (Bank, Accounts Receivable, Expense, etc.) which we will map to Beancount’s hierarchy (Assets, Liabilities, Income, Expenses, etc.). For example, we can use a mapping like:

# QuickBooks account type to Beancount root category
AccountTypeMap = {
'BANK': 'Assets',
'CCARD': 'Liabilities',
'AR': 'Assets', # Accounts Receivable as asset
'AP': 'Liabilities', # Accounts Payable as liability
'FIXASSET': 'Assets',
'OASSET': 'Assets', # Other Asset
'OCASSET': 'Assets', # Other Current Asset
'LTLIAB': 'Liabilities', # Long Term Liability
'OCLIAB': 'Liabilities', # Other Current Liability
'EQUITY': 'Equity',
'INC': 'Income',
'EXP': 'Expenses',
'EXINC': 'Income', # Other Income
'EXEXP': 'Expenses', # Other Expense
}

Using the QuickBooks Desktop IIF export or QBO’s account list CSV, we retrieve each account’s name and type. Then:

  • Create Beancount account names: QuickBooks sometimes uses colons (:) in account names to denote subaccounts (e.g., “Current Assets:Checking”). Beancount uses the same colon notation for hierarchy. You can often reuse the name directly. If the QuickBooks account names do not start with a category, prepend the mapped category. For example, a QuickBooks account of type BANK named "Checking" will become Assets:Checking in Beancount. An EXP (expense) account "Meals" becomes Expenses:Meals, etc.

  • Ensure valid naming: Remove or replace any characters that might confuse Beancount. QuickBooks allows characters like & or / in names. It’s wise to strip out or replace special characters (e.g., replace & with and, remove slashes or spaces). Also, ensure all account names are unique after transformation – QuickBooks might have allowed same subaccount name under different parents which is fine, but in Beancount the full name (with parents) must be unique. If needed, rename or append a qualifier to distinguish them.

  • Output account openings: In Beancount, every account used must be opened with an open directive. You can pick a date before your first transaction (e.g., if migrating 2019–2023 data, use 2018-12-31 or an even earlier date for all opens). The script will write lines like: 2018-12-31 open Assets:Checking USD 2018-12-31 open Expenses:Meals USD for each account (assuming USD is the main currency). Use the appropriate currency for each account (see multi-currency notes below).

Transaction Conversion: The main challenge is converting the QuickBooks transaction export (CSV) into Beancount entries. Each QuickBooks transaction (invoice, bill, check, journal entry, etc.) can have multiple splits (lines) that must be gathered into one Beancount transaction.

We will use Python’s CSV reader to iterate through the exported lines and accumulate splits:

import csv
from collections import defaultdict

# Read all lines from QuickBooks Journal CSV
rows = []
with open('quickbooks_exported_journal.csv', 'r', encoding='utf-8') as f:
reader = csv.DictReader(f)
for line in reader:
rows.append(line)

# Group lines by transaction (assuming 'Trans #' identifies transactions)
transactions = defaultdict(list)
for line in rows:
trans_id = line.get('Trans #') or line.get('Transaction ID') or line.get('Num')
transactions[trans_id].append(line)

Now transactions is a dictionary where each key is a transaction ID/number and the value is the list of splits for that transaction. Next, we convert each group to Beancount:

def format_date(qb_date):
# QuickBooks dates might be like "12/31/2019"
m, d, y = qb_date.split('/')
return f"{y}-{int(m):02d}-{int(d):02d}"

output_lines = []
for trans_id, splits in transactions.items():
# Sort splits by line order if needed (they usually come out in order)
splits = sorted(splits, key=lambda x: x.get('Line') or 0)
first = splits[0]
date = format_date(first['Date'])
payee = first.get('Name', "").strip()
memo = first.get('Memo', "").strip()
# Transaction header
output_lines.append(f"{date} * \"{payee}\" \"{memo}\"")
if first.get('Num'): # include reference number if available
output_lines.append(f" number: \"{first['Num']}\"")
# Loop through each split/posting
for split in splits:
acct_name = split['Account'].strip()
# Map QuickBooks account name to Beancount account (using earlier mapping)
beancount_acct = account_map.get(acct_name, acct_name)
# Determine amount with sign:
amount = split.get('Amount') or ""
debit = split.get('Debit') or ""
credit = split.get('Credit') or ""
if amount:
# Some exports have a single Amount column (negative for credits)
amt_str = amount
else:
# If separate Debit/Credit columns
amt_str = debit if debit else f"-{credit}"
# Remove any commas in numbers for safety
amt_str = amt_str.replace(",", "")
# Append currency
currency = split.get('Currency') or "USD"
amt_str = f"{amt_str} {currency}"
# Memo/description for the split
line_memo = split.get('Memo', "").strip()
comment = f" ; {line_memo}" if line_memo else ""
output_lines.append(f" {beancount_acct:<40} {amt_str}{comment}")
# End of transaction – blank line
output_lines.append("")

This script logic does the following:

  • Formats the date to YYYY-MM-DD for Beancount.

  • Uses the payee (Name) and memo for the transaction narration. For example: 2020-05-01 * "ACME Corp" "Invoice payment" (If no payee, you might use the QuickBooks transaction Type or leave the payee empty quotes).

  • Adds a number metadata if there's a reference number (check #, invoice #, etc.).

  • Iterates through each split line:

    • Maps the QuickBooks account name to the Beancount account using a dictionary account_map (populated from the chart of accounts step).
    • Determines the amount. Depending on your export, you might have a single Amount column (with positive/negative values) or separate Debit and Credit columns. The code above handles both cases. It ensures credits are represented as negative amounts for Beancount (since in Beancount, a single number with sign is used per posting).
    • Attaches the currency (assuming USD unless a different currency column is present).
    • Writes the Beancount posting line with the account, amount, and a comment with the line memo. For example: Assets:Checking 500.00 USD ; Deposit Income:Sales -500.00 USD ; Deposit This reflects a $500 deposit (from Income into Checking).
  • After listing all splits, a blank line separates the transaction.

Multi-currency handling: If your QuickBooks data involves multiple currencies, include the currency code on each posting (as shown above). Ensure that accounts that are in foreign currencies are opened with that currency. For example, if you have a bank account in EUR, you’d output open Assets:Bank:Checking EUR and the transactions in that account will use EUR. Beancount supports multi-currency ledgers and will track implicit conversions, but you might need to add price entries for exchange rates if you want conversion to a base currency in reports. It’s also recommended to declare your main operating currency at the top of the Beancount file (e.g., option "operating_currency" "USD").

Running the conversion: Save the Python script (for example, as qb_to_beancount.py) and run it on your exported files. It should produce a .beancount file containing all accounts and transactions.

2.2 Handling Edge Cases and Data Cleaning

During transformation, be mindful of these common gotchas and how to address them:

  • Account Name Mismatches: QuickBooks might have account names that clash with Beancount’s hierarchical names. For instance, QuickBooks could have two different parent accounts each with a subaccount named "Insurance". In Beancount, Expenses:Insurance must be unique. Resolve this by renaming one (e.g., "Insurance-Vehicle" vs "Insurance-Health") before export or map them to unique Beancount accounts in your script. Consistent naming conventions (no special characters, and use of hierarchy) will save headaches. Use the remapping file approach if needed: maintain a CSV or dictionary of old name → new Beancount name and apply it during conversion (our example code uses an account_map and could load overrides from a file).

  • Dates and Formats: Ensure all dates are consistently formatted. The script above normalizes M/D/Y to ISO format. Also, watch out for fiscal year vs calendar year issues if your five-year span crosses a year-end. Beancount doesn’t care about fiscal year boundaries, but you might later want to split files by year for convenience.

  • Numerical Precision: QuickBooks handles currency with cents, so working in cents is usually fine. All amounts should ideally have two decimal places in the CSV. If any amounts turned into integers (no decimal) or have commas/parentheses (for negatives), clean those in the script (strip commas, convert (100.00) to -100.00, etc.). The CSV export if done correctly (as per instructions) should already avoid those formatting issues.

  • Negative Amounts and Signs: QuickBooks reports sometimes show negatives as -100.00 or as (100.00) or even --100.00 in certain Excel exports. The cleaning step should handle these. Ensure that each transaction’s debits and credits balance out to zero. Beancount will enforce this (if not balanced, it will throw an error on import).

  • Transaction Duplicates: If you had to export transactions in batches (e.g., year by year or account by account), be careful to merge them without overlap. Check that the first transaction of a year isn’t also the last of the previous batch, etc. It’s easy to accidentally duplicate a few transactions at the boundaries. If you suspect duplicates, you can sort the final Beancount entries by date and look for identical entries, or use Beancount’s unique transaction tags to catch them. One strategy is to include QuickBooks transaction numbers as metadata (e.g., use the Trans # or invoice number as a txn tag or quickbooks_id metadata) and then ensure no duplicates of those IDs exist.

  • Unbalanced Splits / Suspense Accounts: QuickBooks might have odd cases like a transaction with an imbalance that QuickBooks auto-adjusted to a “Opening Balance Equity” or “Retained Earnings”. For example, when setting up initial account balances, QuickBooks often posts differences to an Equity account. These will appear in the exported transactions. Beancount will require explicit balancing. You might need to introduce an Equity account for opening balances (commonly Equity:Opening-Balances) to mirror QuickBooks. It’s good practice to have an opening balance entry on the first day of your ledger that establishes starting balances of all accounts (see Stage 5).

  • Multi-currency Edge Cases: If using multi-currency, QuickBooks’s export might list all amounts in home currency or in their native currency. Ideally, get the data in native currency for each account (QuickBooks Online’s reports usually do this). In Beancount, each posting carries a currency. If QuickBooks provided exchange rates or a home-currency conversion, you might ignore those and rely on Beancount’s price entries. If QuickBooks did not export exchange rates, you may want to manually add price records (e.g., using Beancount’s price directive) for key dates to match valuation. However, for basic ledger integrity, it’s enough that transactions balance in their original currencies – unrealized gains/losses don’t need to be explicitly recorded unless you want the same reports.

  • Accounts Receivable / Accounts Payable: QuickBooks tracks invoice and bill details (due dates, paid status, etc.) which won’t fully transfer in a plain ledger. You will get the A/R and A/P transactions (invoices increasing A/R, payments decreasing A/R, etc.), but not the invoice documents or customer balances per invoice. As a result, after migration, you should verify that your A/R and A/P account balances in Beancount equal the open balances of customers/vendors in QuickBooks. If you need to track invoices, you might use Beancount’s metadata (e.g., include an invoice tag or link). The QuickBooks invoice numbers should have come through in the Num or Memo fields – our script preserves the Num as number: "..." in the transaction metadata.

  • Inactive or Closed Accounts: The IIF export might include inactive accounts (if you chose to include them). It’s fine to import them (they will just have no transactions and a zero balance if truly inactive). You may mark them as closed in Beancount after the last transaction date with a close directive. This keeps your ledger tidy. For example: 2023-12-31 close Expenses:OldAccount ; closed after migration This is optional and mostly for cleanliness.

By carefully cleaning and mapping the data as above, you’ll have a Beancount ledger file that structurally mirrors your QuickBooks data. The next step is to verify that it also numerically mirrors QuickBooks.

Stage 3: Data Validation and Reconciliation

Validation is a critical stage in an accounting data migration. We need to ensure the Beancount ledger matches the QuickBooks books to the penny. Several strategies and tools can be used:

3.1 Trial Balance Reconciliation

A trial balance report lists ending balances of all accounts (with debits and credits or positive/negative indicated) and should net to zero. Running a trial balance in both systems for the same date is the fastest way to confirm overall accuracy.

  • In QuickBooks: Run a Trial Balance report for the last day of the final year (e.g., December 31, 2023). This report shows each account’s balance. Export it or note down key figures.

  • In Beancount: Use Beancount’s reporting to generate a trial balance. One easy method is via the command line:

    bean-report migrated.beancount balances

    The balances report is a trial balance listing all accounts and their balances. You can also open the file in Fava (Beancount’s web UI) and look at the Balances or Balance Sheet section. Every account balance in Beancount should match the QuickBooks trial balance. For example, if QuickBooks shows Accounts Receivable = $5,000, then Beancount’s Assets:Accounts Receivable account should total $5,000 (debit). If Sales Income = $200,000, the Income:Sales in Beancount should show $200,000 (credit, which might display as -200,000 if using a trial balance that presents credits as negatives).

If there are discrepancies, pinpoint them:

  • Check if an entire account is missing or extra (did we forget an account or include one that was already closed before the migration period?).
  • If a balance is off, drill down: QuickBooks can run an Account QuickReport or ledger detail for that account, and you can compare with Beancount’s register for that account (bean-report migrated.beancount register -a AccountName). Sometimes differences come from a missing transaction or a duplicate.

Also verify the sum of all accounts is zero in Beancount’s trial balance (it prints a total that should be zero or very close to zero). Beancount enforces double-entry, so if you have any non-zero imbalance, it means assets minus liabilities-equity didn’t net to zero, indicating an issue (which QuickBooks would not normally allow either, but could happen if some data was dropped).

3.2 Account Balance Comparisons

Beyond trial balance, you can compare specific financial statements:

  • Balance Sheet: Run a QuickBooks Balance Sheet for the final date and a Beancount balance sheet (bean-report migrated.beancount balsheet). This is similar to trial balance but organized by Assets, Liabilities, Equity. The numbers should align category-wise. For a more granular check, compare major account totals: cash, A/R, fixed assets, accounts payable, equity, etc.

  • Profit & Loss (Income Statement): Run a Profit & Loss for the five-year period (or year by year) in QuickBooks and in Beancount (bean-report migrated.beancount income for a full-period income statement). The net income from Beancount should equal QuickBooks for each period. If you migrated all five years, the cumulative net income should match. You can also compare individual revenue and expense totals to ensure no category was missed or doubled.

  • Random Transaction Sampling: Pick a few random transactions (especially from each year and each major account) and verify they migrated correctly. For instance, find an invoice from 3 years ago in QuickBooks and then search for its amount or memo in the Beancount file (since all transactions are text, you can open the .beancount file in a text editor or use search tools). Check that the date, amounts, and accounts match. This helps catch any date formatting issues or mis-mapped accounts.

3.3 Automated Integrity Checks

Leverage Beancount’s own validation tools:

  • bean-check: Run bean-check migrated.beancount. This will parse the file and report any errors in syntax or balancing. If the script missed something like an account not opened or a transaction not balanced, bean-check will flag it. A clean pass (no output) means the file is at least internally consistent.

  • Balance Assertions: You may add explicit balance assertions in the ledger for key accounts as an extra check. For example, if you know the bank account balance on a certain date, add a line: 2023-12-31 balance Assets:Bank:Checking 10000.00 USD Then bean-check will ensure that in the ledger, as of that date, the balance is indeed $10,000. This is optional but can be useful for high importance accounts. You could take ending balances from QuickBooks (e.g., end of each year) and assert them in the Beancount file. If any assertion fails, Beancount will report a difference.

  • Trial Balance Rollforward: If you prefer, you can do a period-by-period check. For each year, compare the net change. For example, net income in QuickBooks 2020 vs Beancount 2020, etc., to ensure each year closed properly into equity (QuickBooks automatically rolls net income into Retained Earnings each new year; in Beancount you’ll just see cumulative equity). If you see differences, it might indicate an issue in a specific year’s data.

  • Transaction Counts and Duplicates: Count the number of transactions in QuickBooks vs Beancount. QuickBooks doesn’t show a direct count easily, but you can gauge by counting lines in the CSV (each transaction header vs splits). In Beancount, a quick way is to count occurrences of txn or * " in the file. They should be equal to or slightly above QuickBooks (if you added opening balance transactions or adjustments). A significant mismatch means something might have been omitted or duplicated. Our use of unique IDs in metadata can assist: if you suspect duplicates, search the Beancount file for the same check number or invoice number appearing twice when it shouldn’t.

  • Reconciliation status: We included a rec: "y" or "n" metadata based on QuickBooks’ cleared status in our script (as rec in the example). This isn’t a standard Beancount feature (Beancount doesn’t track cleared/pending in the same way as Ledger), but it can be helpful metadata. You might verify that all transactions that were reconciled in QuickBooks are present. Ultimately, reconciling bank accounts in Beancount anew (using your statements) could be the final proof that nothing is missing.

By performing these validations, you build confidence that the migration preserved the data. Take your time with this stage – it’s easier to fix anomalies now than months later when books might be relied on. Common issues if validation fails: an account’s opening balance missing, a transaction dated outside the range, or a sign inversion on an entry. All are fixable once identified.

Stage 4: Committing to the Beancount Ledger

After cleaning and validating, it’s time to formalize the data into your Beancount ledger structure. “Committing” here means both finalizing the ledger files and potentially checking them into a version control system for auditability.

4.1 Organizing Ledger Files and Configuration

Decide how to structure the Beancount ledger files. For five years of data, you can keep everything in one file or split by year or category. A common, clear structure is:

  • Main Ledger File: e.g., ledger.beancount – This is the entry point that can include other files. It might contain global options and then include yearly files.
  • Accounts File: Define the chart of accounts and opening balances. For example, accounts.beancount with all the open directives (as generated by the script). You might also list commodities (currencies) here.
  • Transactions Files: One per year, e.g., 2019.beancount, 2020.beancount, etc., containing transactions for that year. This keeps each file a manageable size and lets you focus on a year if needed. Alternatively, you can split by entity or account, but time-based splitting is straightforward for financial data.

Example main file:

option "title" "My Business Ledger"
option "operating_currency" "USD"

include "accounts.beancount"
include "2019.beancount"
include "2020.beancount"
...
include "2023.beancount"

This way, all data is aggregated when you run reports, but you maintain order.

Beancount doesn’t require multiple files – you could have one big file – but the above structure improves clarity and version control. According to Beancount best practices, it’s good to use clear section headers and group related entries logically.

4.2 Setting Opening Balances and Equity

If your migration is not from an absolute zero start, you’ll need to handle opening balances. Two scenarios:

  • Books starting from scratch: If the five-year period starts at inception of the business (e.g., you started using QuickBooks in Jan 2019 with all accounts zeroed out except initial equity), then you might not need a separate opening balance transaction. The first transactions in 2019 (like initial funding to a bank account) will naturally establish beginning balances. Just ensure any initial capital or retained earnings prior are accounted for via equity transactions.

  • Books mid-stream (partial history): If you began QuickBooks earlier and 2019 is a mid-point, then as of 1 Jan 2019 each account had a balance brought forward. QuickBooks would have those as opening balances or retained earnings. In Beancount, it’s typical to create an Opening Balances entry on the day before your start date:

    • Use an equity account called Equity:Opening-Balances (or similar) to offset the sum of all opening amounts.
    • Example: if on 2018-12-31, Cash was $10,000 and A/R $5,000 and A/P $3,000 (credit), you’d write a transaction: 2018-12-31 * "Opening Balances" Assets:Cash 10000.00 USD Assets:Accounts Receivable 5000.00 USD Liabilities:Accounts Payable -3000.00 USD Equity:Opening-Balances -12000.00 USD This leaves Opening-Balances with the negative sum (–$12k) which balances the entry. Now all asset/liability accounts start 2019 with correct balances. This should mirror any QuickBooks “Retained Earnings” or carry-over balances.
    • Alternatively, use Beancount’s pad and balance directives: For each account, you can pad it from Opening-Balances and assert the balance. This is a more automated way. For example: 2018-12-31 pad Assets:Cash Equity:Opening-Balances 2018-12-31 balance Assets:Cash 10000.00 USD This tells Beancount to insert whatever entry needed (to Opening-Balances) so that Cash equals 10000 USD at that date. Do this for each account. The result is similar, but writing an explicit transaction as in the first method is straightforward too.
  • Retained Earnings: QuickBooks doesn’t explicitly export a “Retained Earnings” transaction – it just computes it. After migration, you might notice Equity:Retained Earnings is zero if you didn’t create it. In Beancount, retained earnings are just prior years’ profit. You can choose to create a Retained Earnings account and transfer prior profits into it on the first day of each new year, or simply let equity be the sum of all income/expenses (which appears under Equity section in reports). For transparency, some users journal closing entries annually. This is optional and mainly for presentation. Since we migrated all transactions, the profit for each year will naturally roll up if you run a report per year.

  • Comparative Checks: After setting opening balances, run a balance sheet on the start date to ensure everything is correct (it should show those opening balances vs Opening Equity netting to zero).

4.3 Finalizing and Version Control

Now that the data is in Beancount format and structured, it’s wise to commit the files to a version control repository (e.g., git). Each change to the ledger can be tracked, and you have an audit trail of all modifications. This is a major advantage of plaintext accounting. For example, in QuickBooks changes might not be easily diffable, but in Beancount, you can see line-by-line differences. As some users note, with Beancount you get transparency and the ability to revert changes if needed – every entry can be tied to a change history.

Consider tagging the commit of this initial migration as v1.0 or similar, so you know it represents the state of books as imported from QuickBooks. Going forward, you’ll enter new transactions directly in Beancount (or import from bank feeds, etc.), and you can use normal software development practices (committing monthly or daily, using branches for experiments, etc.).

Setting up Fava or other tools: Fava is a web interface for Beancount that makes it easy to view reports. After committing, run fava ledger.beancount to browse the financial statements and compare them with your QuickBooks reports one last time. You might spot small differences more easily in a UI (for example, an account that should be zero but shows a small balance indicates a missing closing entry or a stray transaction).

Naming conventions and consistency: You have full control now, so ensure consistency:

  • All accounts should have clear names, starting with capitalized category names (Assets, Liabilities, etc.). If any look odd (e.g., Assets:assets:SomeAccount due to a case mismatch from QuickBooks), rename them in the accounts file and update the transactions (a quick find/replace on the file can do this, or use Beancount’s bean-format or editor multi-cursor).
  • Commodity symbols (currency codes) should be consistent. For USD, use USD everywhere (not $ or US$). For others, use standard codes (EUR, GBP, etc.). This consistency is important for Beancount’s price lookups and reports.
  • Remove any temporary or dummy accounts that might have been created (for example, if you used Expenses:Miscellaneous for unknown accounts in the script as a catch-all, try to eliminate those by properly mapping all accounts).

Closing QuickBooks: At this point, you should have parallel books in Beancount that match QuickBooks. Some choose to run both systems in parallel for a short period to ensure nothing was missed. But if validation is solid, you can “close” the QuickBooks books:

  • If this is a corporate environment, consider exporting all QuickBooks source documents (invoices, bills, receipts) for records, since those won’t exist in Beancount unless you attach them manually.
  • Keep a backup of the QuickBooks data (both the company file and the export files).
  • Going forward, maintain the Beancount ledger as the primary system of record.

By committing the data into the Beancount ledger, you have completed the migration pipeline. The final step is to perform an audit and demonstrate consistency of financial statements, to satisfy yourself (and any stakeholders or auditors) that the migration was successful.

Stage 5: Post-Migration Audit and Examples

To illustrate the success of the migration, prepare a before-and-after comparison of financial statements and possibly a diff of transactions. This provides evidence that the books are consistent.

5.1 Verifying Financial Statements

Produce key financial reports from both QuickBooks and Beancount for the same dates and compare:

  • Balance Sheet as of Dec 31, 2023: Compare Assets, Liabilities, and Equity totals line by line. They should match. For example, if QuickBooks showed Total Assets = $150,000 and Total Liabilities + Equity = $150,000, the Beancount balance sheet should show the same totals. If you structured accounts slightly differently (say you merged some subaccounts), adjust for that in comparison or break down to the next level to ensure sums are equal.

  • Profit & Loss 2019–2023: Ensure total Income, total Expenses, and Net Profit for each year (or the whole range) are identical. Minor differences could arise if QuickBooks did some rounding on reports, but transactions usually carry cents exactly so net profit should be exact. If any year’s profit differs, drill down into that year’s data – often an indicator of a missing or duplicate entry in that period.

  • Trial Balance Differences: If possible, create a spreadsheet where you list each account and the balance from QuickBooks vs Beancount. Since we expect them to match, this might be an all-zero difference column. This is essentially the trial balance cross-check we discussed, but writing it out helps document it.

5.2 Example Comparison (Before vs After)

Below is an example snippet demonstrating data consistency. Let’s say our QuickBooks trial balance for Dec 31, 2023 was:

AccountQuickBooks Balance (Dec 31, 2023)
Assets
  Assets:Bank:Checking$12,500.00 (debit)
  Assets:Accounts Receivable$3,200.00 (debit)
Liabilities
  Liabilities:Credit Card$-1,200.00 (credit)
  Liabilities:Loans Payable$-5,000.00 (credit)
Equity
  Equity:Opening-Balances$-7,500.00 (credit)
  Equity:Retained Earnings$-2,000.00 (credit)
  Equity:Current Year Profit$0.00

In Beancount, after importing and posting all transactions up to 2023, a bean-report balances (trial balance) outputs:

AccountBeancount Balance (Dec 31, 2023)
Assets
  Assets:Bank:Checking12,500.00 USD (debit)
  Assets:Accounts Receivable3,200.00 USD (debit)
Liabilities
  Liabilities:Credit Card-1,200.00 USD (credit)
  Liabilities:Loans Payable-5,000.00 USD (credit)
Equity
  Equity:Opening-Balances-7,500.00 USD (credit)
  Equity:Retained Earnings-2,000.00 USD (credit)
  Equity:Profit (2019-2023)0.00 USD

(Note: Equity sections might be structured differently; the key is totals align. Here, “Profit (2019-2023)” in Beancount plays the role of current year profit/retained earnings combined, showing zero because profit was closed into Retained Earnings.)

As shown, every account matches to the cent. The sum of debits equals sum of credits on both sides.

Additionally, if we run a Profit & Loss for 2023:

  • QuickBooks: Income $50,000, Expenses $48,000, Net Profit $2,000.
  • Beancount: Income $50,000, Expenses $48,000, Net Profit $2,000 (which then got closed to Retained Earnings or appears under Equity in year-end balance sheet).

You can create a diff of transactions if needed, but since QuickBooks data isn’t in ledger form, it’s more effective to rely on reports. One could sort both the QuickBooks CSV and the Beancount transactions by date and compare key fields as a final check (this can be done in Excel or with a script). However, given that we trust our earlier validation, the financial statements check is usually sufficient.

5.3 Auditing Tips

  • If an auditor or stakeholder needs reassurance, present the before-and-after financial statements side by side. The transparency of Beancount can actually simplify audits because you can trace every number from a statement back to the source entry quickly (especially using Fava’s drill-down functionality).
  • Keep the QuickBooks backup and exported CSVs as part of your audit trail. Document any adjustments made during migration (for example, “Renamed account X to Y for consistency” or “Split transaction Z into two entries for clarity” if you did such changes).
  • Going forward, implement regular checks in Beancount. For instance, monthly reconciliation of bank accounts and an assertion of their ending balance helps catch any data issues or mistakes in entry. The migration gives a good baseline; maintaining discipline in the new system will ensure continued accuracy.

Finally, celebrate the migration completion: you have successfully transferred five years of accounting data from QuickBooks to Beancount. The data is now in a lightweight, version-controlled text format with full double-entry integrity. You’ve exported the data, transformed it with Python scripts, validated the integrity through trial balances and reports, and committed it into a well-organized Beancount ledger. This comprehensive process ensures that the Beancount ledger is an accurate, faithful replica of your QuickBooks books over the five-year period, setting you up for streamlined accounting going forward.

Introducing Multi-File Support in Beancount

· 2 min read
Mike Thrift
Mike Thrift
Marketing Manager

Many of our customers have been asking us how to add multiple files to one ledger since February. They need the file structure to archive or categorize transactions. So, finally, after a couple of months of work, we are glad to announce the feature is released for free.

Here is how to use it:

File > create a new file

2021-09-24-multi-file-one-ledger

Go to the file editor tab on the left navigation sidebar. And then, follow the "File" dropdown and click "Create a new file".

File > create a new file

Name your new file

Give your file a valid filename and save it. All filenames must be ended with ".bean".

Name your new file

Include the file

Here is a crucial step, you have to include the newly-created file in main.bean.

For example, if you added stock.bean, then specify include "stock.bean" in main.bean.

Include the file

Refresh and navigate to file

Refresh the page, and you will see the file appears in the "File" dropdown.

Refresh and go to file

Rename or delete the file

When navigated to the file, you could rename or delete it in the "Edit" dropdown.

Rename or delete the file

Having troubles?

Ask questions in https://t.me/beancount.

Fava Upgrade to Version 1.19: Key Changes and Improvements

· One min read
Mike Thrift
Mike Thrift
Marketing Manager

We upgraded the MIT-licensed open-source software Fava to version 1.19. Here are the changes since our last update:

  • v1.19 (2021-05-18)
    • migrate from conversion and interval options to default-page option
    • add option invert-income-liabilities-equity
    • upgrade to CodeMirror 6
    • adds a Bulgarian translation
    • other small improvements and bug fixes
  • v1.18 (2021-01-16)
    • couple of small improvements and various bug fixes.

Feeling excited? Try it now at https://beancount.io/ledger/

2021-07-16-upgrade-fava-to-1-19

Having questions? We will be there for you at https://t.me/beancount :)