メインコンテンツへスキップ

bea 0.2.0: ワンインストールでBeancountツールチェーン一式

公開日 約5分Mike ThriftMike Thrift
bea 0.2.0: ワンインストールでBeancountツールチェーン一式

同僚、新しいラップトップ、または夜間のcronジョブに動作するBeancount環境を渡したことがあるなら、会計自体が難しい部分ではなかったことをご存じでしょう。難しいのはツールチェーンでした。一致するPython、パス上のbean-checkbean-query、1つの貸借対照表のために導入したレポートライブラリ、そして質問した瞬間にファイルを書き換えるフォーマッタ。2026年9月12日にリリースされたbea 0.2.0は、そのチェックリストを1つのインストールに置き換えます。beaコマンドは現在、完全なネイティブBeancountツールチェーンを内包し、自己プロビジョニングする管理型エンジン内で実行し、スクリプトやAIエージェントがすでに依存している機械可読な契約を維持します。

これは0.2.0のリリースノートであり、私たちが社内でリリースを追跡する方法で書かれています。何が出荷されたか、裏で何が変わったか、パッケージインデックスに到達する前にどのように検証されたか、意図的にまだやらないこと、そしてアップグレード方法です。初回実行のストーリーを読みたい場合は、0.1.0ローンチ記事CLIクイックスタートが短めの読み物です。

リリース概要

2つのチャンネルが同じコマンドを公開します。1つを選び、バージョンで応答することを確認します:

$ brew install bex-co/tap/bea        # macOSおよびLinuxbrew
$ uv tool install beancount-io       # uvとPython 3.12以降があればどこでも
$ bea --version
bea 0.2.0
bea 0.2.0
cli-v0.2.02026-09-12
エンジン
beancount 3.2.3 beanquery 0.2.0
オプション
beangulp 0.2.0 beanprice 2.1.0
Python
3.12 3.14

0.2.0リリースカード: タグと公開日、管理型エンジンが固定するBeancountとBeanqueryのバージョン、2つのオプションエンジン機能、およびリリースがインストール・テストされたPythonバージョン。

項目内容
バージョン0.2.0、タグcli-v0.2.0、2026-09-12にPyPIとbex-co/homebrew-tap Homebrewタップに公開
前回リリース0.1.0、3日前の2026-09-09にタグ付け
変更セットCLIに影響する27コミット、119ファイル変更、約12,300行追加、2,100行削除
エンジン固定ベースエンジンのBeancount 3.2.3とBeanquery 0.2.0。Beangulp 0.2.0とBeanprice 2.1.0はオプトイン機能
ヘッドラインすべてのネイティブBeancountツールが1つのプレフィックス配下に、管理型エンジンが提供。0.1.0のJSONエンベロープと終了コード契約は変更なし

裏側の変更: 管理型エンジン

0.1.0では、beaはBeancountを独自のプロセスにインポートしていました。これはどのPythonツールでも同じ方法です。これは機能しましたが、CLIの依存関係グラフがBeancountの依存関係グラフと同じになり、「まずBeancountをインストールする」という暗黙のステップがすべてのガイドに残りました。

0.2.0はプログラムの中央に線を引きます。コマンド、オプション、レンダリングを所有するbeaフロントエンドは、Beancount、Beanquery、またはベンダリングされたFavaレポートコードを決してロードしません。ローカルの台帳作業は管理型エンジンで実行されます。これはbeaがハッシュ固定されたロックからプロビジョニングし、子インタープリターとして起動する独立したPython環境です。フロントエンドはその境界を越えてJSONリクエストを送信し、返ってきたものをレンダリングします。Beancountをインストールしたり、bean-*ツールをパスに置いたり、それらがどのPythonを見つけたかを考える必要はありません。

エンジンの入手方法はチャンネルによって異なります:

  • Homebrewはインストール中にフロントエンドとエンジン環境を作成します。ローカルコマンドは追加ダウンロードなしでkegローカルエンジンを使用します。
  • PyPI(uv tool installまたはpipx)は初回使用時にプロビジョニングします。エンジンを必要とする最初のローカルコマンドが固定された組み合わせをダウンロードします。これにはネットワークアクセスとパス上のuvが一度必要です。以降のコマンドは~/.local/share/bea/engine/<version>からオフラインで再利用するか、XDG_DATA_HOMEを設定している場合はその下から再利用します。

この設計から3つの特性が生まれ、それぞれがすでに目撃したサポートチケットを1つ削減します:

  1. アップグレードはペアを維持。 bea upgradeは、このコピーをインストールしたパッケージマネージャーに更新を委ね、その後で一致するエンジンを再構築するため、フロントエンドとエンジンが異なるバージョンにドリフトすることはありません。
  2. 壊れたエンジンは自己修復。 プロビジョニングが途中で失敗した場合、管理環境は破棄され、次の成功した試行で再構築されます。パス上の他の場所にある迷子のbean-checkバイナリは誤って拾われることなく無視されます。
  3. 重いオプション部品はオプションのまま。 Beangulpインポートフレームワークはシステムのlibmagicライブラリを必要とし、Beanpriceは見積もり取得依存関係を引き込みます。どちらもベースエンジンにはありません。エンジンにのみ明示的に有効にします。
$ bea engine status
$ bea engine enable beangulp     # 取り込みヘルパー。システムのlibmagicライブラリが必要
$ bea engine enable beanprice    # bean-price見積もり取得

bea engine statusはエンジンがプロビジョニングされているか、どのオプション機能が有効かを報告し、ネットワークなしでそれを伝えます。初回使用のプロビジョニングが失敗した場合は、ネットワークまたはuvを修正して、bea checkなどのローカルコマンドを再実行してください。その横にpip install beancountをしないでください。フロントエンドはそれを使用しません。

すべてのネイティブツール、1つのプレフィックス

エンジンはメカニズムです。ユーザー向けの変更は同等性です。アップストリームのBeancountプロジェクトが出荷するすべての実行可能ファイルにbeaの対応物があり、同じ引数が転送され、同じ出力が維持されます。

$ bea check                                    # bean-checkに加えてbeaの--jsonエンベロープ
$ bea format main.bean -o clean.bean           # bean-format: デフォルトはstdout、-iで書き換え
$ bea query "SELECT account, sum(position) GROUP BY account"
$ bea doctor context main.bean 2026-01-02      # 11すべてのbean-doctor操作
$ bea example --seed 1 -o example.beancount    # bean-example
$ bea treeify < balances.txt                   # treeify
$ bea ingest identify --config ingest.py inbox # Beangulp、エンジン有効化後
$ bea price -e USD:yahoo/AAPL                  # bean-price、エンジン有効化後
bean-check
bea check
bean-format
bea format
bean-query
bea query
bean-doctor
bea doctor
bean-example
bea example
treeify
bea treeify
beangulp
bea ingest bea engine enable beangulp
bean-price
bea price bea engine enable beanprice

同等性マップ: 破線より上の6つのネイティブBeancount実行可能ファイルはそのまま動作。下の2つはエンジンでその機能を有効にするとBeangulpとBeanpriceに転送されます。

これらのいくつかはテーブルの1行以上の価値があります。

bea checkbean-check にbeaのJSONエンベロープを重ねたものです。同じ検証、同じエラーメッセージ、そして--jsonの下でスクリプトがすでに解析している同じvaliderrorsフィールド。

bea formatは動作が変更されました。これはこのリリースでスクリプトを驚かせる可能性がある唯一の変更です。0.1.0では、bea format PATHはファイルを書き換えました。現在はフォーマットされたテキストをstdoutに出力し、ファイルはそのままにします。--in-place(-i)が書き換えを行い、--output FILE(-o)は別の場所に書き込み、--checkはファイルがフォーマットを必要とするときに1で終了するCIゲート、--dry-runは何が変更されるかを一覧表示します。これはbean-formatに従います。そのデフォルトは安全なものです。パスを読み取って静かに書き換えるコマンドは、事前に試すことができません。フォーマットはパースではなくテキスト変換なので、構文エラーのあるファイルを拒否しなくなりました。認識したものを整列し、残りはそのままにします。有効性はbea checkを実行してください。

bea queryはネイティブの全機能を備えました。 引数、stdin、または対話型シェルでBQLを受け取ります。対話型シェルは現在、アップストリームのBeanqueryシェルを子プロセスとして起動し、.format.output.run.setコマンドがそのまま動作します。--formattextcsv、またはbeancountレンダリングを選択し、--numberifyは金額を通貨ごとに1列に分割し、-oはファイルに書き込み、--source URIはネイティブのBeanqueryソースをそのまま渡します。

bea doctorは11すべてのbean-doctor操作を公開します: lexparseroundtripdirectorieslist-optionsprint-optionscontextlinkedregionmissing-opendisplay-contextbean-doctor contextで予約問題をデバッグしたことがあれば、同じツールが同じアドレスにあります。

bea examplebea treeify はネイティブのジェネレーターとネイティブのツリーレンダラーで、そのまま転送されます。

bea ingestbea price は、bea engine enableの後、それぞれBeangulpのidentifyextractarchivebean-priceに転送します。Python不要のCSVパスであるbea import --csvはどちらも必要とせず、変更なしです。

転送されたコマンドを結びつける1つのルールがあります: doctorexampletreeifypriceingestは引数をアップストリームに変更なしで渡し、アップストリームの出力と終了ステータスを維持します。つまり、台帳をbea doctor lex main.beanのようにグローバルな--fileではなく独自の位置引数として受け取ります。エンベロープと以下の終了コードカテゴリはbea自身のコマンドを説明しています。

スクリプトが信頼し続けられる契約

機械可読なインターフェースは何も移動していません。グローバルな--jsonは引き続きbeatargetdatatruncatedを含む1つのエンベロープをstdoutに置き、さらに制限付きリストにはlimit、ページングされたホスト型リストにはpageを含みます。金額は浮動小数点数ではなく常に10進文字列で、日付はISO YYYY-MM-DDです。--json--no-inputを暗黙に含みます。非端末のstdinまたは真のCI変数も同様で、無人ジョブが人間を待つことはありません。--strictは端末でも部分的な回答を拒否し、各読み取りコマンドの--allow-errorsでオプトインに戻ります。

失敗はstdoutに何も書き込まず、stderrに正確に1つのオブジェクトを書き込みます:

{
  "error": {
    "category": "validation",
    "message": "Ledger has 3 error(s). Pass --allow-errors to report anyway.",
    "exit_code": 1,
    "details": ["main.bean:1: Transaction does not balance: (2.50 USD)"]
  }
}
0
ok
1
validation
2
usage
3
auth
4
conflict

5つの終了コードと、各コードがJSONエラーオブジェクトで運ぶcategory文字列。スクリプトは数値で分岐し、人間はカテゴリを読みます。

コードカテゴリ意味
0なし成功。プレビューや意図的な重複スキップを含む
1validation台帳または検証エラー。その他の実行時失敗のキャッチオール
2usage不正な引数、欠落したターゲットまたは余分なもの、または--no-input下で必要な入力
3auth認証または権限の失敗。読み取り専用の宛先を含む
4conflict同時変更、重複レビューが必要なインポート、または結果が不明な書き込み

失敗時に再試行する人にとって重要な2つの詳細があります。ゼロ以外の終了が普遍的に何も変更されなかったことを意味するわけではありません: add transactions --partialは受け入れられた行を書き込むことができ、複数ファイルでのformat -iは1つで失敗する前にいくつかを書き換えることができ、cloud ledger create --cloneはクローンが失敗する前に台帳を作成できます。再試行する前にerror.resultを読んでください。また、ホスト型コマンドはサーバーのHTTPステータスを同じテーブルにマッピングし、サーバー自身のメッセージを保持します: 401と403は3で終了、400は2で終了、409は4で終了、レート制限を含むその他すべては1で終了します。CLIが結果を知ることができない書き込み(削除途中のタイムアウトなど)は4で終了し、推測するのではなくその旨を伝えます。

自動化ガイドは、このエンベロープを端から端までjqパイプラインで説明しています。

一緒に運ばれた修正

同等性リリースは、最初のリリースが明らかにした欠陥を修正する機会でもあります。これらは2つのタグの間に、それぞれ回帰テスト付きで取り込まれました:

  • 数値は科学的記数法ではなく固定小数点テキストとして書かれますbea initがレンダリングする期首残高を含みます。1E+3と書かれた台帳は技術的には有効ですが、実質的に読めません。
  • コストロットは日付とラベルを保持したままJSONシリアライゼーションを生き延びます、トランザクションが書かれるときにロットラベルは正しくエスケープされます。
  • インポート中、明示的なゼロポスティングは実額として扱われます、「省略された、バランスを取ってください」と読まれるのではなく。
  • CSVインポートは1つの厳格なリーダーを使用します。 ヘッダー検出は列名を削除するのに、抽出は生のキーを保持していたため、ドキュメントが受け入れると約束したパディングされたヘッダーが欠落列として失敗しました。現在、名前は一度削除され、マッピングされた列は正確に一度出現する必要があり、閉じられていない引用符は何かが書かれる前に行番号付きで失敗します。
  • BQLはURL解析された接続文字列ではなく正確な台帳パスを読み込みます、異常なパスがCLIの残りと同じ方法で解決されるように。
  • bea balance <term>は表示するものだけを合計します。 保持された親はもはや除外された兄弟の合計を報告せず、無関係な未価格の保有はもはやUSD選択を失敗させず、エンベロープは適用されたフィルターを報告します。レポートの不正な--accountパターンは使用法エラーとして2で終了します。
  • JSONモードのstderrは常に1つのオブジェクトです、許容された警告が失敗に先行する場合でも。
  • ホスト型資格情報は早期かつ一貫して失敗します: 空白を含むBEA_TOKENは任意のリクエストの前に拒否され、失効した資格情報はcloud statusと台帳コマンドによって同じ方法で報告され、owner/nameは確認プロンプトまたは認証済み呼び出しの前に検証されます。cloud logoutBEA_TOKENをそのまま残し、cloud ledger list --jsonは実際に提供したページをエコーします。
  • Homebrewフォーミュラは正確なPyPIアーティファクトURLを固定します、タップインストールとPyPIインストールが証明可能に同じバイトであることを保証します。

あなたが見る前にどのように検証されたか

リリースは主張であり、パイプラインがその証拠です。cli-v0.2.0タグは、pyproject.tomlのバージョンが正確に一致するmain上のコミットを指名する必要があります。ワークフローはそれ以外のものを拒否します(プレリリースサフィックスを含む)。そこから:

  1. 完全なチェックスイートが最初に実行されます。 make check-allはlint、フォーマット、厳格なmypy、デッドコード検出、生成されたリファレンスのドリフトチェック、テストスイートをカバーします。リリースプルリクエストは635テスト合格を記録します。
  2. エンジンロックがエクスポートされハッシュ固定され、ソース配布物とホイールが一度だけ構築されます。以降のすべてのステップは、再構築ではなくこれらの正確なアーティファクトをテストします。
  3. 3つのオペレーティングシステムと2つのPythonでのクリーンインストール。 ホイールはuv toolで、sdistはpipでLinux、macOS、Windows、Python 3.12と3.14でインストールされ、オプションのAIエクストラを含みます。HomebrewジョブはmacOSとLinuxの一時タップを通じてsdistをインストールします。
  4. 公開は順次的かつトークンレスです。 PyPIは信頼できる公開を通じてアーティファクトを受け取り、漏洩する可能性のある長期APIトークンはありません。GitHubリリースは公開証明書を添付して作成され、Formula/bea.rbはPyPIが実際に提供したsdist URLとハッシュとともに公開タップにプッシュされます。
  5. 公開後のスモークテストは実際のインデックスからインストールします。 別々のジョブがPyPIと公開タップから固定バージョンをインストールし、インストールされた実行可能ファイルに対して同じ顧客スモークテストを実行します。そこでの失敗は何もロールバックしませんが、リリースが誰かに伝えられる前に注意が必要であることを意味します。

この投稿はステップ5の向こう側で書かれています。

0.1.0からのアップグレード

コピーをインストールしたマネージャーを通じてアップグレードを実行するか、beaに任せてください:

$ bea upgrade --check      # インストール済みと最新のバージョン、実行されるコマンドを報告
$ bea upgrade              # brew upgrade bea、uv tool upgrade beancount-io、またはpipx upgrade beancount-io

マネージャーが完了した後、bea upgradeは管理型エンジンを更新して2つがペアを維持します。次に3つのことを確認します:

  • ファイルを書き換えるためにbea format PATHを実行したスクリプトは現在bea format -i PATHが必要です。以前のデフォルトはプレビューできませんでしたが、新しいものはできます。
  • フォーマットが構文エラーをキャッチすることに依存していたスクリプトはそのためにbea checkを呼び出すべきです。フォーマットはもはやパースしないためです。
  • PyPIインストールはアップグレード後の最初のローカルコマンドでネットワークとuvが一度必要です、エンジンがプロビジョニングできるように。Homebrewインストールは何も必要ありません。

スクリプトがすでに解析しているすべて、エンベロープキー、10進文字列、終了コードは変更されていません。エンベロープのbeaフィールドは現在0.2.0を読み取ります。

このリリースがやらないこと

  • ホスト型ターゲットは実装されていません。 --ledgerフラグはありません。ローカルコマンドはローカルファイルを読み取り、暗黙的にアップロードすることはありません。ホスト型台帳はbea cloudで管理され、gitクローンとして作業されます。
  • bea askは引き続きaskエクストラとBeancount.io資格情報が必要です--jsonをサポートしていません。デフォルトのインストールはAI依存関係を含みません。
  • BeangulpとBeanpriceはオプトインです、Beangulpはシステムのlibmagicライブラリが必要です。bea import --csvはどちらもなしで銀行エクスポートをカバーします。
  • 転送されたネイティブコマンドはエンベロープを出力しません。 doctor操作から構造化出力が必要な場合、それは私たちが聞きたいリクエストです。

タグ以来、mainはすでに0.2.0のQAの最初のラウンドを取り込んでおり、次のリリースに乗ります: bea formatはフィルターとしてstdinを読み取り、その-o FILEモードは何を書いたかを示すエンベロープで応答します。--json checkbean-check専用フラグを拒否し、--jsondoctorexampletreeifyで完全に拒否されるため、スクリプトがネイティブテキストをエンベロープと誤認できません。--json query -o FILEはエンベロープをファイルに原子的に書き込み、--numberifyはJSONにも適用されます。bea engine statusはどのエンジンティアが提供しているかを示します。コメントで始まるBQLクエリが実行されます。ネイティブのパススルー--helpはエンジンがプロビジョニングされる前に動作します。クエリシェルの.outputは失敗したリダイレクトの後に元のストリームを復元します。

次のステップ

帳簿をコードとして保つ

1行でインストールできるツールチェーンは、誰にでも渡せるツールチェーンです。共同創業者、簿記係、CIランナー、AIエージェント。Beancount.ioは透明で、バージョン管理され、再現可能なプレーンテキスト会計を提供し、beaはローカル台帳を誠実に保つコマンドであり、ホスト型サービスはチーム、電話、アシスタントが同じ帳簿に会う場所です。beaをインストールして最初のチェックを実行してください。リリースが予期しないことをした場合、GitHubリポジトリが私たちがそれを聞きたい場所です。

この記事を共有

出典: https://beancount.io/ja/blog/2026/09/16/bea-0-2-0-one-install-whole-beancount-toolchain

公開日: 2026年9月16日