コマンドラインインターフェース(CLI)

はじめに

blunderDBはグラフィカルインターフェースと同じ実行ファイルに完全なコマンドラインインターフェース(CLI)を搭載しています。CLIは特に以下の用途に便利です:

  • マッチの一括インポート:1つのコマンドでマッチファイル(XG、SGF、MAT、BGF…)のディレクトリ全体をインポートする、

  • 自動化:定期的なバックアップ、スケジュールされたエクスポート、または処理パイプラインのためにblunderDBをシェルスクリプトに統合する、

  • サーバー使用:グラフィカル環境のないマシンでデータベースを管理する、

  • クイック検査:グラフィカルインターフェースを起動せずにデータベースのコンテンツや整合性を確認する。

CLI はグラフィカルインターフェースとまったく同じデータベース形式を共有しています。どちらも同じファイルに書き込むので、同期するものは何もありません。

注釈

スクリプトが書き込んでいる間にアプリケーションが開いている場合。ファイルは WAL モードです。読み取りが書き込みを妨げることはなく、2つのプログラムは互いに邪魔をせず同じデータベースを扱えます。一方、2つの書き込みは順番に処理されます。あとの書き込みは書き込みロックを待ち(1文につき10秒、さらに数回の再試行)、待ち時間が尽きたときにだけ失敗します。そのときのメッセージには SQLite の名が現れます:

Error: failed to import match: sqlite: save match: database is locked (5) (SQLITE_BUSY)

グラフィカルインターフェースはファイルを監視しません。CTRL-R でポジションを読み込み直すまで、読み込んだ内容を表示し続けます。何も失われませんが、画面はデータベースより遅れています。

一般的な構文

モードは自動的に検出されます:最初の引数がCLIコマンドであれば、blunderDBはヘッドレスモードで起動し、そうでなければグラフィカルインターフェースを起動します。

# GUI
./blunderdb

# CLI
./blunderdb <command> [options]

このページの例は ./blunderdb と書いています。ダウンロードしたままのバイナリを、それが置かれているフォルダから呼び出す形です。パッケージでインストールした場合や、PATH にあるフォルダからリンクしている場合(ダウンロードとインストールを参照)は、単に blunderdb と呼び出します。

「デフォルト:はい」と書かれた真偽値のオプションは、--option=false の形で無効にします——--recursive=false、--analysis=false のようにです。空白で区切る形は存在しません。--recursive false はオプションをデフォルト値のままにし、false を余分な引数として扱います。

利用可能なコマンド

コマンド

説明

create

新しいデータベースを作成する。

import

データをインポートする(マッチ、ポジション、バッチ)。

export

データをエクスポートする。

identity

発行者アイデンティティ(透かしの署名鍵)を表示または移動します。

open

パスワードで保護されたファイル(.dbx)を通常のデータベースに変換します。

search

フィルターでポジションを検索する。

list

データベースの内容を表示する。

match

マッチのポジションと分析を表示する。

collection

コレクションを管理します(一覧、内容、作成、名前変更、削除、エクスポート)。

anki

間隔反復デッキ(一覧、統計、予測、同期)。

ロールアウト

局面を最後までプレイして、候補手またはキューブ判断を比較します(XGID または OGID)。

epc

ベアオフ局面(XGID または OGID)の Effective Pip Count とキューブ判断を計算します。

bearoff

ベアオフ・データベースを作成、一覧表示、検証、削除します。

analyze

分析を一つも持たないポジションごとに gammonNet 分析を書き込みます。

info

データベースのメタデータを表示する。

edit

データベースのメタデータと閾値を編集する。

verify

データベースの整合性を確認する。

vacuum

データベースファイルを最適化し、解放された領域を回収します。

repair

データベースが保存内容から導くものを再計算します。

delete

データを削除する。

healthcheck

稼働中のserveデーモンに問い合わせ、準備ができていれば終了コード 0 を返します。

mcp

データベースのツールを AI アシスタントに提供します(Model Context Protocol)。

completion

シェル補完スクリプト(bash、zsh、fish)を表示する。

help

ヘルプを表示する。

version

バージョンを表示する。

serve, migrate, call

サーバーモードと PostgreSQL への移行:ヘッドレスモード(サーバー) を参照。

各コマンドは --help オプションで詳細なヘルプを表示できます。

create — データベースを作成する

任意のメタデータとともに新しいデータベースファイルを作成します。

./blunderdb create --db <path> [--user <name>] [--description <text>] [--force]

オプション:

  • --db — 作成するデータベースファイルのパス(必須)。

  • --user — データベースの所有者名。

  • --description — データベースの説明。

  • --force — ファイルが既に存在する場合は上書きする。

  • --format — 出力フォーマット:text(デフォルト)またはjson(パス、バージョン、ユーザー、説明、作成日時)。

.db 拡張子がない場合は自動的に追加されます。必要に応じて親ディレクトリが作成されます。

例:

./blunderdb create --db mes_matchs.db --user "Jean" --description "Matchs de tournoi 2025"

import — データをインポートする

マッチまたはポジションファイルをデータベースにインポートします。

./blunderdb import --db <path> --type <type> [options]

オプション:

  • --db — データベースのパス(必須)。

  • --type — インポートの種類:match、position、または batch(必須)。

  • --file — インポートするファイル(match および position 用)。

  • --dir — インポートするディレクトリ(batch 用)。

  • --recursive — サブディレクトリを再帰的にスキャンする(デフォルト:はい)。

  • --watch— --type batch と併用します。終了せずに、--dir に現れるたびにマッチファイルを取り込みます(Ctrl-C で停止)。

  • --watch-every— --watch が見に行く間隔(既定:10s、下限 2s)。

  • --format — 出力フォーマット:text(デフォルト)またはjson。

  • --fail-on-error — 他の要素が成功していても、少なくとも1つの要素(positionまたはbatch)をインポートできなかった場合に失敗する。

終了コードは 4 つの規則に従います:

  • 何も認識されなかった場合(すべてのファイルが失敗):--fail-on-error を渡したかどうかにかかわらずエラー。

  • 重複のみの場合(すべてのファイルがすでにデータベースにあった):成功。新しいファイルがないまま再実行されたディレクトリ、つまりスクリプトのごく普通の夜は、duplicates だけがゼロでない状態で 0 を返します。

  • 部分的な失敗(一部の要素はインポートされ、他は拒否された):--fail-on-error が渡された場合にのみエラーになります。

  • 新しい要素が少なくとも 1 つインポートされ、--fail-on-error が渡されていない場合:成功となり、拒否されたファイルは表に一覧されます。

フォルダを監視する

--watchはディレクトリの取り込みを監視に変えます。コマンドは戻らず、フォルダに現れたマッチファイルを次々に取り込みます。アプリケーションの 監視フォルダ の、画面を持たない形です。

# Importer ce que le dossier contient déjà, puis surveiller ce qui arrive
./blunderdb import --db base.db --type batch --dir ~/XG/Matches
./blunderdb import --db base.db --type batch --dir ~/XG/Matches --watch

取り込まれるのは現れたファイルだけです。開始時点でフォルダにあるものは既知として記録され、そのまま残されます。四年分のマッチに監視を向けたからといって、それらをすべて取り込んではいけません。上の二つのコマンドは、まさに期待どおりに組み合わさります。

ファイルはサイズが安定してから、つまり二度続けて変化がないと確認されてから取り込まれます。他のプログラムが書いている途中のマッチは見るたびに大きくなり、書きかけで取り込めば、誰にも手の打ちようがない構文エラーになります。フォルダは再帰的にはたどりません。読めなくなったネットワーク共有は監視を止めず、復帰したときにその中身が新規と見なされることもありません。

Ctrl-C はファイルとファイルのあいだで止まり、途中では止まりません。取り込み中のファイルは最後まで処理され、その報告が出てからコマンドが戻ります。

マッチのインポート

対応フォーマット:eXtreme Gammon(.xg、.xgp)、GNUbg(.sgf)、Jellyfish(.mat、.txt)、BGBlitz(.bgf)、HedgeHog(.ogxm)。

./blunderdb import --db base.db --type match --file match.xg

# Successfully imported match (ID: 1)
#
# Match Details:
#   Players: Kévin Unger vs Maxence Job
#   Event: HSBT Paris 2023
#   Match Length: 7
#   Games: 7

--format json は同じ項目を1つのドキュメントで返します:

{
  "type": "match",
  "match_id": 1,
  "player1": "Kévin Unger",
  "player2": "Maxence Job",
  "event": "HSBT Paris 2023",
  "location": "Paris, Fédération Française de Bridge",
  "match_length": 7,
  "games": 7
}

ポジションのインポート

テキストファイルからポジションをインポートします。1行に1つの JSON ポジションです。これはまさに export --type positions が書き出すものです。2つのコマンドは対をなしており、エクスポートしたものは何も手を加えずそのまま再インポートできます。

./blunderdb import --db base.db --type position --file positions.txt

# Successfully imported 4 positions

export が生成する1行は次のとおりです——大半を盤面が占めており、26のポイントに続いて上がったチェッカーが並びます:

{"id":1,"board":{"points":[{"checkers":0,"color":0},{"checkers":1,"color":1},…],"bearoff":[0,0]},"cube":{"owner":-1,"value":0},"dice":[0,0],"score":[7,7],"player_on_roll":0,"decision_type":1,"has_jacoby":0,"has_beaver":0,"individually_imported":true,"flagged":false}

分析とコメントはこの形式では運ばれません。運ばれるのはポジションだけです。ライブラリ全体を移すには export --type database が必要です。

一括インポート

1回の操作でディレクトリのすべてのマッチファイルをインポートします。これは多数のマッチをインポートする最も効率的な方法です。

./blunderdb import --db base.db --type batch --dir ./matchs/
./blunderdb import --db base.db --type batch --dir ./matchs/ --recursive=false
./blunderdb import --db base.db --type batch --dir ./matchs/ --format json --fail-on-error

まとめの表に、各ファイルについてインポートが成功したか(✓)、失敗したか(✗)、重複だったか(⊘)が示されます。重複は失敗として数えられず、重複しか含まないバッチも成功です(上記の規則を参照)。

Batch importing from: ./matchs/ (recursive: true)

Found 3 match file(s) to import

[1/3] Importing: 02_NDT_FR.txt... ERROR: failed to parse file: ingest: parse gnubg file: invalid MAT file: no match header found
[2/3] Importing: test.mat... DUPLICATE
[3/3] Importing: test.xg... OK (ID: 1, 341 positions)

====================================================================
IMPORT SUMMARY
====================================================================
Status  File           ID  Player 1     Player 2     Games  Positions  Error
------  ----           --  --------     --------     -----  ---------  -----
✗       02_NDT_FR.txt                                0      0          failed to parse file: ingest: ...
⊘       test.mat                                     0      0
✓       test.xg        1   Kévin Unger  Maxence Job  7      341
--------------------------------------------------------------------
Total: 3 files | Success: 1 | Duplicates: 1 | Failed: 1 | Positions imported: 341

--format json は同じ内容を、スクリプトで扱える形で返します。files にファイルごとのオブジェクトが並び、続いて合計が来ます。何ごともない夜であれば、duplicates だけがゼロでなく、failed はゼロのままで、終了コードも 0 です。エラーで終了するのは、何も認識されなかったバッチだけです。

{
  "files": [
    {"file_path": "02_NDT_FR.txt", "success": false, "error": "failed to parse file: …"},
    {"file_path": "test.xg", "success": true, "positions": 341}
  ],
  "total": 3,
  "success": 1,
  "duplicates": 1,
  "failed": 1,
  "positions_imported": 341
}

export — データをエクスポートする

データベースの内容をファイルにエクスポートします。

./blunderdb export --db <path> --type <type> --file <output> [options]

オプション:

  • --db — ソースデータベース(必須)。

  • --type — エクスポートの種類:database、positions、matches、または mat(1つまたは複数のマッチをJellyfish .mat トランスクリプションでエクスポート)(必須)。

  • --file — 出力ファイル(--dirと併用する --type mat を除き必須)。

  • --dir — バッチ .mat エクスポートの出力ディレクトリ(複数のマッチ、マッチごとに1ファイル。--match-idsなしの場合、すべてのマッチがエクスポートされます)。

  • --analysis — 分析を含める(デフォルト:はい)。

  • --comments — コメントを含める(デフォルト:はい)。

  • --filters — フィルターライブラリを含める(デフォルト:はい)。

  • --played-moves — プレイされた手を含める(デフォルト:はい)。

  • --matches — マッチを含める(デフォルト:はい)。

  • --collections — コレクションを含める(デフォルト:いいえ)。

  • --collection-ids — エクスポートするコレクションのID(カンマ区切り)。

  • --match-ids — エクスポートするマッチのID(カンマ区切り、空=すべて)。

  • --tournament-ids — エクスポートするトーナメントのID(カンマ区切り)。

  • --password — 結果を暗号化されたコンテナ(.dbx)に包みます。

  • --watermark — 出力ファイルに署名付きの出所表明を書き込みます(データベースの配布:出所とパスワード を参照)。

  • --watermark-note — 透かしに添える自由記述(利用条件、連絡先)。--watermark と併用します。

  • --format — 出力フォーマット:text(デフォルト)またはjson(エクスポートの要約文書:パス、バイト単位のサイズ、件数)。

例:

./blunderdb export --db base.db --type database --file sauvegarde.db
./blunderdb export --db base.db --type positions --file positions.txt
./blunderdb export --db base.db --type matches --file selection.db --match-ids 1,3,5

# .mat : un match, puis plusieurs (ou tous) dans un répertoire
./blunderdb export --db base.db --type mat --match-ids 5 --file match5.mat
./blunderdb export --db base.db --type mat --match-ids 5,9,12 --dir sorties/
./blunderdb export --db base.db --type mat --dir sorties/

# .dbx : filigrané et protégé par mot de passe
./blunderdb export --db cours.db --type database --file cours-diffusion.dbx \
    --watermark "Cours de Jean Dupont — 12 mars 2026" \
    --watermark-note "Merci de ne pas rediffuser." \
    --password secret

透かしはローカルの発行者アイデンティティで署名されます(下記の identity コマンドを参照)。偽造はできませんが、取り除けないわけではありません。ファイルは通常の SQLite データベースのままです。透かしは何も保護せず、そのファイルがどこから来たかを示すだけです。パスワードが守るのはファイルの運搬(置き忘れたコピー、誤って送った添付)であって、データベース自体ではありません。パスワードを受け取った人は誰でも開けます。blunderDB は受け取る側に何も記録しません(台帳もログもありません)——ADR-0007 を参照してください。

identity — 発行者アイデンティティ

あなたの発行者アイデンティティ——すべての透かしに署名する Ed25519 鍵——を表示または移動します。最初の透かしを付けた時点で自動的に作られ、設定は不要です。これはデータベースではなく個人に属します。あなたが印を付けたものはすべて、ただ一つの公開フィンガープリントを帯びます。

./blunderdb identity
./blunderdb identity --name "Jean Dupont"
./blunderdb identity --export jean.bdbid --passphrase pw
./blunderdb identity --import jean.bdbid --passphrase pw

オプション:

  • --name — アイデンティティの表示名を変更します。

  • --export — アイデンティティを .bdbid ファイルに書き出します。

  • --import — .bdbid ファイルからアイデンティティを読み込みます。

  • --passphrase — 書き出し/読み込みするファイルを保護する任意のパスフレーズ(ローカルのアイデンティティ自体は意図的に保護しません)。

  • --format — 出力フォーマット:text(デフォルト)またはjson(名前、フィンガープリント、保存先パス)。

書き出したファイルを持つ者は誰でも、あなたの名前で署名できます。共有しないでください。名前の変更はラベルを変えるだけです。すでに印を付けたファイルは封をした時点の名前を保ち、検証も通り続けます。

open — 保護されたファイルを開く

パスワードで保護されたファイル(.dbx)を通常のデータベースに変換します。パスワードを尋ねられるのは一度だけで、その後は普通のファイルです。

./blunderdb open --db cours.dbx --password secret
./blunderdb open --db cours.dbx --password secret --file ./mon-cours.db

オプション:

  • --db — 開く .dbx ファイル(必須)。

  • --password — コンテナのパスワード(必須)。

  • --file — 通常のデータベースの出力先パス(既定:同じ名前で拡張子 .db)。

パスワードが守るのはファイルの運搬です——ダウンロードフォルダに置き忘れたコピー、誤って送った添付。データベース自体ではありません。パスワードを受け取った人は誰でも開けます。コンテナのヘッダーは平文なので、blunderdb info はパスワードなしでも保護されたファイルの出所を読み取れます。

search — ポジションを検索する

組み合わせ可能な条件でデータベース内のポジションを検索します。

./blunderdb search --db <path> [options]

主なオプション:

  • --db — データベース(必須)。

  • --format — 出力フォーマット:table、json、または xgid(デフォルト:table)。

  • --limit — 結果の最大件数(0 = 無制限)。

  • --offset — 数え始める前に最初の n 件の結果を飛ばします。--limit と組み合わせればページネーションになります。

  • --export — 結果を新しいデータベースにエクスポートする。

  • --query-help — --query が解釈するトークンの一覧を表示して、そこで終了します。データベースは開かれないので、--db は不要です。

利用可能なフィルター:

  • --decision — 決定の種類:checker または cube。

  • --dice — ダイスの目。5,3 は両方のダイスが一致するポジションを検索します(順序不問)。5 はいずれかのダイスに5が現れるポジションを検索します(もう一方のダイスの値は無視されます)。--decision の値が指定されていない場合は --decision checker を意味します。

  • --pip-min / --pip-max — ピップカウント差の範囲。

  • --winrate-min / --winrate-max — 勝率の範囲(%)。

  • --cube — キューブの値。

  • --score1 / --score2 — プレイヤーのスコア。

  • --match-length — マッチの長さ。

  • --error-min — そのポジションで間違えたときの代償に対するしきい値です。最善手と次善手の差、またはキューブの3つのエラーのうち最大のものを指します。単位はエクイティのポイントです——--error-min 0.1 は、間違えると少なくとも 0.1 ポイントを失うポジションを残します。そこで実際に何が打たれたかについては何も言いません。

  • --move-error-min / --move-error-max — プレイヤー1が実際に打った手のエラーに対するしきい値です。単位はエクイティの千分の1(ミリポイント)です。--move-error-min 50 は 0.05 ポイントにあたります。これは検索文法の E トークンそのもので、同じ書き方をします。

  • --has-analysis — 分析のあるポジションのみ。

  • --off1-min / --off2-min — ベアオフした最小チェッカー数(プレイヤー1/2)。

  • --match-ids — マッチIDでフィルタリングする(カンマ区切り)。

  • --tournament-ids — トーナメントIDでフィルタリングする(カンマ区切り)。

  • --position-ids — ポジションIDでフィルタリングする:範囲 2,7(ポジション2から7)、またはセミコロン区切りの明示的なリスト 5;10;15。

  • --individual — 単独でインポートされた局面のみ。つまり、マッチのインポートで入ったものではなく、自分で追加した局面です。

  • --flagged — 元のソフトウェアで学習用にフラグを立てた局面のみ(eXtreme Gammon のフラグ)。遡及はしません。すでにインポート済みの対戦は、フラグを取り込むために再インポートが必要です。

  • --has-comment — コメントの付いた局面のみ。由来は区別しません。手で書いたメモも、マッチのインポートで入ってきたコメントも、どちらも数えます。マッチやトーナメントのコメントは参照しません。

  • --no-comment — コメントのない局面のみ。--has-comment とは排他です。

警告

--error-min と --move-error-min は同じものを測っておらず、単位も同じではありません。その差は1000倍です。前者はエクイティのポイント(0.1)で指定し、あとの2つは千分の1(100)で指定します——1ポイントは 1000 の千分の1です。「どこで間違えたのか」に答えるのは --move-error-min で、「どのポジションが難しかったのか」に答えるのは --error-min です。

search が出力するもの:

--format table(デフォルト)は、ポジションごとに1行を出します。識別子、スコア、キューブの値、決定の種類、出目、最善の決定とそのエクイティです。分析のないポジションでは、最後の2列は空のままになります。

Found 5 position(s)

ID  Score  Cube  Type  Dice  Best Move  Equity
--  -----  ----  ----  ----  ---------  ------
2   7-7    0     cube        No Double  -0.005
4   7-7    0     cube        No Double  -0.027
6   7-7    0     cube        No Double  -0.161
8   7-7    0     cube        No Double  0.256
10  7-7    0     cube        No Double  -0.234

--format json は同じポジションの配列を返します。項目 id、score、cube、decision_type(checker または cube)、dice は常に存在します。best_move、equity、xgid は、ポジションにそれらを記した分析がある場合にだけ現れます。Found n position(s) の行は表の前に出力されたままなので、JSON しか受け付けないスクリプトは最初の1行を飛ばすか、--export を使う必要があります。

[
  {
    "id": 5266,
    "score": [
      5,
      4
    ],
    "cube": 1,
    "decision_type": "checker",
    "dice": [
      4,
      3
    ],
    "best_move": "10/3",
    "equity": 0.565
  }
]

--format xgid は1行に1つの XGID を出力し、それ以外は何も出しません。出力されるのは、記録された分析が XGID を持つポジションだけです。テキストのエクスポートからアプリケーションに貼り付けられたポジションや、XGID を運ぶ BGF ファイルがそれにあたります。XG、GNUbg、Jellyfish のマッチのインポートで入ったポジションは XGID を持たないため、その場合の出力は空になります。一方 collection show サブコマンドは、盤面から XGID を再生成します。

クエリ言語:

上記のフラグが扱えるのはフィルターの一部だけです。--query は、アプリケーションのクエリ言語——コマンドバーのもの——へのアクセスを与えます。したがって、盤面に描かれないすべてのフィルター、すなわち手のパターン、コメント本文、プレイヤー、日付、エクイティ、除外するダイス、ゾーン、ブロットが使えます。

文法が書かれている場所は1つだけ、検索フィルタ です。その表が、各トークン、その形、そして対応する search のフラグ(存在する場合)を示します。このページはそれを繰り返しません。

./blunderdb search --db base.db --query 's p>30 E>50'
./blunderdb search --db base.db --query 's m"13/11" t"blunder" pl"Alice" T>2026/01/01'

局面の近傍の並べ替えも同じ文法を通ります。--query 's like42' を単独で、あるいは並んだ集合を絞り込む他のトークンを続けて使います。

--query-help は、データベースを開かずにその一覧を示します:

$ ./blunderdb search --query-help
blunderdb search --query — the interface's query language

A query is the same text the application's command bar takes:
  s cube p>30 E>50        cube decisions, 30+ pips behind, 50+ millipoints of error
  s m"13/11" T>2026/01/01 played 13/11, imported this year

Flags (no value):
  cube score   match the cube / the score of the position on the board
  d            match the decision type (checker or cube)
  …

Ranges — each takes x>n, x<n or xa,b (lower-case: you; upper-case: the opponent):
  p P          pip count difference / absolute pip count
  …
  E            error of the played move, in millipoints
  T            creation date, T>2026/01/01

Values:
  t"tag"       comment text (";" separates alternatives)
  …

--queryはフィルターのフラグに加わるのではなく、それらを置き換えます。両方を組み合わせると、問題のフラグ名を挙げて拒否されます。どこを探すか、どのように表示するかを指定するフラグ — --db、--format、--limit、--offset、--export — は引き続き使えます。

どの規則も認識しないトークンは、検索を黙って絞り込むのではなく、コマンドを失敗させます。コマンドラインに盤面がないことから、2つの制限が生じます。チェッカーの配置パターンは入力できません。また、盤面を読む5つのトークン——cube、score、d、D/D1、x——は、ここでは空の盤面と比較されます。これらのいずれかを必要とする検索は、--query がそれらと組み合わせられないため、すべてフラグで書きます — 例えば、30 ピップ遅れている状況でのキューブの決定のうち、少なくとも 50 ミリポイントのエラーがあるものは次のようになります:

./blunderdb search --db base.db --decision cube --pip-min 30 --move-error-min 50

例:

./blunderdb search --db base.db --decision cube
./blunderdb search --db base.db --individual
./blunderdb search --db base.db --error-min 0.1
./blunderdb search --db base.db --tournament-ids 1 --export cubes.db

# 6-5 dans les deux ordres, puis un 6 sur l'un des deux dés
./blunderdb search --db base.db --dice 6,5
./blunderdb search --db base.db --dice 6

# Pagination
./blunderdb search --db base.db --format json --limit 10 --offset 20

list — 内容を一覧表示する

データベースの内容を表示します。

./blunderdb list --db <path> --type <type> [--limit <n>] [--offset <n>]

タイプ:

  • matches — インポートされたマッチのリスト。

  • tournaments — トーナメントのリスト。

  • positions — ポジションの一覧(既定は 10 件。--offset <n> で先頭の n 件を飛ばします)。データベースの大きさにかかわらず、読み込むのは表示する範囲だけです。--format csv を付けると表形式のエクスポートになります:ポジションごとに 1 行で、XGID、局面、スコア、キューブ、ピップ、導出された分析列を含みます。

  • imports — 記録されたインポートを新しい順に一覧する:識別子、日付、形式、ソース、取り込まれた/飛ばされた/補強されたマッチ、読めなかったファイル、新しい局面。--batch <id> を付けると一つのインポートの完全な報告を表示する:マーク済みの局面、解析のない局面、そのロットの PR、最も損の大きい五つの判断(インポート報告 を参照)。

  • stats — パフォーマンス統計レポート:PR / Snowie ER / MWC(全体、チェッカー、ダブリングキューブ)、直近N手の決定に対する移動平均PR、トップブランダー、ダブリングキューブアクション別の内訳、エラーの大きさのヒストグラム。

  • players — データベースのプレイヤーごとに1行の比較表:対戦数、勝敗、集計された判断数、PR の全体/チェッカー/キューブ、Snowie ER、エラー数、ブランダー数、運。統計パネルのプレイヤータブに対応するコマンドライン版です。

  • moves— 記録された手の表形式エクスポート。1 行に 1 手、その手が属するマッチを各行に繰り返して載せます。識別子、日付、対戦者、マッチ長、手数と種類、局面、出目、指した手、キューブの行動、運。--format csv が必要です。

  • analyses— 保存された解析の表形式エクスポート。1 行に 1 件で、エンジン、深さ、最善手とそのエクイティ、指した手の誤差、最善のキューブ行動とその誤差、六つの勝率が並びます。--format csv が必要です。

  • tags— データベースのタグ語彙。コメントに書かれた各 #語 と、それを持つ局面の数を、よく使う順に並べます。タグがひとつもないデータベースでは、空のリストではなく推奨語彙を表示します(タグ を参照)。--format json と --format csv を受け付けます。

表形式のエクスポート

positions、moves、analyses の三つの型は、notebook や表計算、スクリプトのために CSV で書き出せます。

./blunderdb list --db base.db --type positions --format csv > positions.csv
./blunderdb list --db base.db --type moves     --format csv > moves.csv
./blunderdb list --db base.db --type analyses  --format csv > analyses.csv

--limit は明示的に指定したときだけ効きます。既定値 10 は、端末に出す list がデータベース全体を流してしまわないためのものです。エクスポートはプログラムが読むファイルへ行くので、黙って 10 行で切ると、数字がおかしくなるまで誰も気づかない罠になります。

列は契約です。これらの名前に対して書かれた notebook やスクリプトは動き続けなければなりません。列は末尾に追加され、名前が変わることも順序が変わることもありません。エクイティはすべて整数のミリポイントです。保存形式がそうであることに加え、CSV 中の小数はロケールに書式を変えさせる誘いになるからです。

Parquet は提供しません。教条ではなく計測に基づく判断です。列指向ライブラリはサイズを注視している実行ファイルに数メガバイトを足しますが、このエクスポートの用途はどれも CSV を一行で読めます(pd.read_csv、polars.read_csv、read.csv、表計算)。Parquet が効くのは数千万行の規模で、十年もののバックギャモンのライブラリは十万行です。いつか実際のデータベースでその差が測れたなら、その計測こそがこの判断を開き直すものです。

これらのエクスポートにはJupyter のサンプル notebookが付属します(リポジトリの notebooks/blunderdb-analyse.ipynb)。時系列の PR、誤差の大きさの分布、XGID 付きの最悪の判断 10 件を扱います。使うのはその三つの CSV だけで、毎晩の継続的インテグレーションで実行されます。誰も走らせない notebook は、誰にも気づかれないまま動かなくなった notebook だからです。

オプション(stats タイプのみ):

  • --metric — 表示するメトリック:pr または mwc(デフォルト:pr)。

  • --player — 指定したプレイヤーに限定する。

  • --tournament — 1つまたは複数のトーナメントIDに限定する(カンマ区切り)。

  • --from — 開始日(YYYY-MM-DD)。

  • --to — 終了日(YYYY-MM-DD)。

  • --decision-type — 決定の種類:all、checker または cube(デフォルト:all)。

  • --top-blunders — リストする最悪のエラーの数(デフォルト:10)。

  • --format — 出力フォーマット:text または json(デフォルト:text)。

オプション(imports タイプのみ):

  • --batch — ロットの識別子:一覧の代わりにその完全な報告を表示する。

  • --queue— --type imports --batch と併用します。報告の代わりに、その取り込みの学習キュー、すなわち見直す価値のある局面を、たどるべき順に返します(学習キュー を参照)。まず損失を生んだ判断、次に元のソフトで印の付いた局面、最後に際どいキューブ判断。ひとつの局面は一度しか現れません。

  • --format — 出力フォーマット:text または json(デフォルト:text)。

報告の測定部分は呼び出しのたびに再計算される:以後に局面が解析されたロットは、インポート当日の数字ではなく今日の数字を返す。

オプション(players タイプのみ):

  • --from / --to — 日付の範囲(YYYY-MM-DD)。たとえば大会の開催日。

  • --tournament — 1つまたは複数のトーナメント ID に絞り込みます。

  • --format — 出力形式:text、json、csv(既定:text)。

--player と --decision-type はこのタイプには適用されません。表はすべてのプレイヤーを対象とし、チェッカーとキューブはすでに別の列に分けているからです。

注釈

ダッシュ「—」(CSV では空欄)は一度も測定されていない値を示すもので、ゼロと混同してはいけません。スキーマのバージョン 2.15.0 より前にインポートしたすべての対戦の運、および運を運ばない形式(BGF、Jellyfish の .mat)がこれにあたります。取得するには元ファイルを再インポートしてください。luck_rolls 列は、その平均が何回のロールに基づくかを示します。

各タイプは要素ごとに 1 ブロックを出力し、その前に見つかった総数を表示します。最後の行は表示中の範囲を示します。範囲は--limit(ポジションの既定値は 10)で切り詰められ、--offsetでずらされます:

Found 3859 position(s):

ID: 1
  Score: 7-7
  Player on roll: 0
  Decision: Checker play

ID: 2
  Score: 7-7
  Player on roll: 0
  Decision: Cube action

…

(Showing 1-10 of 3859 positions, use --offset and --limit to see more)

例:

# Les imports enregistrés, puis le compte rendu de l'un d'eux
./blunderdb list --db base.db --type imports
./blunderdb list --db base.db --type imports --batch 3

./blunderdb list --db base.db --type stats
./blunderdb list --db base.db --type stats --metric mwc --player "Alice"
./blunderdb list --db base.db --type stats --decision-type checker --from 2026-01-01
./blunderdb list --db base.db --type stats --format json

# Un tableau par joueur, borné aux dates d'une compétition
./blunderdb list --db base.db --type players --from 2026-03-01 --to 2026-03-08
./blunderdb list --db base.db --type players --format csv

./blunderdb list --db base.db --type matches
./blunderdb list --db base.db --type positions --limit 20

match — マッチを表示する

インポートされたマッチのポジションと分析を表示します。

./blunderdb match --db <path> --id <id> [--format <format>] [--output <file>]

オプション:

  • --db — データベース(必須)。

  • --id — 表示するマッチのID(必須)。

  • --format — 出力フォーマット:json、text、または summary(デフォルト:json)。

  • --output — 出力ファイル(デフォルト:標準出力)。

例:

./blunderdb match --db base.db --id 1 --format summary
./blunderdb match --db base.db --id 1 --format text
./blunderdb match --db base.db --id 1 --output match1.json

collection — コレクションを管理する

コレクション——グラフィカルインターフェースの Collections パネルで手動で選んだポジションの集合——を管理します。各サブコマンドは--dbを取ります。listとshowは、listコマンドと同様に--format text(デフォルト)、json、csvを受け付けます。

./blunderdb collection <subcommand> [options]

サブコマンド:

  • list — コレクションのリスト:id、名前、ポジション数、説明。

  • show --id <id> — コレクションのポジション:id、index(グラフィカルインターフェースのステータスバーに表示される1始まりの番号)、score、決定の種類、XGID。

  • create --name <nom> [--description <texte>] — 空のコレクションを作成します。

  • filter --id <id> --query <クエリ> — コレクションを生きたものにします。その内容は検索の結果となり、開くたびに再評価されます。クエリはアプリケーション自身の検索文法で書きます(検索フィルタを参照)。--clear は手作業の一覧に戻し、それまで含んでいた局面を保ちます。

  • rename --id <id> --name <nom> [--description <texte>] — コレクションの名前を変更します(説明が指定されない場合は既存のものが保持されます)。

  • delete --id <id> [--confirm] — コレクションを削除します。ポジション自体はデータベースに残ります。

  • export --id <id[,id…]> --out <fichier.db> [--analysis=false] [--comments=false] [--watermark <texte>] [--watermark-note <texte>] — 1つまたは複数のコレクションを新しいデータベースファイルにエクスポートします。グラフィカルインターフェースのエクスポートウィンドウと同じ呼び出しです(透かしについては exportコマンドを参照)。

showが表示する XGID は、存在する場合はポジションの分析とともに記録されたもの(BGF および XGP インポート)です。存在しない場合は、グラフィカルインターフェースのポジションをコピーと全く同じ方法でボードから生成されます——このときマッチの長さは残り2つのスコアのうち大きい方になります。記録されたポジションは実際の値を保持していないためです。

例:

./blunderdb collection list --db base.db

# Found 2 collection(s):
#
# ID  Name              Positions  Description
# --  ----              ---------  -----------
# 1   Ouvertures blitz  0          À revoir
# 2   Videaux ratés     0

コレクションのないデータベースは No collections found in database と応答しますが、それでも終了コード 0 で終わります。

./blunderdb collection show --db base.db --id 3 --format csv

./blunderdb collection create --db base.db --name "Ouvertures blitz"
./blunderdb collection rename --db base.db --id 3 --name "Ouvertures"
./blunderdb collection delete --db base.db --id 3 --confirm

# Exporter deux collections, marquées de leur origine
./blunderdb collection export --db base.db --id 3,4 --out ouvertures.db \
    --watermark "Cours de Jean Dupont - 12 mars 2026"

anki — 間隔反復デッキ

グラフィカルインターフェースの Anki パネルが持つ間隔反復デッキ(FSRS)を確認・維持します。カードの復習にはボードが必要なため、グラフィカルインターフェース側で行います。CLI は一覧表示、計測、再同期を行います。

./blunderdb anki <subcommand> [options]

サブコマンド:

  • decks [--format text|json|csv] — デッキのリスト:ソース、カード数、期限が来ているカード数、新規カード数。

  • stats --deck <id> [--format text|json] — デッキの復習統計:合計、新規、学習中、要復習、現在期限が来ているもの、および FSRS パラメータ。

  • forecast [--deck <id>] [--days <n>] [--format text|json|csv] — 今後 n日間(デフォルト30、最大365)について、暦日(UTC)ごとに期限を迎えるカード数。0日目には期限切れのカードがすべて含まれます。--deck 0(デフォルト)はすべてのデッキを対象とします。

  • sync --deck <id> — デッキのソースに含まれる各ポジションについて、まだカードがなければ追加します。既存のカードのスケジュールはそのまま保持されます。

  • retention --deck <id> [--format text|json]— 所有者が選んだ目標と比べた、デッキの実測保持率。

  • card --id <id> --action suspend|unsuspend|bury|remove [--format text|json]— 一枚のカードに作用します。保留は履歴を失わずに脇へ置きます(以後セッションに出ません)。埋めるは価値については何も言わずに翌日まで隠します。削除はデッキから取り除きます。ポジション自体はライブラリに残ります。デッキはその上に重ねた学習リストにすぎないからです。

  • log [--deck <id>] [--limit <n>] [--format text|json]— 復習の記録。新しいものが先です(--deck 0が既定で、すべてのデッキが対象。--limitの既定は 20)。記録はスケジューラーに実際に伝えられた内容であり、今日の予定とは別物です。誤って入力した評点が見える唯一の場所です。

コレクションに基づくデッキは、そのコレクションを読み直します。検索に基づくデッキは、グラフィカルインターフェースが記録した検索(コマンド、ボード、その時点で見つかったポジションの識別子)をそのまま保持します。検索の文法はグラフィカルインターフェース側にしかないため、CLI は記録された識別子から再同期し、その旨をエラー出力に表示します——検索そのものを再実行するには、グラフィカルインターフェースでデッキを開いてください。

例:

./blunderdb anki decks --db base.db
./blunderdb anki stats --db base.db --deck 2 --format json
./blunderdb anki forecast --db base.db --deck 2 --days 14
./blunderdb anki sync --db base.db --deck 2
./blunderdb anki card --db base.db --id 12 --action suspend
./blunderdb anki log --db base.db --deck 2 --limit 50

# Day         Due
# ---         ---
# 2026-09-02  12
# 2026-09-03  4
# ...
#
# 37 card(s) due over 14 day(s)

stats — 繰り返されるミス

フィルターのミスをプランとテーマごとにまとめ、コストの大きい順に並べます。Stats パネルの Errors タブにある「繰り返されるミス」の表です(Stats パネルを参照)。全体の統計は引き続き list --type stats で取得します。

./blunderdb stats recurring --db <fichier> [options]

オプション:

  • --player <nom> — このプレイヤーの判断のみ。

  • --tournament <ids>、--from <AAAA-MM-JJ>、--to <AAAA-MM-JJ>、--decision-type all|checker|cube — list --type stats と同じフィルターです。

  • --limit <n> — テキストで表示するグループ数(既定は 20、0 ですべて)。

  • --format text|json — JSON は各グループをすべてのポジションの一覧とともに出力します。

  • --quiz — 最もコストの高い3グループのポジションから無作為に引いて表示します(--quiz-size <n>、既定は20)。これらはクイズと quiz_grade が判定する識別子です。JSONでは Quiz フィールド。

  • --deck <名前> — その名前のAnkiデッキを作り、最もコストの高い3グループのすべてのポジションを入れます。

  • --group <順位> — --quiz または --deck と併用:最初の3グループの代わりに、その順位(最もコストの高いものが1)のグループ。

チェッカープレイのテーマは gammon、blots、point、passive のいずれかで、キューブのテーマは offer_missed、offer_premature、answer_wrong_pass、answer_wrong_take のいずれかです。どのルールも名付けないミスは順位から外れ、プランごとに1行で別に一覧されます(JSON では Unthemed フィールド)。説明文が判断を下すのは60 mp以上、つまりミスのしきい値より上だけだからです。COST (PR) 列は、そのグループがフィルターの PR に占める割合です。

例:

./blunderdb stats recurring --db base.db --player "Alice"
./blunderdb stats recurring --db base.db --decision-type checker --format json
./blunderdb stats recurring --db base.db --quiz --format json
./blunderdb stats recurring --db base.db --group 1 --deck "Mon pire groupe"

stats training — 判断クイズの PR、マッチの PR、Anki の定着率を、Stats パネルの トレーニング タブと同様に、暦のウィンドウごとにまとめて表示します(Stats パネル を参照)。

./blunderdb stats training --db <fichier> [options]

オプション:

  • --window week|month — 暦のウィンドウ(既定は week)。

  • --player <名前>、--tournament <ids>、--from <YYYY-MM-DD>、--to <YYYY-MM-DD>、--decision-type all|checker|cube — マッチのフィルタ。クイズと Anki のジャーナルにはプレイヤーがありません。

  • --format text|json — JSON にはクイズセッションの一覧も含まれます。

各系列はサンプル数を保持します。判断のないウィンドウは、テキストでは破線、JSON ではカウント 0 となり、値としてのゼロにはなりません。

例:

./blunderdb stats training --db base.db --player "Alice"
./blunderdb stats training --db base.db --window month --format json

cubematrix — キューブ判断のマトリクス

ある局面のキューブ判断を、マッチのあらゆるスコアで示します。away × away の各セルについて、ダブルすべきか、テイクすべきかを返します。純粋な計算であり、データベースは開かれません。局面は XGID または OGID(OpenGammon)で渡します。

./blunderdb cubematrix [options] '<XGID|OGID>'

オプション:

  • --format— 出力形式。text または json(既定:text)。

  • --match-length— グリッドが覆うマッチ長。1 から 25 まで(既定:7)。

  • --ply— 各セルの探索深さ。0 または 2(既定:2)。

  • --prune-k— 枝刈りネットワークが残す候補手の数(既定:12)。

  • --jobs— 並列に走らせる探索の数(既定:コアあたり 1 つ)。値によらずグリッドは同一で、変わるのは時間だけです。

局面自身のスコアは無視され、グリッドがそれを置き換えますが、キューブはそのまま保たれます。問いは「どのスコアならこのキューブを回すか」です。グリッドは全体がクロフォード後のものです。

エンジンはスコアを考慮するため、各セルはそれぞれ独立した探索です。ひとつの探索を異なるマッチ・エクイティで読み替えると、まさにスコアが効くところで誤った答えになります。

例:

# Grille d'un match en 5 points
./blunderdb cubematrix --match-length 5 'XGID=-b----E-C---eE---c-e----B-:0:0:1:00:0:0:0:7:10'

# Les équités de chaque case, pour un script
./blunderdb cubematrix --format json '<XGID>'

text出力:行が手番側の残り必要点、列が相手の残り必要点であるグリッドに続き、ND / DT / DP / TG の凡例と、評価できなかった各セルの理由が並びます。

rollout — 局面のロールアウト

gammonNet で局面を何度も繰り返しプレイし、探索では決着がつかないもの、つまり差が数千分の一ほどの二つの手や、モデルが迷うキューブ判断を決着させます。ダイスありの場合はその手がプレイされ(ロールアウトの深さでの最善手で少なくとも 2 ply、または --move で指定した手)、ダイスなしの場合はそのキューブ判断(ノーダブルとダブル/テイク。ダブル/パスはちょうど +1)がプレイされます。局面は XGID または OGID、あるいはデータベース(--db と --id)から取得され、--store がなければ何も記録されません。

./blunderdb rollout [options] '<XGID|OGID>'
./blunderdb rollout --db <path> --id <position> [--store] [options]

オプション:

  • --preset — 初期設定:fast\ (既定:7 ハーフムーブで打ち切る 216 ゲーム、108 ゲーム後に JSD 3 で停止)または standard\ (11 で打ち切る 1296 ゲーム、324 ゲーム後に JSD 3 で停止)。どちらも 0 ply でプレイします。つまり手、キューブ、末端のすべてでネットワークだけを使います。--ply 1 以上ではより深くプレイし、時間は数倍かかります。以降のオプションが一つずつこれを上書きします。

  • --games、--min-games、--truncation、--jsd、--ply、--candidates — ロールアウトのパラメータ(--truncation 0 は各ゲームを最後までプレイし、--jsd 0 は終了前には決して停止しません)。

  • --move — プレイする手を blunderDB 表記で指定します(繰り返し指定可)。

  • --seed — ダイスのシード。既定では固定で、同じコマンドは同じ数列を返します。

  • --jobs — 並列でプレイするゲーム数(既定:コアごとに一つ)。変わるのは所要時間だけです。

  • --format— 出力形式。text または json(既定:text)。

  • --db、--id — XGID の代わりに、プレイする局面のデータベースと識別子。

  • --store — 完了したロールアウトを、独自の設定を持つ第二の分析として、インポートまたは評価された分析の横にポジションへ記録します。それを置き換えることはありません。中断されたロールアウトは記録されません。同じ設定の二つのロールアウトでは長い方の系列が残り、別の設定のロールアウトは横に追加されます。

  • --list — ロールアウトを実行する代わりに、そのポジションに保存されたロールアウトを新しい順に表示します。

すべての候補が同じダイスでプレイされ、各ロールの運は各ゲームの結果から取り除かれ(分散削減)、最初の二回のロールは層別化され、ゲームは two-sided ベアオフデータベースがカバーする地点で停止します。各行にはエクイティ、その 95 % 区間、プレイしたゲーム数、JSD(差の標準偏差で表した最善手との差)が示されます。キューブはゲーム中にプレイされるため、順位は絶対エクイティよりも信頼できます。Ctrl-C を押すと、終了したゲームで確立された結果が表示されます。

例:

./blunderdb rollout 'XGID=-b----E-C---eE---c-e----B-:0:0:1:31:0:0:0:0:10'
./blunderdb rollout --move '8/5 6/5' --move '24/23 13/10' '<XGID>'
./blunderdb rollout --db base.db --id 42 --preset standard --store
./blunderdb rollout --db base.db --id 42 --list

epc — EPC 計算機

XGID または OGID(OpenGammon)で与えられたベアオフ局面について、Effective Pip Count、勝率、マネーゲームのキューブ判断を計算します。純粋な計算であり、データベースファイルは一切関わりません。

./blunderdb epc [options] '<XGID|OGID>'

オプション:

  • --format — 出力フォーマット:text または json(デフォルト:text)。

  • --bearoff-ts — 内蔵の TS-06-06 を広げる任意の two-sided ベアオフデータベース(.bd。環境変数 BLUNDERDB_TS_PATH からも読まれます)。有効なもののうち最も広いデータベースが優先されます。無効なファイルは警告のうえ無視されます。

動作モード。two-sided データベースが覆う範囲では、勝率とマネーゲームのキューブ分析(cubeless、ND、D/T、D/P、判断)は厳密です。その外側では勝率は推定となり(one-sided のロール分布の畳み込みに較正済みの補正を加えたもの)、実測した誤差幅とともに表示されます。キューブの判断は意図的に決して推定しません(ADR-0009 を参照)。

例:

# Régime exact : six pions ou moins de chaque côté
./blunderdb epc 'XGID=-BBB------------------bbb-:0:0:1:00:0:0:0:0:10'

# Avec la table TS-06-11 calculée : exact jusqu'à onze pions par joueur
./blunderdb epc --bearoff-ts ~/.local/share/blunderdb/gnubg_ts6x11.bd 'XGID=…'

bearoff — ベアオフ・データベース

ベアオフ・データベースを作り、管理します。ダウンロードも埋め込みもありません。表はここで計算し、その領域に対して gnubg が出す指紋と照合します。どのサブコマンドもデータベースには触れません — ベアオフの表はゲームについての算術であって、誰かの局面についてのものではないからです — したがって --db を取るものはありません。

./blunderdb bearoff generate --ts <domain> [options]
./blunderdb bearoff list [options]
./blunderdb bearoff verify <file.bd> [options]
./blunderdb bearoff delete --ts <domain> [options]

領域は makebearoff と同じ書き方です。1 人あたり 9 個の駒の両面表なら 6x9、八点の片面表なら os8(os だけなら os6 と同じ)。

二つの系統は同じ問いに答えるものではありません。両面 の表は、勝率とキューブ判定が厳密になる範囲を広げます。片面 の表は、EPC が黙らずに済む駒の距離を広げます(最大十点)。

generate. 開始前に大きさ・必要メモリ・推定時間を示し、そのあと進捗率と実測の残り時間を表示します。

  • --ts — 計算する両面領域。例えば 6x9。

  • --os — 計算する片面領域を点数で指定します。6 から 12。二つのうち、ちょうど一方が必要です。

  • --cores — 使うコア数(既定:1 つを除く全部)。

  • --data-dir — 書き込み先(既定:アプリケーションのデータフォルダー)。

  • --quiet — 進捗行を出しません。

CTRL-C は一時停止です。 シグナルを捕まえ、状態を表の隣に書き出します。同じコマンドをもう一度実行すると、すべてを計算し直すのではなく止まったところから続きます。30 分の算術は書き留める価値があります。bearoff delete は待機中の再開を捨てます。一時停止できるのは両面の走査だけです。片面の走査は逐次的で、--cores は役に立ちません。

list. 各領域を数字で示し — 大きさ、メモリ、この計算機での時間 — どれがすでに存在するか(判定つき)、どれに一時停止中の計算があるかを述べます。スクリプト用には --format json、推定の前提を変えるには --cores を使います。

verify. verified(参照と同じバイト列)、unverified(形は正しいが、その領域の指紋が登録されていない)、corrupt(ファイルが自分自身と矛盾する)のいずれかを返します。最後の場合はエラーで終了します。このコマンドはスクリプトに置くために作られています。

delete. 表、待機中の再開、死んだ計算の残骸を取り除きます。既定の領域はアプリケーションの次回起動で再計算されますが、より広い領域はされません。

例:

# Ce que cette machine a, et ce que chaque domaine coûterait
./blunderdb bearoff list

./blunderdb bearoff generate --ts 6x9 --cores 4

# OS-08 : l'EPC répond alors jusqu'à un pion sur la 8
./blunderdb bearoff generate --os 8

# Sur un serveur, dans le volume que lit le démon
./blunderdb bearoff generate --ts 6x11 --data-dir /srv/bearoff

./blunderdb bearoff verify /srv/bearoff/gnubg_ts6x11.bd

analyze — gammonNet の補完分析

分析を一つも持たないポジションごとに gammonNet 分析を書き込みます——この機能が存在する前に構築されたライブラリを追いつかせるための補完です(ADR-0013、ADR-0015)。これはインポート後の自動起動や GUI の「今すぐ解析」ボタン、そして serve デーモンのテナント向けエンドポイント /v1/gammonnet.analyzeMissing と同じ操作です——同じ操作の三つの異なる形であって、三つの別々のロジックではありません(ヘッドレスモード(サーバー) を参照)。

./blunderdb analyze --db <path> [options]

オプション:

  • --db — データベース(必須)。

  • --ply — 探索深さ(デフォルト:2、標準パラメータ)。

  • --prune-k — 枝刈りの幅(デフォルト:12、標準パラメータ)。

  • --candidates — チェッカープレイの判断ごとに保持する候補手の数(デフォルト:10)。

  • --jobs — 並列に分析するポジションの数(デフォルト:マシンのコア数)。

  • --match — 処理を単一のマッチの局面だけに限定します(既定値の 0 はライブラリ全体を意味します)。

  • --compare — 何も書かない:穴を埋めるのではなく、gammonNet をインポート済みの解析と比較する(下記参照)。

  • --limit — --compare と併用:この数の局面で打ち切る(0 はすべて)。

  • --format — 出力フォーマット:text(デフォルト、進捗表示付き)またはjson(最後に出力される1つの要約文書)。

  • --rollout — 欠けた解析を補う代わりに、--query が選ぶ局面のロールアウトを行います(後述)。

  • --query — --rollout と併用して、プレイする局面を検索のクエリ言語(search --query-help)で指定します。空の場合はすべて。

解析なしで取り込んだマッチにも PR が付くようになりました。オンラインで指したマッチや、XG を通していない Jellyfish の .mat ファイルがこれに当たります。blunderDB は局面と指された手を知っていましたが、それがどれだけの価値かを語るものがありませんでした。バッチが走ると、実際に指された手が gammonNet の順位づけと比較され、その差が PR とそのほかすべての指標に反映されます。指された手はマッチの手のテーブル、すなわち取り込み時に書かれたものから来ます。ファイルが解析を持っていたかどうかによらず、推測されることはありません。

本バージョンより前に解析したデータベースを評価し直す必要はありません。repair が既存のデータから列を計算し直し、それらのマッチに PR を取り戻します。

マッチを一つだけ (--match)。list --type matches が表示する識別子を指定すると、処理はそのマッチの局面だけをたどります。空白を埋める規則も保証も同じで、範囲だけが狭くなります。取り込んだばかりのマッチは、ライブラリの残りを走査することなく解析を得られ、修正してから二度目に解析したマッチは、修正が生み出した局面の分しか費用がかかりません。他の局面はすでに解析を持っているからです。このオプションは --stale とも --compare とも組み合わせられません。どちらもすでに解析を持つ局面を見るものであり、両方を求めることは、黙って無視される範囲ではなく誤りです。

並列処理(--jobs)。バッチ内のポジションは互いに独立しており——どの探索も次の探索に影響しない——そのため --jobs 個のスレッドに分配され、各スレッドは独自の評価器を持ちます。書き込まれる分析は --jobs の値にかかわらず同一で、変わるのは計算時間だけです。--jobs 1 はマシンを他の用途のために空けておきます。キャンセルは影響を受けません:Ctrl-C は新しいポジションに入る前にバッチを停止し、すでに計算済みのものはすべて書き込まれます。

穴のルール(ADR-0013)。 すでに分析を持つポジション——XG、GNUbg、BGBlitz、あるいは以前の gammonNet の実行によるもの——は、どのエンジンの分析が欠けていようと決して触られません。書き込まれるのは分析を一つも持たないポジションだけです。したがってこのコマンドは危険なくいつでも再実行でき、きれいに中断できます:Ctrl-C は書き込み済みの内容を一切失わずに中止し、次回の実行は前回が止まった正確にその場所から再開します——「分析のないポジション」は起動のたびに再計算されるため、ジャーナルは一切不要です。

例:

./blunderdb analyze --db base.db

# Analyzing 1204 position(s) with gammonNet (2-ply, k=12, 16 job(s))...
#   1/1204 (0%)
#   61/1204 (5%)
#   ...
#   1204/1204 (100%)
# Done.

./blunderdb analyze --db base.db --jobs 1

# Un seul match, celui qui vient d'être importé
./blunderdb analyze --db base.db --match 12

バッチロールアウト(--rollout)。--query が選んだ各局面はロールアウトでプレイされ、すべてのコアで一つずつ順に処理されます。ロールアウトは解析の隣に記録され、解析の代わりになることはありません。値はプリセット(fast(216 ゲーム、7 で打ち切り)または standard(1296 ゲーム、11 で打ち切り))か、自由な設定(任意のプリセットに続けて games=、min-games=、truncation=、jsd=、ply=、candidates=、seed= をカンマ区切りで指定)です。同じ設定のロールアウトをすでに持つ局面はスキップされます。Ctrl-C で中断した実行は止まったところから再開し、処理中の局面は丸ごと破棄されます。ロールアウトだけが解析した局面は検索でそのロールアウトを通じて見つかり、すでに解析済みの局面はその解析の列を保ちます。

./blunderdb analyze --db base.db --rollout fast --query 'E>80'
./blunderdb analyze --db base.db --rollout 'standard,ply=1' --query 'c'

--compare:あなたのライブラリで gammonNet はどれだけのものか

エンジンの精度は、参照コーパスと正確なベアオフ表に対して別の場所で測定されている。しかしそのどちらも、利用者が実際に抱いている問い——自分の局面についての問い——には答えない:XG からインポートしたマッチにおいて、組み込みエンジンはファイルに付いてきた解析とどこで食い違い、その食い違いは何を犠牲にするのか。

--compare はそれに答え、何も書かない。これは用心ではなくコマンドの要点である:ADR-0013 はインポートされた解析を無条件に守るので、この比較は絶対に上書きされたくないライブラリの上でこそ実行できる。

報告が与えるもの:

  • 最善手の一致率。チェッカープレイとキューブ判断を分けて示す——両者は無関係であり、単一の率ではどちらが崩れているかが隠れてしまう;

  • 食い違いの代償。インポートされた解析自身の尺度で値を付ける:gammonNet が選ぶ手がインポート元のエンジンによればどれだけの価値か、そこからそのエンジン自身の最善手の価値を引いたもの。この向きだけが両エンジンで共通に値付けできる。食い違いを二度値付けすれば、小さいほうの数字を読む誘惑を招く;

  • ゲームの段階ごとの内訳。食い違いがどこに集まっているかを語るのはこれである;

  • 最も代償の大きい十件の食い違いを、局面ごとに。

二つのエンジンは同じ手を違うように書く——XG が「13/7」と書くところを gammonNet は「13/8 8/7」と書き、ヒットは一方では印が付き他方では付かず、繰り返しは「(2)」に縮められることもある。これらは方言であって食い違いではない:比較は両方の記法を正準形に直してから突き合わせる。それをしないと、あるテストコーパスは 93,2 % ではなく 78,8 % の一致を示した——十五ポイントの偽の食い違いである。

インポート元のエンジンが挙げていない手は、その尺度で値付けできない:でっち上げた代償ではなく、代償ゼロの食い違いとして数える。

# Comparer sur un échantillon de 500 positions
./blunderdb analyze --db base.db --compare --limit 500

# compared: 118 decision(s)  (refused 2, failed 0)
# same best answer: 93.2% (110/118)
#   checker play:   93.7% (59/63)
#   cube decision:  92.7% (51/55)
# ...

transcribe — 記譜を再生する

記譜を再生し、再生が見つけたものを報告します。ソースは.matファイル、ライブラリのマッチ、記譜の下書きのいずれか一つだけです。マッチはエクスポート時に生成される.matを通して読まれるため、再生されるのはエクスポートが含むはずのものです。

./blunderdb transcribe --mat <fichier> [--check] [--render <sortie>]
./blunderdb transcribe --db <path> --match <id> --check
./blunderdb transcribe --db <path> --draft <id> --check
./blunderdb transcribe --db <path> --match <id> --edit [--accept-losses]
./blunderdb transcribe --db <path> --draft <id> --finish|--abandon

オプション:

  • --mat — 再生する.matファイル。

  • --db — データベース。--match および --draft 用。

  • --match — 再生するライブラリのマッチの識別子。

  • --draft — 再生する記譜の下書きの識別子。

  • --check — 見つかった不整合を列挙する(既定の動作)。

  • --render — 記譜をこのパスに.matとして書き戻す。

  • --format — 出力フォーマット:text(デフォルト)またはjson。

  • --edit — --match に対して下書きを開きます(すでに開かれている下書きがあればそれを返します)。

  • --accept-losses — 取り込み済みのマッチに対する --edit と併用:その分析とコメントが失われうることを受け入れます。

  • --finish — --draft を完了します:そのマッチを書き込むか、開いた元のマッチを置き換え、下書きを解放します。

  • --abandon — --draft を破棄します:マッチを作らずに削除します。開いた元のマッチはそのまま残ります。

  • --yes — マッチを一度も生み出していない下書きに --abandon を使うとき、その中に書かれたすべてが失われることを確認します。

--check は各不整合を、アクション番号とそれが属するゲームとともに示します。不正な手、同じプレイヤーが続けて二手、不可能なキューブ操作、マッチ終了後のアクション、自身のダイスを使っていない手、ゾロ目で指されたゲームの最初の手(オープニングロールはゾロ目になりえません)、記録されていない手、そして申告スコアの不一致です。記録されていない手とは、gnubg が実際に指された手を残さなかったときに書く ??? のセルであり、ダンスではありません。申告スコアの不一致とは、スコア行が前のゲームから導かれるものと異なるゲームであり、書かれたスコアで再生されます。

不整合は報告されるだけで、けっして拒否の理由になりません。不整合を理由に何かが拒まれることはなく、再生が何を見つけても終了コードは 0 のままです。ゼロ以外の終了コードは本当の失敗を示します — 読めないファイル、開けないデータベース、書き込めない出力です。所見に基づいて動作させたいスクリプトは--format jsonで読み取ります。そこでは壊れたファイルと不正な手を含むゲームが混同されません。

--render は記譜を.matとして書き戻します。これにより、テストの外で実際のファイルについて往復変換を確認できます。

書き込みを行うオプションは三つだけで、記譜パネルと同じメソッドを通します。--edit は既存のマッチに対して下書きを開き、--finish はそれを完了し(マッチは同じ識別子のまま置き換えられます)、--abandon はマッチを作らずに下書きを削除します。一度も完了していない下書きには --yes が必要で、書かれた内容はすべて失われます。取り込み済みのマッチは .mat に含まれない分析とコメントを持っています。--edit は最大でその件数を示し、--accept-losses がなければ拒否します。

例:

./blunderdb transcribe --mat match.mat --check

# match.mat: 7 point match, 4 game(s), 203 action(s)
#   Final score: 9-2
# Inconsistencies: none

tournament — 運営した大会を読む

グラフィカルインターフェースなしで、運営中のトーナメントを読み取ります。トーナメントを対話的に運営するのは Nicomaque エンジンのコンソールの役目です。これらのサブコマンドは読み取りのみで、入力を待つものはなく、書き込むのはmoveだけです。

./blunderdb tournament <sous-commande> --db <chemin> [options]

サブコマンド:

  • list [--format text|json] — データベース内の運営済み大会と、その状態、エンジンのバージョン、それぞれが属するイベント(なければ空欄)、最後の決定の日付。

  • verify --id N [--format text|json] — 運営を再生し、残っている警告をすべて報告します。警告が残っていればエラー終了します。これは大会後の点検であり、シーズン分のデータベースにこれを流すスクリプトが欲しいのは終了コードであって、絞り込むための一行ではありません。

  • standings --id N — 賞金を含む順位表を CSV で、インターフェイスの言語で出力します。

  • ranking --season [--rencontre N] [--from AAAA-MM-JJ] [--to AAAA-MM-JJ] [--points 25,18,15] [--participation P] [--elo] [--format csv|json] — シーズンランキング。イベントまたは期間の終了済みの大会を対象とします(両端を含み、大会の日付で判定。フィルターがなければ運営したすべての大会)。各順位は配点表によってポイントに換算され(優勝者が先頭。既定は 25、18、15、12、10、8、6、4、2、1)、さらに参加した大会ごとに --participation が加わります。同順位は、占める順位の平均を分け合います。大会をまたいで、人物は名前で識別されます。--elo は、シーズンの対戦をやり直して算出したクラブ Elo(FIBS の式、初期値 1500)を加えます。CSV は 1 人 1 行、大会ごとに 1 列のポイント列を出力します。終了していない大会は一覧に載りますが、ポイントにはなりません。

  • page --id N|--rencontre N [--out <フォルダー>] — 種目の HTML 表示ページ(--id)、またはイベントの壁面ページ(--rencontre:どの種目が使っていてもテーブルごとに1行)。どちらか一方が必須です。--out なしなら標準出力へ、指定するとそのフォルダーに書き出され、以後そこが運営またはイベントのフォルダーになります。

  • export --id N — 生のイベントジャーナル。エンジンのツールで再生できます。ジャーナルは運営のすべての真実であり、順位表もトーナメント表も警告もそこから再生されます。この出力を読むツールに blunderDB は一切不要です。

  • move --id N --match M --table T [--format text|json] — 進行中のマッチのテーブルを変更します。グリッドでセルを別のセルへドラッグするのと同じ操作です。移動先のテーブルが使用中なら、2 つのマッチがテーブルを入れ替えます。使用停止中のテーブルは拒否されます。イベント内で、テーブルが別の種目に使われている場合は、2 つの種目の間で入れ替えます。テーブルの変更はそれぞれのログに記録されます。進行中の各マッチのテーブルを表示します。

  • hall --rencontre N [--format text|json] — イベントのすべてのテーブルです。どの種目が使っているかにかかわらずテーブルごとに 1 行(種目、マッチ、プレイヤー)を示し、続けて各種目の提案を示します。Direction のすべてのテーブルビューが表示するグリッドです。イベントに会場がある場合、テーブルは会場ごとにまとめられ、名前を持つテーブルには名前が表示されます。

  • tables --rencontre N|--tournament N [--format text|json] — テーブルのプロパティ(名前、会場、予約済み、割り当て先)と、イベントの各種目が行われる会場(--rencontre)、または単独で行われる種目のプロパティ(--tournament)を表示します。読み取り専用で、書き込みは call を通じて行います(rencontres.setTables、rencontres.setEventRooms、directions.setTables)。

共通オプション: --db(必須)、--id(list、page --rencontre、hall、tables以外で必須)、--format。

例:

./blunderdb tournament list --db base.db
./blunderdb tournament verify --db base.db --id 3
./blunderdb tournament standings --db base.db --id 3 > classement.csv
./blunderdb tournament ranking --db base.db --season --from 2026-01-01 --to 2026-12-31 --elo > saison.csv
./blunderdb tournament page --db base.db --id 3 --out /tmp/affichage
./blunderdb tournament page --db base.db --rencontre 1 --out /tmp/evenement
./blunderdb tournament export --db base.db --id 3 > journal.json
./blunderdb tournament move --db base.db --id 3 --match m4 --table 7
./blunderdb tournament hall --db base.db --rencontre 1
./blunderdb tournament tables --db base.db --rencontre 1

trash — ごみ箱

何が削除され、それを何で戻せるか。削除はやはり削除である:消えるものの JSON スナップショットが先に書かれ、そのテーブルの存在をデータベースの他の何も知らない——検索フィルタも、統計も、保持規則も。

./blunderdb trash <sous-commande> --db <chemin> [options]

サブコマンド:

  • list — ごみ箱の中身を、最近削除したものから順に。

  • restore --id N — 項目 N を戻し、ごみ箱から取り除く。

  • discard --id N — 項目 N を復元せずに今すぐ削除する。

  • empty [--older-than D] — ごみ箱を空にする、または D 日より古いものだけを消す。

  • delete --kind K --id N — 取り消せるように、ごみ箱を経由してオブジェクトを削除する。K は position、collection、comment のいずれか。

共通オプション:--db(必須)、--kind、--limit(既定 50)、--format(text または json)。

注釈

blunderdb delete は今も網なしで削除する:局面を削除するスクリプトはそれが消えることを期待しており、黙ってスナップショットを残せば、誰も大きくしてくれと頼んでいないファイルが太る。取り消しを残すのは trash delete のほうである。

局面の復元は Zobrist 重複排除を再び通る:重複を作ることは決してないが、古い識別子は返さない——元の行はもう存在しない。復元された局面は同じ局面であり、新しい番号を持つ。

三十日より古いものは blunderdb vacuum が削除する——データベースを開いたときには決して削除しない。

例:

# Supprimer une position en gardant l'annulation
./blunderdb trash delete --db base.db --kind position --id 412

# Voir la corbeille, puis remettre une entrée
./blunderdb trash list --db base.db
./blunderdb trash restore --db base.db --id 3

# Ne garder que ce qui a moins de trente jours
./blunderdb trash empty --db base.db --older-than 30

info — データベースのメタデータ

データベースのメタデータと統計を表示します。

./blunderdb info --db <path> [--format <format>]

オプション:

  • --db — データベース(必須)。

  • --format — 出力フォーマット:text または json(デフォルト:text)。

例:

./blunderdb info --db base.db

# Database Information
# ==================================================
# Path: /home/jean/bg/base.db
#
# Metadata:
#   Version: 2.20.0
#   User: Jean
#   Description: Matchs de tournoi 2025
#   Date of Creation: 2026-09-06 02:43:51
#
# Statistics:
#   Positions: 3859
#   Analyses: 3855
#   Matches: 11
#   Games: 61
#   Moves: 3766

--format json はファイルの出所を加えます——issuance には、透かしがあればその透かしと、このマシンの発行者アイデンティティが入ります:

./blunderdb info --db base.db --format json
{
  "issuance": {
    "watermarked": false,
    "issuerFingerprint": "1186-57FA-060C-9378",
    "issuerName": "unger"
  },
  "metadata": {
    "database_version": "2.20.0",
    "dateOfCreation": "2026-09-06 02:43:51",
    "description": "Matchs de tournoi 2025",
    "user": "Jean"
  },
  "path": "/home/jean/bg/base.db",
  "stats": {
    "analysis_count": 3855,
    "game_count": 61,
    "match_count": 11,
    "move_count": 3766,
    "position_count": 3859
  }
}

edit — メタデータを編集する

データベースのユーザー名、説明、または閾値を編集します。

./blunderdb edit --db <path> [options]

オプション:

  • --db — データベース(必須)。

  • --user — 新しいユーザー名。

  • --description — 新しい説明。

  • --clear-user — ユーザー名を削除する。

  • --clear-description — 説明を削除する。

  • --error-threshold — エラーの閾値(ミリポイント単位)。この値以上の損失となる決定はエラーです。

  • --blunder-threshold — ブランダーの閾値(ミリポイント単位)。この値以上の損失となるエラーはブランダーです。

  • --format — 出力フォーマット:text(デフォルト)またはjson({"changes": [...]})。

少なくとも1つの編集オプションが必要です。

例:

./blunderdb edit --db base.db --user "Marie" --description "Ma collection"
./blunderdb edit --db base.db --clear-description
./blunderdb edit --db base.db --error-threshold 20 --blunder-threshold 80

verify — 整合性を確認する

データベースの整合性を確認し、オプションでマッチとそのソースファイルを比較します。

./blunderdb verify --db <path> [--match <id>] [--mat <file.mat>]

オプション:

  • --db — データベース(必須)。

  • --match — 確認するマッチのID。

  • --mat — 比較するMATファイル(--match と共に使用)。

  • --format — 出力フォーマット:text(デフォルト)またはjson(統計、孤立行、スキーマの差分、および該当する場合はマッチの検証)。

--match オプションなしの場合、コマンドはデータベースの一般統計を表示します。--match を使用すると、マッチのデータを確認し、元のソースファイルと比較できます。

各実行では参照整合性も検査します。孤立した行——マッチのないゲーム、ゲームのない手、手のない手の解析、局面のない解析、デッキまたは局面のない復習ジャーナルの項目——を数え、存在すれば合計とともにWARNING行を表示します。健全なデータベースはOrphaned rows: noneと答えます。すべての接続で外部キーを強制していなかったバージョンが書いたデータベース、あるいは復習ジャーナルが自分の外部キーを持つ前のデータベースには、孤立行が残っていることがあります。どのマッチにもどのデッキにも属さず、場所を取るだけです。それでもコマンドの終了コードは 0 のままです。

各実行では、スキーマを参照 DDL と比較し、データベースに欠けているテーブル・列・インデックスを一覧します。データベースを開くときには、可能であれば欠けているものが追加され、追加できないもの(典型的には重複行のせいで再構築できないUNIQUEインデックス)はログに記録されるだけです。このずれが目に見えるのはここであり、これらの要素を名指しするクエリは原因が修正されるまで失敗します。健全なデータベースはSchema: matches the reference DDLと答えます。孤立行と同じく、スキーマのずれは所見であって失敗ではなく、終了コードは 0 のままです。

各実行では最後に、現在の DDL が定めているものの SQLite が既存のテーブルに追加できない規則を検査します。すなわち範囲のCHECK制約(サイコロは 0 から 6、キューブとピップは非負、上がった駒は 0 から 15、復習の評価は 1 から 4)、行に決して欠けてはならない Zobrist ハッシュ、そして 1 つの局面につき 1 つの解析という一意性です。スキーマ 2.18.0 以降に作成されたデータベースはこれらを強制します。それより古いデータベースには、新しいデータベースなら拒否する行が残っていることがあり、ここで規則ごとに数えられるのはそれらです。健全なデータベースはConstraints: every row satisfies the current DDLと答えます。これもまた所見にすぎません。何も修復されず、終了コードは 0 のままです。

各実行では最後に、非正規化された 2 つのカウンタmatch.game_countとgame.move_countを、それらが数えていると称する行から再計算し、いくつが食い違っているか、最悪でどれだけ違うかを報告します。どちらもインポート時に一度だけ、ソースファイルの内容から書かれ、マッチ一覧と対局ビューが表示するのはこの値です。小さなずれはたいてい、変換できなかったものを飛ばしたインポートです。何も書き換えられません——カウンタを保存済みの値で置き換えれば、まさに見るべきずれが消えてしまいます。健全なデータベースはCounters: game_count and move_count agree with the rowsと答えます。

例:

./blunderdb verify --db base.db
./blunderdb verify --db base.db --match 1
./blunderdb verify --db base.db --match 1 --mat original.mat

これを門番として使う。コマンドが何を見つけても終了コードは 0 です。判定を運ぶのは --format json であり、スクリプトは自分でカウンターを読む必要があります。

{
  "stats": {
    "analysis_count": 3855,
    "game_count": 61,
    "match_count": 11,
    "move_count": 3766,
    "position_count": 3859
  },
  "orphans": {
    "games_without_match": 0,
    "moves_without_game": 0,
    "move_analyses_without_move": 0,
    "analyses_without_position": 0,
    "reviews_without_deck": 0,
    "reviews_without_position": 0
  },
  "orphan_total": 0,
  "schema_drift": {
    "missing_tables": null,
    "missing_columns": null,
    "missing_indexes": null
  },
  "schema_drift_count": 0,
  "constraint_violations": [
    {"name": "position.zobrist_hash NOT NULL", "count": 0},
    {"name": "position.dice_1 BETWEEN 0 AND 6", "count": 0}
  ],
  "constraint_violation_total": 0,
  "counter_drift": {
    "matches_with_wrong_game_count": 0,
    "games_with_wrong_move_count": 53,
    "worst_game_count_gap": 0,
    "worst_move_count_gap": 2
  },
  "counter_drift_total": 53
}

警戒すべき項目は3つです。orphan_total、schema_drift_count、constraint_violation_total です。ゼロでなければ、修復が必要なデータベースであることを表しています。

./blunderdb verify --db base.db --format json \
  | jq -e '.orphan_total == 0 and .schema_drift_count == 0 and .constraint_violation_total == 0'

counter_drift_total はそこに含まれません。上の例がそれを示しています。この出力を生んだデータベースはインポートされたばかりですが、手のカウンターが行の内容と食い違うゲームがすでに 53 件あります。これらのカウンターは元のファイルに由来するもので、データベースに由来するものではありません。差はインポートの事情を語るのであって、破損を知らせるものではありません。目を通すのはよいですが、しきい値としては使わないでください。

vacuum — データベースを最適化する

削除(マッチ、トーナメント、パージ)によって空いたディスク領域を回収します。SQLite はデータを削除してもファイルを自分で縮めることはなく、明示的に指示する必要があります。最適化を起こす方法はこれだけです。大きなデータベースでは費用が読めないため、データベースを開いたときに自動で行われることはありません。

./blunderdb vacuum --db <path>

オプション:

  • --db — データベース(必須)。

  • --format — 出力フォーマット:text(デフォルト)またはjson(バイト単位の{"size_before", "size_after", "reclaimed"})。

このコマンドはまず wal_checkpoint(TRUNCATE) を実行し、最適化前に表示されるサイズが正直な値になるようにします。次にディスク上に現在のファイルサイズのおよそ2倍が残っていることを確認し(SQLite は切り替える前にデータベース全体を作り直します)、VACUUM を実行し、続いてクエリプランナが使う統計を更新するために ANALYZE を実行します。ディスク容量が足りない場合は、中断された最適化の危険を冒すのではなく、明確なメッセージとともに開始を拒みます。

例:

./blunderdb vacuum --db base.db

# Compacting database...
#   Before: 128.4 MiB
#   After:  41.2 MiB
#   Reclaimed: 87.2 MiB

repair — 導かれたものを再計算する

データベースが保存内容から導くものを再計算します。各分析の scalar 列を、その分析自体から。各局面の局面フェーズと戦型を、その盤面から。そして各スコアの Crawford 標識を、その局面が由来する対戦、またはその局面が持ち込まれた XGID から。分析そのものには手を触れません。作り直されるのは、そこから導かれていた値です。

./blunderdb repair --db <path>

オプション:

  • --db — データベース(必須)。

  • --format — 出力フォーマット:text(デフォルト)またはjson。パスごとに 1 つのカウンター:repaired(分析列)、phases(再分類された局面)、crawford(ハッシュを再計算した局面)。それぞれが実際に変更された行数を示します。

取り込んだ解析の読み方を修正したあとに役立ちます。これはすでに二度起きています。XG の取り込みは「ダブルしない」を二通りに書き、その二つめが本物のダブルとして解釈されていました。列は起こらなかったダブルの誤差を持っていたのです。また blunderDB 自身が計算した解析はどの手が指されたかを知らず、解析なしで取り込んだマッチはどこも誤差ゼロのまま PR 0,00 になっていました。この列はいまマッチの手から計算し直されます。読み方を直しても、すでに書かれた行は変わりません。このコマンドがそれを作り直します。

Crawford のパスだけは、局面そのものに手を入れます。スコアの1は「あと 1 点、そしてこの試合が Crawford である」を、0は「あと 1 点、Crawford はもう終わっている」を意味します。インポータがこの区別を書かなかった間、Crawford 後の局面はすべて Crawford の局面として保存され、したがってダブリングキューブが死んだものとして読まれていました。実際には、負けている側が最初の機会にダブルする場面です。スコアを直すと局面のハッシュが変わります。つまりその行はハッシュを取り直され、正しい双子がすでにデータベースにあればそれと統合されます。分析、コメント、コレクション、Anki のカードとその復習履歴、対戦の指し手、そしてその行を指すゴミ箱の項目は、残った行に従います。どの対戦からも指されていない局面が修正されるのは、別のソフトウェア(XG、BGBlitz…)から持ち込んだ XGID の言葉によってだけです。その XGID の Crawford 欄がこの試合は Crawford ではないと述べ、かつその XGID がまさにこの局面を表しているときです。逆向きには、対戦のない局面が両側とも0で保存されていて、持ち込んだ XGID が 1 ポイントの対戦のものであり、かつその局面を表しているとき、1に直されます。1 ポイントの対戦の唯一の試合はゴールまであと 1 点の地点から始まるので、それは Crawford であり、インポータもそう書きます。より長い対戦の Crawford 後の DMP は0のままです。その XGID がその対戦の長さを示しているからです。blunderDB 自身が書き直した XGID は保存済みのスコアを繰り返すだけで、何も証明しません。対戦のないそれ以外の局面はそのままにされます。そのスコアが述べていることに反するものが何もないからです。

自動的に実行されることはありません。これは意図的です。データベースを開いただけで全員の分析列を書き換えたり、局面のハッシュを取り直したりするのは、道具が利用者に黙ってやってよいことではないからです。

例:

./blunderdb repair --db base.db

# 42 analyses repaired.
# 7 positions reclassified.
# 3 positions rehashed onto the right Crawford sentinel.

delete — データを削除する

マッチとすべての関連データ(ゲーム、手、分析)を削除します。

./blunderdb delete --db <path> --type match --id <id> [--confirm]

オプション:

  • --db — データベース(必須)。

  • --type — 削除の種類:match(必須)。

  • --id — 削除する要素のID(必須)。

  • --confirm — 確認なしで削除する。

  • --format — 出力フォーマット:text(デフォルト)またはjson({"match_id": N, "deleted": true})。

例:

# Confirmation interactive, puis sans confirmation (scripts)
./blunderdb delete --db base.db --type match --id 1
./blunderdb delete --db base.db --type match --id 1 --confirm

healthcheck — デーモンを確認する

稼働中のserveデーモン(ヘッドレスモード(サーバー)参照)に準備ができているか問い合わせます。GET /readyzリクエストを1回送り、デーモンが 200 を返せば(ストレージに到達でき、スキーマが期待されるバージョンであれば)終了コード0、それ以外(ストレージに到達できない、スキーマが古い、アドレスで何もリッスンしていない)なら1を返します。データベースファイルは一切開きません。

./blunderdb healthcheck [--addr host:port] [--timeout 2s]

オプション:

  • --addr — デーモンがリッスンするアドレス(既定はBLUNDERDB_ADDR、なければ:8080)。ホストのないアドレス(:8080)やワイルドカードホスト(0.0.0.0、[::])はループバックインターフェースで確認します。

  • --timeout — この時間を過ぎると確認を諦めます(既定は2s)。

これはコンテナイメージのHEALTHCHECKが実行するコマンドです(distrolessイメージで、curlはありません)。cmd/serveからビルドしたserveバイナリも同じコマンドを理解します。スクリプトや systemd ユニットからも同様に使えます。

例:

./blunderdb serve --db base.db --addr 127.0.0.1:8080 &
./blunderdb healthcheck --addr 127.0.0.1:8080 && echo "démon disponible"

# ready

失敗した場合はその理由が表示され、docker inspectもunhealthyなコンテナについて同じ内容を示します:

Error: healthcheck: http://127.0.0.1:8080/readyz answered 503 Service Unavailable (version_mismatch)

mcp — データベースを AI アシスタントに提供する

Model Context Protocol を通じて、標準入出力でデータベースのツールを AI アシスタントに提供します。コマンドを起動するのはアシスタントです。ツールは、コマンドバーの文法でポジションを検索し、ポジションとその解析を読み取り、ミスを説明し、プレイヤーの統計を計算し、マッチ・トーナメント・コレクションを一覧表示し、クイズを出題します。--write を付けない限り、読み取りのみを行います。完全な一覧とデーモンの HTTP 版:AI アシスタント向けツール(MCP)。

./blunderdb mcp --db base.db [--write]

オプション:

  • --db — データベースファイル(必須)。

  • --write — 書き込みを行うツールも提供します:ポジションの保存、コメントの追加、コレクションの作成と追加。削除は一切行いません。

call と同じく、このコマンドは --write なしでも、開くときに古いデータベースのスキーマを移行します。

例: データベースを Claude Code に登録する。

claude mcp add blunderdb -- blunderdb mcp --db /chemin/vers/base.db

completion ――― シェル補完

サブコマンド名の補完スクリプトを標準出力に表示する。各スクリプトに組み込まれるコマンド一覧は、blunderdb helpやmain.goのディスパッチ(handlers())が読み込むのと同じテーブルから生成される。そのため、新しいサブコマンドが組み込まれると同時に補完でも提供され、手作業で維持する必要は何もない。

./blunderdb completion <bash|zsh|fish>

例:

# bash
source <(blunderdb completion bash)
blunderdb completion bash | sudo tee /etc/bash_completion.d/blunderdb > /dev/null

# zsh : un répertoire déjà sur $fpath
blunderdb completion zsh > "${fpath[1]}/_blunderdb"

# fish
blunderdb completion fish | source

パッケージはこれを自動的にインストールする:.deb/.rpm(nfpm)と AUR パッケージはビルド時にパッケージ済みのバイナリから3つのスクリプトを生成し、Homebrew の cask はインストール時に一度、generate_completions_from_executableを通じてblunderdb completion <shell>を実行する。リポジトリには何もコミットされないため、補完がサブコマンドのテーブルからずれることは決してない。

version — バージョンを表示する

blunderDB のバージョンと、このバイナリが書き込むデータベーススキーマのバージョンを表示します。バグ報告に最初に添えるべき情報です。

./blunderdb version
# blunderDB version 0.36.0 (database schema 2.20.0)

ワークフロー例

トーナメントディレクトリのインポート

./blunderdb create --db tournoi_paris.db --user "Jean" --description "Open de Paris 2025"
./blunderdb import --db tournoi_paris.db --type batch --dir ./matchs_open_paris/
./blunderdb list --db tournoi_paris.db --type stats

定期バックアップ

./blunderdb export --db production.db --type database --file sauvegarde-$(date +%Y%m%d).db

エラー分析

# Les positions délicates, puis celles de videau
./blunderdb search --db production.db --error-min 0.1 --export blunders.db
./blunderdb search --db production.db --decision cube --error-min 0.05 --export cube_errors.db

# Les coups réellement fautifs : au moins 100 millièmes d'équité perdus
./blunderdb search --db production.db --move-error-min 100 --format json

終了コード

  • 0 — 成功。

  • 1 — エラー。

これにより、エラー処理を含むスクリプトでCLIを使用できます:

if ./blunderdb import --db base.db --type match --file match.xg; then
    echo "OK"
else
    echo "KO"
    exit 1
fi