Un script pilote bea avec quatre décisions : quel grand livre il lit, --json pour une sortie lisible par machine, jq pour la valeur dont il a besoin, et le code de sortie sur lequel il se branche. Ce guide parcourt ces quatre décisions de bout en bout, puis les planifie.
Vous avez besoin de bea sur la machine qui exécute le travail et d'un grand livre auquel il peut accéder. Si vous démarrez de nouveaux livres, suivez d'abord le guide de démarrage rapide CLI. Tous les faits sur les drapeaux, les clés d'enveloppe et les codes de sortie sont consultés dans la référence CLI Beancount, non répétés ici.
Choisissez le grand livre explicitement
Nommez le fichier. Une commande locale résout sa cible à partir de --file, puis de $BEA_FILE, puis de ./main.bean dans le répertoire de travail, et un travail planifié s'exécute rarement là où vous pensez qu'il le fait.
bea --file ~/books/main.bean check
BEA_FILE=~/books/main.bean bea check
cd ~/books && bea checkLes options globales vont avant la commande, comme dans bea --file main.bean check. Si le fichier résolu n'existe pas, la commande se termine avec 2 et nomme les trois sources, donc une faute de frappe dans une entrée cron échoue bruyamment au lieu de valider les mauvais livres. Le ciblage hébergé via un drapeau --ledger n'existe pas encore ; bea ne téléverse jamais un fichier local implicitement.
Lisez l'enveloppe JSON
Ajoutez --json global et chaque commande prise en charge répond avec la même enveloppe : bea, target, data, truncated et limit sur les listes bornées. Les montants sont des chaînes décimales et les dates sont au format ISO YYYY-MM-DD, donc une valeur est sûre à comparer sans qu'un flottant n'entre jamais dans le pipeline. Les clés de l'enveloppe sont tabulées dans la référence JSON et codes de sortie.
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}'Ces trois commandes — report, list et import — conservent leurs formes de résultat, donc un chemin jq écrit contre elles reste valide. bea --json check et bea --json query émettent également l'enveloppe aujourd'hui, mais ce sont les commandes confiées aux exécutables Beancount natifs, donc un script doit se baser sur le statut de sortie de check plutôt que sur sa forme de sortie. Choisissez votre politique de doublons délibérément : --duplicates est toujours requis lorsqu'une importation a besoin d'une décision, comme l'explique la procédure pas à pas d'importation.
Arrêtez-vous sur le bon code de sortie
Branchez-vous sur le statut et lisez l'objet d'erreur avant de réessayer quoi que ce soit qui écrit. En mode --json, un échec n'écrit rien sur stdout et exactement un objet sur stderr, dont error.category nomme la classe : 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" ;;
esacLa sortie 4 est celle qu'un script ne doit jamais réessayer aveuglément : elle signifie que le résultat est un conflit ou est inconnu, comme une modification externe arrivant en plein écriture ou une cible init qui existe déjà. Inspectez le grand livre, puis réessayez à partir d'une lecture fraîche. La sortie 1 couvre les échecs de validation et toute autre erreur d'exécution ; error.details contient les erreurs individuelles du grand livre, et error.result contient ce qu'une écriture partielle a réellement fait. Une sortie non nulle ne garantit jamais que rien n'a changé.
Exécutez sans terminal
bea arrête de demander de lui-même. --no-input est implicite chaque fois que stdin n'est pas un terminal, chaque fois que --json est défini, et chaque fois que CI est vrai — 1, true, yes ou on. Dans ce mode, une confirmation manquante échoue avec la sortie 2 au lieu d'attendre indéfiniment.
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 oldestLes lectures sont indulgentes dans un terminal et strictes partout ailleurs. Lorsque le grand livre a des erreurs de chargeur, query, list et report sortent avec 1 sous --json, sous une sortie stdout canalisée, sous un CI vrai, ou avec --strict ; passez le propre --allow-errors de la commande pour accepter la réponse partielle à la place, ce qui définit également ledger_valid: false et remplit ledger_errors dans le JSON. --strict est l'image miroir : il refuse les réponses partielles même dans un terminal, ce qui est ce que vous voulez lorsqu'un humain exécute le même script à la main. bea check n'a pas de --allow-errors — signaler les erreurs est son travail entier — et sort toujours avec 1 lorsqu'il en trouve. Définissez BEA_NO_UPDATE_NOTIFIER=1 pour faire taire l'avis de mise à jour passif ; un CI vrai le fait déjà.
Planifiez une vérification
Exécutez une validation chaque nuit et laissez le code de sortie être l'alerte. Les deux blocs ci-dessous sont des modèles — les chemins, le calendrier et l'exécuteur sont les vôtres.
# 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.jsonLa première commande soutenue par le moteur télécharge le moteur géré, donc l'exécuteur a besoin d'un accès réseau. Pour le réutiliser entre les travaux, mettez en cache ~/.local/share/bea/engine avec une clé contenant l'OS de l'exécuteur, l'architecture, la version Python et la version épinglée de bea. Épinglez la version lorsque le travail doit être reproductible, et retirez l'épingle lorsque vous préférez suivre les versions. CI est déjà vrai sur GitHub Actions, donc les invites sont désactivées et l'avis de mise à jour est silencieux avant que vous définissiez quoi que ce soit. Il n'y a volontairement aucune étape de formatage ici. Un travail planifié ne doit pas réécrire des fichiers qu'il n'a pas à le faire, donc utilisez bea format main.bean --check dans un hook pre-commit, qui ne touche à rien et sort avec 1 lorsqu'un fichier a besoin d'être formaté.
Utilisez une identité hébergée dans un travail
Définissez BEA_TOKEN, depuis le stockage secret de votre fournisseur CI, et sautez entièrement la connexion par navigateur. Le jeton est lu depuis l'environnement et jamais écrit sur disque, donc rien n'atterrit dans le répertoire personnel de l'exécuteur pour que le prochain travail le trouve.
export BEA_TOKEN="$YOUR_CI_SECRET"
bea --json cloud statusLa sortie 0 signifie que l'identité a été résolue et que l'enveloppe nomme le compte auquel elle appartient ; la sortie 3 avec error.category de auth signifie qu'elle ne l'a pas été, et le message distingue une identité non définie d'une identité rejetée. bea cloud logout ne fait rien à un jeton fourni de cette manière — il ne le révoque ni ne le désactive, car un autre travail peut le partager — donc révoquez un jeton fuité depuis le tableau de bord à la place. Les commandes locales n'ont besoin d'aucune identité du tout ; seuls bea cloud et bea ask atteignent le service hébergé. La liste complète des variables se trouve dans la référence des paramètres.
Tout ne répond pas en JSON. bea ask rejette carrément le mode JSON, bea cloud login a besoin d'un humain, et un bea cloud logout ou bea cloud ledger clone réussi ne renvoie aucun objet JSON de succès — lisez leur statut de sortie à la place. L'aide, la version et la sortie de complétion de shell restent textuelles.
Prochaines étapes
- Automatisez les fichiers bancaires avec la procédure pas à pas d'importation CLI.
- Consultez n'importe quel drapeau, clé d'enveloppe ou code de sortie dans la référence CLI Beancount.
- Utilisez Python uniquement lorsque la CLI ne suffit plus : voir workflows scriptables.