はじめに
AI にバッチ(.bat)や PowerShell を書かせると、「動くけど危ない」コードが平気で出てきます。
- ルートフォルダを対象にした
del - プレビューなしの
robocopy /MIR(宛先のファイルを消す) - 文字コードを UTF-8 決め打ちで、SJIS 環境で文字化け
-
WHEREの無いUPDATE
オンプレミス/閉域網(エアギャップ)環境では、こうした事故がそのまま本番の障害になります。実際に「入力リストの改行コード(LF)を誤認識して、バッチ設置フォルダの直下を全削除した」という事故も起きています。
そこで、AI に安全なバッチしか作らせないためのガードレールを Claude Skill として実装しました。この記事では、その設計思想と中身を紹介します。
LLM は構文を知っている。現場エンジニアは現実を知っている。
Execute first ではなく Preview first。One-click ではなく Safe automation。
Claude Skill とは
Claude Skill は、SKILL.md(指示書)と関連ファイル(テンプレート等)をまとめたフォルダを配置するだけで、Claude に特定ドメインの振る舞いを追加できる仕組みです。
onprem-batch/
├── SKILL.md # スキル本体(ワークフロー・安全設計・禁止事項)
├── references/
│ └── checklist.md # 実行前セルフレビュー用チェックリスト
└── assets/
├── safe-copy.bat # コピー系テンプレート
├── safe-delete.bat # 削除系テンプレート
├── safe-sql.bat # SQL 実行テンプレート
└── safe-worker.ps1 # 日本語パス対応のランチャ + PS1 構成
「オンプレのバッチを作って」と依頼すると、このスキルが起動し、Claude は安全設計を必ず組み込んだバッチを生成します。
このスキルが強制する「安全設計」
生成されるすべてのバッチに、以下を必ず組み込みます。
| # | 設計要件 | 内容 |
|---|---|---|
| 1 | Dry-run 既定 | 引数なしはプレビューのみ。--execute 明示時だけ実行 |
| 2 | プレビュー出力 | MODE / ユーザー / ホスト / Source / Destination / 対象件数 / 予定コマンドを表示 |
| 3 | パスガード | 空・ルート・同一 Source/Destination・ワイルドカードのみ・設置場所と同一/直下を拒否 |
| 4 | 存在チェック | Source/Destination・入力ファイルの存在を実行前に確認 |
| 5 | 危険操作の二重確認 |
YES 入力など明示確認を要求 |
| 6 | ログ | 日時・ユーザー・ホスト・mode・対象・結果・エラーを記録 |
| 7 | バックアップ | 上書き・削除・DB 変更の前に日時付きで退避 |
| 8 | ロールバック | 戻し方を同じ文書/コメントに記載 |
| 9 | 外部入力ファイルのSJIS確認 |
filelist.txt 等を読む場合、実行時に改行コード・BOM・文字コードを確認し、SJIS 想定に合わなければ中止 |
さらに、過去の事故を踏まえてプレビューに必ず出す2項目があります。
- ① 改行コード:処理対象/スクリプト自身の CRLF / LF を検出・表示
-
② バッチ設置場所:
%~dp0(設置場所のフルパス)を表示し、設置場所と同一/直下は操作させない
なぜ「改行コード」と「設置場所」なのか
これは実際に起きた事故が背景です。
- 入力リストが LF 改行だったため、CRLF 前提の処理が行の区切りを誤認
- 削除対象をバッチ設置場所からの相対パスで組み立てていた
- 設置場所自体をガードしていなかった
結果、バッチを置いたフォルダの直下すべてを削除する事故が発生しました。
再発防止として、生成物には必ず次を入れます。
- 改行コードを検出・正規化してから処理する(LF を CRLF 前提の処理に流さない)
- 対象は必ず絶対パスで確定する
-
%~dp0を表示し、設置場所と同一/その直下は拒否する
実際の生成物(抜粋)
dry-run が既定
引数なしで実行すると、何も変更せずプレビューだけを出します。
set "MODE=DRYRUN"
if /I "%~1"=="--execute" set "MODE=EXECUTE"
実行イメージ(架空データ):
============================================================
Safe Copy Preview
============================================================
MODE = DRYRUN
COMPUTER = SAMPLE-HOST
USER = sampleuser
SOURCE_DIR = C:\work\PROD_source
DEST_DIR = C:\work\TEST_dest
LOG_FILE = C:\work\logs\safe-copy_20260728_103000.log
============================================================
[PREVIEW] Files to copy:
New File 1234 data_001.csv
New File 5678 data_002.csv
[DRY-RUN] No files were copied. To execute: safe-copy.bat --execute
設置場所ガード
削除テンプレートは、設置場所と同一/直下を対象にできません。
REM Reject when TARGET_DIR is the script dir or a subfolder of it.
if /I not "%TARGET_DIR:%SCRIPT_DIR%=%"=="%TARGET_DIR%" (
echo [ERROR] TARGET_DIR must not be inside the batch's own folder: "%SCRIPT_DIR%"
exit /b 1
)
外部入力ファイルの SJIS 確認
filelist.txt を読む場合、実行時に改行コード・BOM・文字コードを確認し、SJIS(cp932) 想定に合わなければ処理を中止します。PowerShell 補助では文字コードを決め打ちしません。
$enc = [Text.Encoding]::GetEncoding(932) # cp932 を明示(Default/UTF-8決め打ちに依存しない)
文字コード・改行の事故防止
日本の Legacy 環境で最も多い二次被害です。スクリプト自身の保存文字コードにも注意します。
-
.batに日本語リテラルを含むなら cp932(Shift_JIS) で保存し、先頭でchcp 932を明示 -
.ps1に日本語を含むなら UTF-8(BOM 付き) で保存(BOM 無しは cp932 と誤読される) - 推奨構成:入口
.batは ASCII のみのランチャにし、日本語を扱う実処理を UTF-8(BOM) の.ps1に委譲
禁止事項
生成物に含めてはならないもの:
- 外部入力の文字列を切り出してそのまま実行する(eval 的実行)
- プレビューなしの削除、ワイルドカードのみ/ルート対象の操作
-
robocopy /MIRを警告なしで使う - 文字コードを UTF-8 決め打ちし、CRLF/LF の差異を無視する
- SQL を接続先・実行内容の確認なしに本番へ流す
「自動化しない」判断も正しい
年一回のみ/仕様不明/失敗時の影響大/検証環境なし/ロールバック不可/ツール導入不可 ——
こうした場合は、自動化しない判断も正しいとしています。ただしその場合もチェックリスト・作業前確認・ログは残します。
まとめ
- AI は構文を知っていても、**現場の落とし穴(文字コード・改行・相対パス)**は考慮してくれない
- Claude Skill に安全設計をルール化することで、誰でも・短時間で・規定どおりのバッチを作れる
- 目指すのは「速く作る」より 事故を減らす・追跡できる・元に戻せる
オフライン環境にも配置でき(ZIP 配布可)、サーバ不要で導入できます。
リポジトリ
MIT ライセンスで公開しています。
- GitHub:
https://github.com/huangmenjimifan1013/onprem-batch-skill
SKILL.md とテンプレート一式が入っているので、.claude/skills/onprem-batch に配置すればすぐ使えます。