Claude Media
Claude CodeでVB6のコードを読み仕様書に起こす — イベント表と業務ルール表にする

Claude CodeでVB6のコードを読み仕様書に起こす — イベント表と業務ルール表にする

VB6の.frm・.bas・.clsをClaude Codeに読ませ、イベント→処理→参照テーブルの表と業務ルール表に起こす手順。読み取り専用のサブエージェントをフォーム単位で回し、文字コードと抜け漏れの検算までまとめます。

VB6の古いコードから仕様書を起こすなら、成果物を「イベント表」と「業務ルール表」の2枚に分けると読み取りが安定します。イベント表は、どのコントロールのどのイベントで、どの処理が走り、どのテーブルを触るかを1行ずつ並べたものです。業務ルール表は、コードに埋まった条件分岐や計算式を、日本語の規則として一覧にしたものです。

Claude Codeには、この2枚を作る読み取りだけを任せます。ソースを書き換える権限は渡しません。この記事では、読み取り専用のサブエージェントの定義、フォーム単位の分担、文字コードの落とし穴、表の抜けを数で検算する方法を順に示します。

仕様書を「イベント表」と「業務ルール表」に分ける理由

VB6のプログラムは、画面(.frm)のイベントプロシージャに処理が散らばっています。共通処理は標準モジュール(.bas)やクラス(.cls)にあります。上から順に読んで文章にまとめると、どの操作がどの処理につながるのかが追えなくなります。

そこで、読み方の軸を2つ決めます。

表1行の単位主な列
イベント表1行の単位1つのイベントプロシージャ主な列画面・コントロール・イベント・呼ぶ処理・参照するテーブル
業務ルール表1行の単位1つの判定や計算主な列ルール文・条件・メッセージ・根拠の位置

イベント表は機械的に作れるので抜けを数で検算できます。業務ルール表は解釈が入るので、根拠となるファイルと行を必ず添えさせます。人が確認するのは、この根拠の行です。

読む前に済ませる準備 — 文字コードと作業コピー

日本語環境で作られたVB6のソースは、Shift_JIS(CP932)で保存されていることがあります。Claude Codeのツールの扱いを知っておくと、準備の理由が分かります。

Readは、読めないバイト列を置換文字(U+FFFD)にして見せます。EditとNotebookEditは、UTF-8でないファイルの変更を拒否します。Shift-JISで保存された日本語を含むファイルがこれに当たります。WriteでShift-JISのファイルを置き換えると、新しい内容はUTF-8で保存され、元の文字コードは失われます。

読むだけの作業でも、原本を直接渡す理由はありません。原本とは別のディレクトリにUTF-8へ変換したコピーを作り、読ませるのはそちらだけにします。

mkdir -p spec-src
for f in src/*.frm src/*.bas src/*.cls; do
  iconv -f CP932 -t UTF-8 "$f" > "spec-src/$(basename "$f")"
done
grep -c $'\xef\xbf\xbd' spec-src/* | grep -v ':0'

最後の行は、変換後のファイルに置換文字が残っていないかの確認です。何も出なければ変換できています。CP932で表せない文字が混じっていると、iconvがエラーを返します。

フォームの見た目を持つ.frxはバイナリなので、読ませる対象に入れません。画面の項目名はテキストの.frm側にも書かれています。

読み取りだけのサブエージェントを定義する

サブエージェントは .claude/agents/ にMarkdownで置きます。必須の項目は name と description で、tools を書けば使えるツールを絞れます。

---
name: vb6-form-reader
description: VB6のフォーム1つを読み、イベント表と業務ルール表を返す。ソースは変更しない
tools: Read, Grep, Glob
permissionMode: plan
---
 
あなたはVB6の読解担当です。渡された.frmを1つ読み、次の2つの表を返します。
 
1. イベント表: 画面 | コントロール | イベント | 呼ぶ処理 | 参照テーブル
2. 業務ルール表: ルール文 | 条件 | メッセージ | 根拠(ファイル:行)
 
- 呼び先がmodule(.bas)やclass(.cls)にあるときは、そこも読んで追う
- SQL文字列からテーブル名を拾う。組み立て式で分からないときは「要確認」と書く
- コードに書かれていない目的や背景を推測で書かない
- ファイルは書き換えない。表をそのまま返す

権限の掛け方は二重にしています。tools でRead・Grep・Globだけを許可すれば、書き込み系のツールはそもそも使えません。そのうえで permissionMode: plan を指定し、読み取り専用の探索モードに入れます。

permissionMode には注意点があります。メインの会話が bypassPermissions、acceptEdits、auto modeのいずれかで動いているときは、サブエージェントも同じモードで動き、指定は無視されます。メインがplan modeなら、サブエージェントも指定にかかわらずplan modeのままです。メインが通常のモードのときだけ、指定した値が効きます。

つまり、permissionMode: plan だけを頼りにすると、メインの設定次第で効かなくなります。読み取り専用の担保は tools の許可リストに置くのが確実です。

Bashを許可リストに入れていない点も意図しています。grepやwcが必要になったときは、メイン側で実行します。

組み込みのExploreやPlanではなく自作する理由

Exploreは読み取り専用の探索役で、WriteとEditが拒否されます。Planもplan mode中の調査役として同じく読み取り専用です。ただし、この2つはCLAUDE.mdを読み込まずに始まります。

自作のサブエージェントは、omitClaudeMd を指定しない限りCLAUDE.mdを読み込んで始まります。表の列名や「要確認」の書き方といった書式の決まりを、CLAUDE.mdに一度書いておけば、全フォームの読み手に同じ書式が届きます。

## VB6仕様書の書式
 
- 表はMarkdown。列名は固定: イベント表=画面|コントロール|イベント|呼ぶ処理|参照テーブル
- 根拠は「ファイル名:行番号」で書く
- テーブル名が動的に組み立てられているときは「要確認(動的SQL)」と書く
- 推測で補った記述には「推測」と付ける

最初にプロジェクトファイルで読む範囲を決める

フォームに入る前に、メインの会話でプロジェクトファイル(.vbp)を読ませます。一覧に出てくるフォーム、モジュール、クラスの数が、後で検算する母数になるからです。起動時に最初に開くフォームも.vbpに書かれているので、仕様書の「画面遷移の入口」として先頭に置けます。

spec-src/の.vbpを読み、フォーム・標準モジュール・クラスの一覧と、
起動時に最初に開くフォームを表にしてください。ソースの読解はまだしないでください

この一覧を docs/spec/00-index.md として保存しておけば、フォームごとの表が揃ったときに、一覧との差で未着手のファイルが分かります。グローバル変数を多用した作りでは、標準モジュールの Public 変数が画面をまたいだ状態になります。これは1つのフォームを読むだけでは見えません。標準モジュールを専任で読む担当を別に1回走らせ、変数名と使われている画面の対応を、フォームの表とは別の表にしておくと後で効きます。

フォーム単位で分担して表を集める

サブエージェントは、メインの会話とは別のコンテキストで動きます。大きなソースをフォームごとに読ませても、読んだ全文はメインに残らず、返ってくるのは表だけです。

依頼は、フォーム名を列挙して並列に調べさせる形が基本です。

vb6-form-readerサブエージェントを使い、spec-src/にある次のフォームを
並列で読んでください。各フォームの結果は、イベント表と業務ルール表を
そのまま返してください: frmOrder, frmCustomer, frmInvoice

並列に回すときの条件は2つあります。調査の経路が互いに独立していること、そして結果が返るたびにメインの会話の文脈を消費することです。詳細な表を返すサブエージェントを大量に走らせると、メインの文脈が先に埋まります。

同時に走らせられるサブエージェントは、既定で20個までです。フォームが数十ある画面群でも、1回の依頼に入れるのは数個から十数個に留め、終わったものから次を依頼するほうが扱いやすくなります。

読み取り専用に絞ったので、サブエージェントは仕様書のファイルを書けません。表を docs/spec/frmOrder.md のように保存するのは、メインの会話の役目です。

返ってきた表の抜けを数で検算する

イベント表は、行数をソースの数と突き合わせれば検算できます。VB6のイベントプロシージャは Private Sub コントロール名_イベント名( の形で宣言されます。

grep -c -E '^(Private|Public) Sub ' spec-src/frmOrder.frm
grep -c '^|' docs/spec/frmOrder.md

1行目は宣言の数、2行目は表の行の数です。表には見出し行と区切り行があるので、イベント表だけを別ファイルに保存してから比べます。共通処理の Sub はイベントではないため、数が一致しなくても不具合とは限りません。差が出たときは、メインの会話にその差分を渡して、どの宣言が表に載っていないかを探させます。

業務ルール表は数で検算できません。確認の対象は根拠の行です。

  1. 表の中から数行を選ぶ
  2. 根拠の ファイル:行 を開く
  3. そのルール文が、その行の条件と一致しているかを見る

ルール文に、コードに無い目的や理由が混じっていれば、サブエージェントの出力に「推測」の印が付いているはずです。付いていなければ、指示が守られていません。

出力の形の例

次は、架空の受注入力フォームから起こす例です。フォームの宣言は、実際のVB6の.frmの形式に沿っています。

Private Sub cmdRegister_Click()
    If Val(txtQty.Text) <= 0 Then
        MsgBox "数量を入力してください"
        Exit Sub
    End If
    If CalcCredit(cboCustomer.ItemData(cboCustomer.ListIndex)) > 1000000 Then
        MsgBox "与信限度額を超えています"
        Exit Sub
    End If
    SaveOrder
End Sub

この宣言から、次のような表が得られるのが期待する形です。サブエージェントの実際の出力ではなく、書式の見本です。

画面コントロールイベント呼ぶ処理参照テーブル
frmOrderコントロールcmdRegisterイベントClick呼ぶ処理CalcCredit, SaveOrder参照テーブル要確認(modCredit.bas内のSQL)
ルール文条件メッセージ根拠
数量は1以上で登録する条件Val(txtQty.Text) <= 0メッセージ数量を入力してください根拠frmOrder.frm:48
与信限度額を超える受注は登録できない条件与信額が1,000,000を超えるメッセージ与信限度額を超えています根拠frmOrder.frm:52

参照テーブルが「要確認」になっているのは、CalcCredit の先が別ファイルにあるためです。呼び先を追わせる指示を入れておくと、modCredit.basまで読んで埋まります。

落とし穴

表が整って見えても、根拠の行がずれている

行番号は、読ませた変換後のコピーのものです。原本と変換後で行数は変わりませんが、原本を別の編集で書き換えると番号が合わなくなります。仕様書に載せる根拠は、確定させた作業コピーの時点のものに固定します。

つまずきやすい点

  • コピーでなく原本を渡してしまう: 原本の文字コードを壊すおそれがあります。読ませるのは spec-src/ だけにします
  • 動的SQLのテーブル名を推測で埋める: "SELECT * FROM " & tbl のような組み立て式は、実行時の値でしか決まりません。「要確認」のまま残し、人が実行ログやDB側で確かめます
  • 1回の依頼にフォームを詰め込みすぎる: 返ってくる表の量でメインの文脈が埋まります。数個ずつに分けます
  • 業務ルールに目的を書き足される: 「顧客満足のため」のような背景は、コードから読めません。指示に「推測と付ける」を入れて、付いていない行は疑います

まとめ

VB6の読解では、サブエージェントに任せる範囲を「読んで表を返す」までに絞り、保存と判断はメインの会話と人が受け持つと、権限も文脈も扱いやすくなります。読み取り専用の担保は tools の許可リストに置き、イベント表は宣言の数との突き合わせで検算し、業務ルール表は根拠の行を人が開いて確かめる。この3点で、仕様書の信頼度をコードから直接たどれる形で保てます。

COBOLのような別の言語で同じ読解をする場合は、Claude CodeでCOBOLを移す手順のように、元の出力を固定してから突き合わせる検証ループが仕上げに入ります。サブエージェントを読み取り専用に絞る設定の一般形は、サブエージェントをhookで読み取り専用のDB分析役にする記事にもあります。仕様書を読み終えたあとの移行の進め方は、Claude Codeでレガシー移行を進める考え方を参照してください。

参照した一次ソース

この記事の記述は、次の一次ソースと照合しています。更新時に参照先が変わった場合は一覧も更新します。

  1. code.claude.com/docs/en/sub-agents
  2. code.claude.com/docs/en/tools-reference
この記事を共有:XはてブLinkedIn