Notes
PreToolUse hookでAIエージェントの望まないコマンドパターンを禁止する
Claude Codeのエージェントがバックグラウンドタスクの完了を sleep && grep でポーリングし始めた。許可プロンプトが出るたびにユーザーが判断する必要があり、作業の邪魔になる。
PreToolUse hookを設定すると、特定のコマンドパターンをエージェントが実行する前にブロックできる。
// .claude/settings.local.json
{
"hooks": {
"PreToolUse": [
{
"matcher": "Bash",
"hooks": [
{
"type": "command",
"command": "if echo \"$CLAUDE_TOOL_INPUT\" | grep -q 'sleep.*grep'; then echo 'BLOCK: sleep+grep polling is not allowed' >&2; exit 2; fi"
}
]
}
]
}
}
仕組み:
PreToolUseはツール実行前に発火するフックmatcherでツール名を指定(Bashでシェルコマンドを対象に)- exit code 2 でツール実行をブロックし、エラーメッセージがエージェントに返る
- エージェントは別のアプローチを試みるようになる
ポーリング以外にも、rm -rf や git push --force など危険なパターンの防止に使える。エージェントの行動を事後チェックでなく事前にゲートする仕組みとして便利。
refs: https://docs.anthropic.com/en/docs/claude-code/hooks
AIエージェントでプラクティスのギャップ分析→バックログ自動追加を行う
開発ツールやCI/CD周りのベストプラクティスを定期的に棚卸ししたいが、手動だと「何が足りないか」のリストアップだけで時間が溶ける。AIエージェントに既存構成の分析→Web上のプラクティスとの比較→不足分のIssue化までを一気通貫で任せてみた。
仕組み:
- エージェントにリポジトリの既存構成(スキル一覧、CI設定、フック設定等)を読ませる
- 「未適用のプラクティス」をWeb検索も交えてリストアップさせる
- 既存バックログとの重複チェックを行い、新規分だけIssue化する
# エージェントへの指示(概要)
1. ハーネスエンジニアリングにおいて、未適用のプラクティスを調べてリストアップ
2. 既存バックログと重複するものは除外
3. 残りをIssue化する
やってみてどうだったか:
- 24スキル・6スケジュールタスク・3レビューエージェントの構成を分析し、5件の未適用プラクティスを特定してくれた
- 既存バックログ(4件)との重複除外も正しく動いた
- 「エージェントが知っているベストプラクティス」の範囲に依存するので、ドメイン固有のプラクティスは拾えない。汎用的なプラクティス(セキュリティ監査、PR自動レビュー等)の漏れ検出に向いている
- 定期実行(週次・月次)にすると、ツールのアップデートで新しく使えるようになったプラクティスも拾える可能性がある
CSS columnsで手軽にMasonryレイアウトを実現する
カード一覧をMasonryレイアウト(Pinterest風の段違いグリッド)にしたいとき、CSS columns プロパティで簡単に実現できる。JavaScriptライブラリなしでレスポンシブ対応もできる。
.masonry-grid {
columns: 3 300px; /* 最大3列、1列の最小幅300px */
column-gap: 1rem;
}
.masonry-grid > * {
break-inside: avoid; /* カードが列をまたがないようにする */
margin-bottom: 1rem;
}
Tailwind CSSなら columns-3 と break-inside-avoid だけで済む。
<div class="columns-1 sm:columns-2 lg:columns-3 gap-4">
<div class="break-inside-avoid mb-4">カード1(高さ可変)</div>
<div class="break-inside-avoid mb-4">カード2</div>
<div class="break-inside-avoid mb-4">カード3</div>
</div>
注意点:
- CSS columnsは上から下に流れるので、並び順がグリッドと異なる(左→右ではなく上→下→次の列)
- カード高さが固定の場合はMasonryにする意味が薄い。コンテンツの高さがバラつくときに効果的
break-inside: avoidを忘れるとカードが列の境界で分断される
Cloudflare D1のテスト環境はCREATE TEMP TABLEを拒否する
D1のテスト環境(miniflare)でマイグレーションSQLを実行したら SQLITE_AUTH エラーになった。原因は CREATE TEMP TABLE 文。
D1はSQLiteベースだが、セキュリティポリシーで一部のSQLite機能を制限している。CREATE TEMP TABLE はその一つで、テスト環境でもプロダクション環境でも使えない。
マイグレーションで一時テーブルが必要な場合の代替手段:
- 通常テーブルを使って最後にDROPする —
CREATE TABLE tmp_xxx→ 処理 →DROP TABLE tmp_xxxで同じことができる - CTEやサブクエリで完結させる — 一時テーブルなしで書き換え可能なケースも多い
-- NG: D1では SQLITE_AUTH エラー
CREATE TEMP TABLE migration_data AS SELECT ...;
-- OK: 通常テーブルを使って最後にDROP
CREATE TABLE migration_data AS SELECT ...;
-- ... 処理 ...
DROP TABLE migration_data;
lefthookで既存マイグレーションファイルの変更をブロックする
AIエージェントにDB機能の実装を任せたら、既存のマイグレーションファイルを直接書き換えてしまった。CREATE TEMP TABLE → CREATE TABLE のような「テストを通すための修正」をマイグレーションに入れてしまうパターン。マイグレーションファイルは一度適用したら変更禁止が鉄則なので、ハーネス(ガードレール)として仕組み化した。
仕組み:
- lefthookのpre-commitフックで、既存マイグレーションファイルがstagingされていたらエラーにする
- CLAUDE.mdにルールを明記して、AIがそもそも編集しないよう指示する
- 新規マイグレーションの追加は許可、既存ファイルの変更のみブロック
# hook-migration-guard.sh の要点
MIGRATION_DIR="migrations"
CHANGED=$(git diff --cached --name-only -- "$MIGRATION_DIR/" | while read f; do
git show "HEAD:$f" 2>/dev/null && echo "$f" # HEADに存在する = 既存ファイル
done)
if [ -n "$CHANGED" ]; then
echo "ERROR: 既存マイグレーションファイルの変更は禁止です"
exit 1
fi
やってみてどうだったか:
- lefthookフックは人間・AI両方に効くので、CLAUDE.mdだけに頼るより確実
- 「テストを通すためにマイグレーションを変える」というAIの判断は合理的に見えるので、ルール明記だけだと突破されがち。仕組みでブロックするのが大事
- 次はCI側にも同様のチェックを入れたい
TILにノートタイプを導入してテンプレートを分ける
TILを全て同じフォーマットで書くと、内容の性質に合わない構成になりがち。「バグ修正の話」と「ツール紹介」では読み手が期待する情報構造が違う。
ノートタイプ(insight, tried, automation, harness, architecture, bugfix)を定義し、タイプごとにテンプレートとスタイルガイドを分けた。
templates/
insight.md # 知見: コード例必須、Before/After推奨
tried.md # 試した: 良かった点・気になった点・向いている場面
automation.md # 自動化: Before(手動)→After(自動)の対比
harness.md # AI制御: 設計判断+プロンプト例
architecture.md # 設計: 構造図+トレードオフ
bugfix.md # バグ: 症状→原因→解決
- AIエージェントが抽出時にタイプを自動判定し、対応するテンプレートで生成する
- タイプごとのスタイルガイド(
writing-style.md)で「insightはコード例なしだと却下」のようなルールを管理する - フロントマターに
type: insightを記録して、後から集計や検索に使える
タイプを増やしすぎると分類に迷うので、6種類くらいが運用しやすい。新タイプの追加はフィードバックから「既存タイプに当てはまらないTILが繰り返し出る」場合のみにする。
