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

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

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

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

Goal Tracking

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

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

Import Configuration

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

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

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

Report Configuration

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

Value Types

String

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

Date

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

Boolean

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

Amount

2024-01-01 custom "target" 10000 USD

Account

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

Number

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

Mixed Values

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

Namespacing

Convention: prefix type names to avoid conflicts:

; 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:

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:

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

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

Workflow Markers

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

Analytics Tags

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