Ein Skript steuert bea mit vier Entscheidungen: welches Hauptbuch es liest, --json für maschinenlesbare Ausgabe, jq für den benötigten Wert und den Exit-Code, auf den es verzweigt. Diese Anleitung führt durch diese vier Entscheidungen von Anfang bis Ende und plant sie dann ein.
Sie benötigen bea auf dem Rechner, der den Job ausführt, und ein Hauptbuch, das es erreichen kann. Wenn Sie neue Bücher beginnen, folgen Sie zuerst dem CLI-Schnellstart. Jede Tatsache über Flags, Envelope-Schlüssel und Exit-Codes finden Sie in der Beancount-CLI-Referenz, nicht hier wiederholt.
Wählen Sie das Hauptbuch explizit
Benennen Sie die Datei. Ein lokaler Befehl löst sein Ziel aus --file auf, dann aus $BEA_FILE, dann aus ./main.bean im Arbeitsverzeichnis, und ein geplanter Job läuft selten dort, wo Sie denken.
bea --file ~/books/main.bean check
BEA_FILE=~/books/main.bean bea check
cd ~/books && bea checkGlobale Optionen stehen vor dem Befehl, wie in bea --file main.bean check. Wenn die aufgelöste Datei nicht existiert, beendet sich der Befehl mit 2 und nennt alle drei Quellen, sodass ein Tippfehler in einem Cron-Eintrag laut scheitert, anstatt die falschen Bücher zu validieren. Gehostete Adressierung über ein --ledger-Flag existiert noch nicht; bea lädt niemals eine lokale Datei implizit hoch.
Den JSON-Envelope lesen
Fügen Sie globales --json hinzu, und jeder unterstützte Befehl antwortet mit demselben Envelope: bea, target, data, truncated und limit bei begrenzten Listen. Beträge sind Dezimalzeichenfolgen und Daten sind ISO YYYY-MM-DD, sodass ein Wert sicher vergleichbar ist, ohne dass je ein Float in die Pipeline gelangt. Die Schlüssel des Envelopes sind in der JSON- und Exit-Code-Referenz tabellarisch aufgeführt.
bea --json --file main.bean report income-statement | jq .data.net_profit
bea --json --file main.bean list transaction --limit 2 | jq '.data[0].postings[0].units'
bea --json --file main.bean import statement.csv --csv date=Date,amount=Amount,payee=Payee \
--account Assets:Checking --apply --duplicates skip | jq '.data | {written, ready, duplicates}'Diese drei Befehle — report, list und import — behalten ihre Ergebnisformen bei, sodass ein dagegen geschriebener jq-Pfad gültig bleibt. bea --json check und bea --json query geben heute ebenfalls den Envelope aus, aber sie sind die Befehle, die an die nativen Beancount-Executables übergeben werden, sodass ein Skript sich auf den Exit-Status von check stützen sollte, nicht auf seine Ausgabeform. Wählen Sie Ihre Duplikatrichtlinie bewusst: --duplicates ist weiterhin erforderlich, wenn ein Import eine Entscheidung benötigt, wie im Import-Walkthrough erklärt.
Beim richtigen Exit-Code anhalten
Verzweigen Sie auf den Status und lesen Sie das Fehlerobjekt, bevor Sie etwas wiederholen, das schreibt. Im --json-Modus schreibt ein Fehler nichts auf stdout und genau ein Objekt auf stderr, dessen error.category die Klasse benennt: validation (1), usage (2), auth (3), conflict (4).
#!/usr/bin/env bash
set -euo pipefail
out=$(mktemp)
err=$(mktemp)
status=0
bea --json --file main.bean report income-statement >"$out" 2>"$err" || status=$?
case "$status" in
0) jq -r '.data.net_profit | to_entries[] | "net profit: \(.value) \(.key)"' "$out" ;;
4) echo "conflict — inspect the ledger before retrying" >&2
jq -r '.error.message' "$err" >&2
exit 4 ;;
*) jq -r '.error | "\(.category) (exit \(.exit_code)): \(.message)"' "$err" >&2
exit "$status" ;;
esacExit 4 ist derjenige, den ein Skript niemals blind wiederholen darf: Er bedeutet, dass das Ergebnis ein Konflikt oder unbekannt ist, wie eine externe Bearbeitung, die mitten im Schreiben eintrifft, oder ein init-Ziel, das bereits existiert. Prüfen Sie das Hauptbuch und wiederholen Sie dann von einem frischen Lesezugriff. Exit 1 deckt Validierungsfehler und alle anderen Laufzeitfehler ab; error.details trägt die einzelnen Hauptbuchfehler, und error.result trägt, was ein teilweiser Schreibvorgang tatsächlich getan hat. Ein Nicht-Null-Exit garantiert niemals, dass sich nichts geändert hat.
Ohne Terminal ausführen
bea hört von selbst auf zu fragen. --no-input wird impliziert, wenn stdin kein Terminal ist, wenn --json gesetzt ist und wenn CI wahrheitsgemäß ist — 1, true, yes oder on. In diesem Modus schlägt eine fehlende Bestätigung mit Exit 2 fehl, anstatt endlos zu warten.
CI=true BEA_NO_UPDATE_NOTIFIER=1 bea --json --file main.bean report balance-sheet
bea --json --file main.bean list transaction --limit 100 --sort oldestLesezugriffe sind in einem Terminal nachsichtig und überall sonst streng. Wenn das Hauptbuch Ladefehler hat, beenden sich query, list und report mit 1 unter --json, unter einem gepipten stdout, unter einem wahrheitsgemäßen CI oder mit --strict; übergeben Sie stattdessen das eigene --allow-errors des Befehls, um die Teilantwort zu akzeptieren, was auch ledger_valid: false setzt und ledger_errors im JSON füllt. --strict ist das Spiegelbild: Es verweigert Teilantworten sogar in einem Terminal, was Sie wollen, wenn ein Mensch dasselbe Skript von Hand ausführt. bea check hat kein --allow-errors — Fehler zu melden ist seine eigentliche Aufgabe — und beendet sich immer mit 1, wenn es welche findet. Setzen Sie BEA_NO_UPDATE_NOTIFIER=1, um die passive Update-Benachrichtigung zu unterdrücken; ein wahrheitsgemäßes CI tut dies bereits.
Eine Prüfung planen
Führen Sie jede Nacht eine Validierung aus und lassen Sie den Exit-Code die Warnung sein. Beide Blöcke unten sind Vorlagen — die Pfade, der Zeitplan und der Runner sind Ihre.
# crontab -e — 07:15 daily; cron mails you only when bea exits nonzero
15 7 * * * BEA_NO_UPDATE_NOTIFIER=1 /opt/homebrew/bin/bea --file /home/alice/books/main.bean checkname: ledger
on:
schedule:
- cron: "15 7 * * *"
push:
jobs:
check:
runs-on: ubuntu-latest
env:
BEA_NO_UPDATE_NOTIFIER: "1"
steps:
- uses: actions/checkout@v4
- uses: astral-sh/setup-uv@v5
- run: uv tool install beancount-io==0.1.0
- run: bea --file main.bean check
- run: bea --json --file main.bean report balance-sheet > balance-sheet.jsonPinnen Sie die Version, wenn der Job reproduzierbar sein muss, und entfernen Sie den Pin, wenn Sie lieber Releases folgen möchten. CI ist auf GitHub Actions bereits wahrheitsgemäß, sodass Aufforderungen aus sind und die Update-Benachrichtigung still ist, bevor Sie etwas setzen. Es gibt hier absichtlich keinen Formatierungsschritt. Ein geplanter Job sollte keine Dateien umschreiben, die er nicht musste, greifen Sie also in einem Pre-Commit-Hook zu bea format --check, das nichts berührt und mit 1 endet, wenn eine Datei formatiert werden muss.
Eine gehostete Anmeldedaten in einem Job verwenden
Setzen Sie BEA_TOKEN aus dem Secret-Store Ihres CI-Anbieters und überspringen Sie die Browser-Anmeldung vollständig. Das Token wird aus der Umgebung gelesen und niemals auf die Festplatte geschrieben, sodass nichts im Home-Verzeichnis des Runners landet, das der nächste Job finden könnte.
export BEA_TOKEN="$YOUR_CI_SECRET"
bea --json cloud statusExit 0 bedeutet, dass die Anmeldedaten aufgelöst wurden und der Envelope das Konto benennt, zu dem sie gehören; Exit 3 mit error.category von auth bedeutet, dass dies nicht der Fall ist, und die Nachricht unterscheidet ein nicht gesetztes Token von einem abgelehnten. bea cloud logout tut nichts mit einem so gelieferten Token — es widerruft es weder, noch setzt es es zurück, da ein anderer Job es teilen kann — widerrufen Sie ein geleaktes Token also stattdessen über das Dashboard. Lokale Befehle benötigen überhaupt keine Anmeldedaten; nur bea cloud und bea ask erreichen den gehosteten Dienst. Die vollständige Variablenliste finden Sie in der Einstellungsreferenz.
Nicht alles antwortet in JSON. bea ask lehnt den JSON-Modus rundweg ab, bea cloud login benötigt einen Menschen, und ein erfolgreiches bea cloud logout oder bea cloud ledger clone gibt kein JSON-Erfolgsobjekt zurück — lesen Sie stattdessen deren Exit-Status. Hilfe-, Versions- und Shell-Vervollständigungsausgaben bleiben textuell.
Nächste Schritte
- Automatisieren Sie Bankdateien mit dem CLI-Import-Walkthrough.
- Schlagen Sie jedes Flag, jeden Envelope-Schlüssel oder Exit-Code in der Beancount-CLI-Referenz nach.
- Greifen Sie nur dann zu Python, wenn die CLI nicht mehr ausreicht: siehe skriptbare Workflows.