2
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

定期タスクの1行の $( ) で、誰もいない朝に止まった:Claude Code の承認待ちと日付の取り方

2
Posted at

Claude のデスクトップアプリで、Code タブのローカル定期タスクに Bash のコマンドを書いている人に向けた、失敗の記録です。日付を取り出すために書いた $( ) の1行で、誰も見ていない朝に実行が止まった話です。

対象と前提

  • 対象は、Claude デスクトップアプリの Code タブで作るローカルの定期タスクです。クラウドで動く定期タスクは確かめていません
  • 起きたことは、2026年9月の私の環境のものです。公式の資料は2026年10月24日に読んだもので、当時と今とで仕様が同じかは分かりません

何が起きたか

2026年9月5日は、SNS へ毎日1本投稿する定期タスクが、初めて自動で動いた朝でした。

7時6分に実行が始まり、最初の Bash のコマンドで4分以上止まりました。誰も画面を見ていない時間です。エラーの知らせは来ていません。

止まっていたのは、「今日はもう投稿したか」を数える1行でした。投稿の履歴を1行1件のファイルに残していて、行の頭が今日の日付なら、もう投稿済みという判定です。

grep -c "^$(date +%Y-%m-%d)" 投稿履歴.tsv

その朝の投稿が出たのは7時16分です。止まっていた実行がどうやって先へ進んだのかは、記録に残っていません。

この日はもう1つ、「常に許可」を選んだ結果、日付の入った使い捨ての許可が4本増えています。日付が入っている以上、次の日のコマンドには当たらないはずの許可です。

なぜ止まったか

公式の資料で確かめられたこと

定期タスクの資料(Schedule recurring tasks in Claude Code Desktop)に書いてあることです。

  • ローカルの定期タスクは、時刻が来るたびに新しいセッションを始める
  • 許可のモードはタスクごとに決める。~/.claude/settings.json の allow のルールも効く
  • Manual のモードで許可の無い道具を使おうとすると、人が承認するまで実行が止まる
  • 止まらないように、作ったあと Run now で一度動かし、出てきた許可を「常に許可」にしておく、と勧めている

許可の資料(Configure permissions)には、Bash について次のことが書いてあります。

  • && や | でつないだコマンドは、ひとつずつ分けてルールに合うかを見る
  • deny や ask のルールは、コマンド置換や for の中のコマンドにも効く
  • 解析しきれないコマンドは、承認を求める

$( ) の中身も調べられる、というところまでは公式に書いてあります。allow のルールが $( ) 入りのコマンドを通すかどうかは、私が読んだ範囲では書かれていませんでした。また、いまの資料では grep は承認なしで動く読み取りだけのコマンドの一覧に入っています。9月5日に止まった理由を、当時の仕様と照らし合わせることはできていません。

私の環境で起きたこと

  • grep を許可の一覧に入れていても、$( ) が入った1行は自動では通らず、承認待ちになった
  • チャットの中で私が積み上げた承認は、定期タスクの新しいセッションには引き継がれなかった
  • 承認待ちになっても、知らせは来なかった

$( ) は、動かしてみるまで中で何が走るかが決まらない書き方です。10月1日には、for や while のループ、$変数、ヒアドキュメントでも、私の環境では同じように承認待ちになることが分かりました。

人がそばにいれば、承認の画面が出たところで押せば済みます。定期タスクは、人がいない時間に動かすためのものです。そこで承認待ちになると、知らせる仕組みが別に無い限り、誰も気づきません。

直し方

日付はスクリプトの中で取る

コマンドの中で日付を作らず、日付を取る所から判定までを、小さなスクリプトにまとめました。定期タスクの指示に書くのは、それを呼ぶ1行だけです。

python3 /絶対パス/kyou_toukou.py

スクリプトの形はこうです(実物を一般化したものです)。

#!/usr/bin/env python3
"""今日の分がもう履歴にあるかを見る。定期タスクの最初に呼ぶ。
まだなら 0、済んでいれば 1 で終わる。"""
import sys
from datetime import datetime
from pathlib import Path

LOG = Path("/絶対パス/投稿履歴.tsv")
kyou = datetime.now().strftime("%Y-%m-%d")

if not LOG.exists():
    print("まだ:履歴ファイルがありません。進んでよい。")
    sys.exit(0)

with LOG.open(encoding="utf-8") as f:
    hit = [line.rstrip("\n") for line in f if line.startswith(kyou)]

if hit:
    print(f"済:{kyou} の分はもうあります。何もしないこと。")
    for h in hit:
        print("   " + h)
    sys.exit(1)

print(f"まだ:{kyou} の分はありません。進んでよい。")
sys.exit(0)

考えたことは3つです。

1つ目は、コマンドの文字を毎回同じにすることです。日付はスクリプトの中で決まるので、定期タスクが打つ1行は今日も明日も同じ文字です。公式の資料が勧める「一度動かして常に許可」は、文字が毎回同じであってはじめて次の日にも効く、と私は理解しています。

2つ目は、読む相手に向けた出力です。結果を読むのは定期タスクの中の Claude なので、「済」「まだ」と次にどうするかを、そのまま文で出しています。

3つ目は終了コードです。ここでは「済」を1にしています。launchd や cron が直接見るものではなく、定期タスクの中で結果を読むための道具なので、1は失敗ではなく「もう済んでいる」の意味です。スケジューラーに直接つなぐなら、紛らわしいので分けたほうがよいと思います。

弱いところも1つ残っています。履歴のファイルが無いときは「まだ」と答えるので、ファイルの場所を書き間違えたり置き場を移したりすると、毎回「まだ」と答え、同じ日に2回出す方向に倒れます。見直したい所です。

指示に「書かない形」を書いておく

あわせて、定期タスクの指示の側に、使わない形を書いておくようにしました。$( ) とバッククォート、ループ、$変数、ヒアドキュメントは使わない。日付や時刻が要るならスクリプトに見させる。ファイルの場所は頭から全部書く。許可の範囲を広げるのではなく、止まる形を指示から外す向きです。

置き換えたあと、この1行で止まったという記録は私の手元にはありません。ただ、当時のアプリのログはもう残っていないので、止まらなかったことを数で示せるわけではありません。この投稿の仕事は、その後、定期タスクの外(launchd)へ移しました。

確かめ方

どれも読み取りだけです。場所は私の環境のものです。

定期タスクの指示に $( ) が残っていないかは、この1行で探しています。

grep -n -F '$(' ~/.claude/scheduled-tasks/*/SKILL.md

私の環境では、当たった行のほとんどが「$( ) を使わない」という注意書きそのものでした。当たった行は、ひとつずつ目で見て分けています。バッククォートは Markdown のコードの書き方と見分けがつかないので、機械では探していません。

ほかに見ている所です。

  • ループ、$変数、ヒアドキュメントも、指示に入っていないか
  • タスクの詳しい画面の Always allowed に、日付の入った使い捨ての許可が並んでいないか。並んでいるなら、毎回文字が変わるコマンドを打っているのかもしれません
  • 作ったタスクを Run now で一度動かし、承認の画面が出ないかを見たか
  • 承認待ちで止まったとき、誰かに知らせが届く仕組みがあるか。無いなら、出るはずのものが出たかを、別の仕組みで数えているか

定期タスクの中の1行の $( ) は、人のいる時間なら一度押せば済む話です。人のいない朝には、それだけで止まります。少なくとも私の環境ではそうでした。

この件を含む定期タスクの実測の記録は note にまとめています:https://note.com/vellum_office/n/n466306e5553b

2
0
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?