> ## Documentation Index
> Fetch the complete documentation index at: https://ngquct-docs-fix-500-query-results.mintlify.site/llms.txt
> Use this file to discover all available pages before exploring further.

# Beancount

> Backend requirements, the table layout, source locations, includes, and BQL support

export const name_0 = "Beancount"

export const plugin_0 = "Beancount Driver"

Install `rledger` or Python Beancount before you connect. The plugin parses nothing itself: it shells out to one of those two and projects the answer into 17 read-only SQL tables.

The {name_0} driver is not in the app. Picking {name_0} in the **Choose a Database** sheet offers the
download before the form opens, and opening a saved {name_0} connection installs it without asking.
**Settings > Plugins > Browse > {plugin_0}** installs it up front. See [Plugins](/features/plugins).

## Backend requirements

Either backend browses the tables, at any version. Install `rledger` if you are choosing: it wins when both are present, it is the only one that fills `diagnostics`, and BQL runs through it and nothing else.

<CodeGroup>
  ```bash rledger theme={null}
  # build or download rustledger, put it on PATH, then:
  rledger --version
  ```

  ```bash Python Beancount theme={null}
  pip3 install beancount
  python3 -c "import beancount"
  ```
</CodeGroup>

An app launched from Finder does not inherit your shell's `PATH`, so a backend that answers in Terminal can still be invisible. Name it outright, then relaunch:

```bash theme={null}
launchctl setenv TABLEPRO_RUSTLEDGER_BINARY /opt/homebrew/bin/rledger
launchctl setenv TABLEPRO_BEANCOUNT_PYTHON /opt/homebrew/bin/python3
```

`TABLEPRO_BEANCOUNT_BACKEND` overrides which one wins. It takes `rledger` or `python`.

## Quick setup

<Steps>
  <Step title="Create a connection">
    Click **Create Connection…** and choose **Beancount**.
  </Step>

  <Step title="Choose your ledger">
    Click **Browse…** and select a `.beancount` file. No host, no port, no password, no Database field: the ledger path is the whole connection.
  </Step>

  <Step title="Connect">
    Click **Save & Connect**.
  </Step>
</Steps>

<Frame caption="A Beancount ledger projected into SQL tables">
  <img className="block dark:hidden" src="https://mintcdn.com/ngquct-docs-fix-500-query-results/hA72m8tSnRe3b-ew/images/beancount-ledger-tables.png?fit=max&auto=format&n=hA72m8tSnRe3b-ew&q=85&s=e1f715a1c43928687bb59f35b8ed8467" alt="Beancount ledger open in TablePro with projected tables in the sidebar" width="1560" height="960" data-path="images/beancount-ledger-tables.png" />

  <img className="hidden dark:block" src="https://mintcdn.com/ngquct-docs-fix-500-query-results/hA72m8tSnRe3b-ew/images/beancount-ledger-tables-dark.png?fit=max&auto=format&n=hA72m8tSnRe3b-ew&q=85&s=3a255972eae8107ee787c8ed2022699c" alt="Beancount ledger open in TablePro with projected tables in the sidebar" width="1560" height="960" data-path="images/beancount-ledger-tables-dark.png" />
</Frame>

## Connection URL

```text theme={null}
beancount:///path/to/main.beancount
```

Three slashes: the path is absolute. See [Connection URL Reference](/connections/urls).

## Tables

| Table                                      | Contents                                                                                          |
| ------------------------------------------ | ------------------------------------------------------------------------------------------------- |
| `transactions`                             | Date, flag, payee, narration, source location. Includes transactions with no postings             |
| `postings`                                 | Account, amount, commodity, resolved cost basis (`cost_number`, `cost_currency`), source location |
| `accounts`                                 | Opened accounts and declared currencies                                                           |
| `prices`                                   | Price directives                                                                                  |
| `balances`                                 | Computed account balances by commodity                                                            |
| `balance_assertions`                       | Beancount balance directives                                                                      |
| `commodities`                              | Commodity directives                                                                              |
| `documents`                                | Document directives, their attached paths, tags, and links                                        |
| `notes`                                    | Account notes                                                                                     |
| `events`                                   | Event type and description directives                                                             |
| `closes`                                   | Close directives                                                                                  |
| `transaction_metadata`, `posting_metadata` | Metadata key/value pairs                                                                          |
| `transaction_tags`, `transaction_links`    | Tags and links                                                                                    |
| `diagnostics`                              | Validation output from `rledger check`                                                            |
| `source_files`                             | Parsed ledger and include files                                                                   |

`postings.transaction_id` points at `transactions.id`, and so do `transaction_metadata`, `transaction_tags`, and `transaction_links`. `posting_metadata.posting_id` points at `postings.id`. The rest join by name: an account column against `accounts.name`, a `source_file` column against `source_files.path`.

```sql theme={null}
SELECT t.date, t.payee, p.account, p.amount, p.commodity
FROM postings p
JOIN transactions t ON t.id = p.transaction_id
WHERE p.account LIKE 'Expenses:%'
ORDER BY t.date DESC;
```

Amounts arrive booked, so thousands separators, arithmetic, cost (`{}`) and price (`@`/`@@`) annotations are resolved before they reach a cell. Metadata values are text, and booleans keep their Beancount spelling of `TRUE` and `FALSE`.

Every ledger file, glob directory, and referenced document is watched by modification date, size, and directory listing. Change one and the next query rebuilds the projection first, so an edit in your text editor lands without reconnecting.

## Source locations

`transactions` and `postings` carry `source_file`, `line`, and `source_location`, the last formatted `path:line` so it copies, filters, and exports as it stands. A posting points at its own line, not at its transaction's.

The backends disagree about generated entries. For the transaction a `pad` inserts, `rledger` leaves these columns empty and Python Beancount points them at the `pad`.

## Diagnostics

`diagnostics` carries `source_file`, `line`, `source_location`, `column_number`, `end_line`, `end_column`, `severity`, `phase`, `code`, and `message`. A ledger opened through `rledger` is projected even when validation fails, so whatever the projection skipped is readable here. The Python backend leaves the table empty.

## Includes

`include` directives are followed, both literal paths and glob patterns such as `include "imports/*.beancount"` and `include "imports/**/*.beancount"`.

## BQL

Prefix a query with `BQL:` to send it to `rledger` instead of the projection.

```sql theme={null}
BQL: SELECT account FROM accounts ORDER BY account
```

Table browsing, row counts, and pagination work on a BQL result. SQL parameters do not.

## Limitations

* No writes. INSERT, UPDATE, DELETE, and every form of schema editing are rejected. Edit the ledger in a text editor; the next query picks the change up.
* No import, SSH, SSL, or ledger switching. One connection is one ledger file.
* BQL needs `rledger` even when the ledger opened on the Python backend. The query is refused. Install `rledger`, or drop the `BQL:` prefix and query the projected tables.
* `pad` directives get no table of their own. The balancing transaction they insert is projected; read the directive in the source file.
* Directives outside the 17 tables are not projected. They stay in the source files.

## Troubleshooting

**Beancount needs rledger or Python Beancount**: Neither was found on `PATH`, in `/opt/homebrew/bin`, or in `/usr/local/bin`. Set `TABLEPRO_RUSTLEDGER_BINARY` or `TABLEPRO_BEANCOUNT_PYTHON` with `launchctl setenv`, then relaunch.

**TABLEPRO\_BEANCOUNT\_PYTHON points to a Python executable that cannot import beancount**: Run `pip3 install beancount` with that exact interpreter, or point the variable at one that already has the package.

**BQL queries need rledger**: Install rustledger so `rledger` lands on `PATH` or in Homebrew, or point `TABLEPRO_RUSTLEDGER_BINARY` at it.

**File does not exist**: The ledger moved or was renamed. Re-pick it with **Browse…** in the connection form.

**Beancount include cycle detected**: Two ledger files include each other. Break the loop in the source files.
