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, an dem es verzweigt. Diese Anleitung führt diese vier Entscheidungen Ende zu Ende durch 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 wird im Beancount-CLI-Referenz nachgeschlagen und hier nicht wiederholt.
Wählen Sie das Hauptbuch explizit
Benennen Sie die Datei. Ein lokaler Befehl löst sein Ziel aus --file, dann $BEA_FILE, dann ./main.bean im Arbeitsverzeichnis auf, 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. Gehostetes Targeting über ein --ledger-Flag existiert noch nicht; bea lädt niemals implizit eine lokale Datei hoch.
Lesen Sie den JSON-Envelope
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 jemals 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 Ergebnisstrukturen, 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, daher sollte ein Skript auf den Exit-Status von check achten, nicht auf seine Ausgabestruktur. Wählen Sie Ihre Duplikatrichtlinie bewusst: --duplicates ist weiterhin erforderlich, wenn ein Import eine Entscheidung benötigt, wie der Import-Walkthrough erklärt.
Stoppen Sie beim richtigen Exit-Code
Verzweigen Sie auf den Status und lesen Sie das Fehlerobjekt, bevor Sie etwas erneut versuchen, 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 erneut versuchen 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. Untersuchen Sie das Hauptbuch und versuchen Sie es dann mit einem frischen Lesen erneut. Exit 1 deckt Validierungsfehler und alle anderen Laufzeitfehler ab; error.details trägt die einzelnen Hauptbuchfehler, und error.result trägt, was ein teilweises Schreiben tatsächlich getan hat. Ein Nicht-Null-Exit garantiert nie, dass sich nichts geändert hat.
Ohne Terminal ausführen
bea hört von selbst auf, Eingabeaufforderungen zu zeigen. --no-input ist impliziert, wenn stdin kein Terminal ist, wenn --json gesetzt ist und wenn CI wahr ist — 1, true, yes oder on. In diesem Modus schlägt eine fehlende Bestätigung mit Exit 2 fehl, anstatt ewig 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 wahren 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 sein ganzer Job — und beendet sich immer mit 1, wenn es welche findet. Setzen Sie BEA_NO_UPDATE_NOTIFIER=1, um die passive Update-Benachrichtigung zu deaktivieren; ein wahres 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.2.0
- run: bea --file main.bean check
- run: bea --json --file main.bean report balance-sheet > balance-sheet.jsonDer erste engine-gestützte Befehl lädt die verwaltete Engine herunter, daher benötigt der Runner Netzwerkzugriff. Um sie über Jobs hinweg wiederzuverwenden, cachen Sie ~/.local/share/bea/engine mit einem Schlüssel, der das Runner-Betriebssystem, die Architektur, die Python-Version und die festgepinnte bea-Version enthält. Pinnen Sie die Version, wenn der Job reproduzierbar sein muss, und entfernen Sie den Pin, wenn Sie Releases lieber verfolgen möchten. CI ist auf GitHub Actions bereits wahr, sodass Eingabeaufforderungen aus sind und die Update-Benachrichtigung still ist, bevor Sie etwas setzen. Es gibt hier bewusst keinen Formatierungsschritt. Ein geplanter Job sollte keine Dateien neu schreiben, die er nicht musste, also greifen Sie in einem Pre-Commit-Hook zu bea format main.bean --check, das nichts berührt und sich mit 1 beendet, wenn eine Datei formatiert werden muss.
Eine gehostete Anmeldedaten in einem Job verwenden
Setzen Sie BEA_TOKEN aus dem Geheimnisspeicher Ihres CI-Anbieters und überspringen Sie die Browser-Anmeldung vollständig. Das Token wird aus der Umgebung gelesen und nie 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 war, und die Nachricht unterscheidet eine nicht gesetzte von einer abgelehnten Anmeldedaten. 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 könnte — widerrufen Sie also ein durchgesickertes Token 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 ihren 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 im Beancount-CLI-Referenz nach.
- Greifen Sie nur dann zu Python, wenn die CLI nicht mehr ausreicht: siehe skriptbare Workflows.