关于 recall
面向编码 Agent 的 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 行。
这项检查很轻量,对于你正在处理的任何范围,都应养成习惯。