更新日: ・ 自動化ノートの管理人

WindowsのタスクスケジューラでClaude Codeを毎日自動で動かす

「毎朝、Notionのタスクを整理しておいてほしい」「毎晩、その日の記録をまとめておいてほしい」。Claude Codeに頼みたいことが決まってくると、毎回自分で起動して頼むのが面倒になってきます。Windowsなら、標準のタスクスケジューラで決まった時間に動かせます。

ただ、手で動かすと動くのに、自動にしたとたん動かない、ということがよく起きます。この記事では、私が毎日の自動実行を組んだときの形と、引っかかった所をまとめます。

自動実行の仕組み

  1. タスクスケジューラ決まった時間にPowerShellを起動する
  2. PowerShellのスクリプト作業フォルダに移り、claude -p を呼ぶ
  3. Claude Code頼んだ作業をして、結果を返す
  4. ログと終了コード結果をファイルに残し、失敗ならタスクも失敗にする
Claude Codeを直接タスクに登録せず、間にPowerShellのスクリプトを1枚はさむ形です。ログを残し、失敗を知らせやすくなります。

claude -p で、対話なしに1回だけ動かす

Claude Codeは、-p(--print)を付けると、対話の画面を開かずに1回だけ作業して終わります。公式ドキュメントでは、スクリプトやCIから使う方法として紹介されています。

claude -p "今日のタスクを整理して" --output-format json

押さえておきたい点は次の3つです。

なお、--bare を付けると起動が速くなりますが、CLAUDE.md やMCPの設定を読み込まず、普段のログインではなくAPIキーが必要になります。いつもの設定やNotion MCPをそのまま使いたいなら、付けずに動かします。

権限は「許可したものだけ」にする

自動実行のときは、確認を求められても答える人がいません。そこで、使ってよい道具を --allowedTools で並べ、それ以外は確認を出さずに断るモード --permission-mode dontAsk にしておきます。公式ドキュメントでは、dontAskは「確認が必要になる操作をすべて断る」モードで、--allowedTools で許可したものは動くと説明されています。

claude -p "/daily-tasks" `
  --allowedTools "Read,Write,mcp__notion" `
  --permission-mode dontAsk `
  --output-format json

mcp__notion は、notion という名前で登録したMCPサーバーの道具をまとめて許可する書き方です。サーバーの名前は、Claude Codeの /mcp の一覧で確かめられます。何でも許可するのではなく、その作業に要るものだけを並べておけば、思わぬ操作を防げます。

PowerShellのスクリプトを用意する

タスクから直接 claude を呼ぶより、間にスクリプトをはさむほうが扱いやすくなります。次は、私が使っている形を簡単にしたものです。

run_daily.ps1(UTF-8のBOM付きで保存する)

# 毎朝タスクスケジューラから呼ばれる
[Console]::OutputEncoding = [System.Text.Encoding]::UTF8

$ProjectDir = "C:\path\to\作業フォルダ"
$LogDir = Join-Path $ProjectDir "logs"
New-Item -ItemType Directory -Force -Path $LogDir | Out-Null
Set-Location $ProjectDir

# where.exe claude で調べた場所をフルパスで書く
$claude = "C:\path\to\claude.cmd"
$log = Join-Path $LogDir ("run_" + (Get-Date -Format "yyyy-MM-dd_HHmmss") + ".log")

$output = & $claude -p "/daily-tasks" `
    --allowedTools "Read,Write,mcp__notion" `
    --permission-mode dontAsk `
    --output-format json 2>&1
$code = $LASTEXITCODE

$output | Out-File -FilePath $log -Encoding utf8
Add-Content -Path $log -Value "exit code: $code"

# これが無いと、claude が失敗してもタスクは「成功」に見える
exit $code

このスクリプトで気をつけた点は次のとおりです。

日本語を含むスクリプトはBOM付きで保存する

Windowsに最初から入っているPowerShell 5.1は、BOMの無いUTF-8のスクリプトを、古い「ANSI」の文字コードとして読みます。Microsoftの説明でも、ASCII以外の文字を使うならBOM付きのUTF-8で保存するよう書かれています。日本語のコメントや文字列を入れたスクリプトをBOM無しで保存すると、読み込みの段階でエラーになることがあります。メモ帳やVS Codeの保存時に「UTF-8(BOM付き)」を選んでください。

タスクを登録する

登録は画面からでもできますが、PowerShellで書いておくと、あとで設定を見直しやすくなります。

$action = New-ScheduledTaskAction -Execute "powershell.exe" `
    -Argument '-NoProfile -ExecutionPolicy Bypass -File "C:\path\to\run_daily.ps1"'
$trigger = New-ScheduledTaskTrigger -Daily -At 07:00
$settings = New-ScheduledTaskSettingsSet `
    -StartWhenAvailable `
    -AllowStartIfOnBatteries `
    -DontStopIfGoingOnBatteries `
    -MultipleInstances IgnoreNew `
    -ExecutionTimeLimit (New-TimeSpan -Hours 1)
$principal = New-ScheduledTaskPrincipal -UserId $env:USERNAME -LogonType Interactive

Register-ScheduledTask -TaskName "DailyTasks" -Action $action -Trigger $trigger `
    -Settings $settings -Principal $principal
設定意味付けた理由
-ExecutionPolicy Bypassこのスクリプトの実行に限って、実行ポリシーの制限を外すWindowsの既定の実行ポリシー(Restricted)では、スクリプトを実行できないため
-StartWhenAvailable予定の時刻を過ぎていても、あとで実行できるその時刻にPCがスリープだった日も、起きたときに動かすため
-AllowStartIfOnBatteriesバッテリー駆動中でも開始する既定では、バッテリー駆動中は開始しない設定になっているため
-DontStopIfGoingOnBatteries途中で電源が外れても止めない作業の途中で止まると、中途半端な状態が残るため
-MultipleInstances IgnoreNew前の回がまだ動いていたら、新しい回は始めない同じ作業が重なって二重に書き込むのを防ぐため
-ExecutionTimeLimit実行時間の上限指定しないと上限は3日。止まったまま残らないよう短くしておく

ノートPCは、バッテリーの設定で止まりやすい

Microsoftの説明では、タスクの「バッテリー駆動中は開始しない」という設定は、既定で有効です。私はノートPCを持ち歩いて使っているので、この設定のままだと、電源につないでいない日はタスクが待ったまま動きませんでした。手元では動くのに自動だと動かない、という場合は、まずこの設定を疑ってみてください。画面からなら、タスクのプロパティの「条件」タブで確認できます。

費用と、動かさない日の作り方

Claude Codeは、1回動かすたびに使える量(または費用)を消費します。私の環境では、Notionを読み書きする程度の作業で、JSONの total_cost_usd が1回あたりおおむね0.5〜1ドルでした。毎日、やることが無い日まで起動していると、それなりの量になります。

そこで、Claude Codeを呼ぶ前に、PowerShellやPythonの小さな処理で「今日はやることがあるか」を確かめ、無ければ起動せずに終わるようにしています。たとえば、Notionに新しい依頼が無ければ終わる、取り込むファイルが無ければ終わる、といった判定です。AIに頼まなくても判断できることは、手前で済ませておくのが節約のこつです。

まとめ

Pythonのスクリプトも一緒に自動で動かす場合は、仮想環境(venv)の置き場所にも注意が要ります。OneDriveの中にPythonの仮想環境を置くと、自動実行で壊れることがあるで、私が実際にはまった例を紹介しています。