Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -19,3 +19,5 @@ site/
!README.md
!CONTRIBUTING.md
!docs/**/*
.cache
__pycache__
4 changes: 4 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
#!/usr/bin/env make

serve:
uv run mkdocs serve
2 changes: 1 addition & 1 deletion docs/command_line_accounting_in_context.md
Original file line number Diff line number Diff line change
Expand Up @@ -363,7 +363,7 @@ The thing is, although I am by nature quite methodical, I would sometimes, just

But one day… one day… I saw the light: I discovered the double-entry method. I don’t recall exactly how. I think it was on a website, yes… this site: [<u>dwmbeancounter.com</u>](http://www.dwmbeancounter.com/) (it’s a wonderful site). I realized that using a *single system*, I could account for all of these problems at the same time, and in a way that would impose an inherent error-checking mechanism. I was blown away! I think I printed the whole thing on paper at the time and worked my way through every tutorial. This simple counting trick is exactly what I was in dire need for.

But all the software I tried was either disappointing, broken, or too complicated. So I read up on Ledger. And I got in touch with [<u>its author</u>](http://www.newartisans.com/). And then shortly after I started on Beancount[^1]. I’ll admit that going through the effort of designing my own system just to solve my accounting problems is a bit overkill, but I’ve been known to be a little more than extreme about [<u>certain things</u>](http://furius.ca/salsa-book/), and I’ve really enjoyed solving this problem. My life is fulfilled when I maintain a good balance of “learning” and “doing,” and this falls squarely in the “doing” domain.
But all the software I tried was either disappointing, broken, or too complicated. So I read up on Ledger. And I got in touch with [<u>its author</u>](http://www.newartisans.com/). I found the concept amazon, but I wanted a Python interface to it. And then shortly after I started on Beancount[^1]. I’ll admit that going through the effort of designing my own system just to solve my accounting problems is a bit overkill, but I’ve been known to be a little more than extreme about [<u>certain things</u>](http://furius.ca/salsa-book/), and I’ve really enjoyed solving this problem. My life is fulfilled when I maintain a good balance of “learning” and “doing,” and this falls squarely in the “doing” domain.

Ever since, I feel so excited about anything related to personal finance. Probably because it makes me so happy to have such a level of awareness about what’s going on with mine. I even sometimes find myself *loving* spending money in a new way, just from knowing that I’ll have to figure out how to account for it later. I feel so elated by the ability to solve these financial puzzles that I have had bouts of engaging complete weekends in building this software. They are small challenges with a truly practical application and a tangible consequence. Instant gratification. I get a feeling of *empowerment*. And I wish the same for you.

Expand Down
37 changes: 37 additions & 0 deletions docs/css/custom.css
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,40 @@
.doc-contents details {
margin-bottom: 24px;
}

/*
Force Theme Colors (#0065a3 and #a6c4da)
Targeting Material's specific color scheme attributes to prevent overrides
*/

:root, [data-md-color-scheme="default"], [data-md-color-scheme="slate"] {
--md-primary-fg-color: #0065a3;
--md-primary-fg-color--light: #a6c4da;
--md-primary-fg-color--dark: #004b7a;

--md-accent-fg-color: #a6c4da;
--md-accent-fg-color--transparent: rgba(166, 196, 218, 0.1);
}

/* Header and Tabs specific overrides */
.md-header {
background-color: #0065a3 !important;
}

.md-tabs {
background-color: #0065a3 !important;
}

/* Link and active element colors */
.md-typeset a {
color: #0065a3;
}

.md-nav__link--active {
color: #0065a3 !important;
}

/* Search bar focus */
.md-search__input:focus {
background-color: #fff;
}
8 changes: 7 additions & 1 deletion docs/getting_started_with_beancount.md
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,8 @@ Here’s what the opening accounts might look like for an investment account:

The point is that all these accounts are related somehow. The various sections of the cookbook will describe the set of accounts suggested to create for each section.

A note about the above: if you don't like the redundancy of the currency appearing both in the account name and in the constraint, you can place more than a single current in an account, Beancount handles that just fine. Doing it as per the above example just helps for some configurations with, e.g., beangrow.

Not all sections have to be that way. For example, I have the following sections:

- **Eternal accounts.** I have a section at the top dedicated to contain special and “eternal” accounts, such as payables and receivables.
Expand Down Expand Up @@ -147,7 +149,7 @@ The credit card download will yield you this:
2014-06-10 * "AMEX EPAYMENT ACH PMT"
Liabilities:US:Amex:Platinum 923.24 USD

Many times, transactions from these accounts need to be booked to an expense account, but in this case, these are two separate legs of the same transaction: a transfer. When you import one of these, you normally look for the other side and merge them together:
Many times, transactions from these accounts need to be booked to an expense account, but in this case, these are two separate legs of the same transaction: a transfer. When you import one of these, you typicallynormally look for the other side and merge them together:

;2014-06-08 * "ONLINE PAYMENT - THANK YOU"
2014-06-10 * "AMEX EPAYMENT ACH PMT"
Expand All @@ -174,6 +176,10 @@ So if you organize your account in sections the way I suggest above, which secti

Personally I’m a little careless about being consistent which of the section I choose to leave the transaction in; sometimes I choose one section of my input file, or that of the other account, for the same pair of accounts. It hasn’t been a problem, as I use Emacs and i-search liberally which makes it easy to dig around my gigantic input file. If you want to keep your input more tidy and organized, you could come up with a rule for yourself, e.g. “credit card payments are always left in the paying account’s section, not in the credit card account’s section”, or perhaps you could leave the transaction in both sections and comment one out[^2].

### Suspense Accounts<a id="suspense-accounts"></a>

Eventually the correct thing to be done will be to support [<u>suspense accounts</u>](https://www.google.com/url?q=http://en.wikipedia.org/wiki/Suspense_account&sa=D&source=docs&ust=1776012592990052&usg=AOvVaw0ucmanriL2B86xf-AgKu1l) (which I also refer to as "transfer accounts" in these documents). This will be done with an input style that involves inputting two incomplete transactions with a way to automatically link together those transactions in order to avoid forgotten amounts posted to transfer/suspense accounts. See [<u>this document</u>](settlement_dates_in_beancount.md) for a discussion.

## Padding<a id="padding"></a>

If you’re just starting out—and you probably are if you’re reading this—you will have no historical data. This means that the balances of your Assets and Liabilities accounts in Beancount will all be zero. But the first thing you should want to do after defining some accounts is establish a balance sheet and bring those amounts to their actual current value.
Expand Down
41 changes: 41 additions & 0 deletions docs/hooks/strip_manual_toc.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
import re
import os

def on_page_markdown(markdown, page, **kwargs):
# 1. Strip manual TOCs
lines = markdown.split('\n')
new_lines = []
in_toc_area = True

# Pattern for manual TOC links: [<u>...</u>](#...) or > [<u>...</u>](#...)
toc_pattern = re.compile(r'^(\s*>\s*)?\[(?:<u>)?.*(?:</u>)?\]\(#.*\)\s*$')

for line in lines:
stripped_line = line.strip()

# Once we hit the first H2 header, we are definitely out of the TOC area.
if stripped_line.startswith('## '):
in_toc_area = False

if in_toc_area and stripped_line:
if toc_pattern.match(stripped_line):
continue

new_lines.append(line)

markdown = '\n'.join(new_lines)

# 2. Fix image paths for use_directory_urls: true
# If page is 'foo.md', and it contains <img src="foo/media/bar.png">,
# it should be converted to <img src="media/bar.png"> because with
# use_directory_urls: true, the page is served from 'foo/index.html'

page_name = os.path.splitext(os.path.basename(page.file.src_path))[0]

# Replace src="page_name/media/ with src="media/
# Using 'media/' directly because the page is at 'page_name/' and the folder is at 'page_name/media/'
markdown = re.sub(fr'src="{page_name}/media/', 'src="media/', markdown)
# Also handle markdown-style images ![alt](page_name/media/...)
markdown = re.sub(fr'\]\({page_name}/media/', '](media/', markdown)

return markdown
Binary file added docs/img/logo.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
16 changes: 10 additions & 6 deletions docs/installing_beancount.md
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,14 @@ Beancount supports setuptools since Feb 2016, and you will need to install depen

### Installing Beancount<a id="installing-beancount"></a>

#### Installing Beancount using uv<a id="installing-beancount-using-uv"></a>

By far the easiest way to run beancount in 2026 is via uv, e.g.,

uvx --from beancount <command>

See the uv manual for more details.

#### Installing Beancount using pipx<a id="installing-beancount-using-pipx"></a>

If you haven’t already, first [<u>install pipx</u>](https://github.com/pypa/pipx).
Expand Down Expand Up @@ -98,11 +106,7 @@ You can then install all the dependencies and Beancount itself using pip:

##### Installing for Development<a id="installing-for-development"></a>

If you want to execute the source in-place for making changes to it, you can use the setuptools “develop” command to point to it:

sudo python3 setup.py develop

Warning: This modifies a .pth file in your Python installation to point to the path to your clone. You may or may not want this. I don't do this myself; the way I work is by compiling locally and setting up my shell's environment to find its libraries. You can do it like this:
If you want to compile and execute the source in-place for making changes to it, you can do it like this:

make build

Expand Down Expand Up @@ -326,7 +330,7 @@ The newly released Windows 10 Anniversary Update brings WSL 'Windows Subsystem f
This makes beancount installation easy, from bash:

sudo apt-get install python3-pip
sudo pip3 install m3-cdecimal
sudo pip3 install m3-cdecimal # probably not needed anymore
sudo pip3 install beancount --pre

This is not totally “Windows compatible”, as it is running in a pico-process, but provides a convenient way to get the Linux command-line experience on Windows. *(Contrib: willwray)*
Expand Down
7 changes: 7 additions & 0 deletions docs/javascripts/shortcuts.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
keyboard$.subscribe(function(key) {
if (key.mode === "global" && key.type === "k" && (key.ctrl || key.meta)) {
/* Focus the search input */
document.querySelector(".md-search__input").focus()
key.claim() // Prevent default browser behavior
}
})
102 changes: 90 additions & 12 deletions mkdocs.yml
Original file line number Diff line number Diff line change
@@ -1,14 +1,44 @@
site_name: Beancount Documentation
site_description: Auto-generated markdown version
site_url: "https://beancount.github.io/docs/"
strict: false
use_directory_urls: true

# Don't show "Edit on GitHub" link
# repo_url: https://github.com/beancount/docs
use_directory_urls: false
repo_url: https://github.com/beancount/docs
repo_name: beancount/docs

theme:
name: readthedocs
highlightjs: false
name: "material"
palette:
- media: "(prefers-color-scheme)"
toggle:
icon: material/brightness-auto
name: "Switch to light mode"
- media: "(prefers-color-scheme: light)"
scheme: default
toggle:
icon: material/brightness-7
name: "Switch to dark mode"
- media: "(prefers-color-scheme: dark)"
scheme: slate
toggle:
icon: material/brightness-4
name: "Switch to system preference"
features:
- search.suggest
- search.highlight
- content.tabs.link
- content.code.annotate
- content.code.copy
- content.code.select
- navigation.path
- navigation.indexes
- navigation.sections
- navigation.tracking
- toc.follow
- announce.dismiss
logo: "img/logo.png"
favicon: "img/logo.png"

nav:
- Index: index.md
Expand Down Expand Up @@ -67,28 +97,76 @@ nav:
- api_reference/beancount.tools.md
- api_reference/beancount.utils.md

extra_css:
- css/custom.css
extra_javascript:
- javascripts/shortcuts.js

extra:
version:
provider: mike

markdown_extensions:
- tables
- admonition
- attr_list
- md_in_html
- footnotes
- toc:
permalink: 
- footnotes
- pymdownx.details
- pymdownx.caret
- pymdownx.critic
- pymdownx.mark
- pymdownx.superfences
- pymdownx.snippets
- pymdownx.tilde
- pymdownx.inlinehilite
- pymdownx.highlight:
pygments_lang_class: true
- pymdownx.extra:
pymdownx.superfences:
custom_fences:
- name: mermaid
class: mermaid
format: !!python/name:pymdownx.superfences.fence_code_format
- pymdownx.emoji:
emoji_index: !!python/name:material.extensions.emoji.twemoji
emoji_generator: !!python/name:material.extensions.emoji.to_svg
- pymdownx.tabbed:
alternate_style: true
- pymdownx.tasklist:
custom_checkbox: true
- sane_lists

validation:
omitted_files: warn
absolute_links: warn
unrecognized_links: warn
anchors: warn

plugins:
- search
- social
- glightbox
- mike
- mkdocstrings:
default_handler: python
handlers:
python:
rendering:
options:
show_source: true
show_object_full_path: true
selection:
# 3 because docs are in pages with an H2 just above them
heading_level: 3
filters:
- "!_test$"
- "!^_[^_]"
inventories:
- url: https://docs.python.org/3/objects.inv
- url: https://docs.pydantic.dev/latest/objects.inv
- redirects:
redirect_maps:
'g/export/index.md': 'https://docs.google.com/document/d/1mNyE_ONuyEkF_I2l6V_AoAU5HJgI654AOBhHsnNPPqw/'

# Additional styles for readthedocs theme
extra_css:
- css/custom.css
hooks:
- docs/hooks/strip_manual_toc.py