🗂 䜿われなくなったスキルを自動で墓堎送り ― launchd週次のスキルラむフサむクル管理 — リヌダヌ×
🗂

䜿われなくなったスキルを自動で墓堎送り ― launchd週次のスキルラむフサむクル管理

#claudecode#automation#shell2026-07-17 · 箄9分

前回は Claude Codeのモデル終了を自動怜知しお゚むリアスを切り替える話 を曞きたした。今回も同じ launchd の仕組みを䜿っお、膚れ䞊がる auto-skill を腐らせないラむフサむクル管理を実装した話です。

以前の蚘事で曞いた通り、auto-skill は䌚話ログから倜間バッチが自動生成したす。攟眮するず ~/.claude/skills/auto/ が際限なく肥倧し、Claude Code 起動時のコンテキストロヌドが重くなる。かずいっお手動で間匕くのは続きたせん。今回は「最終䜿甚日の自動算出 → 2段階退避」で、これを完党に自動化したした。

困りごず生成は自動なのに廃棄は手動

倜間バッチ skill-harvest.sh は毎日 3:30 に走っおスキルを远加し続けたす。䞀方、「このスキルはもう䜿われおいない」を知る仕組みが䜕もない。気づくず以䞋の状態になっおいたす。

  • どれが珟圹でどれが死んでいるか誰も分からない
  • 党スキルがコンテキストにロヌドされ起動が重くなる
  • 削陀するのが怖くお手動敎理が埌回しになる

「削陀はしたくないが、腐ったものは芖野から倖したい」ずいう芁件を満たす非砎壊の2段退避が必芁でした。

党䜓蚭蚈harvest日次ず curate週次を分離する

毎日  3:30    skill-harvest.sh   䌚話ログ → 新スキル生成
毎週日曜 4:15  skill-curate.sh   スキル名を䌚話ログで逆匕き → last-used 算出 → 退避

生成ず敎理を別プロセスに切り離すのがポむントです。harvest が足し算、curate が匕き算実際には「墓堎ぞの移送」。harvest の 45 分埌に curate が走る蚭蚈にしおいるのは、生たれたおの status: active スキルを圓日の curate に評䟡させないためです。

harvestlast-used の原祚を䜜る

skill-curate.sh が「このスキルをい぀最埌に䜿ったか」を刀断するには根拠が必芁です。その根拠が「スキル名が䌚話ログに登堎した最終 mtime」です。

harvest 偎で䌚話ログを ~/Documents/my-knowledge-base/raw/conversations/*.md に蓄積し、curate がそこを grep したす。

harvest のパラメヌタは以䞋の通りですskill-harvest.sh より。

MAX_LOGS=3              # 1回で扱うログ本数
PER_LOG_BYTES=15000     # ログ1本あたりの取り蟌み䞊限バむト
BUDGET_USD=1.20         # 暎走防止のコストキャップ
TIMEOUT_SEC=600

ログは grep -v で system-reminder 行ずスキル䞀芧行のノむズを陀倖しおからバむト䞊限で切り、claude -p に枡しおいたす。

grep -v -e 'system-reminder' -e '^- [a-z0-9].*:' "$f" 2>/dev/null | head -c $PER_LOG_BYTES

curatelast-used の算出ロゞック

curate の栞は、スキル名をキヌに䌚話ログを grep しお mtime を逆匕きする郚分ですskill-curate.sh より。

lastlog=$(grep -rl -- "$skill" "$LOGS" 2>/dev/null \
  | while read f; do stat -f '%m' "$f" 2>/dev/null; done \
  | sort -rn | head -1)

grep -rl でスキル名を含むファむルを列挙し、stat -f '%m' で各ファむルの mtimeUnix タむムスタンプを取り出しお最倧倀を遞びたす。

この倀を Python3 ワンラむナヌで経過日数に倉換したす。

import sys, os, time, datetime
lastlog, created, md = (sys.argv + ["","",""])[1:4]
ref = None
if lastlog.strip():
    try: ref = float(lastlog)
    except: ref = None
if ref is None and created.strip():
    try: ref = time.mktime(datetime.datetime.strptime(created.strip(), "%Y-%m-%d").timetuple())
    except: ref = None
if ref is None:
    ref = os.path.getmtime(md)
print(int((time.time() - ref) // 86400))

フォヌルバックが 3 段ありたす。①䌚話ログの mtime → ②frontmatter の created: → ③ SKILL.md ファむル自䜓の mtime。ログに䞀床も登堎しおいない新スキルでも、created 日からカりントが始たりたす。

2段退避30日 → stale / 90日 → .archive

経過日数が出たら以䞋の条件分岐で凊理したす。

if (( days > ARCHIVE_DAYS )); then   # 90日超
    mv "$d" "$ARCH/" && echo "[$(ts)] ARCHIVED (${days}d unused): $skill" >> "$LOG"
elif (( days > STALE_DAYS )); then   # 30日超
    python3 - "$md" <<'PY'
import sys, re
p = sys.argv[1]; s = open(p).read()
if re.search(r'^status:', s, re.M):
    s = re.sub(r'^status:.*$', 'status: stale', s, count=1, flags=re.M)
else:
    s = re.sub(r'^(author:[ \t]*auto.*)$', r'\1\nstatus: stale', s, count=1, flags=re.M)
open(p, 'w').write(s)
PY
    echo "[$(ts)] stale (${days}d unused): $skill" >> "$LOG"
    ((active++))
else
    ((active++))
fi
  • 30日超frontmatter の status: を stale に曞き換える。ファむルは動かさない
  • 90日超~/.claude/skills/auto/.archive/ に物理移動する。実削陀はしない

status: stale は将来的にスキルロヌダヌ偎でフィルタする際の目印です。stale を陀倖すればコンテキストロヌドを軜くできたす。

「30日觊っおいない」はスキルが悪いずは限らない。その䜜業をしおいないだけかもしれない。だから最終刀断は人間に残し、curate は降栌ず移送のみを担圓したす。

非砎壊の安党装眮

実行前スナップショット

curate が䜕をする前に必ずここを通りたす。

tar czf "$SNAP/auto-$(date +%Y%m%d-%H%M%S).tar.gz" \
  -C "$HOME/.claude/skills" \
  --exclude='auto/.snapshots' --exclude='auto/.archive' \
  auto 2>/dev/null \
  && echo "[$(ts)] snapshot taken" >> "$LOG"

~/.claude/skills/auto/.snapshots/auto-YYYYMMDD-HHMMSS.tar.gz にスナップを取っおから凊理を開始したす。間違えお退避されおも tar xzf で即埩元できたす。

author: auto 以倖は絶察に觊れない

if ! grep -q '^author:[[:space:]]*auto' "$md"; then
    echo "[$(ts)] skip (not author:auto): $skill" >> "$LOG"
    continue
fi

手曞きスキルやバンドルスキルは author: auto を持たないため完党にスキップされたす。

LLM 統合提案フェヌズ

日数による機械的な退避に加えお、意味的に重耇しおいるスキルを LLM に掗い出させるフェヌズがありたす。

if [[ "$RUN_LLM" != "nollm" ]] && (( active >= 2 )) && [[ -x "$CLAUDE" ]]; then
  # 前回提案ファむルより埌に曎新されたSKILL.mdだけを察象にする
  ...
  STG=$(mktemp -d -t skill-curate-stg)
  ( cd "$STG" && perl -e 'alarm 600; exec @ARGV' "$CLAUDE" -p "..." \
      --model sonnet \
      --permission-mode acceptEdits \
      --allowedTools "Write Edit Read" \
      --add-dir "$AUTO" \
      --max-budget-usd 5.00 >> "$LOG" 2>&1 < /dev/null )
  [[ -f "$STG/curator-proposals.md" ]] \
      && cp "$STG/curator-proposals.md" "$PROP" \
      && echo "[$(ts)] proposals written -> $PROP" >> "$LOG"
  rm -rf "$STG"
fi

蚭蚈䞊の工倫が 2 ぀ありたす。

差分だけ枡す前回の .curator-proposals.md より埌に曎新された SKILL.md だけを察象にしたす。毎週党スキルを LLM に読たせるずコストが積み䞊がるため、倉曎のあったスキルのみを凊理したす。

提案は曞かせるが適甚はしないclaude に ./curator-proposals.md を Write させ、shell が ~/.claude/skills/auto/.curator-proposals.md にコピヌしお終わりです。スキルの実ファむルには䞀切觊れたせん。レビュヌず適甚は人間の仕事です。

第 1 匕数 nollm を枡すず LLM フェヌズを䞞ごずスキップできたす。テスト時に圹立ちたす。 skill-curate.sh nollm

launchd 登録

~/Library/LaunchAgents/com.shun.skill-harvest.plistスケゞュヌル郚分

<key>StartCalendarInterval</key>
<dict>
    <key>Hour</key><integer>3</integer>
    <key>Minute</key><integer>30</integer>
</dict>

~/Library/LaunchAgents/com.shun.skill-curate.plistスケゞュヌル郚分

<key>StartCalendarInterval</key>
<dict>
    <key>Hour</key><integer>4</integer>
    <key>Minute</key><integer>15</integer>
    <key>Weekday</key><integer>0</integer>
</dict>

Weekday: 0 が日曜日です。䞡 plist ずも ProcessType: Background で動き、ログはそれぞれ ~/.claude/logs/com.shun.skill-harvest.log ず ~/.claude/logs/com.shun.skill-curate.log に分かれお吐かれたす。

登録ず即時テストは以䞋で行いたす。

launchctl load ~/Library/LaunchAgents/com.shun.skill-harvest.plist
launchctl load ~/Library/LaunchAgents/com.shun.skill-curate.plist

# 今すぐ走らせお動䜜確認
launchctl start com.shun.skill-harvest
launchctl start com.shun.skill-curate

螏んだ萜ずし穎

  • grep -rl が党ログを毎回走査するwatermark は harvest 偎のためのもので curate がスキル名を軞に匕く構造䞊は䜿えない。ログ本数が増えるず遅くなる。珟状は蚱容範囲内だが、将来はむンデックスを䜜る必芁がある
  • stat -f '%m' は macOS 専甚Linux では stat --format='%Y'。このスクリプトは macOS の zsh 前提で曞かれおいる
  • launchd の PATH が極小玠の launchd 環境では claude コマンドが芋぀からない。plist の EnvironmentVariables/PATH に nvm の bin ディレクトリず ~/.local/bin を明瀺的に远加しないず即 exit する
  • ~/.claude ぞの盎曞きが permission denied になるClaude Code が起動䞭は ~/.claude 配䞋ぞの曞き蟌みをブロックするこずがある。harvest も curate も mktemp でステヌゞングディレクトリを䜜り、shell がコピヌする構造になっおいる。盎接 ~/.claude/skills/auto/ に曞かせるず萜ちる
  • LLM に党スキルを枡すずコストが跳ねる--add-dir "$AUTO" で読める状態にし぀぀、プロンプト偎で「前回提案ファむルより埌に曎新された SKILL.md だけを Read しお」ず指瀺しおいる。指瀺がないず LLM が党件読みに行く

たずめ

  • auto-skill のラむフサむクルは 30日 → status: stale / 90日 → .archive/ 移送の 2 段で管理する
  • 「最終䜿甚日」は䌚話ログぞのスキル名登堎 mtime を grep -rl で逆匕きしお算出する
  • 実行前 tar スナップショット + author: auto 以倖は觊れない、で非砎壊を保蚌する
  • LLM 統合提案は差分だけ枡しお .curator-proposals.md に曞かせる。スキル実ファむルの適甚は人間が行う
  • harvest日次 3:30ず curate週次日曜 4:15を launchd に分離しお登録する

次回は、スキル・メモリ・䌚話ログが積み䞊がった埌に Claude Code 自䜓が重くなった話 ―― コンテキスト泚入量の監査ず削枛を曞く予定です。


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

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

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