Claude Codeã®ã¢ãã«çµäºãlaunchdã§ç¡äººç§»è¡ãã â settings.jsonãèªåãããããäœ¿ãæšãŠãžã§ã
ãClaude Codeç°å¢ãã·ãªãŒãºãåå launchdã®ãã«ãã¹ããããªãã©ã€èšèš ã§ãææŒå€3ååªççºç«ããã¿ãŒã³ãæžãããä»åã¯ãã®å¿çšã§ã**Fable 5ã®çµäºïŒ2026-07-07ïŒã«åããŠä»èŸŒãã§ãããäœ¿ãæšãŠç§»è¡ãžã§ãã**ã®å®è£ ãå ¬éããã
settings.jsonã®modelãã£ãŒã«ããjqã§æžãæãããã¹ã¯ãããéç¥ãé£ã°ããæåŸã«launchctl unloadã§èªåã®ç»é²ãå€ããŠæ¶ãããèµ·åã»å®è¡ã»èªæ»
ã1ã¹ã¯ãªããã§å®çµãããèšèšã ãã¢ãã«ç§»è¡ã«éãããç¹å®æ¥ã«äžåºŠã ãèšå®ãå€ããŠæ¶ãããžã§ãããšããŠæ±çšã§äœ¿ãããã¿ãŒã³ãªã®ã§ãå®ã³ãŒããå
šéšåºãã
å°ãããšïŒã¢ãã«EOLã¯éãã«å£ãã
Claude Codeã®~/.claude/settings.jsonã«"model": "claude-fable-5"ãæžããç°å¢ã§ãEOLåœæ¥ä»¥éããã®èšå®ãæ®ãç¶ãããšãéãã«æå³ããªãæåã«ãªãããšã©ãŒã¯åºãããã©ãŒã«ããã¯ãå¥ã¢ãã«ã§åããŠãããããããªãããèªåãã©ã®ã¢ãã«ã䜿ã£ãŠãããåãããªããªãã
æåã§settings.jsonãéããŠæžãæããã®ãæãã·ã³ãã«ã ãããåœæ¥ã«ç¢ºå®ã«ããå¿ããã«ããäžåºŠã ããã人éãæããã®ã¯æ¡å€é£ãããlaunchdã«å§è²ããŠèªååããã
èšèšïŒ3ã¹ãããã§å®çµããã
1. æ¥ä»ã¬ãŒã â 7/7ããåãªãå³ exit 0ïŒcatch-upçºç«å¯ŸçïŒ
2. settings.json ããã â ããã¯ã¢ãã â jqæžãæã â JSONæ€èšŒ â mv
3. éç¥ + self-unload â osascript ã§éç¥ â launchctl unload ã§èªåãå€ã
ãäœ¿ãæšãŠãã®æ žã¯ ã¹ããã3ã§ãžã§ãèªèº«ãç»é²è§£é€ããããšãããã§æ¬¡å以éã®çºç«ããªãããã ã plist ãã¡ã€ã«ã¯æ¶ãã~/Library/LaunchAgents/ã«æ®ããåã³launchctl loadããã°åŸ©åž°ã§ããããã«ããŠããïŒã¹ã¯ãªããã®ã³ã¡ã³ãã«ããplistã¯æ®ãïŒåç»é²å¯èœããšæžããŠããïŒã
æ¥ä»ã¬ãŒãïŒæ©æçºç«ãç¡å®³åãã
launchdã«ã¯ãmacãèµ·åãããšãã«ãæ¬æ¥çºç«ããã¯ãã ã£ãéå»ã®ã¹ããããé¡ã£ãŠå®è¡ãããcatch-upãããã7/7以åã«ç»é²ããå Žåãmacåèµ·åã®ã¿ã€ãã³ã°ã§ååãçºç«ããå¯èœæ§ããããæåã®äžè¡ã§ãããæ¢ããã
# 7/7ããåãªãäœãããªãïŒcatch-upçºç«å¯ŸçïŒ
if [ "$(date +%Y%m%d)" -lt 20260707 ]; then
log "skip: before 2026-07-07"; exit 0
fi
date +%Y%m%dã¯20260707圢åŒã®æŽæ°ãè¿ãã®ã§ãæ°å€æ¯èŒã§å€å®ã§ããã7/7åœæ¥ä»¥éã«åããŠå®éã®åŠçãèµ°ãã
ãã®æ¥ä»ã¬ãŒãããªããšã7/7åã«ç»é²ããŠmacãåèµ·åãããã³ã«ã¹ã¯ãªãããèµ°ããcatch-upã¯
StartCalendarIntervalãžã§ãç¹æã®æåãªã®ã§ã宿ãžã§ããçµãéã¯å¿ ãæèããã
settings.jsonã®ãããïŒã¢ãããã¯ãª4ã¹ããã
ã¢ãã«æžãæãã¯4ã¹ãããã®ã¢ãããã¯æäœã«ããŠããã
current=$(jq -r '.model // empty' "$SETTINGS")
if echo "$current" | grep -qi 'fable'; then
cp "$SETTINGS" "$SETTINGS.bak-model-transition"
jq '.model = "opus"' "$SETTINGS" > "$SETTINGS.tmp" \
&& jq . "$SETTINGS.tmp" > /dev/null \
&& mv "$SETTINGS.tmp" "$SETTINGS"
log "switched model: $current -> opus"
else
log "no-op: model is already '$current'"
fi
åã¹ãããã®æå³ïŒ
jq -r '.model // empty'â.modelããŒãååšããªãå Žåã¯ç©ºæåãè¿ããnullæååãåŸæ®µã«æµããªãgrep -qi 'fable'â 倧æåå°æåãåããfableãå«ãå Žåã ãæžãæããããã§ã«å¥ã¢ãã«ã«ç§»è¡æžã¿ãªãelseã«èœã¡ãŠno-opãã°ã ãæžããŠçµããïŒåªçïŒcp "$SETTINGS" "$SETTINGS.bak-model-transition"â æžãæãåã®ããã¯ã¢ããã倱ææã®åŸ©æ§çšjq . "$SETTINGS.tmp" > /dev/nullâ æžãæãã.tmpãJSONçã«æ£ãããæ€èšŒããŠããmvãããå£ããJSONãæ¬çªãã¹ã«çœ®ããªã
ã¹ã¯ãªããåé ã§set -uo pipefailã宣èšããŠããã®ã§ã&&ãã§ãŒã³ã®ã©ããã倱æããã°mvã¯èµ°ããªãã
jq . file > /dev/nullã«ããæ€èšŒãæãçç±ã¯ãjqã®åºåãäœããã®çç±ã§å£ããJSONã«ãªã£ãå Žåã«ã.tmpâæ¬çªãžã®mvãæ¢ããããã--argjsonã䜿ããæååãªãã©ã«ãåã蟌ãä»åã®æ§é ã§ã¯å®éã«ã¯èµ·ãã«ããããç¿æ £ãšããŠå ¥ããŠãããšä»ã®æžãæãã¹ã¯ãªãããžã®è»¢çšæã«å®å šã ã
éç¥ãšã»ã«ãunload
æžãæããå®äºãããosascriptã§ãã¹ã¯ãããéç¥ãéãã
/usr/bin/osascript -e 'display notification "Fable 5çµäºã«äŒŽãããã©ã«ãã¢ãã«ãOpusãžåæ¿ããŸãã" with title "Claude model transition"' \
>/dev/null 2>&1 || true
|| trueãä»ããŠããã®ã¯ãéç¥ã倱æããŠããžã§ãå
šäœããšã©ãŒæ±ãã«ããããªããããéç¥ã¯ãããŸã§äººéãžã®å ±åã§ãããåŠçã®æ¬äœã§ã¯ãªãã
圹ç®ãçµãããèªåãunloadããã
# 圹ç®ãçµããããžã§ããå€ãïŒplistã¯æ®ãïŒåç»é²å¯èœïŒ
launchctl unload "$PLIST" 2>/dev/null || true
log "done (job unloaded)"
PLIST倿°ã¯ã¹ã¯ãªããåé ã§PLIST="$HOME/Library/LaunchAgents/com.shun.model-transition-0707.plist"ãšå®çŸ©ããŠãããlaunchctl unloadã¯plistãã¡ã€ã«ãåé€ããªãã®ã§ã~/Library/LaunchAgents/ã«ãã¡ã€ã«ã¯æ®ã£ããŸãŸã ãæ¬¡ålaunchctl load "$PLIST"ãæãŠã°å³åº§ã«åç»é²ã§ããã
plistã®é ç·ïŒ3ã¹ãããåªççºç«
<?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.shun.model-transition-0707</string>
<key>ProgramArguments</key><array>
<string>/bin/bash</string>
<string>~/.claude/scripts/model-transition-0707.sh</string>
</array>
<key>StartCalendarInterval</key><array>
<dict><key>Hour</key><integer>6</integer><key>Minute</key><integer>50</integer></dict>
<dict><key>Hour</key><integer>12</integer><key>Minute</key><integer>50</integer></dict>
<dict><key>Hour</key><integer>20</integer><key>Minute</key><integer>50</integer></dict>
</array>
<key>EnvironmentVariables</key><dict>
<key>PATH</key>
<string>~/.nvm/versions/node/v24.13.0/bin:/opt/homebrew/bin:/opt/homebrew/sbin:/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin:~/.local/bin</string>
</dict>
<key>StandardErrorPath</key><string>~/.claude/logs/model-transition.err</string>
</dict></plist>
6:50ã»12:50ã»20:50ã®1æ¥3ã¹ããããååã®èšäºã§æžãããã«ãã¹ãããèšèšã®çŽæ¥å¿çšã ã1åç®ãå®èµ°ããŠself-unloadããã°2åç®ä»¥éã¯çºç«ããªããmacãã¹ãªãŒãã§6:50ãéããŠãã12:50ã»20:50ã§æŸããã
StandardErrorPathãplistã§èšå®ããŠããã®ã§ãã¹ã¯ãªããå
ã§stderrã®ãªãã€ã¬ã¯ããæžããªããŠããããããã°æã¯~/.claude/logs/model-transition.errãèŠãã
èžãã èœãšã穎
jqãpathã«ç¡ããŠexit 127 â plistã®EnvironmentVariables.PATHã«/opt/homebrew/binãç¡ããšãHomebrewå ¥ãã®jqãèŠã€ãããªããã¿ãŒããã«ããæåå®è¡ã¯æåããã®ã«ãlaunchdã ãå£ããå žåãã¿ãŒã³ãApple Siliconã®å®çªçœ- æ¥ä»ã¬ãŒããå ¥ããåã®ãã¹ãã§catch-upçºç« â 7/7åã«åäœç¢ºèªã§ããŒããããšãããmacåèµ·åã®catch-upãèµ°ã£ãŠ7/7ããæ©ãç§»è¡ãå®äºããŠããŸã£ããæ¥ä»ã¬ãŒãã¯åŸä»ãã§ã¯ãªãæåããå¿ é
.modelããŒãååšããªãsettings.jsonã§èª€åäœ âjq -r '.model'ã ãšnullæååãè¿ããgrep -qi 'fable'ãäžäžèŽã§æžãããå°æ¥çãªããŒå倿Žãæ¬ èœãèããŠ// emptyã§ç©ºæåãã©ãŒã«ããã¯ãæç€ºãã- self-unloadåŸã«æ¬¡ã¹ãããã§åçºç«ãããå¿é
ãã â
launchctl unloadãå®è¡ããæç¹ã§ãã®ãžã§ãã®ã¹ã±ãžã¥ãŒã«ã¯æ¶ãããåãlaunchctl loadãªãã«ã¯åçºç«ããªã - stderrã®è¡æ¹ãåãããªããªã â
StandardErrorPathãèšå®ããŠããªããšãlaunchdã¯stderrã/dev/nullãäºæž¬äžèœãªå Žæã«æšãŠãããããã°äžèœã«ãªãã®ã§å¿ ãèšå®ãã
æ±çšãã¿ãŒã³ãšããŠ
ãã®ãžã§ãã¯Fable 5ã®EOLåºæã«èŠãããã以äžã®3èŠä»¶ãæãã°ãã®ãŸãŸè»¢çšã§ããã
| èŠä»¶ | æ¬ãžã§ãã§ã®å®è£ |
|---|---|
| ç¹å®æ¥ä»¥éã«äžåºŠã ãå®è¡ | date +%Y%m%dæ¯èŒã§æ¥ä»ã¬ãŒã |
| åªçïŒäœåºŠèµ°ã£ãŠãåãçµæïŒ | çŸåšå€ãã§ãã¯ããŠããæžãæã |
| å®äºåŸã«èªåçã«æ¶ãã | launchctl unload "$PLIST" |
å¿çšäŸïŒ
- ç¹å®æ¥ä»¥éã«configã®æ©èœãã©ã°ãON/OFFãã
- æéåãã®APIãšã³ããã€ã³ããæ°URLã«æžãæãã
- ããŒãžã§ã³ã¢ããã«äŒŽãJSONèšå®ã®ã¹ããŒãç§»è¡
ãäžåºŠã ãå®è¡ããŠã»ããcronãã¯ãcronãlaunchdã«æ°žç¶ç»é²ãããšæ¯åçºç«ããŠããŸãåªçæ§ã®ç¢ºä¿ãé¢åã«ãªããself-unloadã§ãèµ°ã£ããæ¶ãããèšèšã«ããæ¹ããæ°žç¶ãžã§ãã®dedupeåŠçãæžãããåçŽã ã
ãŸãšã
- æ¥ä»ã¬ãŒãïŒ
date +%Y%m%dæ¯èŒïŒã§catch-upçºç«ãç¡å®³åãã ââ æåããå ¥ãã jqãããã¯ããã¯ã¢ããâæžãæãâJSONæ€èšŒâmvã®ã¢ãããã¯4ã¹ããã- çŸåšå€ãã§ãã¯ïŒ
grep -qi 'fable'ïŒã§åªçã«ãããç§»è¡æžã¿ç°å¢ã§ãå®å šã«åå®è¡ã§ãã - **
launchctl unload "$PLIST"**ã§self-unload ââ plistã¯æ®ããŠåç»é²å¯èœã«ãã - plistã®ãã«ãã¹ãããïŒ6:50/12:50/20:50ïŒã§ã¹ãªãŒãæã®skipã«åãã
- Homebrewå
¥ãã®
jqã䜿ããªã**plistã®PATHã«/opt/homebrew/bin**ãå¿ããªã
次åã¯ããã®ãããªäœ¿ãæšãŠãžã§ããå«ããlaunchdå
šäœã®æ»æŽ»ãäžã³ãã³ãã§ãã§ãã¯ãã automation-health.sh ã®è©±ãæžãäºå®ã§ãã
LilyïŒ@bokuwalilyïŒâ å人éçºè ãClaude Code ã§èªåååºç€ãçµã¿ãªãããiOSã¢ããªãWebãµãŒãã¹ãéç£ããŠããŸã
- AIã§ãå¯ãŠãŠãåãä»çµã¿ããäœã£ãŠæ120äžã«ãã話㯠noteã®ææèšäº ã«ð°
- OSS: github.com/bokuwalily ð
- ææ°æ å ±ã»ãåãåãã㯠X @bokuwalily ãžð
çããã® â€ïž ãã·ã§ã¢ãå±ã¿ã«ãªããŸãïŒ