本文へスキップ

法令改正チェックを定期実行する:e-Gov法令API law_revisions の差分検知とClaude Code連携

e-Gov法令API v2の law_revisions を定期取得し、履歴IDと施行状態の変化を検知する70行のNode.jsスクリプトを実行確認。変化時だけ claude -p で要約し、タスクスケジューラやcronで回す設計を2026年9月14日の実測で整理します。

codeagent.jp編集部 更新 約6分

法令の改正を見逃さない仕組みは、本文の差分を取らなくても作れます。e-Gov法令API v2の law_revisions を1日1回取り、履歴IDの集合と施行状態を前回と比べれば、改正法の公布も施行日の到来も検知できます。 変化があった日だけ claude -p に差分を渡して要約させれば、毎日AIを呼ぶ必要もありません。

この記事では、70行のNode.jsスクリプトを実際に4パターンで実行し、Windowsタスクスケジューラとcronで回す設計、そしてClaude Codeのヘッドレス実行に渡すところまでを整理します。claude -p の呼び出し自体はこの記事では実行しておらず、Claude Code公式ドキュメントで確認した範囲で書いています。ヘッドレス実行の基本はclaude -p の記事にあります。

  1. 監視対象は law_revisions 本文(数百KB〜16MB)ではなく履歴の一覧(労働基準法で12KB)を比べます。
  2. 検知するのは3種類。 履歴IDの追加、current_revision_status の変化、updated の変化です。
  3. 終了コードで分岐する。 0=変化なし、2=変化あり、1=エラー。スケジューラ側はこれだけ見ます。
  4. AIは要約役。 差分JSONを claude -p に渡して日本語にする。施行日の判断は人が原文で確認します。

なぜ law_revisions を監視するのか

労働基準法(322AC0000000049)の law_revisions を2026年9月14日に取ると、15件の履歴のうち未施行が2件ありました。

  1. 2025-06-01
    令和四年法律第六十八号が施行
    322AC0000000049_20250601_504AC0000000068。現在は PreviousEnforced
  2. 2026-06-24
    令和八年法律第四十六号が公布・一部施行
    322AC0000000049_20260624_508AC0000000046。同じ改正法による 2028-12-23 施行予定の版も別の履歴として登録されている
  3. 2026-07-17
    令和八年法律第六十号が公布・施行
    322AC0000000049_20260717_508AC0000000060。現行版(CurrentEnforced)
  4. 2027-04-01
    令和八年法律第六十号の残りが施行予定
    322AC0000000049_20270401_508AC0000000060。UnEnforced
  5. 2028-12-23
    令和八年法律第四十六号の残りが施行予定
    322AC0000000049_20281223_508AC0000000046。UnEnforced。データ更新は 2026-07-23
law_revisions/322AC0000000049 の revisions より(2026-09-14 取得)。amendment_enforcement_date と updated を使用

ここで分かるのは、改正が「公布」と「施行」の2段階でデータに現れることです。公布されると新しい履歴IDが UnEnforced で追加され、施行日が来ると CurrentEnforced に変わります。本文を毎日ダウンロードして diff を取るより、この2つの変化を見る方が軽く、しかも「いつ効力を持つか」まで分かります。asof を使った時点指定の考え方はasof指定の記事と同じです。

law_revisions の履歴を比べる
本文を取って diff する
1法令あたりの転送量
労働基準法 12KB、会社法 25KB
労働基準法 420KB、所得税法 16MB
公布の検知
履歴IDの追加として現れる
未施行の本文は現行版に含まれず検知できない
施行の検知
UnEnforced → CurrentEnforced の変化
本文が変わった日として現れる(理由は分からない)
正誤などの更新
updated の変化
本文 diff に埋もれる
何が変わったかの中身
分からない(改正法令番号までは分かる)
条文単位で分かる
向いている役割
毎日の検知
検知後に人が確認する段階
2026-09-14 の実測サイズ。本文サイズはエラーと制限の記事を参照

スクリプト(70行、依存なし)

watch-revisions.mjs と、監視対象を書く watch.json の2ファイルです。状態は同じフォルダの state.json に保存し、変化があれば diff.json を書きます。

{
"law_ids": ["322AC0000000049", "331AC0000000120", "417AC0000000086"]
}
// e-Gov 法令API v2 の law_revisions を定期取得し、前回スナップショットとの差分を報告する
// 使い方: node watch-revisions.mjs (watch.json の law_ids を監視)
// 終了コード: 0 = 変化なし / 2 = 変化あり(diff.json を出力) / 1 = エラー
import { readFile, writeFile } from 'node:fs/promises';
const BASE = 'https://laws.e-gov.go.jp/api/2';
const CONFIG = new URL('./watch.json', import.meta.url);
const STATE = new URL('./state.json', import.meta.url);
const DIFF = new URL('./diff.json', import.meta.url);
const config = JSON.parse(await readFile(CONFIG, 'utf8'));
let state = {};
try { state = JSON.parse(await readFile(STATE, 'utf8')); } catch { /* 初回 */ }
const changes = [];
const errors = [];
const next = {};
for (const lawId of config.law_ids) {
const res = await fetch(`${BASE}/law_revisions/${lawId}`, {
headers: { Accept: 'application/json' },
signal: AbortSignal.timeout(30_000),
});
if (!res.ok) {
// 存在しない ID は 404 {"code":"404001"} で返る。前回の状態を保持して次へ
errors.push({ law_id: lawId, status: res.status, body: (await res.text()).slice(0, 120) });
if (state[lawId]) next[lawId] = state[lawId];
continue;
}
const data = await res.json();
// 比較に使う項目だけ残す(本文は取らない)
const revisions = data.revisions.map((r) => ({
law_revision_id: r.law_revision_id,
law_title: r.law_title,
amendment_enforcement_date: r.amendment_enforcement_date,
amendment_law_num: r.amendment_law_num,
current_revision_status: r.current_revision_status,
updated: r.updated,
}));
next[lawId] = { law_num: data.law_info.law_num, revisions };
const prev = state[lawId];
if (!prev) { changes.push({ law_id: lawId, kind: 'initial', title: revisions[0]?.law_title, count: revisions.length }); continue; }
const prevById = new Map(prev.revisions.map((r) => [r.law_revision_id, r]));
for (const r of revisions) {
const p = prevById.get(r.law_revision_id);
if (!p) { changes.push({ law_id: lawId, kind: 'new_revision', ...r }); continue; }
if (p.current_revision_status !== r.current_revision_status)
changes.push({ law_id: lawId, kind: 'status_changed', law_revision_id: r.law_revision_id, from: p.current_revision_status, to: r.current_revision_status, title: r.law_title });
else if (p.updated !== r.updated)
changes.push({ law_id: lawId, kind: 'updated', law_revision_id: r.law_revision_id, from: p.updated, to: r.updated, title: r.law_title });
}
for (const p of prev.revisions) if (!revisions.some((r) => r.law_revision_id === p.law_revision_id))
changes.push({ law_id: lawId, kind: 'removed', law_revision_id: p.law_revision_id });
}
await writeFile(STATE, JSON.stringify(next, null, 2), 'utf8');
const checkedAt = new Date().toISOString();
const real = changes.filter((c) => c.kind !== 'initial');
for (const e of errors) console.error(`[error] ${e.law_id} HTTP ${e.status} ${e.body}`);
if (changes.length === 0) {
console.log(`${checkedAt} 変化なし (${config.law_ids.length - errors.length} 法令)`);
} else {
await writeFile(DIFF, JSON.stringify({ checked_at: checkedAt, changes }, null, 2), 'utf8');
for (const c of changes) console.log(`[${c.kind}] ${c.law_id} ${c.law_revision_id ?? ''} ${c.title ?? ''} ${c.from ? `${c.from} -> ${c.to}` : ''}`.trim());
}
process.exitCode = errors.length > 0 ? 1 : real.length > 0 ? 2 : 0;

比較に使う項目だけを state.json に残すのがポイントです。本文を保存しないので、3法令(労働基準法15履歴・旧下請法3履歴・会社法32履歴)でも状態ファイルは小さく、git管理しても差分が読めます。

実行結果:4パターン

Node.js 24.8.0で、初回、変化なし、変化あり(state.json を手で書き換えて再現)、存在しないIDの4パターンを流しました。

### 初回(state.json なし)
[initial] 322AC0000000049 労働基準法
[initial] 331AC0000000120 製造委託等に係る中小受託事業者に対する代金の支払の遅延等の防止に関する法律
[initial] 417AC0000000086 会社法
exit=0
### 2回目(変化なし)
2026-09-14T04:37:09.167Z 変化なし (3 法令)
exit=0
### state.json から最新履歴を1件消して再実行(改正公布を模擬)
[new_revision] 322AC0000000049 322AC0000000049_20281223_508AC0000000046
exit=2
### 存在しないIDを watch.json に混ぜる
[error] 999AC9999999999 HTTP 404 {"code":"404001","message":"取得結果が0件です。"}
2026-09-14T04:37:10.961Z 変化なし (1 法令)
exit=1

初回は全法令が initial として出ますが、これは「変化」ではないので終了コードは0です。変化ありのときに書かれた diff.json はこの形でした。

{
"checked_at": "2026-09-14T04:37:09.943Z",
"changes": [
{
"law_id": "322AC0000000049",
"kind": "new_revision",
"law_revision_id": "322AC0000000049_20281223_508AC0000000046",
"law_title": "労働基準法",
"amendment_enforcement_date": "2028-12-23",
"amendment_law_num": "令和八年法律第四十六号",
"current_revision_status": "UnEnforced",
"updated": "2026-07-23T15:54:56+09:00"
}
]
}

改正法令番号と施行予定日が入っているので、この時点で「令和八年法律第四十六号による改正が2028年12月23日に施行される」まで機械的に分かります。存在しないIDは404(コード404001)を記録して他の法令の処理を続け、終了コードを1にします。監視対象の書き間違いに翌朝気づける仕組みです。エラーコードの意味はエラーと制限の記事にまとめています。

変化があった日だけ claude -p に渡す

スクリプトの終了コードが2のときだけClaude Codeを呼ぶラッパーです。claude -p はstdinを読めるので、diff.json をそのまま流し込みます。

#!/usr/bin/env bash
# run-watch.sh : 差分検知 → 変化があれば claude -p で要約
cd "$(dirname "$0")"
node watch-revisions.mjs >> watch.log 2>&1
code=$?
if [ "$code" -eq 2 ]; then
claude --bare -p "以下は e-Gov 法令API の law_revisions の差分(JSON)です。法令ごとに、何が起きたか(新しい版の追加 / 施行状態の変化 / 更新日時のみ)と施行日を日本語で3行以内に要約してください。差分に含まれない情報は書かないでください。" \
--output-format json < diff.json > summary.json
jq -r '.result' summary.json >> watch.log
fi
exit "$code"

公式ドキュメントで確認したフラグの意味は次のとおりです。

  • -p:非対話で1回だけ実行し、結果を標準出力に出す。stdinから入力を読める(上限10MB)
  • --bare:フック・スキル・MCP・CLAUDE.md などの自動読み込みを省いて起動する。スクリプト用に推奨されているが、ANTHROPIC_API_KEY が必要でサブスクリプションのログインは使われない
  • --output-format json:結果を result フィールドに持つJSONで返す。total_cost_usd も含まれる
  • 終了コード:成功で0、失敗で非0

要約させる内容は「差分に含まれる事実」に限定し、--json-schemastructured_output を強制すればさらに機械的に扱えます。改正の中身(どの条がどう変わったか)を書かせるなら、diff.json だけでは足りないので law_data で新旧の本文を取って渡す段階を挟みます。そこは検知とは別のジョブに分けた方が、毎日の処理が軽いままです。

通知先はチーム次第です。watch.log への追記だけでも成り立ちますし、summary.jsonresultcurl -X POST でチャットのWebhookに送るのも1行で済みます。

スケジューラで回す

Windowsは schtasks、Linux/macOSはcronで、1日1回で十分です。e-Govのデータ更新は日単位で、updated も日時までしか入っていません。

Terminal window
# Windows: 毎日 7:00 に実行(/SC DAILY /ST 開始時刻 /TN タスク名 /TR 実行コマンド)
schtasks /Create /SC DAILY /ST 07:00 /TN "egov-law-watch" ^
/TR "cmd /c cd /d C:\egov-watch && node watch-revisions.mjs >> watch.log 2>&1"
# Linux / macOS: crontab -e
0 7 * * * cd /opt/egov-watch && bash run-watch.sh

schtasks /Create/SC /ST /TN /TRschtasks /Create /? のヘルプで確認した構文です。実際のタスク登録はこの記事では行っていません。運用で決めておくことを3つ挙げます。

  1. state.json はスクリプトと同じフォルダに置く。 import.meta.url 基準で解決しているので、スケジューラの作業ディレクトリに依存しません。
  2. 終了コード1(エラー)を放置しない。 404が続くならIDの書き間違い、タイムアウトが続くならネットワークです。ログの [error] 行を週1回は見ます。
  3. 新法は別の入口で拾う。 law_revisions は既知のIDが前提なので、新しく制定された法令は laws?promulgation_date_from=YYYY-MM-DD&law_type=Act で取ります。2026-06-01以降では8件(508AC0000000040 など)が返りました。

人が確認する線

検知と要約まで自動化しても、「この改正がうちの契約に効くか」は自動化しません。diff.json にある law_revision_idamendment_enforcement_date を持って、e-Gov法令検索の原文で新旧を読む段階は人の作業として残します。AIに任せる範囲と人が確認する範囲の線引きは法令をAIで扱うときの安全境界にまとめたチェックリストと同じで、履歴IDを出力に残すのはそのためです。

まとめ

  • 監視対象は本文ではなく law_revisions。履歴IDの追加(公布)と current_revision_status の変化(施行)で改正の2段階を検知できる
  • 70行のスクリプトで、初回0・変化なし0・変化あり2・エラー1の終了コードを確認。変化時は diff.json に改正法令番号と施行予定日が入る
  • claude -p は終了コード2のときだけ呼ぶ。--bare--output-format json で要約をJSONに固定する(呼び出しは公式ドキュメントで確認、未実行)
  • Windowsは schtasks /SC DAILY、cronは 0 7 * * *。新法は laws?promulgation_date_from で別途拾う

Claude Codeに条文の内容まで調べさせる構成はe-Gov法令API活用ガイド、MCP経由で条文を引く手順はClaude Codeでの設定と使い方から辿れます。

関連して読む

この記事の情報・検証メモ
Tags
公開日
情報確認
参考リンク
3件
更新性
定期更新
更新管理

仕様・料金・提供範囲が変わりやすいテーマは、公開日・更新日・情報確認日を分けて管理します。 導入前には必ず記事末尾の一次情報と公式ドキュメントで最新状況を確認してください。

検証メモ
Node.js 24.8.0 で watch-revisions.mjs を実行(初回・変化なし・変化あり・存在しないID の4パターン) e-Gov法令API v2 / OpenAPI 2.1.139、実行日 2026-09-14 schtasks /Create /? の構文確認(Windows 11)
図解を保存・共有

記事の要点を1枚にまとめました。画像は新しいタブで開いて保存できます。

法令改正チェックを定期実行する:e-Gov法令API law_revisions の差分検知とClaude Code連携 本文ではなく law_revisions の履歴IDを監視し、変化があった日だけ claude -p に要約させる 何を監視するか:law_revisions の履歴IDの集合(新しい版の追加)。current_revision_status の変化(未施行→現施行)。updated の変化(正誤などの更新)。 スクリプトの振る舞い:終了コード 0=変化なし / 2=変化あり / 1=エラー。変化があれば diff.json を書く。存在しないIDは 404 を記録して他の法令を続行。 回し方:Windows は schtasks、Linux/macOS は cron で1日1回。終了コード2のときだけ claude -p に diff.json を渡す。AIは要約まで。施行日の判断は人が原文で確認。
法令改正チェックを定期実行する:e-Gov法令API law_revisions の差分検知とClaude Code連携 記事の要約 2026.09.14 設計・ワークフロー
Primary sources

一次情報・参考リンク

About the author
codeagent.jp編集部

Claude Code / Codex / MCP を個人開発サイト運用と公開MCPサーバー開発で試し、一次情報・検証ログ・失敗例をもとに整理します。