コマンド

bcaは、ソースコードを解析して情報を抽出するためのさまざまなコマンドを提供します。各コマンドは、実行するタスクに固有のパラメーターを持つ場合があります。以下では、bca で利用できる主要なコマンドの種類を説明します。

インストール

bca コマンドラインツールは、pip でインストールできる wheel として提供されています。配布名は big-code-analysis-cliで、インストールされるコマンドは bca です — この 2 つは意図的に異なります(PyPI 上の bca という名前は無関係なプロジェクトのものであり、big-code-analysis は本プロジェクトのインポート可能な ライブラリ バインディングです):

pip install big-code-analysis-cli   # PATH に `bca` コマンドをインストールします
bca --version

これにより、pip install ruffruff コマンドを提供するのと同じように、コンパイル済みの bca バイナリが PATH に配置されます — Rust ツールチェインは不要です。wheel には完全な all-languages 文法セットが含まれているため、すべての 対応言語 が追加設定なしで動作します。単一の py3-none-<platform> wheel が、そのプラットフォーム上のすべての CPython 3.x(および PyPy)をカバーします。ビルド済み wheel は Linux(manylinux_2_28 x86_64 / aarch64)、macOS(x86_64 / arm64)、Windows(x86_64)向けに提供されます。それ以外のプラットフォームでは pip はソースビルドにフォールバックし、その場合は Rust ツールチェインが必要です。

これはバイナリの CLI であり、インポート可能な Python バインディングpip install big-code-analysis)とは別物です。その他のインストール方法 — Homebrew、.deb / .rpm / .apk パッケージ、ビルド済みリリースアーカイブ、cargo install big-code-analysis-cli — はリポジトリの README に記載されています。

wheel のビルドと公開のマトリクスは .github/workflows/python-cli-wheels.yml で定義されています。

終了コード

bca はすべてのサブコマンドで単一の終了コード規約に従うため、CI スクリプトは出力を検査せずにプロセスのステータスで分岐できます:

コード意味
0成功。
1ツールエラー — 不正なフラグ / しきい値 / glob 指定、読み取れない入力、またはパース失敗。使用方法エラー(未知のフラグ、不正なサブコマンド、clap に拒否された不正な --threshold 値)も含まれます。決して メトリクスのシグナルではありません。
2メトリクスゲート: check のしきい値を超過した、vcs commit --fail-above に違反した、または --exit-code 指定時の diff / diff-baseline がフィルター後の空でない差分を検出した場合。
35check --exit-codes=tiered のみ: 段階化された違反の重大度(回帰のみ / 混在 / ハード違反。tiered モードではコード 2 は新規のみを意味します)。

コード 25 はゲートシグナルであり、checkvcs commit --fail-above、およびオプトインの --exit-code フラグ指定時の diff / diff-baseline だけが発行します。これらはメトリクスの結果を報告するものであって、ツール自体の失敗ではありません。それ以外のすべてのサブコマンド — metricsopsreportdiffdiff-baselineexemptionsinit など — は、成功時に 0、エラー時に 1 で終了します。1 はツールエラー専用であり — 使用方法エラーも含むため、フラグの打ち間違いがゲート帯域に入ることはありません — CI は常に「ゲートが回帰を検出した」(25)と「ツール自体がクラッシュした」(1)を区別できます。

読み取れない入力

ソースファイルを走査するすべてのサブコマンド — metricsopsreportfunctionsfindcountdumpexemptionspreprocstrip-commentscheckinit(ベースラインを check 経由で生成します)、および diff --since — は、入力ファイルのいずれかが読み取れなかった場合に 1 で終了します。権限がない場合や、走査から読み取りまでの間にパスが消えた場合です。個々の失敗は error processing <path>: … として stderr に列挙され、続いて 1 行のサマリーが出力されます。

この規則が「出力がまったくない場合」ではなく「読み取り失敗が 1 つでもあった場合」なのは、欠落したファイルが結果からは見えないからです。部分的な metrics --output ドキュメントや reportcount は完全なものに見えてしまいます。ファイルを失った diff --since の片側は、それを本来の I/O エラーではなく_追加_または_削除_として報告します。この失敗は終了コードでしか観測できないため、終了コードがそれを担う必要があります。

走査_中にストリーミングされた_出力は、チェックがその後に走るため、そのまま出力されます。したがって混在した実行でも、読み取れたファイルは表示されます — metrics / ops / dump / find / functions の stdout ツリーと、--output-dir のファイル単位のドキュメントです。

走査_後に組み立てられる_出力は完全に抑制されます。部分的なものと完全なものを区別できないからです。これは metrics --output / ops --output の集約ドキュメント、report ドキュメント、count の集計、preproc の JSON、および exemptions レポートに適用されます — いずれも出力も書き込みもされません。

開けないファイルがツリーに正当に含まれている場合は、--exclude で除外してください(あるいは --include でより狭い集合を指定します)。これらのフィルタで除去されたファイルは開かれないため、読み取り失敗にはなりません。

Unlistable directories

A directory the walk cannot list is the same failure one level up, and carries the same exit 1. Its whole subtree drops out of the analysed set before any file is selected, so every count downstream — the metrics document, the count tally, a diff --since side, vcs rank's ranking — is short by an amount nothing in the output reveals. bca check is the worst case: a gate that reports clean on a tree it could not read is indistinguishable from a gate that passed.

Each unlistable entry warns on stderr as bca: warning: skipping walk entry in …, the walk continues so one bad directory does not take down the rest of the tree, and the run ends with a summary line and exit 1.

To exempt a directory you knowingly cannot list, name it in an ignore file (.gitignore, .ignore) or narrow --paths so the walk never reaches it. --exclude does not work here, though it is the right answer for an unreadable file: --exclude filters the paths the walk yielded, and a directory that could not be listed yielded none — the failure happened before the filter could apply.

Two neighbouring cases stay non-fatal by design:

  • A malformed ignore file, or a pattern in one that will not compile. The walker reports these through the same channel and they warn identically, but they describe how the walk was configured rather than files it lost. Only errors carrying an underlying I/O error are counted, so a stray .gitignore typo cannot fail a build.
  • A broken symlink discovered by walking. It is dropped for not being a regular file and never surfaces as an error at all — the walk does not follow links, so it deliberately does not resolve symlinks and has nothing to report. Treating one as fatal would make a stale symlink in a vendored tree a hard CI failure.

An explicitly named path is the exception to that last point, and a pre-existing one: --paths resolves a symlink seed once, and a seed that does not exist — dangling link or typo — is its own error, also exit 1.

Unwritable output

The mirror image is the same rule, and it holds for every emission path: a run whose output could not be written exits 1. That covers a per-file document under an unwritable --output-dir, and a full disk on stdout — dump's banners and trees, find's matches, strip-comments' rewritten source, count's tally, preproc's JSON, and the single-document reports from vcs, vcs commit, and vcs trend alike, in every format. A per-file failure is named on stderr and counted in a summary line; output assembled after the walk reports the operating system's error directly.

The one exemption is a closed downstream pipe: bca dump | head is routine rather than a failure, so BrokenPipe is swallowed and the run still exits 0.

フラグの位置と入力パス

ほとんどのサブコマンドは、解析対象の入力を末尾の位置引数パスとして読み取るため、一般的なケースは他のコードツール(tokeiclocsccrg)と同じ書き方になります。例外は次のとおりです: reportvcs--paths で入力を選択し、diff は 2 つの結果セットを比較し、init--dir でディレクトリを対象にします。

bca metrics src/            # src/ ツリーを解析する
bca check src/ tests/       # 2 つのサブツリーをゲートする
bca find -t function_item . # 現在のツリー内のすべての関数を検索する

フラグは それを消費するサブコマンドにスコープされ、サブコマンドのトークンの後に 書く必要があります:

bca metrics --exclude '*.generated.rs' src/   # 正しい
bca --exclude '*.generated.rs' metrics src/   # エラー(終了コード 1)

どの位置でも受け付けられる汎用フラグは -w / --warnings--report-skipped だけです。すべての入力選択フラグ(-p / --paths-I / --include-X / --exclude-l / --language--paths-from--exclude-from--no-ignore--no-skip-generated--no-config)、ウォーカー調整フラグ(-j / --jobs--exclude-tests--cyclomatic-count-try)、プリプロセッサフラグ(--preproc-data)、および出力フラグ(--color)は、それを読み取るサブコマンドのヘルプ内でグループ化されたセクション(Input selection / Walker tuning / Preprocessor / Output)に属します。あるサブコマンドが消費しないフラグをそのサブコマンドに渡すと、黙って無視されるのではなくハードな使用方法エラー(終了コード 1)になります — そのため bca vcs commit --exclude-testsbca list-metrics --paths はどちらもエラーになり、bca list-metrics --help はウォーカーフラグを表示しません。

-p / --paths フラグは引き続き機能し、位置引数のパスと 和集合 になります。つまり bca metrics a.rs --paths b.rs は両方を走査します。findcount サブコマンドは、繰り返し指定できる -t / --type フラグでノード種別を受け取ります(そのため位置引数のスロットはパス用に空いています): bca find -t function_item -t struct_item src/

メトリクス

メトリクスはソースコードに関する定量的な指標を提供し、次のことに役立ちます:

  • 異なるプログラミング言語を比較する
  • コードの品質に関する情報を提供する
  • コードのどこが扱いにくいかを開発者に伝える
  • 開発プロセスの早い段階で潜在的な問題を発見する

big-code-analysis は、プログラムのソースコードを起点にメトリクスを計算します。この種のメトリクスは 静的メトリクス と呼ばれます。

ノード

プログラムコードの構造を表現するために、bca抽象構文木(AST) を構築します。ノード はこの木の要素であり、言語に存在する任意の構文構造を表します。

ノードは次の用途に使えます:

  • ソースファイルの構文構造を作成する
  • 解析対象のコードに、ある言語構造が存在するかどうかを調べる
  • 特定の種類の構造の数を数える
  • ソースコード内のエラーを検出する

REST API

bca-web は REST API を提供するサーバーを実行します。これにより、ユーザーは HTTP 経由でソースコードを送信し、対応するメトリクスを JSON 形式で受け取れます。

生成コードのスキップ

生成されたバインディング(protobuf スタブ、OpenAPI クライアント、lex/yacc の出力、ビルドシステムの補助コード)は、誰もリファクタリングしないコードでメトリクスを水増しします。デフォルトでは、bca は各ファイルの先頭約 50 行 / 5 KiB を走査して生成コードマーカーを探し、一致したファイルをパース 「前に」 スキップします。そのため、スキップされたファイルに tree-sitter のパースコストはかかりません。

認識されるマーカー(大文字小文字を区別しません):

  • @generated — Facebook / Meta の慣習。buck2、rustfmt、prettier をはじめ、多くのコードジェネレーターも出力します。
  • DO NOT EDIT — Go の // Code generated by … DO NOT EDIT. が標準形です。この語句単体でも広くコピーされています(Bazel、protoc、OpenAPI クライアント)。
  • GENERATED CODE — Lizard のマーカーで、互換性のために認識されます。

マーカー語句がファイル本体の深い位置(走査ウィンドウの外)にのみ現れる場合、スキップは 発動しません — 検出器は意図的にファイルヘッダーだけを見ます。

このスキップは bca metricsbca report、およびしきい値エンジンに一律に適用されます。

フラグ

  • --no-skip-generated — 自動スキップを無効にし、以前の動作(すべてのファイルをパースする)に戻します。
  • --report-skipped — 検出器が除外した各ファイルについて skipped (generated): <path> を stderr にログ出力します。これにより除外を監査でき、ファイルが誤って生成コード扱いされていた場合は明示的な include を追加できます。

.gitignore の尊重

--paths にディレクトリが渡されると、bca はデフォルトで .gitignore を考慮して走査します。次のいずれかに一致するファイルは、パース前にスキップされます:

  • 走査対象ツリー内の .gitignore ファイル。
  • .ignore ファイル(ripgrep / fd の慣習)。
  • .git/info/exclude
  • グローバル gitignore(~/.config/git/ignore、または core.excludesFile が指す先)。
  • 起点の祖先ディレクトリにある .gitignore ファイル(そのため、プロジェクトルートから bca metrics src/ を実行すると、プロジェクト最上位の .gitignore が反映されます)。

ウォーカーは、チェックインされた git リポジトリの外でも .gitignore を尊重します。そのため、.gitignore ファイルを含む展開済みのソース tarball も、git clone した直後と同じ扱いになります。

隠しファイル(ベース名が . で始まるもの)は走査中に除外され、以前の動作と一致します。

明示的なパスはフィルターを迂回する

Files passed by name — via --paths, --paths-from, or a trailing positional path — are always analyzed, even when the project's ignore rules cover them. This makes it safe to do bca metrics --paths-from - from git diff --name-only-style pipelines without losing files that happen to match a wildcard ignore rule.

The override is deliberate, and it is the same rule rg and fd apply: a path you named is a direct request. It spans every deny-set the walk consults — .gitignore and friends, -X / --exclude, --exclude-from, a .bcaignore, and a manifest exclude list alike. rg --glob '!x.txt' pattern x.txt searches x.txt for exactly this reason.

Two boundaries on it:

  • -I / --include still applies. The allow-list narrows which named files are analyzed, so bca metrics -I '*.rs' notes.md analyzes nothing. Only the deny-sets are overridden.
  • [check] exclude still applies. The gate-exemption set (--check-exclude / --check-exclude-from, or exclude under [check] in bca.toml) is not a walk filter — it drops violations, not files — so it survives an explicit path and reports bca: skipped N violations via [check.exclude] when it fires. One caveat while #1164 is open: for an explicitly named path those globs resolve against the working directory rather than the manifest root, so run bca from the directory holding bca.toml — which is what CI and the agent hooks already do.

That second point is the one to reach for. A walker exclude shapes what gets analyzed; a check exclude shapes what gets gated. Anything you want kept out of the threshold gate permanently — dev tooling, generated code you still want measured, a subtree under active rewrite — belongs in [check] exclude, because any caller that names paths one at a time bypasses the walker excludes by design. Per-file callers are not hypothetical: that is the shape the agent feedback hooks use on every edit.

When an explicitly named path does override a walker exclude, bca says so on stderr and names the glob:

bca: warning: utils/gate.py matches an exclude pattern (./utils/**) but was named explicitly; analyzing anyway

パス探索フラグ

  • --no-ignore — ディレクトリの起点を展開する際の .gitignore / .ignore / グローバル gitignore の考慮を無効にします。
  • --paths-from <FILE> — read newline-separated input paths from <FILE>, or from stdin when <FILE> is -. Combined as a union with any --paths values. -I globs still apply; -X globs do not reach an entry that names a file directly, per Explicit paths bypass the filter. Blank lines are skipped; # is treated as a path character (not a comment). To pass a file literally named -, write ./-.
  • --exclude-from <FILE> — 改行区切りの --exclude glob パターンを <FILE> から読み取ります。<FILE>- の場合は stdin から読み取ります。パターンはインラインの --exclude / -X の値と和集合として 1 つの拒否セットにまとめられ、順序は関係ありません。.gitignore 形式です: 空行と、最初の非空白文字が # の行はスキップされ、先頭の UTF-8 BOM は取り除かれます。慣習としては、.gitignore / .dockerignore に倣ってリポジトリルートに .bcaignore を置きます。文字どおり - という名前のファイルを渡すには ./- と書きます。