recall について
コミット履歴と作業ツリーの差分から開発経緯をまとめる、コーディングエージェント向けのGit履歴参照スキルです。ブランチ要約や条件指定検索に対応し、決定事項、制約、却下案を整理します。
主な機能
- 01ブランチのコミットと未コミット差分を要約
- 02スコープで文脈付き記録を検索
- 03アクション種別で履歴を絞り込み
- 04意図、決定、制約、却下案を整理
活用シーン
- 01ブランチ作業前に既存の経緯を確認
- 02作業再開時に進捗と変更を把握
- 03判断前に特定分野の却下案を検索
- 04デフォルトブランチの最近の活動を要約
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ berserkdisruptors/ contextual-commits --skill recallインストール後、Claude Code で/recallを入力して読み込まれたか確認します。
詳細
コンテキストの想起
コンテキストを含むコミット履歴から開発の経緯を再構成し、自然なブリーフィングとして提示します。
引数の判定
recall の呼び出し方を確認します。
- 引数なし — デフォルトモード(以下のブランチ/セッション全体のブリーフィング)を実行します。
- 単語のみ(例:
recall auth)— スコープクエリとして扱います。スコープクエリに進みます。 word(word)パターン(例:recall rejected(auth))— アクション+スコープクエリとして扱います。アクション+スコープクエリに進みます。
デフォルトモード(引数なし)
ステップ 1:ブランチの状態を検出する
作業状態を判定します。
CURRENT_BRANCH=$(git branch --show-current)
DEFAULT_BRANCH=$(git symbolic-ref refs/remotes/origin/HEAD 2>/dev/null | sed 's@^refs/remotes/origin/@@' || echo "main")
# Find the actual parent branch, not just the repo default.
# Try upstream tracking branch first (fast path).
BASE_BRANCH=$(git rev-parse --abbrev-ref @{upstream} 2>/dev/null | sed 's|^origin/||')
# If no upstream, find the nearest local branch by commit distance.
if [ -z "$BASE_BRANCH" ]; then
BASE_BRANCH=$(git for-each-ref --format='%(refname:short)' refs/heads/ | while read branch; do
[ "$branch" = "$CURRENT_BRANCH" ] && continue
echo "$(git log --oneline "$branch..$CURRENT_BRANCH" 2>/dev/null | wc -l | tr -d ' ') $branch"
done | sort -n | head -1 | awk '{print $2}')
fi
# Final fallback to default branch.
BASE_BRANCH=${BASE_BRANCH:-$DEFAULT_BRANCH}
UNSTAGED=$(git diff --stat)
STAGED=$(git diff --cached --stat)
BRANCH_COMMITS=$(git log ${BASE_BRANCH}..HEAD --oneline 2>/dev/null | wc -l | tr -d ' ')
DEFAULT_BRANCH はリポジトリのプライマリブランチ(シナリオ C/D の判定用)を示します。BASE_BRANCH は最も近い祖先ブランチを示します。機能ブランチがデフォルト以外のブランチ(例:develop)から作成されている場合は、両者が異なることがあります。ブランチを基準とするクエリではすべて BASE_BRANCH を使用します。
ステップ 2:素材を収集する
シナリオ A — コミットのある機能ブランチ
最も多くの情報を得られるシナリオです。以下を収集します。
# Contextual action lines from all branch commits
git log ${BASE_BRANCH}..HEAD --format="%H%n%s%n%b%n---COMMIT_END---"
# Unstaged changes (what's in progress right now)
git diff --stat
git diff # read the actual diff for key changes
# Staged changes
git diff --cached --stat
シナリオ B — まだコミットのない機能ブランチ
# Unstaged and staged changes only
git diff --stat
git diff --cached --stat
# Last few commits on the parent branch for project context
git log ${BASE_BRANCH} -10 --format="%H%n%s%n%b%n---COMMIT_END---"
シナリオ C — デフォルトブランチ上
# Recent commit history with contextual action lines
git log -20 --format="%H%n%s%n%b%n---COMMIT_END---"
シナリオ D — 未コミットの変更があるデフォルトブランチ上
# Same as C plus uncommitted changes
git log -20 --format="%H%n%s%n%b%n---COMMIT_END---"
git diff --stat
git diff --cached --stat
ステップ 3:アクション行を抽出する
収集したコミット本文から、次に一致する行を抽出します。
^(intent|decision|rejected|constraint|learned)\(
コミットごと(時系列順を維持)および種類ごと(統合用)にまとめます。
ステップ 4:出力を統合する
物語の流れより情報密度を重視します。 出力は簡潔で読み取りやすく、コミットと差分に完全に根拠を置くものにしてください。すべての行に、実行に役立つ情報を含めます。無駄な表現や会話的な前置きは不要です。
シナリオ A(コミットのあるブランチ)の場合:
ブランチの状態を示してから、コンテキストを含むアクション行を、作業の継続に重要な順にまとめたブリーフィングとして提示します。
出力例:
Branch: feat/google-oauth (4 commits ahead of main, unstaged changes in tests/)
Active intent: Add Google as first social login provider. GitHub and Apple to follow.
Approach: passport.js with /api/auth/callback/:provider convention.
Rejected: auth0-sdk — session model incompatible with redis store.
Constraints:
- Redis session TTL 24h, tokens must refresh within window
- Callback routes must follow existing :provider pattern
Learned: passport-google needs explicit offline_access scope for refresh tokens.
In progress: Integration tests for callback handler (unstaged).
デフォルト以外のブランチから分岐した場合:
Branch: feat/oauth-refresh (2 commits ahead of develop, no uncommitted changes)
Active intent: Implement token refresh for OAuth providers.
Constraint: Must stay compatible with the session store changes on develop.
優先順位:
- 現在の意図(何を、なぜ構築しているか)
- 現在のアプローチ(決定事項)
- 却下されたアプローチ(再検討すべきでないこと — 重要)
- 制約(厳守すべき境界)
- 学び(時間の節約につながる情報)
- 進行中の作業(ステージング前/済みの変更)
ブランチの途中で意図が変化した場合(方向転換)、方向転換が分かるように、当初の意図と現在の意図の両方を示します。
シナリオ B(コミットのないブランチ)の場合:
Branch: feat/new-feature (0 commits ahead of develop)
No contextual history on this branch yet.
Staged: 2 files (src/auth/provider.ts, src/auth/types.ts)
Unstaged: none
Recent project activity (from develop):
- Auth: OAuth provider framework merged, Google working
- Payments: Multi-currency support shipped (EUR, GBP alongside USD)
シナリオ C(変更のないデフォルトブランチ)の場合:
直近 20 件のコミットから、最近マージされた作業をまとめます。活動領域ごとにグループ化します。広く適用される有効な制約や学びがあれば明示します。
Recent project activity:
Auth: OAuth provider framework merged. Google working, GitHub and Apple planned.
- Rejected auth0-sdk (session model incompatible with redis store)
- Constraint: redis session TTL 24h, tokens must refresh within window
Payments: Multi-currency support shipped (USD, EUR, GBP).
- Per-transaction currency, not account-level
- Constraint: Stripe locks currency at PaymentIntent creation
- Learned: presentment ≠ settlement currency in Stripe
What do you want to work on?
シナリオ D(未コミットの変更があるデフォルトブランチ)の場合:
シナリオ C と同様にしますが、先頭に未コミットの変更を記載します。
コンテキストを含むコミットがまったくない場合
履歴に通常のコミットはあるものの、コンテキストを含むアクション行がない場合でも、存在する情報から有用な出力を作成します。
Branch: main (no contextual commits found in recent history)
Recent activity (from commit subjects):
- auth: 6 commits (OAuth implementation, middleware updates) — 2 days ago
- payments: 4 commits (currency handling, Stripe integration) — last week
- tests: 3 commits — last week
- config: 2 commits
Most recent: feat(auth): implement Google OAuth provider
No explicit intent, decisions, or constraints are captured in commit history.
Using the contextual-commit skill on future commits will surface
the reasoning behind changes that commit subjects alone cannot show.
これにより、情報の質を正直に示しつつ、有用な状況把握を提供できます。このスキルの導入を提案するのは自然な次のステップであり、売り込みではありません。
ガイドライン
- 会話的な表現より情報密度を重視します。 すべての行に情報を含めます。「これまでの経緯をご紹介します」や「説明させてください」といった表現は使いません。
- データに基づきます。 アクション行、コミットの要約、差分が実際に示している内容だけを報告します。推論、憶測、情報の補完は行いません。
- 却下事項を目立たせます。 却下されたアプローチは最も価値の高い情報です。無駄な再検討を防ぎます。
- 複数のスコープがある場合は、スコープごとにまとめます。 デフォルトブランチに広範な履歴がある場合は、時系列ではなく領域ごとに整理します。
- プロンプトで締めくくります。 「何に取り組みますか?」などで締めます。短くまとめてください。
- データ量に応じた分量にします。 コンテキストを含むコミットが 2 件なら出力は 3〜4 行、20 件ならグループ化した段落を数個にします。情報が少ないのに、長い出力で埋め合わせてはいけません。
スコープクエリ(recall <scope>)
指定したスコープについて、リポジトリの全履歴を対象に絞り込んで検索します。前方一致です。auth は auth、auth-tokens、auth-library などに一致します。
ステップ 1:クエリ
git log --all --grep="(${SCOPE}" --format="%H%n%s%n%b%n---COMMIT_END---"
ステップ 2:抽出
収集したコミット本文から、次に一致する行を抽出します。
grep -E "^(intent|decision|rejected|constraint|learned)\(${SCOPE}"
これにより、スコープがクエリ語で始まるすべてのアクション行を取得できます。
ステップ 3:出力
アクションの種類ごとにグループ化し、各グループ内では時系列順に並べます。見つかったサブスコープを示します。
例(recall auth):
Scope: auth (also found: auth-tokens, auth-library)
intent:
- social login starting with Google, then GitHub and Apple
- original session approach incompatible with redis cluster setup
decision:
- passport.js over auth0-sdk for multi-provider flexibility
- JWT with short expiry + refresh token pattern
rejected:
- auth0-sdk — locks into their session model, incompatible with redis store
- auth-sessions — redis cluster doesn't support session stickiness needed by passport sessions
constraint:
- callback routes must follow /api/auth/callback/:provider pattern per existing convention
- redis 24h TTL means tokens must refresh within that window
learned:
- passport-google needs explicit offline_access scope for refresh tokens
- redis-cluster session affinity requires sticky sessions at load balancer level — too invasive
一致するものが見つからない場合は、その旨を明確に伝え、スコープ名を確認するよう提案します。
アクション+スコープクエリ(recall <action>(<scope>))
指定したスコープについて、特定のアクションの種類をリポジトリの全履歴から検索します。
ステップ 1:クエリ
git log --all --grep="${ACTION}(${SCOPE}" --format="%H%n%s%n%b%n---COMMIT_END---"
ステップ 2:抽出
grep "^${ACTION}(${SCOPE}"
ステップ 3:出力
コミットの件名を出典として添えた、時系列順のフラットなリストを出力します。
例(recall rejected(auth)):
rejected(auth) across history:
- auth0-sdk — locks into their session model, incompatible with redis store
from: feat(auth): implement Google OAuth provider
- auth-sessions — redis cluster doesn't support session stickiness needed by passport sessions
from: refactor(auth): switch from session-based to JWT tokens
一致するものが見つからない場合は、その旨を明確に伝えます。
積極的な活用
スコープに関する重要な判断を下す前に、まずそのスコープの rejected 行と constraint 行を確認します。
git log --all --grep="rejected(${SCOPE}" --format="%b" | grep "^rejected(${SCOPE}"
git log --all --grep="constraint(${SCOPE}" --format="%b" | grep "^constraint(${SCOPE}"
これから提案しようとしているアプローチについて、過去のコミットに rejected 行が記録されていた場合は、再提案する前に却下の理由をユーザーに伝えます。その却下の判断は今も有効かもしれませんし、状況が変わっているかもしれません。いずれにせよ、ユーザーが同じ行き止まりを再発見するのではなく、背景を十分に把握したうえで判断できるようにします。
同様に、既知の制約に違反する可能性のあるアプローチを提案する前に、constraint 行を確認します。
この確認は手軽に行えるため、取り組んでいるスコープについては習慣にしましょう。