Claude Codeでテーブル定義書をtblsで作り、説明が空のカラムを補う
tbls docで定義書を生成し、tbls lintでコメントが空のカラムを洗い出します。説明案はClaude Codeに作らせ、COMMENT ONか.tbls.ymlのどちらかに戻して再生成します。
テーブル定義書は、tblsでデータベースから生成するのが手早い方法です。ただし、生成できるのは構造までです。カラムのコメントがデータベースに無ければ、説明の欄は空のまま出力されます。
その空欄を埋める作業はClaude Codeに向いています。tblsが「どのカラムが空か」を数え、Claude Codeが「コードでどう使われているか」を調べて説明案を作ります。この記事では、空のカラムの洗い出しから、説明の戻し先の選び方、再生成での確認までを通します。
tbls docで定義書を作り、空欄の量を測る
tblsは、データベースを解析してMarkdown形式のドキュメントを生成するCLIです。PostgreSQLのほか、MySQL、SQLite、BigQueryなどに対応しています。最短の使い方は、接続先を渡して tbls doc を実行するだけです。
brew install tbls
tbls doc postgres://dbuser:dbpass@localhost:5432/dbnameリポジトリで継続して使うなら、.tbls.yml に接続先と出力先を書きます。出力先の既定は dbdoc です。
# .tbls.yml
dsn: postgres://${DB_USER}:${DB_PASSWORD}@localhost:5432/dbname
docPath: doc/schemadsn に環境変数を展開する書き方は、設定値すべてで使えます。パスワードを直書きしないために、この形にしておきます。理由は後の節で触れます。
定義書ができたら、説明の整備状況を測ります。tbls coverage はテーブルごとに、説明とコメントがどれだけ埋まっているかを割合で出します。
tbls coverage出力は、全テーブルの割合の下に、public.users 20% のようにテーブル別の行が並ぶ形です。0%のテーブルから着手すれば、効果が一番見えやすくなります。
tbls lintで説明が空のカラムを一覧にする
どのカラムが空なのかを、Claude Codeに渡せる形で取り出します。使うのは tbls lint の requireColumnComment です。
# .tbls.yml(追記)
lint:
requireTableComment:
enabled: true
requireColumnComment:
enabled: true
exclude:
- id
- created_at
- updated_atrequireTableComment はテーブルの説明が空のものを、requireColumnComment はカラムの説明が空のものを検出します。tbls coverage が測る対象もテーブルとカラムの両方なので、lintの設定も両方に揃えておきます。requireColumnComment の exclude に挙げたカラムは警告の対象から外れます。主キーや作成日時のように、説明が自明なものを除いておくと、一覧に残るのは人が判断すべきカラムだけになります。
tbls lintコメントの無いカラムは、users.username: column comment required. のように「テーブル名.カラム名」の形で1行ずつ出ます。テーブルのカラム数に上限を設ける columnCount も同じ出力に混ざるので、カラムだけを拾うなら文言で絞ります。
tbls lint | grep 'column comment required' \
| sed 's/: column comment required\.//' > doc/missing_columns.txtdoc/missing_columns.txt が、Claude Codeへの入力になります。1行が1カラムなので、件数は wc -l で分かります。
テーブルの説明が空のものも、同じ tbls lint の出力に混ざります。テーブル単位の指摘は文言がカラムと違うため、まず tbls lint の素の出力でどう表示されるかを見てから、同じ要領で別ファイル(例: doc/missing_tables.txt)に抜き出します。カラムの説明案は、テーブルの役割が分かってから作るほうが根拠を探しやすいので、テーブルの説明を先に埋める順番が合います。コメントが空のカラムが数百件あるときは、テーブル単位に分けて渡したほうが、出力が混ざりません。
allOrNothingで着手の単位を決める
lintの設定には allOrNothing というオプションもあります。READMEの設定例では、requireTableComment に false、requireColumnComment に true が入っていて、コメントは「全部付いている」か「全部付いていない」かのどちらかに揃える、という意味のコメントが添えられています。
# .tbls.yml
lint:
requireColumnComment:
enabled: true
allOrNothing: truetrue にすると、一部のカラムにだけ説明がある状態が違反になります。テーブル単位で「書き始めたら全カラムを埋める」と決めたいときに合います。数百カラムを一度に埋める必要はなく、tbls coverage で選んだ1テーブルずつ、このオプションで取りこぼしを防ぎながら進められます。
Claude Codeに説明案を作らせる
先に、tbls lint と tbls coverage を毎回の承認なしで実行できるようにします。どちらもデータベースを読むだけで、書き換えません。権限ルールは、サブコマンドの後ろに * を置く形で書きます。
{
"permissions": {
"allow": [
"Bash(tbls lint *)",
"Bash(tbls coverage *)",
"Bash(tbls diff *)"
],
"deny": [
"Read(./.env)"
]
}
}末尾に空白付きの * を置いたルールは、引数なしの tbls lint にも一致します。tbls doc は接続してファイルを書き出すため、許可には入れず、承認を挟む設定です。Read(./.env) の拒否は、接続情報を含む環境変数ファイルを読ませないためです。
依頼は、入力ファイルと根拠の求め方を指定して出します。
doc/missing_columns.txt の users テーブルについて、
テーブル自体の説明案(1文)と、カラムの説明案を作ってください。
- src/ 以下でそのカラムが使われている箇所を検索し、
列挙定数・バリデーション・外部キーから意味が分かるものを
「確証」、名前と型からの推測を「推測」に分ける
- 手がかりがないカラムは説明を書かず、質問として返す
- 出力は doc/drafts/users_columns.md に、
カラムごとに根拠のファイルと行を添えて書く
- データベースには接続しない確証と推測を分けさせる理由は、定義書に載った説明は、すべて事実として読まれるからです。「税込か税抜か」のように、コードを読まないと分からない前提を推測のまま載せると、後から気づけません。区分の考え方とSkillへの固定のしかたは、Claude Codeでカラム定義書を作る手順に詳しく書いています。
出力の形は、例えば次のようになります(区分の考え方に沿った例示です。内容は対象のコードで変わります)。
| カラム | 区分 | 説明案 | 根拠 |
|---|---|---|---|
| users(テーブル) | 確証 | 会員アカウント。1行が1会員 | src/domain/user.ts のクラス定義 |
| users.status | 確証 | 0=仮登録、1=有効、2=退会 | src/domain/user.ts の UserStatus |
| users.phone_number | 推測 | [要確認] 連絡先電話番号 | 名前と型のみ |
| users.legacy_flag | 不明 | (質問)どの値が入るか | 参照するコードなし |Claude Codeの共通ワークフロー集には、ドキュメント整備を「未記載の箇所を探す、生成する、見直す、基準に合うか検証する」の4段で進める例があります。カラム説明も同じ流れで、洗い出しにあたるのがtbls lintです。毎回この依頼文を書く代わりにSkillへ固定する方法は、Claude Code Skillsの書き方にまとめています。
説明の戻し先は2か所ある
人が確証のある分を選んだら、説明をどこに書き戻すかを決めます。tblsの定義書は、データベース上のコメントを読んで作られます。そのため戻し先は、データベースか、.tbls.yml の2つです。
| 戻し先 | 書き方 | 向く場面 |
|---|---|---|
| データベースのコメント | 書き方COMMENT ON TABLE / COMMENT ON COLUMN をマイグレーションで適用 | 向く場面定義書以外(psqlなど)でも説明を見せたいとき |
.tbls.yml の comments: | 書き方tableComment にテーブルの説明、columnComments にカラムごとの説明を書く | 向く場面ALTER TABLEをせずに定義書だけ補いたいとき、ビューやSQLiteのカラム |
データベース側に入れる場合は、確証の分だけを COMMENT ON TABLE と COMMENT ON COLUMN にして、所有者のロールで流し込みます。文面の書式と適用手順は、先に挙げたカラム定義書の記事が詳細です。
.tbls.yml 側に入れる場合は、次の形です。
# .tbls.yml
comments:
- table: users
tableComment: "会員アカウント。1行が1会員"
columnComments:
status: "0=仮登録、1=有効、2=退会"
phone_number: "連絡先電話番号"ここで注意が要るのは、.tbls.yml のコメントがデータベース上の既存コメントを上書きする点です。tblsのドキュメントにも、その旨の注記があります。データベース側に人が書いた説明があるテーブルやカラムを、Claude Codeの下書きでうっかり tableComment や columnComments に入れると、エラーも警告も出さずに定義書の表示だけが置き換わります。lintが拾うのは空の説明だけですが、comments: は空でない説明にも効きます。書き戻す前に、既存のコメントと重なる行がないかを見ておきます。
comments: には、テーブルとカラム以外の戻し先もあります。インデックス用の indexComments、制約用の constraintComments、トリガー用の triggerComments、テーブルに付ける labels です。READMEの例では、posts_user_id_idx のインデックスに user.id index と書いています。requireColumnComment が検出するのはカラムだけなので、これらはlintの一覧には出ません。説明が欲しい制約やトリガーがあれば、依頼文に加えて別枠で下書きさせます。
落とし穴
定義書の説明とデータベースのコメントが食い違う
.tbls.yml の comments: に書いた説明は、定義書の出力でデータベースのコメントより優先されます。psqlで見える説明と定義書の説明が別物になり、どちらが正か分からなくなります。戻し先はカラムごとに1か所に決め、ビューやSQLiteのように COMMENT ON が使えないものだけを .tbls.yml に置くと、食い違いを避けられます。
再生成して、空欄が減ったことを確かめる
説明を戻したら、定義書を作り直します。既存のドキュメントを上書きするには --force、出力先を空にしてから作るには --rm-dist を付けます。--force は、削除したテーブルのファイルを消しません。テーブルを落とした後は --rm-dist のほうが確実です。
tbls doc --rm-dist
tbls coverage
tbls lint | grep -c 'column comment required'tbls coverage の割合が上がり、lintの件数が減っていれば、補完は反映されています。残ったカラムが、「不明」として返された質問の分です。担当者の回答が入ったところで、同じ手順をもう一周します。
CIで空欄の再発を止める
新しいカラムが説明なしで増えないよう、CIで tbls lint を回しておく方法もあります。tblsのドキュメントは、定義書をコミットし、スキーマを変えたら tbls diff と tbls lint をCIで確認する流れを示しています。
# .github/workflows/doc.yml
name: Document
on:
pull_request:
jobs:
lint:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: k1low/setup-tbls@v1
- run: tbls diff
- run: tbls linttbls diff は、データベースの現状とコミット済みの定義書のずれを検出します。定義書にER図を含める場合の描き分けは、Claude CodeでER図をMermaidで起こす記事が扱っています。
接続情報をClaude Codeに読ませない
tblsの接続先は dsn に書くので、パスワードを直書きした .tbls.yml をClaude Codeが読める状態にしておくと、秘密がそのまま会話に載ります。
dsnは環境変数の展開で書き、実値はシェルの環境かCIのシークレットに置く- 接続情報を置く
.envは、上で示したRead(./.env)の拒否ルールで読ませない - Claude Codeには
doc/以下の生成物とmissing_columns.txtだけを渡し、tbls docは人が実行する
DSNにパスワードの記号が含まれるときは、URLエンコードが必要です。# や < を含むパスワードは、そのままでは接続できません。
まとめ
tblsは、定義書の生成と、説明が空のカラムの検出までを自動で行います。説明の中身を考える部分だけが人の仕事で、そこをClaude Codeが下書きします。
分担の要点は、空欄の特定をtbls lintに任せ、説明案の根拠をコードから探させ、書き戻す場所をカラムごとに1つに決めることです。まずは tbls coverage で0%のテーブルを1つ選び、確証の分だけを戻して再生成すると、効果と手間を測れます。
参照した一次ソース
この記事の記述は、次の一次ソースと照合しています。更新時に参照先が変わった場合は一覧も更新します。