Uno script controlla bea con quattro decisioni: quale libro contabile leggere, --json per l'output leggibile dalla macchina, jq per il valore richiesto e il codice di uscita su cui fare branching. Questa guida illustra queste quattro decisioni dall'inizio alla fine, quindi le schedula.
Serve bea sulla macchina che esegue il lavoro e un libro contabile a cui può accedere. Se stai iniziando nuovi libri, segui prima la guida rapida CLI. Ogni dettaglio su flag, chiavi degli envelope e codici di uscita si trova nella riferimento CLI di Beancount, qui non è ripetuto.
Scegli esplicitamente il libro contabile
Nomina il file. Un comando locale risolve il suo target da --file, poi $BEA_FILE, poi ./main.bean nella directory di lavoro, e un lavoro schedulato raramente gira dove pensi.
bea --file ~/books/main.bean check
BEA_FILE=~/books/main.bean bea check
cd ~/books && bea checkLe opzioni globali vanno prima del comando, come in bea --file main.bean check. Se il file risolto non esiste il comando esce con 2 e nomina tutte e tre le fonti, così un errore di battitura in una voce cron fallisce rumorosamente invece di validare i libri sbagliati. Il targeting ospitato tramite una flag --ledger non esiste ancora; bea non carica mai implicitamente un file locale.
Leggi l'envelope JSON
Aggiungi --json globale e ogni comando supportato risponde con lo stesso envelope: bea, target, data, truncated e limit su liste limitate. Gli importi sono stringhe decimali e le date sono YYYY-MM-DD ISO, così un valore è sicuro da confrontare senza che un float entri mai nel flusso. Le chiavi dell'envelope sono tabulate nella riferimento JSON e codici di uscita.
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}'Quei tre comandi — report, list e import — mantengono la forma del risultato, così un percorso jq scritto contro di loro rimane valido. Anche bea --json check e bea --json query emettono oggi l'envelope, ma sono i comandi assegnati agli eseguibili nativi di Beancount, quindi uno script dovrebbe basare la chiave sul codice di uscita di check piuttosto che sulla forma dell'output. Scegli con attenzione la tua politica sui duplicati: --duplicates è ancora richiesta quando un'importazione necessita una decisione, come spiega la guida all'importazione.
Fermati sul codice di uscita corretto
Fai branching sullo stato e leggi l'oggetto errore prima di ritentare qualsiasi scrittura. In modalità --json un fallimento non scrive nulla su stdout e esattamente un oggetto su stderr, il cui error.category nomina 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" ;;
esacExit 4 è quello che uno script non deve mai ripetere ciecamente: significa che il risultato è un conflitto o è sconosciuto, come una modifica esterna arrivata a metà scrittura o un target init che esiste già. Ispeziona il libro contabile, poi riprova da una lettura fresca. Exit 1 copre errori di validazione e qualsiasi altro errore a runtime; error.details porta gli errori individuali del libro contabile, e error.result rappresenta ciò che una scrittura parziale ha effettivamente fatto. Un exit diverso da zero non garantisce mai che nulla sia cambiato.
Eseguire senza terminale
bea interrompe le richieste automaticamente. --no-input è implicito ogni volta che stdin non è un terminale, ogni volta che --json è impostato, e ogni volta che CI è vero — 1, true, yes o on. In quella modalità una conferma mancante fallisce con exit 2 invece di attendere per sempre.
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 oldestLe letture sono permissive in un terminale e rigorose altrove. Quando il libro contabile presenta errori di caricamento, query, list e report escono con 1 sotto --json, sotto uno stdout canalizzato, quando CI è vero, o con --strict; passa il proprio --allow-errors del comando per accettare la risposta parziale invece, che imposta anche ledger_valid: false e popola ledger_errors nel JSON. --strict è l'immagine speculare: rifiuta risposte parziali anche in un terminale, cosa desiderabile quando un umano esegue lo stesso script manualmente. bea check non ha --allow-errors — segnalare errori è il suo compito principale — e esce sempre con 1 quando ne trova. Imposta BEA_NO_UPDATE_NOTIFIER=1 per silenziare l'avviso di aggiornamento passivo; un CI vero già lo fa.
Programmare un controllo
Esegui una validazione ogni notte e lascia che il codice di uscita sia l'avviso. Entrambi i blocchi sottostanti sono modelli — i percorsi, la pianificazione e il runner sono tuoi.
# 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.jsonIl primo comando supportato da motore scarica il motore gestito, quindi il runner necessita di accesso alla rete. Per riutilizzarlo tra i lavori, memorizza nella cache ~/.local/share/bea/engine con una chiave contenente il sistema operativo del runner, l'architettura, la versione di Python e la versione bloccata di bea. Blocca la versione quando il lavoro deve essere riproducibile, e rimuovi il blocco quando preferisci seguire i rilasci. CI è già vero su GitHub Actions, quindi i prompt sono spenti e l'avviso di aggiornamento è silenzioso prima che tu imposti qualsiasi cosa. Non c'è nessuna operazione di formattazione qui di proposito. Un lavoro schedulato non dovrebbe riscrivere file che non deve modificare, quindi usa bea format main.bean --check in un hook pre-commit, che non tocca nulla e esce con 1 quando un file necessita di formattazione.
Usare una credenziale ospitata in un lavoro
Imposta BEA_TOKEN, dal negozio segreto del tuo provider CI, e salta completamente l'accesso via browser. Il token viene letto dall'ambiente e mai scritto su disco, quindi nulla finisce nella directory home del runner per il job successivo.
export BEA_TOKEN="$YOUR_CI_SECRET"
bea --json cloud statusL'uscita 0 significa che la credenziale è stata risolta e la busta nomina l'account a cui appartiene; l'uscita 3 con error.category di auth significa che non è successo, e il messaggio distingue una credenziale non impostata da una rifiutata. bea cloud logout non fa nulla a un token fornito in questo modo — non lo revoca né lo annulla, visto che un altro job potrebbe condividerlo — quindi revoca un token compromesso dalla dashboard invece. I comandi locali non necessitano affatto di credenziali; solo bea cloud e bea ask raggiungono il servizio ospitato. L'elenco completo delle variabili è nella reference sulle impostazioni.
Non tutto risponde in JSON. bea ask rifiuta categoricamente la modalità JSON, bea cloud login ha bisogno di un umano, e un bea cloud logout o bea cloud ledger clone riuscito non restituisce un oggetto successo JSON — leggi invece il loro codice di uscita. L'output di help, versione e completamento della shell resta testuale.
Prossimi passi
- Automatizza i file bancari con la guida all'importazione CLI.
- Cerca qualsiasi flag, chiave busta o codice di uscita nella reference della CLI di Beancount.
- Ricorri a Python solo quando la CLI si esaurisce: vedi i flussi di lavoro scriptabili.