
こんにちは、サーバーワークスで生成AIの活用推進を担当している針生です。
Claude Code を使っていると、AI が処理中のときにターミナルにスピナーが表示されます。その横に出る「Thinking...」「Reasoning...」の部分、実は ~/.claude/settings.json で自由に書き換えられます。

最初は「ゴリラ」「ラッパ」の2語にして楽しんでいたのですが、1日で飽きました。毎回同じ文字がループするだけでは面白くない。「どうせなら毎朝変わったら楽しくない?」と思い、今日のニュース見出しをスピナーに流すようにしました。
spinnerVerbs とは
~/.claude/settings.json に以下のように書くと、スピナーに表示される動詞をカスタムできます。
"spinnerVerbs": { "mode": "replace", "verbs": ["ゴリラ", "ラッパ"] }
mode は2種類あります。
replace— 標準の「Thinking」「Reasoning」などをリストで完全に置き換えるappend— 標準語句に自分のリストを追加する
「ゴリラ」だけ流したいなら replace 一択です。append にすると「Thinking」「Reasoning」「ゴリラ」が混在します。
外部スケジューラで settings.json を書き換える
Claude Code は settings.json を動的に読み込むので、verbs の中身を差し替えると 再起動なしで次のスピナーから新しい動詞が使われます。裏で毎朝書き換えておけば、10:00 以降は自動でその日のニュースに切り替わる、という寸法です。
仕組みは以下のとおりです。
[launchd 平日10:00]
↓
[~/.claude/scripts/update-spinner-verbs.sh]
↓
[claude -p "今日のニュース見出しをJSON配列で" --allowedTools WebSearch]
↓
[~/.claude/settings.json の spinnerVerbs.verbs を書き換え]
ニュースの取得に RSS パーサーを使っても良いですが、今回は実装がシンプルな claude -p + WebSearch を選びました。LLM に当日の見出しをまとめてもらうだけです。
しかも claude -p は Claude Code 本体の認証をそのまま使うので、Anthropic API キーを別途用意する必要もありません。
実装
シェルスクリプト
~/.claude/scripts/update-spinner-verbs.sh:
#!/usr/bin/env bash
set -euo pipefail
SETTINGS="$HOME/.claude/settings.json"
BACKUP="$HOME/.claude/settings.json.bak"
LOG="$HOME/.claude/logs/update-spinner-verbs.log"
CLAUDE_BIN="$HOME/.local/bin/claude"
mkdir -p "$(dirname "$LOG")"
exec >> "$LOG" 2>&1
echo "[$(date '+%Y-%m-%d %H:%M:%S')] start"
PROMPT='今日(日本時間)の主要ニュース見出しを、一般・国際・経済・テック・クラウド/AWS から幅広く選び、日本語で8〜10本。文字数制限なし、見出しは元の長さのまま。出力は JSON 配列のみ。前後に ``` や説明を付けない。例: ["見出し1","見出し2"]'
RAW=$("$CLAUDE_BIN" -p "$PROMPT" --allowedTools WebSearch --output-format text 2>&1) || {
echo "[$(date '+%H:%M:%S')] claude call failed: $RAW"; exit 1;
}
VERBS=$(printf '%s' "$RAW" | python3 -c '
import sys, re, json
txt = sys.stdin.read()
m = re.search(r"\[.*?\]", txt, re.S)
if not m:
m = re.search(r"\[[\s\S]*?\]", txt)
if not m:
sys.exit("no array found in: " + txt[:200])
arr = json.loads(m.group(0))
if not (isinstance(arr, list) and 5 <= len(arr) <= 12 and all(isinstance(x, str) and x.strip() for x in arr)):
sys.exit("invalid array: " + repr(arr))
print(json.dumps(arr, ensure_ascii=False))
') || { echo "[$(date '+%H:%M:%S')] extract failed. raw: $RAW"; exit 1; }
cp "$SETTINGS" "$BACKUP"
TMP=$(mktemp)
jq --argjson v "$VERBS" '.spinnerVerbs.verbs = $v | .spinnerVerbs.mode = "replace"' "$SETTINGS" > "$TMP"
jq empty "$TMP"
mv "$TMP" "$SETTINGS"
echo "[$(date '+%H:%M:%S')] updated: $VERBS"
ポイントは3つです。
1. claude -p --allowedTools WebSearch
Claude Code headless モードではツールの利用範囲が制限されます。WebSearch を使うには --allowedTools WebSearch で明示的に許可する必要があります。
2. 正規表現で JSON 配列を抜き出す
LLM は「配列だけ返して」と言っても前後に説明文を添えることがあります。Python の正規表現で [...] 部分だけを抽出しています。抽出後に件数(5〜12本)と型(文字列のみ)をチェックし、外れた場合はスクリプトを失敗扱いにして既存の settings.json を触りません。
3. atomic 書き換え
一時ファイルに書いて jq empty で JSON バリデーションを通してから mv します。途中で処理が中断されても settings.json が壊れません。書き換え前には cp でバックアップも作ります。
launchd への登録
ここから先は MacBook(macOS)前提です。Linux なら cron、Windows ならタスクスケジューラに読み替えてください。
~/Library/LaunchAgents/com.yourname.claude-spinner-verbs.plist:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>Label</key><string>com.yourname.claude-spinner-verbs</string>
<key>ProgramArguments</key>
<array>
<string>/bin/bash</string>
<string>/Users/yourname/.claude/scripts/update-spinner-verbs.sh</string>
</array>
<key>StartCalendarInterval</key>
<array>
<dict><key>Weekday</key><integer>1</integer><key>Hour</key><integer>10</integer><key>Minute</key><integer>0</integer></dict>
<dict><key>Weekday</key><integer>2</integer><key>Hour</key><integer>10</integer><key>Minute</key><integer>0</integer></dict>
<dict><key>Weekday</key><integer>3</integer><key>Hour</key><integer>10</integer><key>Minute</key><integer>0</integer></dict>
<dict><key>Weekday</key><integer>4</integer><key>Hour</key><integer>10</integer><key>Minute</key><integer>0</integer></dict>
<dict><key>Weekday</key><integer>5</integer><key>Hour</key><integer>10</integer><key>Minute</key><integer>0</integer></dict>
</array>
<key>StandardOutPath</key><string>/Users/yourname/.claude/logs/update-spinner-verbs.out</string>
<key>StandardErrorPath</key><string>/Users/yourname/.claude/logs/update-spinner-verbs.err</string>
</dict>
</plist>
StartCalendarInterval を配列にして Weekday 1〜5(月曜〜金曜)の 10:00 を指定しています。cron でも同じことはできますが(0 10 * * 1-5)、launchd の方が MacBook を使う場合に有利です。cron はスリープ中に予定時刻を跨ぐとジョブをスキップしますが、launchd は起床後に自動で実行してくれます。
登録は以下のコマンドで1行です。
launchctl load ~/Library/LaunchAgents/com.yourname.claude-spinner-verbs.plist
実際に Claude Code を動かすと、ニュースが表示されました。

応用アイデア
同じ仕組みで verbs の中身は何でも変えられます。
- 天気予報 — Weather API から当日の天気・気温を取得して流す
- 今日の TODO — Google Calendar から当日の予定を抜いてくる
- PR レビュー待ち — 自分宛のレビュー依頼タイトルを GitHub API から取得して流す
仕事に関係する情報を流せば、ターミナルがちょっとしたダッシュボードになります。
まとめ
- Claude Code の
spinnerVerbsはsettings.jsonで差し替えられる。mode: "replace"で標準語句を完全置換 claude -p --allowedTools WebSearchで API キー不要の LLM + Web 検索が使える。当日のニュース取得に便利- launchd の
StartCalendarInterval(Weekday 1〜5)でスリープを跨いでも平日 10:00 に確実に実行できる
ニュース見出しが流れるスピナーを眺めながら「今日もいろいろ起きているな」と思う朝。実用性はともかく、気分は悪くないです。
針生 泰有(執筆記事の一覧)
サーバーワークスで生成AIの活用推進を担当