Claude Code を cron / systemd で定期実行する(-p 非対話モード)

Claude Code は対話で使うだけでなく、-p(print)モードで「指示を渡して結果だけ受け取る」使い方ができます。これを cron や systemd timer から呼べば、VPS 上で定期的に作業させられます。

前提として、VPS に Claude Code が入っている状態から始めます。まだの場合は ConoHa VPS に Claude Code を入れる手順 を先に。

-p モードの基本

cd ~/work/myrepo
claude -p "テストを実行して、失敗があれば原因を調べて修正し、変更内容を要約して"

標準出力に結果が返ります。JSON で受け取りたい場合は出力形式を指定します。

claude -p "..." --output-format json

オプション名はバージョンで変わることがあるため、claude --help で確認してください。

認証は API キーにする

cron からはブラウザ認証ができません。API キーを環境変数で渡します。

# ~/.claude_env(パーミッション 600)
export ANTHROPIC_API_KEY=sk-ant-...

API は従量課金です。1 回のジョブで何トークン使うかを、まず手動で数回動かして把握してから定期実行にします。

許可するツールを絞る

非対話モードでは、人が「許可」を押せません。何を許可するかを明示します。

claude -p "テストを実行して結果を要約して" \
  --allowedTools "Read,Bash(npm test)" \
  --max-turns 10
  • 読み取りとテスト実行だけ: Read,Bash(npm test)
  • 修正もさせる: Read,Edit,Write,Bash(npm test),Bash(git diff)
  • git pushrm は許可しない。人がレビューしてから push する

--max-turns で暴走を止められます。

ジョブスクリプトにする

#!/usr/bin/env bash
# ~/bin/nightly-test.sh
set -euo pipefail
source ~/.claude_env
export PATH="$HOME/.local/bin:$PATH"
cd ~/work/myrepo

git pull --ff-only
LOG=~/logs/nightly-$(date +%F).log
mkdir -p ~/logs

claude -p "npm test を実行して、失敗があれば原因を調べて修正して。修正した場合は git diff を出力して。" \
  --allowedTools "Read,Edit,Write,Bash(npm test),Bash(git diff)" \
  --max-turns 15 \
  > "$LOG" 2>&1

# 変更があればブランチに退避(push は人が確認してから)
if ! git diff --quiet; then
  git checkout -b "auto/nightly-$(date +%F)"
  git commit -am "auto: nightly fix"
  git checkout -
fi
chmod +x ~/bin/nightly-test.sh

cron で毎晩 3 時に動かす

crontab -e
0 3 * * * /home/dev/bin/nightly-test.sh

cron は PATH が最小限なので、スクリプト内で環境変数と PATH を設定しておきます(上のスクリプトはそうしています)。

systemd timer で動かす(ログ管理が楽)

~/.config/systemd/user/nightly-test.service

[Unit]
Description=Claude Code nightly test

[Service]
Type=oneshot
EnvironmentFile=%h/.claude_env
ExecStart=%h/bin/nightly-test.sh

~/.config/systemd/user/nightly-test.timer

[Unit]
Description=Run nightly test at 03:00

[Timer]
OnCalendar=*-*-* 03:00:00
Persistent=true

[Install]
WantedBy=timers.target
systemctl --user daemon-reload
systemctl --user enable --now nightly-test.timer
systemctl --user list-timers
journalctl --user -u nightly-test.service -n 50

ログアウト後も動かすには loginctl enable-linger dev を一度実行します。

結果を通知する

ログの末尾を Discord の Webhook に投げると、朝に結果が見られます。

tail -c 1500 "$LOG" > /tmp/nightly-tail.txt
python3 - <<'PY'
import json, os, urllib.request
body = open('/tmp/nightly-tail.txt', encoding='utf-8', errors='replace').read()
req = urllib.request.Request(
    os.environ['DISCORD_WEBHOOK_URL'],
    data=json.dumps({'content': 'nightly-test 完了\n' + body}).encode(),
    headers={'Content-Type': 'application/json'},
)
urllib.request.urlopen(req)
PY

実際に動かしている例

(執筆中)

まとめ

  • -p モードで指示を渡し、結果だけ受け取れる
  • 定期実行は API キー認証。使用量を先に把握する
  • 許可ツールと --max-turns で暴走を防ぐ。push は人がやる
  • cron でも動くが、ログを見るなら systemd timer が楽
  • VPS の選び方は Claude Code を VPS で 24 時間動かす構成と費用

よくある質問

Q. cron から Claude Code を動かすとログインを求められませんか?

ANTHROPIC_API_KEY を環境変数に置いておけば、ブラウザ認証なしで動きます。定期実行は API キー認証にしてください。

Q. 勝手に危険なコマンドを実行しませんか?

非対話モードでは許可するツールを明示的に指定します。読み取りとテスト実行だけ許可する、といった絞り込みができます。

検証環境: Ubuntu 24.04 LTS / ConoHa VPS 2GB / 2026-09-19 時点。料金や仕様は変更されることがあるため、最新情報は公式サイトで確認してください。

関連記事