Claude CodeでAutoHotkey v2のスクリプトを書く — v1構文を混ぜない手順
AutoHotkeyのスクリプトをClaude Codeに書かせるとき、v1の書き方が混ざると動きません。CLAUDE.mdでv2に固定し、/Validateの終了コードを検証に使う手順を示します。
AutoHotkeyのスクリプトをClaude Codeに書かせるときの最大の落とし穴は、v1とv2が同じ.ahk拡張子を使うことです。v1の書き方が一行混ざるだけで、v2では読み込みの段階で止まります。
対策は3つです。CLAUDE.mdでv2に固定する。ファイルの先頭に#Requiresを置く。/Validateスイッチの終了コードを完了条件にする。この記事では、この3つをつなぐ書き方と、検証が拾えない範囲まで順に示します。
v2で何が変わったのか: 混ざると止まる理由
v2では、v1までの「コマンド構文」が丸ごとなくなりました。変更点一覧には、リテラル代入var = valueの削除、旧式のIf文の削除、コマンド構文そのものの削除が並んでいます。
つまり、v1らしい行はv2の文法として成立しません。「少し古い書き方」ではなく、構文エラーになります。Claudeに書かせたコードで特に注意したい対応を表にします。
| v1の書き方 | v2での書き方 | 根拠になる変更 |
|---|---|---|
x = 5 | v2での書き方x := 5 | 根拠になる変更リテラル代入の削除 |
MsgBox, Hello | v2での書き方MsgBox "Hello" | 根拠になる変更コマンド構文の廃止。引数はすべて式 |
Text %var% | v2での書き方連結かFormat() | 根拠になる変更変数参照を%で囲まない |
StringReplace | v2での書き方StrReplace | 根拠になる変更旧コマンドの削除 |
ErrorLevelを調べる | v2での書き方try / catch | 根拠になる変更失敗は例外で通知される |
#If | v2での書き方#HotIf | 根拠になる変更ディレクティブの改名 |
a <> b | v2での書き方a != b | 根拠になる変更<>の削除 |
複数行ホットキーのreturn | v2での書き方{ }で本体を囲む | 根拠になる変更ホットキーが関数になった |
ホットキーの書き換えは見落としやすい箇所です。v2ではホットキーが自動的に関数を定義するため、複数行にするなら波括弧で囲みます。returnで終える旧来の形は使えません。
; v2: 複数行のホットキーは波括弧で囲む
#Requires AutoHotkey v2.0
^!n:: {
Run "notepad.exe"
ToolTip "メモ帳を起動しました"
SetTimer () => ToolTip(), -1500
}CLAUDE.mdでv2に固定する
.ahkというファイル名からは、v1かv2かが分かりません。プロジェクトのCLAUDE.mdに、バージョンと禁止事項を書いて固定します。CLAUDE.mdは毎セッションの冒頭で読み込まれる指示書で、Claude Codeのドキュメントは1ファイル200行未満を目安にしています。AutoHotkey用の規約は十数行で足ります。
## AutoHotkey の規約
- すべて AutoHotkey v2 で書く。v1 構文は使わない
- 各ファイルの1行目は `#Requires AutoHotkey v2.0`
- 2行目に `#Warn All, StdOut` を置く
- 代入は `:=`。`=` での代入は使わない
- コマンド構文(`MsgBox, text` など)は使わない。関数形式で書く
- 変数を `%var%` で囲まない。連結か Format() を使う
- ホットキーが複数行なら `{ }` で囲む。`return` で終えない
- 失敗は ErrorLevel でなく try / catch で処理する
- 日本語を含むファイルは UTF-8 の BOM 付きで保存する
- 編集のたびに、下記の検証コマンドを自分で実行して終了コード 0 を確かめる規約を書くときのコツは、「v2で書く」だけで済ませず、混ざりやすい具体の書き方を禁止リストにすることです。禁止の理由まで添えると、Claudeが別の場面で同じ誤りを避けやすくなります。
CLAUDE.md全体の書き方は、CLAUDE.mdの書き方パターン集にまとめています。
1行目の#Requiresは構文エラーのメッセージを変える
#Requires AutoHotkey v2.0はバージョン要件を宣言するディレクティブです。v1のスクリプトには#Requires AutoHotkey v1、v2のスクリプトには#Requires AutoHotkey v2を付けるよう、ディレクティブの説明が勧めています。
効果は2つあります。1つ目は、ランチャーの判定です。AutoHotkey v2のインストーラーが入れるランチャーは、.ahkの中身から実行すべきバージョンを選びます。#Requiresがあれば、その要件を満たす実行ファイルを探します。無ければ構文のパターンから推測しますが、この検出は控えめで、曖昧なら無視されます。曖昧さを消す方法として挙げられているのが、メインファイルの先頭の#Requiresです。
2つ目は、エラーメッセージの読みやすさです。要件を満たさない実行ファイルで起動すると、構文エラーの代わりに「要件を満たしていない」という趣旨のメッセージが出ます。Claudeにエラーを読ませるとき、原因が「v1で動かした」だと一目で分かります。
なお、if (A_AhkVersion < "2.0")のような条件分岐では代わりになりません。別の場所に構文エラーがあればスクリプトは実行されないので、条件式まで到達しないためです。
/Validateの終了コードを完了条件にする
構文チェックは、AutoHotkey本体の/Validateスイッチで行います。スイッチの説明は次のとおりです。
- スクリプトを読み込んだあと、実行せずに終了する
- 読み込めたら終了コード0、エラーがあれば0以外
/ErrorStdOutを付けると、エラーを標準エラー出力へ出せる
Claudeが読める形で結果を返すには、この終了コードとエラー出力を使います。コマンドは次のようになります(AutoHotkey64.exeは、インストール先の実際のパスに置き換えてください)。
& "C:\Program Files\AutoHotkey\v2\AutoHotkey64.exe" `
/ErrorStdOut=UTF-8 /Validate .\hotkeys.ahk
$LASTEXITCODEAutoHotkeyはコンソールアプリではないため、PowerShellでは&で呼ぶとプロセスの終了を待たないことがあります。#ErrorStdOutの説明にも「エラーはコマンドプロンプトに直接は出ない。出力のリダイレクトで拾う」とあります。確実に待つにはStart-Process -Waitを使い、標準エラーをファイルへ向けます。
最初に、わざと壊したファイルで試してください。たとえばx = 5と書いたv1風のファイルに対し、終了コードが0以外になること、エラー文がファイルに残ることを確かめます。正しく動くと分かってから、Claudeの完了条件に使います。
PostToolUseフックで編集のたびに自動検証する
CLAUDE.mdに「検証を実行すること」と書いても、Claudeが忘れる場合があります。確実にしたいときは、Claude Codeのフックで機械的に走らせます。PostToolUseは、ツールの実行が成功したあとに動くイベントです。このイベントでは、フックが終了コード2で終わるとstderrがClaudeに渡されます。ツールはすでに実行済みなので、止めるのではなく「直してほしい」と知らせる用途です。
設定は.claude/settings.jsonに書きます。matcherにWrite|Editを指定すれば、ファイルの作成と編集の両方に反応します。
{
"hooks": {
"PostToolUse": [
{
"matcher": "Write|Edit",
"hooks": [
{
"type": "command",
"command": "powershell.exe -NoProfile -ExecutionPolicy Bypass -File \"${CLAUDE_PROJECT_DIR}/.claude/hooks/ahk-validate.ps1\""
}
]
}
]
}
}フックの入力は標準入力にJSONで届き、編集したファイルのパスはtool_input.file_pathから取れます。スクリプト側で拡張子を絞り、.ahk以外は何もせず抜けます。次の例は、フックのドキュメントにあるWindows向けの書き方に沿った構成です。
# .claude/hooks/ahk-validate.ps1
$payload = [Console]::In.ReadToEnd() | ConvertFrom-Json
$file = $payload.tool_input.file_path
if (-not $file -or $file -notlike '*.ahk') { exit 0 }
$ahk = 'C:\Program Files\AutoHotkey\v2\AutoHotkey64.exe' # 環境に合わせる
$out = New-TemporaryFile
$err = New-TemporaryFile
$p = Start-Process -FilePath $ahk -Wait -PassThru -NoNewWindow `
-ArgumentList '/ErrorStdOut=UTF-8', '/Validate', "`"$file`"" `
-RedirectStandardOutput $out.FullName `
-RedirectStandardError $err.FullName
$text = (Get-Content $err.FullName, $out.FullName -Raw -Encoding UTF8) -join "`n"
Remove-Item $out, $err
if ($p.ExitCode -ne 0 -or $text.Trim()) {
[Console]::Error.WriteLine("AutoHotkey v2 の検証に失敗: $file")
[Console]::Error.WriteLine($text)
exit 2
}
exit 0Claudeは.ahkを書き換えるたびに、エラー文を受け取って直す往復に入ります。フックの全体像はClaude Codeのフック入門、整形やlintの自動修正への応用はフックでlintを自動修正する手順に譲ります。
警告がダイアログで検証を止める点に注意
AutoHotkey v2は、未使用の変数の参照(VarUnset)や、到達できないコード(Unreachable)などに警告を出します。#Warnを書かない場合、警告はメッセージボックスで表示されます。
/Validateでも、ドキュメントはエラーと警告を「通常どおり表示する」と書いています。フックの中でダイアログが開くと、クリックする人がいないので止まります。そこでCLAUDE.mdの規約に#Warn All, StdOutを入れてあります。警告は標準出力へ流れるため、上のスクリプトのように出力が空でなければ失敗として返せます。
一方、/Validateの終了コードは「スクリプトを読み込めたか」で決まります。警告の有無が終了コードに反映されるかは、スイッチの説明に記載がありません。警告も見たい場合は、出力が空かどうかを見る方式が確実です。
最初の依頼は検証までを一続きにして渡す
規約とフックがそろったら、依頼文も「書く」で終わらせません。何を作るかに加えて、完了の条件を同じ文に入れます。
Ctrl+Alt+N でメモ帳を開き、ToolTip で1.5秒だけ知らせるホットキーを
hotkeys.ahk に作ってください。v2 で書き、/Validate が終了コード 0 に
なるまで直してください。実行して確かめる必要がある箇所は、最後に
一覧にして報告してください。この依頼なら、Claudeは書く、検証する、エラーを読んで直す、という往復を1回の指示で回します。報告に「実行が必要な箇所」を求めておくと、検証の外側にある確認事項が人間に戻ってきます。
日本語を含むスクリプトの文字コード
通知文やToolTipに日本語を書くと、文字コードの食い違いで文字化けします。v2は、ファイルの先頭にUTF-8またはUTF-16(LE)のBOMがあればそれに従い、無ければ既定でUTF-8として読みます。この既定はv1と異なり、v1の既定はUTF-8ではありませんでした。
古いv1スクリプトをANSI(日本語Windowsではシステムの既定コードページ)で保存している場合は、v2へ移すと読み方が変わります。/CPnスイッチでコードページを指定できますが、BOM付きUnicodeで保存すれば不要です。Claudeに移行を頼むときは、「保存はUTF-8のBOM付きにする」と一言添えます。
検証が拾わないものとその補い方
/Validateが確かめるのは、読み込み時のエラーまでです。ランチャーの判定も同じで、構文だけを調べ、意味は調べません。次のような誤りはここを通り抜けます。
- ホットキーを押したときの実際の動作(送信するキー、対象ウィンドウ)
- 実行時にだけ分かる誤り(存在しないファイルの指定、型の不一致)
- 別ファイルを
#Includeした先の内容。ランチャーが調べるのはメインファイルだけ
動作の確認は、Claudeに任せきりにしないでください。副作用の小さいホットキー(ToolTipを出すだけなど)から試す、RunやFileDeleteを含む処理は人間が一度実行して確かめる、という分担が現実的です。Claudeには「実行が必要な箇所を一覧にして報告して」と指示しておくと、確認漏れを減らせます。
実行時の挙動までテストで押さえたい場合の考え方は、PowerShellのPesterテストを完了条件にする手順が参考になります。破壊的な操作を差し替えて検証する発想は、AutoHotkeyでも通用します。
混ざったv1を直させるときの指示の出し方
すでにv1で書かれた.ahkをv2へ移したい場合も、同じ仕組みを使えます。指示は「v2へ書き換えて」だけにせず、手順まで渡します。
- ファイル先頭に
#Requires AutoHotkey v2.0と#Warn All, StdOutを追加する - 検証コマンドを実行し、出たエラーを上から順に直す
- 終了コード0になったら、直した箇所を表で報告する
変更点一覧はRemoved Commands, Functions & Directivesの節に、削除された関数と代替をまとめています。Claudeに「この節を読んで置換先を調べること」と指示すれば、StringReplaceからStrReplaceのような対応を、記憶でなく文書から引かせられます。
まとめ
AutoHotkeyをClaude Codeで書く作業の核心は、「v2で書く」をお願いにせず、仕組みに落とすことです。CLAUDE.mdには禁止する書き方を具体的に並べ、1行目の#Requiresでバージョンを宣言し、/Validateの終了コードで機械的に判定します。
ただし検証が保証するのは「読み込めること」までです。ホットキーの挙動は実行して確かめる前提で、そこまでをCLAUDE.mdの完了条件に書いておくと、手戻りが減ります。