Skip to content

Custom Directive ​

Overview ​

The custom directive allows users and plugins to define their own directive types with arbitrary values. It provides an extension mechanism for data that doesn't fit other directive types.

Syntax ​

ebnf
custom = date WHITESPACE "custom" WHITESPACE type [WHITESPACE value]*
         (NEWLINE metadata)*

type  = string
value = string | date | boolean | amount | account | number

Components ​

Date ​

The date of the custom directive.

Type ​

A string identifying the custom directive type. Conventionally uses a namespace prefix.

Values ​

Zero or more values of various types:

  • Strings (quoted)
  • Dates (YYYY-MM-DD)
  • Booleans (TRUE/FALSE)
  • Amounts (number + currency)
  • Accounts
  • Numbers

Examples ​

Budget Entry ​

beancount
2024-01-01 custom "budget" Expenses:Food 500 USD "monthly"
2024-01-01 custom "budget" Expenses:Transport 200 USD "monthly"
2024-01-01 custom "budget" Expenses:Entertainment 150 USD "monthly"

Recurring Transaction Template ​

beancount
2024-01-01 custom "recurring" "rent" Assets:Checking -2000 USD Expenses:Rent "monthly" 1
  description: "Monthly rent payment"
  payee: "Landlord LLC"

Goal Tracking ​

beancount
2024-01-01 custom "goal" "emergency-fund" Assets:Savings 10000 USD
2024-01-01 custom "goal" "vacation" Assets:Savings 3000 USD 2024-12-31

Account Alias ​

beancount
2024-01-01 custom "alias" Assets:Bank:Checking "checking"
2024-01-01 custom "alias" Liabilities:CreditCard:Chase "chase"

Import Configuration ​

beancount
2024-01-01 custom "import" "chase-csv" Assets:CreditCard:Chase
  file-pattern: "Chase*.csv"
  date-format: "MM/DD/YYYY"
  skip-rows: 1

Plugin-Defined Customs ​

Plugins often define their own custom directives:

Fava Budget Plugin ​

beancount
2024-01-01 custom "fava-budget" Expenses:Food 500 USD "monthly"
2024-01-01 custom "fava-budget" Expenses:Rent 2000 USD "monthly"

Auto-Accounts Plugin ​

beancount
2024-01-01 custom "auto-accounts" "pattern" "Expenses:.*" "FIFO"

Report Configuration ​

beancount
2024-01-01 custom "report-config" "balance-sheet"
  title: "Personal Balance Sheet"
  accounts: "Assets,Liabilities,Equity"
  format: "tree"

Value Types ​

String ​

beancount
2024-01-01 custom "note" "This is a string value"

Date ​

beancount
2024-01-01 custom "deadline" 2024-12-31

Boolean ​

beancount
2024-01-01 custom "feature" "dark-mode" TRUE
2024-01-01 custom "feature" "auto-complete" FALSE

Amount ​

beancount
2024-01-01 custom "target" 10000 USD

Account ​

beancount
2024-01-01 custom "default-account" Assets:Checking

Number ​

beancount
2024-01-01 custom "rate" 0.05
2024-01-01 custom "count" 12

Mixed Values ​

beancount
2024-01-01 custom "complex" "type" Assets:Account 100 USD 2024-12-31 TRUE

Namespacing ​

Convention: prefix type names to avoid conflicts:

beancount
; Plugin-specific
2024-01-01 custom "fava-budget" ...
2024-01-01 custom "beancount-import" ...

; User-specific
2024-01-01 custom "my-budget" ...
2024-01-01 custom "acme-corp-expense" ...

Processing Custom Directives ​

Custom directives are:

  1. Parsed and stored with all directives
  2. Available to plugins for processing
  3. Ignored by core validation (no built-in semantics)

Plugins access custom directives:

python
def process_customs(entries, options):
    for entry in entries:
        if isinstance(entry, Custom) and entry.type == "budget":
            # Process budget directive
            account = entry.values[0]
            amount = entry.values[1]
            period = entry.values[2]

Querying Custom Directives ​

In BQL:

sql
SELECT date, type, values FROM custom
WHERE type = "budget"

Validation ​

Custom directives have no built-in validation. Plugins may define their own validation rules.

Common conventions:

  • Type should be a meaningful identifier
  • Values should be documented for each type
  • Use metadata for optional configuration

Use Cases ​

Configuration Storage ​

beancount
2024-01-01 custom "config" "operating-currency" "USD"
2024-01-01 custom "config" "fiscal-year-start" 2024-04-01

Workflow Markers ​

beancount
2024-01-15 custom "review-needed" Assets:Checking "Monthly reconciliation"
2024-02-01 custom "audit-complete" 2024-01-01 2024-01-31 "John Smith"
beancount
2024-01-15 custom "quickbooks-sync" "INV-2024-001" 1500 USD
2024-01-15 custom "stripe-payout" "po_abc123" Assets:Stripe

Analytics Tags ​

beancount
2024-01-01 custom "segment" Expenses:Marketing "acquisition" 0.6
2024-01-01 custom "segment" Expenses:Marketing "retention" 0.4

Implementation Notes ​

  1. Parse all value types (string, date, bool, amount, account, number)
  2. Store values in order as a list
  3. Make available to plugins
  4. No built-in semantic validation
  5. Support querying by type