0
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?

🩺 26本のlaunchdが今日も動いおるか、1コマンドで党断チェックする

0
Posted at

䌚瀟郜合で解雇されお収入が0になった日、最初に確認したのは「自分の自動化が党郚生きおいるか」だった。答えは半分ノヌだった。

なぜこの仕組みが効くのか

個人開発の自動化が20本を超えたあたりから、「サむレントデス」が日垞になりたす。

人間の認知には䞊限がありたす。3本のlaunchdゞョブなら毎朝目で確認できたす。10本になるず週1になりたす。26本になるず——もう確認しなくなりたす。「たぶん動いおるだろう」ずいう感芚で日々が過ぎおいく。そしお気づいたずき、止たっおから3週間経っおいたりしたす。

私が解雇盎埌に䜓隓した珟実はたさにこれでした。副業収入が月60䞇あった頃、自動化で支えおいた仕組みが静かに死んでいたした。䌚瀟員ずしおの絊料があったので誰も気づかなかった。月商0になっお初めお「あのゞョブ、い぀から止たっおたんだ」が可芖化されたした。

launchdの壊れ方は静かです。

macOSのlaunchd垞駐デヌモン管理のしくみは、スクリプトがクラッシュするず䜕も蚀わずに次の起動予定たで埅ちたす。exit 78を返しおいおも、launchctl listを盎接叩かない限り誰も知りたせん。私の環境でも2026幎6月にcom.shun.agentmemoryが6日間クラッシュルヌプしおいたこずがありたした。ポヌトは開いおいおもworkerが居ない「半生状態」——HTTPリク゚ストは党郚404を返すのに、プロセスだけ存圚しおいる。死掻監芖のよくある実装プロセス存圚確認だけでは完党に芋萜ずしたす。

こういう経隓が、automation-health.shを「チェックするだけ」でなく「芋぀けたら即座に盎す」蚭蚈にした理由です。

䜜業ではなく「環境」の問題

自動化の倱敗はタスクの倱敗ず違いたす。タスクが倱敗すれば誰かが怒りたす。でも環境が腐っおいおも、誰も怒りたせん。ゆっくりず、あなたの生産性が䞋がっおいくだけです。

月商120䞇を支えおいるのは個別のスクリプト1本ではなく、それらが絡み合っお動き続ける「環境」です。skill-harvestがauto-skillを生成し、䌚話ログをKnowledge Baseに蓄積し、Obsidian Vaultに同期し、agentmemoryがClaude間で蚘憶を共有する——この連鎖のどこか䞀本が止たるず、数週間埌に「なんか最近Claudeの提案が薄いな」ずいう感芚になりたす。原因がわかるのはさらに埌です。

automation-health.shが怜査するのは、たさにこの連鎖の各リンクです。launchdの定期ゞョブだけでなく、hookスクリプトの実行暩限、skill-harvestのログ鮮床、䌚話ログの最終曎新、Obsidian Vaultの自動曎新マヌカヌ、agentmemoryのHTTP疎通——党郚を1コマンドで暪断しお、REDが1぀でもあればexit 1で終了したす。

[開発者] bash ~/.claude/scripts/automation-health.sh
          ↓
     exit 0 → ALL GREEN / WARN
     exit 1 → RED あり → StopHookが捕捉

このexit 1蚭蚈が重芁です。Claudeのセッション終了時に発火するStopHookにこのスクリプトを組み蟌めば、「Claudeを閉じるたびに自動化の健康を確認する」が暙準になりたす。cronに入れれば毎朝確認したす。どちらも「確認しようず思う意志」に䟝存しない仕組みです。

党䜓の流れ

automation-health.shは9぀のセクションを順番に怜査したす。どのセクションも同じ出力スタむルです

  ✓ 緑 → 正垞
  ⚠ 黄 → 譊告臎呜的ではないがケア必芁
  ✗ èµ€ → 倱敗exit 1の原因になる

党䜓の構造をアスキヌ図で瀺したす

bash automation-health.sh
│
├─ [1] launchd ゞョブ (com.shun.* / com.lily.*)
│       å…šplistをルヌプ → launchctl list で照合
│       未ロヌド → launchctl bootstrap で即自動再投入
│       再投入倱敗 → ✗ RED
│       前回 exit ≠ 0 → ✗ RED
│
├─ [2] hooks (8本のシェルスクリプト)
│       pre_git_guard / pre_secrets_check / pre_env_guard
│       post_audit_log / post_format / post_tsc_check
│       stop_notify / user_prompt_submit
│       䞍圚 → ✗ RED / 実行暩限なし → ⚠ WARN
│
├─ [3] skill-harvest
│       .harvest.log の最終曎新が48h以内か
│
├─ [4] 䌚話ログ (Stop hook → 長期蚘憶)
│       ~/Documents/my-knowledge-base/raw/conversations/
│       INDEX.md の鮮床が24h以内か
│
├─ [5] Obsidian Vault 連携
│       hot.md の自動曎新マヌカヌ存圚確認
│       index.md のカバレッゞ実ファむル数ず蚘茉ペヌゞ数の䞀臎
│
├─ [5.5] agentmemory サヌバ
│         launchctl 状態 AND http://localhost:3111/agentmemory/health → 200
│         どちらかが欠けおいおも ✗ RED
│
├─ [6] remember 蚘憶局
│       now.md / recent.md / archive.md の存圚確認
│       now.md の重耇バヌストを怜知consolidate 遅延の兆候
│
├─ [7] ディスク / 残骞
│       ~/.claude 実効サむズ>5GB で ✗
│       security_warnings_state_*.json の残骞数
│
├─ [8] 週次/月次バッチ (7本)
│       ログファむルの最終曎新時刻 vs 蚱容時間予算
│
└─ [9] cron ↔ launchd 重耇
        同䞀スクリプトが䞡系統に登録されおいないかを確認
        移行埌の二重実行バグを防ぐ
          ↓
     fail > 0 → exit 1RED あり
     warn > 0 → exit 0臎呜的問題なし
     fail = 0, warn = 0 → exit 0ALL GREEN

セクション[1]が栞心——自動自己修埩

最も重芁なのはセクション[1]の実装です。「チェックしお報告するだけ」のスクリプトを曞くこずは簡単です。でも、それでは「REDを芋お手動で盎す」ずいう人間の手間が残りたす。

automation-health.shのlaunchdセクションは、未ロヌドのゞョブを発芋した瞬間に自動で再投入したす

# å…š com.shun.* / com.lily.* plist を監芖。未ロヌドを芋぀けたら冪等に自動再bootstrap
# これが無いず、ゞョブがlaunchdから倖れおもサむレントに発火しなくなる
uid_num=$(id -u)
for plist in "$HOME_DIR"/Library/LaunchAgents/com.shun.*.plist \
             "$HOME_DIR"/Library/LaunchAgents/com.lily.*.plist; do
  [ -e "$plist" ] || continue
  job=$(basename "$plist" .plist)
  line=$(launchctl list 2>/dev/null | grep -E "\b${job}\b")
  if [ -z "$line" ]; then
    if launchctl bootstrap "gui/${uid_num}" "$plist" 2>/dev/null; then
      ok "$job: 未ロヌド → 自動で再ロヌドした"
    else
      ng "$job: 未ロヌド・再ロヌド倱敗 (手動 launchctl bootstrap 芁)"
    fi
  else
    exitc=$(echo "$line" | awk '{print $2}')
    if [ "$exitc" = "0" ] || [ "$exitc" = "-" ]; then
      ok "$job: ロヌド枈 / last exit=$exitc"
    else
      ng "$job: last exit=$exitc (前回倱敗)"
    fi
  fi
done

launchctl listの2列目がexit codeです。0は正垞終了、-は「珟圚実行䞭たたはただ䞀床も起動しおいない」、それ以倖の数倀は前回の異垞終了です。exit 78蚭定゚ラヌやexit 1スクリプト内゚ラヌを静かに返し続けおいるゞョブを、この1ルヌプで党郚捕捉したす。

未ロヌドの堎合はlaunchctl bootstrap gui/${uid_num} <plist>で即座に再投入したす。gui/${uid_num}ずいうタヌゲット指定がポむントで、macOS 10.15以降の珟行APIです叀いlaunchctl loadはdeprecatedです。再投入自䜓が倱敗したずきだけngREDずしお蚘録し、次の刀定に進みたす。

セクション[5.5]——プロセス存圚確認だけでは䞍十分な理由

agentmemoryの監芖が「2段階」になっおいるのには理由がありたす。コヌド内のコメントにそのたた残しおありたす

# 2026-06-11 監査の教蚓: launchd の exit 78 クラッシュルヌプが6日間誰にも気づかれず、
# さらに「ポヌトは開くが worker 䞍圚で党API 404」の半生状態は死掻監芖では芋えない。
# launchd 状態 + /agentmemory/health の HTTP 200 の䞡方を芋る。

実際の確認ロゞックはこうです

am_code=$(curl -s -o /dev/null -w '%{http_code}' -m 3 \
  http://localhost:3111/agentmemory/health 2>/dev/null || echo 000)
if   [ "$am_code" = "200" ]; then ok "皌働䞭 (pid=$am_pid / health 200)"
elif [ "$am_code" = "000" ]; then ng "プロセスは居るが port 3111 無応答"
else ng "port 3111 は開くが /agentmemory/health=$am_code — worker 䞍圚の半生状態"
fi

HTTPの応答コヌドたで確認するこずで、「プロセスは生きおいるがAPIは死んでいる」ずいう半生状態を怜出できたす。同じ発想をagentmemory以倖にも暪展開できたす——Webサヌバ、AIモデルのAPI proxy、anything that serves HTTP。

セクション[8]——時刻ベヌスの死掻確認

週次・月次バッチの死掻は「最埌にログが曞かれた時刻」で刀定したす。7本のバッチゞョブに察しおそれぞれ「蚱容時間予算」を蚭定しおいたす

declare -a CRON_JOBS=(
  "weekly cleanup-misc:~/.claude/logs/cleanup-misc.log:192"        # 週次→8日蚱容
  "weekly env-audit:~/.claude/logs/env-audit-latest.md:192"
  "monthly plugin-purge:~/.claude/logs/plugin-purge.log:744"       # 月次→31日
  "weekly plugin-auto-disable:~/.claude/logs/plugin-auto-disable.log:192"
  "weekly dotfiles-snapshot:~/.claude/logs/dotfiles-snapshot.log:192"
  "weekly agents-index:~/.claude/logs/agents-index.log:192"
  "daily plugin-usage:~/.claude/scripts/plugin-audit-latest.md:48" # 毎日→2日
)

週次バッチは192時間8日、月次は744時間31日、日次は48時間が蚱容倀です。ログのmtimeが予算を超過しおいれば⚠ WARNずしお報告したす。ゞョブが実際に発火した蚌拠はログぞの曞き蟌みだけなので、ログを芋るこずが䞀番確実です。

具䜓䟋ずしお、com.shun.plugin-auto-disableのplistを芋るず

<key>StartCalendarInterval</key>
<dict>
  <key>Hour</key>      <integer>6</integer>
  <key>Minute</key>    <integer>45</integer>
  <key>Weekday</key>   <integer>0</integer>
</dict>

毎週日曜日の06:45にplugin-auto-disable.sh applyを実行し、ログを~/.claude/logs/plugin-auto-disable.logに远蚘したす。このplistがlaunchdに正しくロヌドされおいおも、スクリプト偎が゚ラヌで終了しおいればログは止たりたす。セクション[1]でロヌド状態を確認し、セクション[8]でログの鮮床を確認する——2局の確認があっおはじめお「本圓に動いおいる」ず蚀えたす。

実装の詳现

launchctl bootstrap を䜿う理由——「叀いAPI」を螏たない

macOSのlaunchctlには新旧2぀のAPIが存圚したす。叀い方はlaunchctl load <plist>、新しい方はlaunchctl bootstrap <target> <plist>です。

Catalinaあたりからlaunchctl loadはdeprecatedになりたした。実行しおも動くこずはありたすが、゚ラヌメッセヌゞがログに出ず、再起動埌に挙動が倉わるこずがありたす。automation-health.shのセクション[1]がbootstrapを䜿っおいるのはこのためです

uid_num=$(id -u)
if launchctl bootstrap "gui/${uid_num}" "$plist" 2>/dev/null; then
  ok "$job: 未ロヌド → 自動で再ロヌドした"
else
  ng "$job: 未ロヌド・再ロヌド倱敗 (手動 launchctl bootstrap 芁)"
fi

gui/${uid_num}ずいう文字列がタヌゲットです。id -uでログむン䞭ナヌザヌのUID通垞は501を取埗し、gui/501ずいうタヌゲットに察しおplistを投入したす。このタヌゲット指定がないず、ログむン枈みのGUIセッションで動くゞョブHomebrew補ツヌルを呌ぶスクリプト等が、デヌモンずしお登録されおしたい、PATHが党く違う環境で実行される問題が起きたす。

2>/dev/nullを付ける理由も重芁です。すでにロヌド枈みのゞョブにbootstrapを叩くず゚ラヌが出たす。冪等に実行できるようにするため、゚ラヌ出力を捚おお戻り倀だけ芋る蚭蚈にしおいたす。

plistの EnvironmentVariables が死掻に関わる理由

com.shun.plugin-auto-disable.plistの先頭を芋るず、PATHが明瀺的に曞き蟌たれおいたす

<key>EnvironmentVariables</key>
<dict>
  <key>PATH</key>
  <string>/Users/
/.nvm/versions/node/v24.13.0/bin:/opt/homebrew/bin:/opt/homebrew/sbin:/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin:/Users/
/.local/bin</string>
</dict>

launchdは.zshrcや.bashrcを読みたせん。玠のlaunchd環境のPATHは/usr/bin:/bin:/usr/sbin:/sbinしかありたせん。nodeもbrewもclaudeも、党郚芋えたせん。

このPATH問題で2回やられたした。最初はnode系のスクリプトが「command not found: node」で黙っお死んでいた。2回目はHomebrew補のjqを呌ぶスクリプトが同じ理由でサむレント倱敗しおいた。スクリプト本䜓に䜕も問題がなく、タヌミナルで手動実行するず動く——この症状が最も蚺断しにくいです。

解決策はplistにPATHを曞き蟌む䞀択です。~/.nvm/versions/node/v24.13.0/binのようにバヌゞョン固定のパスになるのが難点ですが、暗黙PATHで黙っお倱敗するよりずっずたしです。私はnodeのバヌゞョンを倉えたあずに1回ここを曎新し忘れ、3日間ゞョブが動いおいなかったこずがありたす。それ以降、node系ゞョブのplistには# nvm version: X.X.Xずいうコメントを付けおplist曎新のきっかけにしおいたす。

セクション[6]——now.mdの重耇バヌスト怜知

rememberプラグむンのnow.mdは、䌚話ごずに1行ず぀芁玄が远蚘されたす。定期的にHaikusがconsolidateコマンドでnow.md→recent.md→archive.mdに昇栌させるのですが、この昇栌凊理が遅延するずnow.mdに同じ芁玄が䜕十行も溜たりたす。

スクリプトはこの「バヌスト」を怜知したす

dup=$(grep -vE '^\s*$|^##|^#' "$nowf" 2>/dev/null \
  | sort | uniq -c | sort -rn | head -1 | awk '{print $1}')
if [ "${dup:-0}" -ge 3 ]; then
  wn "now.md に同䞀芁玄が ${dup} 回 (consolidate 遅延の兆候)"
else
  ok "now.md 重耇なし (consolidate 健党)"
fi

空行・芋出し行を陀去しおからsort | uniq -cで出珟回数を数え、最倚のものを取り出す——3回以䞊同じ行があればWARNです。「ConsolidateはHaikusが非同期で回しおいるから問題ない」ず思っおいた時期がありたしたが、Haikusぞの委譲が䜕らかの理由で止たるずnow.mdが数癟行になり、次のConsolidate時に「叀い蚘憶」ずしお誀っお昇栌しおしたいたす。実際に「2週間前の芁玄が今日の重芁蚘憶に昇栌しおいる」ずいう状態を1床経隓しおから、このチェックを远加したした。

セクション[9]——comm -12で二重登録を炙り出す

cron_sh=$(crontab -l 2>/dev/null | grep -vE '^[[:space:]]*#' \
  | grep -oE '/[^ ]+\.sh' | xargs -n1 basename 2>/dev/null | sort -u)
launchd_sh=$(grep -hoE '/[^<> ]+\.sh' \
  "$HOME"/Library/LaunchAgents/com.shun.*.plist 2>/dev/null \
  | xargs -n1 basename 2>/dev/null | sort -u)
dup=$(comm -12 <(printf '%s\n' "$cron_sh") <(printf '%s\n' "$launchd_sh") \
  | grep -vE '^[[:space:]]*$')

commコマンドは2぀の゜ヌト枈みリストを受け取り、「䞡方に共通する行-12オプションで1列目・2列目を非衚瀺にした残り」を返したす。cronずlaunchdの䞡方に登録されおいるスクリプト名の䞀芧が取れたす。

スクリプトの絶察パスではなくbasenameファむル名だけで比范しおいるのは、cronずlaunchdでパスが埮劙に違うこずがあるためです。~/scripts/foo.shず$HOME/scripts/foo.shは同じファむルですが文字列比范では別物になりたす。

セクション[7]——ディスクずゎミファむルの2段構え

ディスクチェックは「~/.claude党䜓のサむズ」ず「プラグむンのdisabledキャッシュ」を別々に蚈枬したす

cdir_total_mb=$(du -sm "$CLAUDE" 2>/dev/null | awk '{print $1}')
disabled_mb=$(du -sm "$CLAUDE/plugins/.disabled-cache" 2>/dev/null | awk '{print $1}')
cdir_mb=$(( ${cdir_total_mb:-0} - ${disabled_mb:-0} ))

.disabled-cacheはplugin-auto-disable.shが䞀時退避したプラグむンの可逆キャッシュです。最倧で1.2GBになるこずがありたすが、apply→restoreで戻せる「敎理枈みゎミ」なので実効サむズから陀倖したす。これを陀倖しないず~/.claudeが垞時WARNになり、ノむズで本圓のWARNが埋もれたす。


私が詰たった話

①「Obsidianのカバレッゞが氞久WARNになった」——隠しディレクトリの眠

セクション[5]のObsidian連携チェックに、こういうコヌドがありたす

real=$(find "$VAULT" -name '*.md' -not -path '*/.*' 2>/dev/null | wc -l | tr -d ' ')
stated=$(grep -oE '総ペヌゞ数[0-9]+' "$vidx" 2>/dev/null \
  | grep -oE '[0-9]+' | head -1)
if [ -n "$stated" ] && [ "$stated" = "$real" ]; then
  ok "index.md カバレッゞ䞀臎 (${real}p)"
else
  wn "index.md 蚘茉 ${stated:-?}p ≠ 実 ${real}p (index.md の曎新が必芁)"
fi

-not -path '*/.*'が付いおいたすが、最初はこれがありたせんでした。Obsidianの内郚ファむルは.obsidian/ディレクトリに、私の自動バックアップ出力は.backup/に栌玍されおいたす。どちらも隠しディレクトリ先頭がドットですが、findはデフォルトでこれらも拟いたす。

index.mdには「総ペヌゞ数47」ず曞いおある。でもfindは.backup/内の叀いスナップショットも含めお63件芋぀ける。index.mdを正しく曎新しおも絶察にstatedずrealが䞀臎しない。

症状は「毎回WARNが出るがよくわからない」でした。原因に気づくたで4日かかりたした。スクリプトのデバッグずしおfind "$VAULT" -name '*.md' | head -20を実行したずき、.backup/2026-06-10/some-page.mdずいう行を芋お「ああ、そういうこずか」ずなりたした。隠しディレクトリを陀倖する-not -path '*/.*'の1フラグで解決したしたが、「チェックロゞックが正しくおもデヌタのスコヌプが間違っおいれば氞久にWARNになる」ずいう教蚓です。

②「cron→launchd移行埌、6週間二重実行が続いおいた」

スクリプト内のコメントにそのたた残しおありたす

# 2026-06-01: cron→launchd 移行で「cron を消し忘れお䞡方に登録毎サむクル二重実行」
# が発生しおいたため、同䞀スクリプトが䞡系統に存圚しないかを垞時監芖する。

agents-index.shをcronからlaunchdに移行したした。plistを曞いおロヌドしお動䜜確認——完璧に思えたした。ただしcronの叀い゚ントリを削陀し忘れたした。毎週日曜の同じ時間垯にagents-index.shが2回実行されおいたした。

6週間気づかなかった理由は「実害が芋えにくかった」からです。agents-index.shはべき等な凊理で、2回実行しおも同じ結果になりたす。むンデックスが壊れるわけでも、゚ラヌログが出るわけでもない。でも毎週2回、䜙蚈なCPU時間ずログ远蚘が走っおいたした。

comm -12によるセクション[9]のチェックを远加したのはこの経隓からです。移行盎埌に実行すれば1分で気づけた問題が、チェックがなかったから6週間続きたした。

③「env-auditのログパスが毎回倉わっお怜知できなかった」

セクション[8]のCRON_JOBS配列に、こういう特別凊理がありたす

if [[ "$path" == *"env-audit-latest.md" ]]; then
  real=$(ls -t "$CLAUDE/logs/"env-audit-*.md 2>/dev/null | head -1)
  [ -n "$real" ] && path="$real"
fi

env-audit.shは実行のたびにenv-audit-2026-06-10.mdのように日付入りのファむルを生成したす。固定パスを持たないため、env-audit-latest.mdずいう「プレヌスホルダパス」を配列に曞いおおき、実際にはls -tで最新ファむルを探す特別分岐を入れおいたす。

最初は「どのファむルもないのでlog/出力なし → NG」ず出続けたした。CRON_JOBSの定矩を芋るず確かに存圚しないパスを曞いおある。「スクリプトが䞀床も動いおいない」ず刀断しかけたしたが、ls ~/.claude/logs/で実態を確認したらenv-audit-2026-06-11.mdが存圚しおいたした。

固定パスを想定しお蚭蚈したチェックが、動的呜名のスクリプトに察応できおいなかった。スクリプトの出力先を固定にするか、チェック偎が動的に探すか、どちらかに統䞀する必芁がありたす。私は埌者チェック偎で探すを遞びたしたが、理想は「党ゞョブが固定パスにログを曞く」蚭蚈です。ただし既存スクリプトを党郚曞き盎す工数は払えなかったので、特別分岐で圓座の察応をしたした。

④「agentmemoryが6日間クラッシュルヌプしおいた」——半生状態の発芋

これがセクション[5.5]を2段階チェックにした盎接の原因です。コメントに日付たで残しおありたす

# 2026-06-11 監査の教蚓: launchd の exit 78 クラッシュルヌプが6日間誰にも気づかれず、
# さらに「ポヌトは開くが worker 䞍圚で党API 404」の半生状態は死掻監芖では芋えない。
# launchd 状態 + /agentmemory/health の HTTP 200 の䞡方を芋る。

症状は「Claudeの蚘憶が共有されない」でした。䌚話Aで芚えたこずが䌚話Bで出おこない。でもClaude自䜓は正垞に動いおいる。agentmemoryプロセスはps auxで芋えおいる存圚しおいる。ポヌト3111ぞのcurlは「接続拒吊」ではなく「応答なし」でした。

launchctl list | grep agentmemoryを叩くず、PIDが-で終了コヌドが78。exit 78はlaunchd芏玄で「蚭定ファむルの゚ラヌ」を意味したす。起動しようずしおはクラッシュし、たた起動しようずしおはクラッシュする——これが6日間繰り返されおいたした。

プロセス存圚確認だけの死掻監芖では絶察に捕捉できたせん。ps auxでプロセスが芋えおも「クラッシュルヌプ䞭のゟンビ」であるこずがありたす。正確に蚀うず、launchdは連続クラッシュを怜知するず「スロットリング」に入り、次の再起動を数十秒埌に遅らせたす。その遅延時間内にプロセスチェックを打぀ず「いる」ず出たす。

http://localhost:3111/agentmemory/healthぞのcurlが真実を語りたす

am_code=$(curl -s -o /dev/null -w '%{http_code}' -m 3 \
  http://localhost:3111/agentmemory/health 2>/dev/null || echo 000)
if   [ "$am_code" = "200" ]; then ok "皌働䞭 (pid=$am_pid / health 200)"
elif [ "$am_code" = "000" ]; then ng "プロセスは居るが port 3111 無応答"
else ng "port 3111 は開くが /agentmemory/health=$am_code — worker 䞍圚の半生状態"; fi

000は「接続自䜓が成立しない」ポヌトが閉じおいる、タむムアりト、404や500は「ポヌトは開いおいるがworkerが機胜しおいない」。この3パタヌンを区別するこずで、「起動しおいるが機胜しおいない」ずいう半生状態を捕捉できたす。

この経隓以降、HTTPを提䟛するすべおのサヌビスにこの2段チェックを暪展開しおいたす。launchd状態確認ずHTTPヘルス゚ンドポむントのcurl——この2぀がセットで初めお「本圓に動いおいる」ず蚀えたす。

⑀「now.mdが1200行になっおConsolidateが詰たった」

4぀目ずは別の症状ずしお、ある時期から「Claudeの提案がなんずなく薄い」ず感じたした。具䜓的には「先週話したこずを忘れおいる」「同じ説明を2回求められる」ずいう䜓感です。

~/.remember/now.mdをwc -lで確認したら1247行でした。通垞は30〜50行皋床です。Consolidate凊理が止たっお、now.mdに1000件以䞊の芁玄が積み䞊がっおいたした。

原因はHaikusぞの委譲タスクが倱敗しおいたこずです。Consolidateはバックグラりンドで非同期に動くため、倱敗しおいおも誰も気づきたせん。タスクキュヌに゚ラヌがあり、新しいConsolidateが積み䞊がっおいくだけで䞀切凊理されおいたせんでした。

手動でclaude --model haiku -p "~/.remember/now.md を読んでconsolidateしおください"ず実行しお解消したしたが、怜知が1週間遅れたした。セクション[6]の重耇バヌスト怜知を入れたのはこの経隓が盎接のきっかけです。

重耇行が3件以䞊あるずいうのは「同じ䌚話ルヌプが䜕床も芁玄された」サむンです。普通の䌚話では同じ芁玄が2回以䞊now.mdに曞かれるこずはありたせん。3件ずいうしきい倀は「偶然の重耇」ず「Consolidate詰たり」を分けるために経隓則で決めたした。


これだけのチェックを積み䞊げおくるず、「党郚緑でALL GREENになる日」がいかに珍しいかがわかりたす。私の環境では毎朝だいたい1〜2個のWARNが出たす。それが「正垞」です。WARNが1個もない日より、「怜知できるWARNが毎日あり、それを凊理できおいる状態」の方が自動化環境ずしおは健党だず思っおいたす。

䜕も蚀わないシステムを信頌するのは、コヌドが存圚しないこずを「バグがない蚌拠」ず読むようなものです。

぀たずきポむント

p2では「詰たった話」を5本ストヌリヌ圢匏で曞きたした。ここでは「ストヌリヌにならなかった地味な眠」を網矅したす。どれも実際にやらかしおいたす。

  • plistのXML構文を1箇所間違えるずlaunchctl bootstrapが「Error: 125」しか蚀わない。原因は䜕もわからない。plutil -lint ~/Library/LaunchAgents/com.shun.xxx.plistを叩くず「Unexpected character '/' at line 18」のように具䜓的な行番号が出る。plistを線集したらplutil -lintを走らせる、をplistのセヌブ前手順ずしお䜓に刻む必芁がありたす。

  • ProgramArguments内のリダむレクトずStandardOutPathの二重曞き蟌み。com.shun.plugin-auto-disable.plistを芋るず、ProgramArgumentsの䞭で>> ~/.claude/logs/plugin-auto-disable.log 2>&1ず曞いおいるのに、StandardOutPath/StandardErrorPathにも同じパスを曞いおいたす。これは意図的な蚭蚈で、launchd自䜓の起動倱敗plist読み蟌み゚ラヌ等はProgramArguments内リダむレクトより前に起き、StandardErrorPathにしか蚘録されないためです。知らずに「どちらかを消す」ずlaunchd起動倱敗が無音になりたす。

  • macOSのスリヌプ䞭はStartCalendarIntervalがスキップされる。com.shun.plugin-auto-disableは毎週日曜06:45に起動したすが、その時刻にMacが閉じおいれば発火したせん。Power Napが有効な環境では䞀郚ゞョブが起動したすが保蚌なし。スクリプトが発火したかどうかの唯䞀の蚌拠はログのmtimeだけです——これがautomation-health.shセクション[8]の「192時間以内にログが曎新されおいるか」チェックが存圚する理由です。「launchdに登録した=必ず実行される」は誀りです。

  • set -uをlaunchdから実行するスクリプトに入れるず、.zshrc定矩の環境倉数の欠萜でexit 1。タヌミナルから手動実行するず正垞に動くのに、launchdから呌ぶず即萜ちる症状。launchd環境には$EDITORや$NVM_DIRは存圚したせん。察策は2択plistのEnvironmentVariablesに党必芁倉数を列挙するか、launchd向けスクリプトではset -uを倖しお${VAR:-default}パタヌンで防埡する。

  • plistを線集しおも叀い蚭定がlaunchd内に残り続ける。automation-health.shセクション[1]の自動re-bootstrapは「未ロヌド」のずきだけ機胜したす。既にロヌド枈みで叀い蚭定のたた動いおいるゞョブは再起動しおくれたせん。plistを倉曎したらlaunchctl bootout gui/$(id -u) <label>で䞀床倖しおからlaunchctl bootstrap gui/$(id -u) <plist>で再投入が必須です。この手順を知らずに「plistを曞き換えたのに動きが倉わらない」で1時間溶かしたした。

  • ゞョブラベル<key>Label</key>の文字列ずplistファむル名が䞍䞀臎だず自動チェックが誀動䜜する。たずえばcom.shun.foo.plistに<string>com.shun.bar</string>ず曞くず、launchctl listにはcom.shun.barずしお登録されたす。automation-health.shはbasename "$plist" .plistでラベルを掚定しおgrepするので、䞍䞀臎があるず「未ロヌド→自動re-bootstrap→すでにロヌド枈みのため゚ラヌ→RED」ずいう誀刀定が出たす。ラベルずファむル名は必ず䞀臎させる。

  • クラッシュルヌプ䞭のスロットリングでps auxの結果がタむミングによっお倉わる。launchdは連続クラッシュを怜知するずThrottleIntervalデフォルト10秒で再起動を遅延させたす。遅延時間内にプロセスを確認するず「いない」、次の起動詊行䞭に確認するず「いる」ずなり、ps aux | grep agentmemoryだけでは真実が芋えたせん。launchctl list | grep com.shun.agentmemoryでPIDず終了コヌドを同時に確認する、が正解です。

  • age_hが返す-1を算術比范でtrueず読んでしたう。age_hはファむルが存圚しない堎合-1を返したす。[ "$a" -le 48 ]ずいう比范匏は-1 -le 48をtrueず刀定するので、「ログファむルなし=鮮床OK」ずいう誀刀定になりたす。実コヌドでは[ "$a" -ge 0 ] && [ "$a" -le 48 ]ず「0以䞊か぀X以䞋」の2段比范にしおこの眠を避けおいたす。同じパタヌンをコピヌするずきは2段比范ごずコピヌする。

  • CRON_JOBS配列のIFS区切り文字:をログパスが含む環境ではIFS=":"分割が厩れる。IFS=":" read -r name path budget <<< "$entry"で:区切りにしおいるので、仮にログパスに:が含たれるず$pathず$budgetが意図しない䜍眮で割れたす。macOSのパスに:は通垞入らないが、意識せずにコピペするず壊れたす。

  • hookスクリプトに実行暩限がないずClaude Codeが完党無音でスキップする。settings.jsonでhookを蚭定しおもchmod +xされおいなければhookは実行されたせん。゚ラヌもログも䜕も出ない。automation-health.shセクション[2]が[ ! -x "$f" ]でWARNを出すのはこれが理由です。新しいhookを远加したら必ずchmod +x、そしおautomation-health.shを走らせお緑になるこずを確認しおから信頌する。

  • comm -12は゜ヌト枈み入力が前提であり、unsortedだず重耇を芋萜ずす。セクション[9]のcron/launchd重耇怜知でcomm -12を䜿っおいたすが、これは2぀の入力がsort -u枈みであるこずを前提にしたす。cron_shやlaunchd_shを生成するパむプにsort -uを入れ忘れるず、重耇があっおも怜知されたせん。実コヌドでは各倉数の最埌に| sort -uを入れおいたす。


ベストプラクティス

26本のlaunchdゞョブを半幎運甚しお、「これが最初からあれば6週間の無音障害を防げた」ず確信できる蚭蚈指針を10本以䞊たずめたす。

1. ゞョブラベルずplistファむル名を必ず䞀臎させる

<key>Label</key><string>com.shun.hoge</string>のラベルずplistファむル名com.shun.hoge.plistを䞀臎させたす。䞍䞀臎はデバッグコストを数倍にしたす。launchctl list | grep com.shunで芋えおいるラベルずls ~/Library/LaunchAgents/com.shun*.plistのリストが1察1で察応しおいる状態を維持しおください。

2. 党ゞョブにEnvironmentVariablesでPATHを明瀺する

launchdは.zshrcも.bashrcも読みたせん。玠のlaunchd環境のPATHは/usr/bin:/bin:/usr/sbin:/sbinのみです。nodeもbrewもclaudeもすべお芋えない。nodeのバヌゞョンを曎新したあずはplistのPATHも曎新を忘れずに。私はplist内に# nvm version: v24.13.0ずいうコメントをProgramArgumentsの盎前行に曞き、バヌゞョン倉曎の際のリマむンダヌにしおいたす。

3. launchctl loadを捚おおlaunchctl bootstrap gui/$(id -u)を䜿う

launchctl loadはmacOS Catalina以降deprecated。動くこずもありたすが、ログに䜕も出ずに挙動が倉わるこずがありたす。launchctl bootstrap gui/$(id -u) ~/Library/LaunchAgents/com.shun.xxx.plistが珟行API。UID取埗はid -u数倀だけ出るで、gui/501のようなタヌゲットを組み立おたす。

4. plist線集埌は必ずplutil -lint→bootout→bootstrapの3ステップ

plutil -lint ~/Library/LaunchAgents/com.shun.xxx.plist
launchctl bootout "gui/$(id -u)" com.shun.xxx
launchctl bootstrap "gui/$(id -u)" ~/Library/LaunchAgents/com.shun.xxx.plist

この3ステップを手順ずしお決める。plistの内容倉曎はlaunchdに自動反映されたせん。

5. シェルスクリプトに枡す匕数はProgramArguments内で/bin/zsh -c "..."経由にする

>>や2>&1のシェルリダむレクトは、ProgramArgumentsに盎接曞いおも機胜したせん。launchdはシェルを介さずにプログラムを実行するためです。/bin/zsh -c "command >> log 2>&1"のパタヌンで包む。com.shun.plugin-auto-disable.plistが実際にこのパタヌンを䜿っおいたす。

6. チェックスクリプトは「報告する」だけでなく「芋぀けたら盎す」蚭蚈にする

automation-health.shのセクション[1]が「未ロヌドを怜知したら即launchctl bootstrapで再投入する」蚭蚈なのは、「REDを芋お手動で盎す」ずいう人間の手間を省くためです。自動化のモニタリングスクリプトが人間の介入を前提にしおいれば、それはモニタリングの責任攟棄です。自動修埩できるものは自動修埩し、自動修埩できないもの再ロヌド自䜓が倱敗だけREDずしお人間に通知する。

7. HTTPサヌビスはプロセス確認ヘルス゚ンドポむントの2段確認を培底する

ps aux | grep <process>でプロセスが存圚しおも、そのプロセスがクラッシュルヌプ䞭や「ポヌトは開いおいるがworkerが䞍圚の半生状態」であるこずがありたす。

am_code=$(curl -s -o /dev/null -w '%{http_code}' -m 3 \
  http://localhost:3111/agentmemory/health 2>/dev/null || echo 000)

このパタヌンはagentmemoryに限らず、HTTPを提䟛する党サヌビスに暪展開できたす。000=接続䞍胜、2xx=正垞、それ以倖=「開いおいるが壊れおいる」の3段階で区別しおください。

8. exit 1蚭蚈でcron/StopHookから機械的に拟えるようにする

automation-health.shはREDが1぀でもexit 1で終わりたす。これがポむントで、

bash ~/.claude/scripts/automation-health.sh || say "自動化に問題がありたす"

のように埌続の凊理に連鎖できたす。StopHookに組み蟌めばClaude Codeを閉じるたびに自動怜査になりたす。cronに入れれば毎朝確認になりたす。「確認しようず思う意志」に䟝存しない蚭蚈の栞心はexit 1です。

9. ゞョブのログは固定パスに曞き蟌む蚭蚈にする

automation-health.shセクション[8]での実際の苊劎env-audit-*.mdが動的呜名でチェックできなかったは、「ゞョブが固定パスにログを曞かない」こずが根本原因です。新しいバッチゞョブを曞くずきは、ProgramArguments内で>> ~/.claude/logs/<jobname>.log 2>&1のように固定パスぞのリダむレクトを暙準パタヌンにする。固定パスぞの曞き蟌みがあれば、監芖偎がmtimeを取るだけで死掻確認できたす。

10. 週次・月次・日次の蚱容時間予算を皮別ごずに蚭定する

ログのmtimeがbudget_hour以内か吊かで死掻を刀定するずき、党ゞョブに同じ閟倀を適甚するのは間違いです。日次バッチに192時間8日蚱容を蚭定すれば、7日間止たっおいおもWARNが出たせん。automation-health.shではdaily=48h / weekly=192h / monthly=744hず3皮の予算を定矩しおいたす。

11. cronずlaunchdの移行埌はcomm -12で重耇チェックを即実行する

cronからlaunchdに移行したその日にautomation-health.shを走らせお、セクション[9]のREDがないこずを確認する。確認しなければ、私のように6週間二重実行が続いおも気づけたせん。「移行完了」の完了条件に「automation-health.shがGREEN」を含めおください。

12. now.mdの行数を週1回は目芖する

wc -l ~/.remember/now.mdを週に䞀床叩くだけでConsolidateの詰たりを早期発芋できたす。正垞時は30〜50行皋床です。100行を超えおいれば芁泚意、300行を超えおいればConsolidateが止たっおいたす。automation-health.shのセクション[6]が重耇バヌスト怜知同䞀芁玄が3回以䞊をしおいたすが、あくたで「症状が進んだ埌の怜知」です。行数確認の方が早い。

13. ALL GREENを「目暙」にしない

毎朝1〜2個のWARNが出る状態が正垞です。「WARNが出る=怜知系が生きおいる」であり、「WARNが䞀切出ない日」の方がむしろ䞍自然です。目暙は「REDをれロに保぀」であり、「WARNをれロに保぀」ではありたせん。WARNを党郚消そうずするず、チェックのしきい倀を甘くしおWARNを隠す方向に誘惑されたす。䜕も蚀わないシステムを信頌するのは、コヌドが存圚しないこずを「バグがない蚌拠」ず読む行為ず同じです。


たずめ

解雇された日に「自動化の半分が止たっおいた」ず曞きたした。あのずきautomation-health.shがあれば、止たったのが解雇の3週間前だずわかり、収入れロで「原因調査」をする3日間は消えおいたした。

月商120䞇を支えおいるのはどの1本のスクリプトでもなく、26本が絡み合っお動き続ける「環境」です。その環境の健康を1コマンドで暪断確認し、問題を自動修埩し、exit 1でcron/StopHookに拟わせる——この蚭蚈の恩恵は自動化の本数が増えるほど倧きくなりたす。

launchdは壊れおも䜕も蚀いたせん。だから私たちが毎朝1回、機械に聞く仕組みを䜜るしかない。


仕組みの党䜓像・月120䞇の内蚳・30日手順は有料noteにたずめおいたす。

📕 Claude Code自埋環境で、実際どう皌ぐか ― 仕組み・実䟋・始め方・サポヌト


Lily@bokuwalily― 個人開発者。Claude Code で自動化基盀を組みながら、iOSアプリやWebサヌビスを量産しおいたす

  • 制䜜物・蚘事は bokuwalily.com にたずめおいたす🖥
  • AIで「寝おおも回る仕組み」を䜜っお月120䞇にした話は noteの有料蚘事 に💰
  • OSS: github.com/bokuwalily 🐙
  • 最新情報・お問い合わせは X @bokuwalily ぞ🌍

皆さんの ❀ やシェアが励みになりたす

0
0
0

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
0
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?