본문으로 건너뛰기

bea로 장부 작성 자동화

bea로 Beancount 장부를 스크립트화하세요: 원장을 명시적으로 결정하고, jq로 JSON 봉투를 파싱하고, 종료 코드로 분기하고, 무인으로 실행하고, 야간 점검을 예약하세요.

스크립트는 네 가지 결정으로 bea를 구동합니다: 읽을 원장, 기계 판독 가능 출력을 위한 --json, 필요한 값을 위한 jq, 분기할 종료 코드. 이 가이드는 이 네 가지 결정을 처음부터 끝까지 다룬 다음, 이를 예약합니다.

작업을 실행하는 머신에 bea와 도달 가능한 원장이 필요합니다. 새 장부를 시작하는 경우 먼저 CLI 빠른 시작을 따르세요. 플래그, 봉투 키, 종료 코드에 대한 모든 사실은 Beancount CLI 참조에서 확인하며, 여기서 반복하지 않습니다.

원장을 명시적으로 선택​

파일을 지정하세요. 로컬 명령은 --file, 그다음 $BEA_FILE, 그다음 작업 디렉터리의 ./main.bean 순서로 대상을 결정하며, 예약된 작업은 생각한 곳에서 실행되는 경우가 드뭅니다.

bea --file ~/books/main.bean check
BEA_FILE=~/books/main.bean bea check
cd ~/books && bea check

전역 옵션은 bea --file main.bean check처럼 명령 앞에 옵니다. 결정된 파일이 존재하지 않으면 명령은 2로 종료되고 세 가지 소스를 모두 명명하므로, cron 항목의 오타는 잘못된 장부를 검증하는 대신 크게 실패합니다. --ledger 플래그를 통한 호스팅 대상 지정은 아직 존재하지 않습니다. bea는 로컬 파일을 암시적으로 업로드하지 않습니다.

JSON 봉투 읽기​

전역 --json을 추가하면 지원되는 모든 명령이 동일한 봉투로 응답합니다: bea, target, data, truncated, 그리고 제한된 목록의 limit. 금액은 소수 문자열이고 날짜는 ISO YYYY-MM-DD이므로, 부동 소수점이 파이프라인에 들어가지 않고도 값을 비교하기에 안전합니다. 봉투의 키는 JSON 및 종료 코드 참조에 표로 정리되어 있습니다.

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}'

이 세 명령 — report, list, import — 은 결과 형태를 유지하므로, 이에 대해 작성된 jq 경로는 유효하게 유지됩니다. bea --json check와 bea --json query도 오늘 봉투를 내보내지만, 이들은 네이티브 Beancount 실행 파일에 전달되는 명령이므로, 스크립트는 출력 형태보다 check의 종료 상태를 기준으로 해야 합니다. 중복 정책을 의도적으로 선택하세요: 가져오기에 결정이 필요할 때 --duplicates는 여전히 필요하며, 가져오기 연습에서 설명합니다.

올바른 종료 코드에서 중지​

상태에 따라 분기하고, 쓰는 것을 재시도하기 전에 오류 객체를 읽으세요. --json 모드에서 실패는 stdout에 아무것도 쓰지 않고 stderr에 정확히 하나의 객체를 쓰며, 해당 error.category는 클래스를 명명합니다: 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" ;;
esac

종료 4는 스크립트가 절대 맹목적으로 재시도해서는 안 되는 것입니다: 결과가 충돌이거나 알 수 없음을 의미합니다. 예를 들어 쓰기 중 외부 편집이 도착하거나 init 대상이 이미 존재하는 경우입니다. 원장을 검사한 다음, 새 읽기에서 재시도하세요. 종료 1은 검증 실패 및 기타 런타임 오류를 포함합니다. error.details는 개별 원장 오류를 담고, error.result는 부분 쓰기가 실제로 수행한 작업을 담습니다. 0이 아닌 종료는 아무것도 변경되지 않았음을 보장하지 않습니다.

터미널 없이 실행​

bea는 자체적으로 프롬프트를 중지합니다. stdin이 터미널이 아닐 때, --json이 설정될 때, CI가 참일 때 — 1, true, yes 또는 on — --no-input이 암시됩니다. 이 모드에서 누락된 확인은 영원히 기다리는 대신 종료 2로 실패합니다.

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 oldest

읽기는 터미널에서 관대하고 다른 모든 곳에서 엄격합니다. 원장에 로더 오류가 있을 때, query, list, report는 --json 아래, 파이프된 stdout 아래, 참인 CI 아래, 또는 --strict와 함께 종료 1입니다. 대신 부분 답변을 수용하려면 명령 자체의 --allow-errors를 전달하세요. 이는 또한 JSON에서 ledger_valid: false를 설정하고 ledger_errors를 채웁니다. --strict는 반대입니다: 터미널에서도 부분 답변을 거부하며, 이는 사람이 동일한 스크립트를 수동으로 실행할 때 원하는 것입니다. bea check에는 --allow-errors가 없습니다 — 오류 보고가 그것의 전체 작업입니다 — 그리고 오류를 찾으면 항상 1로 종료합니다. 수동 업데이트 알림을 끄려면 BEA_NO_UPDATE_NOTIFIER=1을 설정하세요. 참인 CI는 이미 그렇게 합니다.

점검 예약​

매일 밤 검증을 실행하고 종료 코드를 알림으로 사용하세요. 아래 두 블록은 템플릿입니다 — 경로, 일정, 실행기는 여러분의 것입니다.

# 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 check
name: 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.json

첫 번째 엔진 기반 명령이 관리되는 엔진을 다운로드하므로, 실행기는 네트워크 액세스가 필요합니다. 작업 간에 재사용하려면 실행기 OS, 아키텍처, Python 버전, 고정된 bea 버전을 포함하는 키로 ~/.local/share/bea/engine을 캐시하세요. 작업이 재현 가능해야 하면 버전을 고정하고, 릴리스를 추적하고 싶으면 고정을 제거하세요. GitHub Actions에서 CI는 이미 참이므로, 아무것도 설정하기 전에 프롬프트가 꺼져 있고 업데이트 알림이 조용합니다. 여기에는 의도적으로 포맷 단계가 없습니다. 예약된 작업은 필요하지 않은 파일을 다시 쓰지 않아야 하므로, 터치하지 않고 파일이 포맷이 필요할 때 1로 종료하는 pre-commit 훅에서 bea format main.bean --check를 사용하세요.

작업에서 호스팅된 자격 증명 사용​

CI 제공자의 비밀 저장소에서 BEA_TOKEN을 설정하고 브라우저 로그인을 완전히 건너뛰세요. 토큰은 환경에서 읽히고 디스크에 기록되지 않으므로, 다음 작업이 찾을 수 있도록 실행기의 홈 디렉터리에 아무것도 남지 않습니다.

export BEA_TOKEN="$YOUR_CI_SECRET"
bea --json cloud status

종료 0은 자격 증명이 결정되었고 봉투가 속한 계정을 명명함을 의미합니다. error.category가 auth인 종료 3은 그렇지 않음을 의미하며, 메시지는 설정되지 않은 자격 증명과 거부된 자격 증명을 구분합니다. bea cloud logout은 이렇게 제공된 토큰에 대해 아무것도 하지 않습니다 — 다른 작업이 공유할 수 있으므로 해지하거나 설정 해제하지 않습니다 — 따라서 유출된 토큰은 대시보드에서 해지하세요. 로컬 명령은 자격 증명이 전혀 필요하지 않습니다. bea cloud와 bea ask만 호스팅 서비스에 도달합니다. 전체 변수 목록은 설정 참조에 있습니다.

모든 것이 JSON으로 응답하는 것은 아닙니다. bea ask는 JSON 모드를 완전히 거부하고, bea cloud login은 사람이 필요하며, 성공적인 bea cloud logout 또는 bea cloud ledger clone은 JSON 성공 객체를 반환하지 않습니다 — 대신 종료 상태를 읽으세요. 도움말, 버전 및 셸 완성 출력은 텍스트로 유지됩니다.

다음 단계​

출처: https://beancount.io/ko/docs/Solutions/automate-bookkeeping-with-bea