# Beancount CLI reference

Use this reference to look up `bea` commands and their behavior. For your first ledger, follow the [CLI quick start](https://beancount.io/docs/Basics/bea-cli). To close a full month end to end, work through [Your first month with bea](https://beancount.io/docs/Basics/bea-first-month). For bank files, use the [import walkthrough](https://beancount.io/docs/Solutions/import-bank-exports-cli).

## Commands at a glance

| Command                                 | Purpose                                                         |
| --------------------------------------- | --------------------------------------------------------------- |
| `bea init [DIRECTORY]`                  | Create a ledger with common accounts                            |
| `bea add TYPE`                          | Add a dated directive                                           |
| `bea add transactions --from FILE.json` | Add a transaction batch                                         |
| `bea import SOURCE`                     | Preview an export; add `--apply` to write                       |
| `bea list TYPE`                         | List and filter directives                                      |
| `bea check`                             | Validate the complete ledger                                    |
| `bea format PATH`                     | Align a file or recursively format a directory                  |
| `bea query [BQL]`                       | Run a query or open the interactive query shell                 |
| `bea report TYPE`                       | Produce financial reports                                       |
| `bea balance [ACCOUNT...]`              | Print balances for matching accounts                            |
| `bea ask [QUESTION]`                    | Use optional hosted AI assistance with a local ledger           |
| `bea cloud …`                           | Sign in and manage hosted ledgers                               |
| `bea doctor COMMAND` | Inspect ledger context and diagnostics |
| `bea example [OPTIONS]` | Generate a sample ledger |
| `bea treeify [INPUT]` | Render account names as a text tree |
| `bea ingest COMMAND` | Identify, extract, or archive with a Beangulp configuration |
| `bea price [OPTIONS]` | Inspect, refresh, or export managed prices; otherwise fetch quotes through optional Beanprice |
| `bea engine COMMAND` | Inspect the managed engine or enable optional features |
| `bea upgrade [--check]`                 | Upgrade with the owning package manager, or check for an update |

## Global options and paths

Global options go **before** the command:

```bash
bea --file ~/my-books/main.bean check
bea --json list transaction --limit 100
```

| Option                 | Behavior                                                                             |
| ---------------------- | ------------------------------------------------------------------------------------ |
| `--file / -f PATH`     | Select the root ledger; overrides `BEA_FILE` and `./main.bean`                       |
| `--json`               | Structured output; also disables CLI prompts                                         |
| `--no-input`           | Disable prompts; missing required input exits 2                                      |
| `--yes / -y`           | Confirm operations such as cloud deletion; does not grant AI write permission        |
| `--debug`              | Include exception tracebacks                                                         |
| `--offline` | Resolve managed prices from the local cache without fetching |
| `--strict-prices` | Fail the load when a managed source is stale or unavailable |
| `--strict`             | Refuse partial answers even in a terminal; a command's `--allow-errors` opts back in |
| `--version`            | Show the installed version without a network request                                 |
| `--help / -h`          | Show help; also available on subcommands                                             |
| `--show-completion`    | Print shell completion                                                               |
| `--install-completion` | Install shell completion                                                             |
| `--shell NAME`         | Select `bash`, `zsh`, `fish`, `powershell`, or `pwsh` instead of detecting the shell |

`init` creates its own directory/file target and ignores `BEA_FILE`. It accepts global `--file` instead of its directory argument. `format` uses its own positional target. Supply a filename or directory. Global `--file` does not choose the formatting target.

## Create a ledger

`bea init [DIRECTORY]` defaults to the current directory. A directory creates `main.bean`; a `.bean` or `.beancount` path names the new file directly.

| Option                               | Behavior                                                                         |
| ------------------------------------ | -------------------------------------------------------------------------------- |
| `--currency / -c SYMBOL`             | Operating currency; required unattended, interactive default `USD`               |
| `--date YYYY-MM-DD`                  | Earliest history/opening date; otherwise a prompt or today                       |
| `--opening-balance "ACCOUNT NUMBER"` | Repeat for template asset/liability accounts; amounts use the operating currency |

The template opens `Assets:Checking`, `Assets:Savings`, `Assets:Cash`, `Liabilities:CreditCard`, `Income:Salary`, `Income:Interest`, `Expenses:Groceries`, `Expenses:Dining`, `Expenses:Rent`, `Expenses:Transport`, `Expenses:Utilities`, `Expenses:Fees`, `Expenses:Uncategorized`, and `Equity:OpeningBalances`.

Opening balances offset against `Equity:OpeningBalances`. Debt is negative. Currency input is uppercased. Custom symbols are allowed; a symbol that is not three uppercase letters triggers a typo warning. This is not an ISO currency-registry check.

Existing files are never overwritten. New files use owner-only permissions, mode `0600` on POSIX. Later add and import writes preserve permissions and respect read-only destinations. In-place formatting uses the native formatter and reports its own filesystem errors.

## Add transactions

```bash
bea add transaction -n "Groceries" --payee "Corner Market" \
  -p "Expenses:Groceries 30" -p "Assets:Checking" \
  --flag '!' --tag household --link receipt-42 --meta 'receipt:IMG_42.jpg'
```

| Option                     | Behavior                                                              |
| -------------------------- | --------------------------------------------------------------------- |
| `--posting / -p POSTING`   | Required; repeat for each posting                                     |
| `--date YYYY-MM-DD`        | Default today                                                         |
| `--flag CHARACTER`         | Default `*`; use `!` to mark a transaction for review                 |
| `--payee TEXT`             | Optional other party                                                  |
| `--narration / -n TEXT`    | Optional purpose; omitted text lists as `(no narration)`              |
| `--tag TAG`, `--link LINK` | Repeatable; optional leading `#` or `^` is accepted                   |
| `--meta KEY:VALUE`         | Repeatable transaction metadata                                       |
| `--into FILE`              | Write an included file while validating the root                      |
| `--allow-errors`           | Explicitly permit semantic validation errors; syntax must still parse |

One posting may omit its amount. Numbered postings may omit currency when an account has one allowed currency or the ledger has one compatible operating currency. Otherwise, supply the symbol.

Native posting syntax supports arithmetic such as `84/2 EUR`, costs such as `{100 USD}`, total costs `{{1000 USD}}`, and prices `@` or `@@`. Use decimal amounts such as `1000`, not exponent notation such as `1e3`.

A currency exchange needs its actual transaction rate. For example, post `100 EUR @ 1.08 USD` to an account open in EUR and `-108 USD` to checking. An investment purchase can post `2 AAPL {100 USD}` to an account open in AAPL and `-200 USD` to checking. Add dated `price` quotes when reports need market valuation.

Metadata accepts bare strings such as `--meta 'receipt:IMG_42.jpg'`. Native numbers, booleans, dates, and amounts retain their types. Examples include `--meta 'reviewed:TRUE'`, `--meta 'received:2026-08-03'`, and `--meta 'fee:2.50 USD'`. Inner quotes force a string: `--meta 'code:"1234"'`. Keys must be distinct; `filename` and `lineno` are reserved.

Single adds, bulk adds, and imports replace line breaks in payees, narrations, and string metadata with spaces. Quotes and backslashes retain their contents.

## Add other directives

All these commands require `--date YYYY-MM-DD`. They also accept `--into FILE` and `--allow-errors`.

| Type        | Required fields                                               | Additional options                              |
| ----------- | ------------------------------------------------------------- | ----------------------------------------------- |
| `open`      | `--account / -a`                                              | Repeat `--currency / -c` to restrict currencies |
| `close`     | `--account / -a`                                              | —                                               |
| `balance`   | `--account / -a`, `--amount "NUMBER CURRENCY"`                | `--pad-from ACCOUNT`, `--pad-date YYYY-MM-DD`   |
| `pad`       | `--account / -a`, `--source / -s`                             | —                                               |
| `note`      | `--account / -a`, `--comment / --message / -m`                | —                                               |
| `event`     | `--type / -t`, `--description / -d`                           | —                                               |
| `price`     | `--currency / --commodity / -c`, `--amount "NUMBER CURRENCY"` | Currency names the commodity being priced       |
| `commodity` | `--currency / --commodity / -c`                               | —                                               |
| `document`  | `--account / -a`, `--filename / --path`                       | Repeated `--tag` and `--link`                   |
| `custom`    | `--type / -t`                                                 | Repeated `--value / -v KIND:VALUE`              |

Account names have a capitalized root and colon-separated segments. Each subaccount starts with an uppercase letter or digit. Beancount supports Unicode letters and configured root names.

A balance checks the account at the start of its date. Tolerance syntax is supported, such as `--amount "1538 ~ 1 EUR"`. The tolerance must be nonnegative.

Use `add balance --pad-from Equity:OpeningBalances` to write a pad and its balance assertion together. The pad defaults to the previous day; `--pad-date` can select another earlier day. Both accounts must be active. A standalone pad needs a later balance to consume it. `--allow-errors` can stage that intermediate state but cannot bypass an invalid pad account.

`add price` skips an exact date/commodity/price duplicate across the root and its includes. It exits 0 and identifies the existing location. Different dates or prices are new additions.

Document paths resolve beside the file containing the directive. With `--into years/2026.bean`, `--filename receipt.pdf` means `years/receipt.pdf`, not a file beside your shell's working directory.

Custom value kinds are `text`, `number`, `amount`, `account`, `bool`, and `date`. For example, a budget can use `--value "text:travel" --value "amount:500 USD"`.

## Bulk JSON input

`bea add transactions --from transactions.json` accepts a JSON array:

```json
[
  {
    "date": "2026-08-04",
    "narration": "Groceries",
    "postings": [
      { "account": "Expenses:Groceries", "amount": "45.00 USD" },
      { "account": "Assets:Checking" }
    ],
    "meta": { "receipt": "R-43", "reviewed": true }
  }
]
```

Each transaction requires `date` and `postings`. Optional fields are `flag`, `payee`, `narration`, `tags`, `links`, and `meta`.

A posting uses either `amount` or `units`, such as `{"number":"45.00","currency":"USD"}`. Omit both for the balancing posting. Posting fields also include `cost`, `price`, `flag`, and `meta`. Costs contain `number` and `currency`, with optional `date` and `label`. Prices contain `number` and `currency`.

Use strings for decimals. Metadata uses ordinary strings and booleans, or tagged values such as `{"kind":"number","value":"1.125"}`, `{"kind":"date","value":"2026-08-04"}`, and `{"kind":"amount","number":"2.50","currency":"USD"}`. The optional transaction `source` location is never written as metadata.

The default is an atomic batch: any rejected row leaves the ledger unchanged and exits 1. `--partial` writes a valid subset and still exits 1 if any rows are rejected. JSON errors describe the outcome in `error.result`; row indexes there are zero-based. Human row numbers are one-based.

Bulk add accepts `--into` and `--allow-errors`. It does not deduplicate. Use `bea import` for bank-export review.

## Split ledgers and write safety

Keep `--file` pointed at the root. Add `--into` to select an existing included file:

```bash
bea --file ~/my-books/main.bean add transaction --into 2026.bean \
  --date 2026-08-02 -n "Groceries" \
  -p "Expenses:Groceries 30" -p "Assets:Checking"
```

The destination is relative to the root directory. It must already be included; naming an unrelated file is refused. Add commands, imports, and interactive AI writes support this separation.

Writes validate the complete candidate ledger, including plugins and cost-lot booking. A concurrent change to the root or its include graph exits 4. A read-only destination exits 3. Successful additions align only the new lines. Existing bytes remain unchanged. Use `bea format -i PATH` when you want to realign the whole file.

## List directives

`bea list TYPE` supports the eleven types: `transaction`, `open`, `close`, `balance`, `pad`, `note`, `event`, `price`, `commodity`, `document`, and `custom`.

| Option                     | Applies to                                             | Behavior                                                               |
| -------------------------- | ------------------------------------------------------ | ---------------------------------------------------------------------- |
| `--limit / -l N`           | All types                                              | Positive limit; default 50                                             |
| `--from-date`, `--to-date` | All types                                              | Inclusive `YYYY-MM-DD` bounds                                          |
| `--allow-errors`           | All types                                              | Permit partial data despite loader errors                              |
| `--account / -a TEXT`      | Transaction, open, close, balance, pad, note, document | Case-insensitive account substring                                     |
| `--currency / -c SYMBOL`   | Price, commodity                                       | Case-insensitive exact symbol; price filters its base commodity        |
| `--sort newest/oldest`     | Transaction                                            | Default newest; applied before the limit                               |
| `--flag CHARACTER`         | Transaction                                            | Filter entries such as `!` before the limit                            |
| `--details`                | Transaction                                            | Render Beancount syntax, every posting, metadata, and source locations |

Other directive types retain chronological order. An account-filtered transaction table labels its amount column `MATCHING POSTING AMOUNTS`. Details and JSON still include all postings of each selected transaction. Details render loaded entries, including inferred amounts; they are not raw source excerpts.

## Check, format, and query

`bea check` validates the root and includes. It exits 0 silently on success and 1 for ledger errors. Global `--json` returns the validation envelope. There is no `--allow-errors` option for `check`.

Queries, lists, and reports warn and return partial results in an interactive terminal. Global `--strict`, `--json`, `--no-input`, truthy `CI`, or non-terminal stdin makes reads strict. Their `--allow-errors` option explicitly permits partial results.

Formatting accepts files or recursively searches a directory. In the published 0.2.0 package, a path is required despite the stdin default shown in help. Global `--file` does not choose the formatting target.

| Formatting mode | Writes? | Exit behavior |
| --- | --- | --- |
| `bea format PATH` | Formatted text to stdout; source unchanged | 0 after success |
| `bea format -i PATH` | Rewrites the source | 0 after success |
| `bea format PATH -o formatted.bean` | Writes the named output file | 0 after success |
| `bea format PATH --dry-run` | No file changes | 0 even when formatting is needed |
| `bea format PATH --check` | No file changes | 1 when formatting is needed; 0 when clean |

Formatting aligns text; it does not validate ledger syntax or accounting. Run `bea check` separately. With global `--json`, select `-i`, `-o FILE`, `--check`, or `--dry-run` so stdout can carry the envelope. Do not redirect stdout over the input file: use `-i` to rewrite it.

`bea query "BQL"` runs a [Beancount query](https://beancount.io/docs/Basics/beancount-query-language). Omitting BQL reads queries from stdin or opens the shell when stdin is a terminal. Use `.exit`, `exit`, or `quit` to close the shell. BQL's default table has one row per posting. Query tables retain precision.

| Query option | Behavior |
| --- | --- |
| `--format / -f csv` | Export CSV instead of a text table |
| `--output / -o FILE` | Write the result to a file |
| `--numberify / -m` | Split text or CSV inventory values into numeric columns per currency |
| `--no-errors / -q` | Hide loader diagnostics; does not opt into partial results |
| `--source URI` | Use a native Beanquery source URI |

Select the ledger before the command, for example `bea --file main.bean query -f csv -o balances.csv "SELECT account, sum(position) GROUP BY account"`. Global `--json` uses the product envelope with `data.rows` and `data.columns`; it is distinct from CSV rendering. In the published 0.2.0 release, use shell redirection to save JSON, such as `bea --json query "SELECT account, sum(position) GROUP BY account" > result.json`: query `-o` and `-m` do not apply to JSON in that release.

## Native tools and optional features

`bea doctor context main.bean 42` shows the transaction context at line 42. `bea doctor --help` lists the other diagnostic commands. `bea example -o example.bean` creates a sample history. `bea treeify accounts.txt` renders hierarchical names from a text file; omit the file to read stdin. These commands forward native arguments. The examples above name those arguments explicitly.

Enable optional tools once with `bea engine enable beanprice` for quote fetching or `bea engine enable beangulp` for importer workflows. Enabling needs network access; Beangulp also needs the system `libmagic` library. Use `bea engine status` to inspect availability. `bea price --help` and `bea ingest --help` describe their interfaces. `bea import --csv` and `bea add price` do not need either optional feature.

### Managed price includes

[Live Prices](https://beancount.io/docs/live-prices) is a separate managed-include workflow. Hosted ledgers resolve supported price URLs; compatible `bea` versions also support managed includes and local price exports. Check the [version-specific managed-price guide](https://github.com/bex-co/beancount-io/blob/main/cli/docs/USAGE.md#managed-price-includes) if your installed version does not recognize these commands.

| Command | Purpose |
| --- | --- |
| `bea price status` | Inspect freshness, revision, observation time, and errors for each source |
| `bea price refresh` | Resolve feeds now and report which sources changed |
| `bea --offline balance` | Read managed prices only from the local cache |
| `bea --strict-prices check` | Reject a load with stale or unavailable managed prices |
| `bea price export --output audit` | Export a self-contained ledger with local price files for upstream tools |

The CLI resolves allowlisted managed URLs without sending credentials and refuses redirects. A feed that redirects to a hosted login is therefore unavailable to a fresh local fetch; signing in to the website does not authenticate the CLI price request. Inspect `price status` for source errors. Use cached data, a reachable supported feed, or local dated prices as appropriate.

`price export` writes feed files under `prices/` and rewrites includes to local relative paths. Upstream Beancount, Fava, and Beanquery can load that exported copy. An unavailable source refuses export unless `--allow-errors` is used, which can leave its source marker without prices.

Your own dated price overrides a managed price for the same date and pair. Feed entries are read-only. Failed refreshes retain a previously validated revision, which may be stale. Other arguments to `bea price` still forward to Beanprice; if a quote-job file is named `status`, pass `./status` to distinguish it from the subcommand.

Homebrew installs both the CLI and its managed engine. With PyPI, the first engine-backed command downloads the pinned dependencies; keep `uv` on `PATH` and allow network access for that first run. Later local commands reuse the engine offline. Customers install only `beancount-io`, with no separate Beancount package or native console scripts to manage.

## Financial reports

| Report                        | Output                                                                |
| ----------------------------- | --------------------------------------------------------------------- |
| `bea report overview`         | Assets, liabilities, income, expenses, net worth, and interval series |
| `bea report income-statement` | Income/expense trees, net profit, and period rows                     |
| `bea report balance-sheet`    | Asset/liability/equity trees and derived reconciliation               |
| `bea report trial-balance`    | Account balances                                                      |

All reports accept `--conversion / -x`, `--time / -t`, `--account / -a`, and `--allow-errors`. All except trial balance also accept `--interval / -i`: `monthly` by default, or `quarterly`, `yearly`, `weekly`, or `daily`.

`bea balance [ACCOUNT...]` prints balance subtrees for accounts matching case-insensitive substrings, or the whole ledger when you name none. It accepts `--conversion / -x`, `--time / -t`, and `--allow-errors`, and takes no interval or account option.

Time filters include a year, month, date, quarter, week, or range, such as `2026`, `2026-08`, `2026-08-31`, `2026-Q3`, `2026-W32`, or `"2026-01 - 2026-08"`. Relative periods include `year`, `quarter`, `month`, `week`, `day`, and offsets such as `month-1`. Account filters retain every posting of a matching transaction.

Conversion defaults to the ledger's sole operating currency. Otherwise, it defaults to `units`, keeping commodities separate. `at_cost` uses acquisition costs. `at_value` uses market values with a cost fallback.

An explicit currency conversion needs prices on or before **every valuation date**, including interval dates. A missing-price error names the actual gap, such as `No EUR → USD price on or before 2026-01-31`. A later quote cannot fill an earlier gap. Add a historically appropriate price, use `--conversion units`, or choose `--allow-errors` to inspect partial values.

Partial reports preserve source currencies and mark combined totals unavailable. JSON includes `valuation: "partial"`, `missing_prices`, and `missing_price_dates`. Affected net-profit/net-worth totals are `null` in the requested currency.

Income, liabilities, and equity normally use negative Beancount signs. Net profit is `-(income + expenses)`, positive for a gain. The same convention applies to income-statement period rows. Balance-sheet reconciliation is derived for the report; it writes no directives. `equity_reconciled` identifies whether a complete reconciliation is available.

Report JSON also identifies the period, exclusive end date, as-of date, conversion, account filter, and ledger validation status. Check those fields before comparing totals.

## Optional AI assistance

`bea ask` needs both the `ask` extra and Beancount.io credentials from `bea cloud login` or `BEA_TOKEN`. The default Homebrew installation omits AI dependencies. Homebrew users can run:

```bash
bea cloud login
uvx --from 'beancount-io[ask]' bea ask "What did I spend last month?" --print
```

For a uv installation, install `beancount-io[ask]` and run `bea ask` directly. `--print / -p` answers once and exits. Otherwise, a terminal session is interactive, and an optional question pre-fills its input. Non-interactive use requires a question. JSON mode is not supported.

Queries run locally. Questions, skill context, and tool results go to the hosted Beancount.io AI service. Interactive writes are previewed, confirmed, validated, and written atomically. They accept `--into`. Global `--yes` does not grant AI write permission. One-answer mode does not apply proposed writes.

Ask reads `NAME/SKILL.md` from `.agents/skills/` in the working directory and from `skills/` in the user configuration directory. Project definitions win by name. Each file needs YAML `name` and `description` fields. Full instructions load on demand. For the file layout and a worked example, see [Extend bea ask with skills](https://beancount.io/docs/Solutions/bea-ask-skills).

## Hosted ledgers

| Command                              | Options and behavior                                              |
| ------------------------------------ | ----------------------------------------------------------------- |
| `bea cloud login`                    | Interactive browser/device sign-in                                |
| `bea cloud logout`                   | Attempts remote logout and clears stored credentials              |
| `bea cloud status`                   | Account, credential source, and expiry                            |
| `bea cloud ledger list`              | `--page` defaults to 1; `--limit` defaults to 50, API maximum 100 |
| `bea cloud ledger show OWNER/NAME`   | Inspect a hosted ledger                                           |
| `bea cloud ledger create NAME`       | `--description / -d`, `--private / --public`; private by default  |
| `bea cloud ledger clone OWNER/NAME`  | SSH clone; optional `--dir PATH`                                  |
| `bea cloud ledger delete OWNER/NAME` | Permanent deletion; confirmation or global `--yes` required       |

With global `--json`, `bea cloud status`, `bea cloud ledger list`, `bea cloud ledger show`, `bea cloud ledger create`, and `bea cloud ledger delete` emit the standard envelope. Login requires interaction; successful logout and clone do not return a JSON success object.

Creation also accepts `--clone` and `--dir`. Git and SSH access are required to clone. If cloning fails after creation, the hosted ledger still exists. Local commands do not upload your ledger automatically. There is no global `--ledger` option.

## JSON and exit codes

Global `--json` puts successful results on stdout:

```json
{
  "bea": "0.2.0",
  "target": { "file": "/home/alice/my-books/main.bean" },
  "data": [],
  "truncated": false,
  "limit": 50
}
```

`bea` is the installed version; `data` depends on the command. Targets identify a file, directory, server, or no target. Included writes also identify `into`. Decimal amounts and dates use strings. Limited lists include `limit` and `truncated`.

Failures write `{"error":{"category":"validation","message":"…","exit_code":1}}` to stderr. The error can also include `details`, `result`, a backend `request_id`, and a `traceback` with `--debug`.

| Code | Category     | Meaning                                                                                          |
| ---- | ------------ | ------------------------------------------------------------------------------------------------ |
| 0    | —            | Success, including previews and intentional duplicate skips                                      |
| 1    | `validation` | Ledger/schema error, formatting check failure, or other runtime failure                          |
| 2    | `usage`      | Invalid arguments, missing target/input, or missing optional dependencies                        |
| 3    | `auth`       | Authentication or permission failure                                                             |
| 4    | `conflict`   | Concurrent edit, import review required, existing init target, or uncertain remote write outcome |

Check `error.result` before retrying a mutation. A partial batch can write accepted rows, recursive formatting can change valid files, and create-and-clone can create a hosted ledger before exiting nonzero. For a script that reads this envelope with `jq` and branches on these codes, see [Automate bookkeeping with bea](https://beancount.io/docs/Solutions/automate-bookkeeping-with-bea).

CLI prompts are disabled by `--no-input`, JSON mode, non-terminal stdin, or truthy `CI`. Cloud deletion still needs explicit `--yes`. Imports need an explicit duplicate decision when matches need review.

Output exceptions: `doctor`, `example`, `treeify`, Beanprice-forwarded `price` invocations, and `ingest` preserve native output and exit status, even with global `--json`; the envelope and exit categories above do not describe those forwarded results. Ask rejects JSON; cloud login needs interaction; successful cloud logout and clone return no JSON success object. Help, version, and completion retain text output. `upgrade` can stream its package manager's output to stderr, including in JSON mode.

## Settings, updates, and stored state

| Environment variable     | Purpose                                                                               |
| ------------------------ | ------------------------------------------------------------------------------------- |
| `BEA_FILE`               | Default root ledger after `--file`                                                    |
| `BEA_CONFIG_DIR`         | Override the user configuration directory                                             |
| `XDG_CONFIG_HOME`        | Otherwise use `$XDG_CONFIG_HOME/bea`, falling back to `~/.config/bea`                 |
| `XDG_DATA_HOME` | Managed PyPI engine base; otherwise `~/.local/share/bea/engine/` |
| `XDG_CACHE_HOME`         | Cache directory base; otherwise `~/.cache/bea`                                        |
| `BEA_TOKEN`              | Hosted credential override; takes precedence over stored credentials and is not saved |
| `BEA_API_URL`            | API base; default `https://api.v3.beancount.io`                                       |
| `BEA_DASHBOARD_URL`      | Browser sign-in base; default `https://beancount.io`                                  |
| `BEA_NO_UPDATE_NOTIFIER` | Disable passive update notices when truthy                                            |
| `MANAGED_PRICE_ORIGINS` | Comma-separated allowlisted origins; defaults to `https://beancount.io`; empty disables managed includes |
| `MANAGED_PRICE_OFFLINE` | Truthy uses cached managed prices only, like `--offline` |
| `MANAGED_PRICE_STRICT` | Truthy rejects stale or unavailable managed sources, like `--strict-prices` |
| `CI`                     | Disable CLI prompts and passive update notices when truthy                            |

Truthy values are `1`, `true`, `yes`, and `on`, ignoring case and surrounding whitespace. Configuration state includes credentials, Ask prompt history, user skills, remembered importer paths, and update-check caches. Write locks live under the cache directory's `locks/`, outside your ledger directory.

`bea upgrade --check` reports versions and the installation method without upgrading. `bea upgrade` invokes `brew upgrade bea`, `uv tool upgrade beancount-io`, or `pipx upgrade beancount-io`. Editable installs receive manual update guidance. Passive checks run at most once a day in interactive installed copies; explicit `upgrade --check` still runs when the passive notifier is disabled.

Uninstall with the matching manager: `brew uninstall bea`, `uv tool uninstall beancount-io`, or `pipx uninstall beancount-io`. Your ledger files and user configuration remain.

## Common fixes

| Symptom                             | Next step                                                                             |
| ----------------------------------- | ------------------------------------------------------------------------------------- |
| No ledger found                     | Select `--file PATH`, enter the ledger directory, or use `bea init` for new books     |
| A global flag says “No such option” | Move it before the command, as in `bea --file main.bean check`                        |
| An account is unknown               | Open it with `bea add open --date YYYY-MM-DD --account ACCOUNT`                       |
| An account is inactive              | Read the cited open/close dates; correct the transaction date or account history      |
| A pad is unused                     | Complete its later balance assertion; use `add balance --pad-from` for an atomic pair |
| Currency conversion is incomplete   | Add prices covering the dates named in the error, or inspect `units`                  |
| A document cannot be found          | Resolve its path beside the directive's file, including an `--into` destination       |
| A ledger changed during a write     | Inspect the new content, then retry from a fresh preview                              |
| Shell detection failed              | Specify a shell, such as `bea --shell zsh --show-completion`                          |

Use `bea COMMAND --help` to inspect your installed version. The [source repository reference](https://github.com/bex-co/beancount-io/blob/main/cli/README.md) contains additional examples and the exact directive model definitions.
