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 commencez de nouveaux livres, suivez d'abord le guide de démarrage rapide CLI. Chaque fait concernant les drapeaux, les clés d'enveloppe et les codes de sortie est consulté dans la référence CLI Beancount, et non répété ici.
Choisir le grand livre explicitement
Nommez le fichier. Une commande locale résout sa cible à partir de --file, puis $BEA_FILE, puis ./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 se placent avant la commande, comme dans bea --file main.bean check. Si le fichier résolu n'existe pas, la commande se termine avec le code 2 et nomme les trois sources, de sorte qu'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écharge jamais implicitement un fichier local.
Lire 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 limitées. Les montants sont des chaînes décimales et les dates sont au format ISO AAAA-MM-JJ, de sorte qu'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, de sorte qu'un chemin jq écrit pour 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 nécessite une décision, comme l'explique la procédure pas à pas d'importation.
S'arrêter 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 à l'aveugle : elle signifie que le résultat est un conflit ou est inconnu, comme une modification externe arrivant en pleine écriture ou une cible init qui existe déjà. Inspectez le grand livre, puis réessayez à partir d'une nouvelle lecture. La sortie 1 couvre les erreurs 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écuter sans terminal
bea arrête de demander des invites tout seul. --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 permissives dans un terminal et strictes partout ailleurs. Lorsque le grand livre a des erreurs de chargeur, query, list et report se terminent avec 1 sous --json, sous un stdout redirigé, 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 tout son travail — et se termine 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à.
Planifier 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.1.0
- run: bea --file main.bean check
- run: bea --json --file main.bean report balance-sheet > balance-sheet.jsonÉ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 ne définissiez quoi que ce soit. Il n'y a pas d'étape de formatage ici volontairement. Un travail planifié ne doit pas réécrire des fichiers qu'il n'était pas obligé de réécrire, alors recourez à bea format --check dans un hook de pré-commit, qui ne touche à rien et se termine avec 1 lorsqu'un fichier nécessite un formatage.
Utiliser une identité hébergée dans un travail
Définissez BEA_TOKEN, depuis le stockage de secrets de votre fournisseur CI, et sautez entièrement la connexion par navigateur. Le jeton est lu depuis l'environnement et n'est jamais écrit sur le disque, de sorte que 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 que ce n'est pas le cas, 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 divulgué depuis le tableau de bord à la place. Les commandes locales n'ont besoin d'aucune identité ; 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 nécessite un humain, et un bea cloud logout ou bea cloud ledger clone réussi ne renvoie aucun objet de succès JSON — 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.
- Recherchez tout drapeau, clé d'enveloppe ou code de sortie dans la référence CLI Beancount.
- Recourez à Python uniquement lorsque la CLI est à court de fonctions : voir workflows scriptables.