recall

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

Context Recall

Context Recall

Reconstruct the development story from contextual commit history and present it as a natural briefing.
基于上下文提交历史重构开发历程,以自然简报的形式呈现。

Argument Detection

参数检测

Check how
recall
was invoked:
  • No arguments — run the default mode (full branch/session briefing below).
  • Bare word (e.g.
    recall auth
    ) — treat as a scope query. Jump to Scope Query.
  • word(word)
    pattern
    (e.g.
    recall rejected(auth)
    ) — treat as an action+scope query. Jump to Action+Scope Query.

检查
recall
命令的调用方式:
  • 无参数 — 运行默认模式(见下方完整分支/会话简报)。
  • 裸词(例如
    recall auth
    ) — 视为范围查询,跳转至 范围查询 部分。
  • 操作(范围)
    模式
    (例如
    recall rejected(auth)
    ) — 视为操作+范围查询,跳转至 操作+范围查询 部分。

Default Mode (no arguments)

默认模式(无参数)

Step 1: Detect Branch State

步骤1:检测分支状态

Determine the working state:
bash
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")
确定工作区状态:
bash
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/||')
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
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` identifies the repository's primary branch (for scenario C/D detection). `BASE_BRANCH` identifies the closest ancestor branch — which may differ when feature branches are created from non-default branches (e.g., a feature branched from `develop`). All branch-relative queries use `BASE_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`。

Step 2: Gather Raw Material

步骤2:收集原始数据

Scenario A — On a feature branch with commits

场景A — 有提交记录的功能分支

This is the richest scenario. Gather:
bash
undefined
这是信息最丰富的场景,收集以下内容:
bash
undefined

Contextual action lines from all branch commits

所有分支提交的上下文操作行

git log ${BASE_BRANCH}..HEAD --format="%H%n%s%n%b%n---COMMIT_END---"
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
git diff --stat git diff # 读取实际diff获取关键改动

Staged changes

已暂存更改

git diff --cached --stat
undefined
git diff --cached --stat
undefined

Scenario B — On a feature branch with no commits yet

场景B — 尚无提交记录的功能分支

bash
undefined
bash
undefined

Unstaged and staged changes only

仅收集未暂存和已暂存更改

git diff --stat git diff --cached --stat
git diff --stat git diff --cached --stat

Last few commits on the parent branch for project context

父分支最近的10条提交记录,用于提供项目上下文

git log ${BASE_BRANCH} -10 --format="%H%n%s%n%b%n---COMMIT_END---"
undefined
git log ${BASE_BRANCH} -10 --format="%H%n%s%n%b%n---COMMIT_END---"
undefined

Scenario C — On the default branch

场景C — 位于默认分支

bash
undefined
bash
undefined

Recent commit history with contextual action lines

最近的提交历史及上下文操作行

git log -20 --format="%H%n%s%n%b%n---COMMIT_END---"
undefined
git log -20 --format="%H%n%s%n%b%n---COMMIT_END---"
undefined

Scenario D — On the default branch with uncommitted changes

场景D — 位于默认分支且有未提交更改

bash
undefined
bash
undefined

Same as C plus uncommitted changes

同场景C,额外添加未提交更改

git log -20 --format="%H%n%s%n%b%n---COMMIT_END---" git diff --stat git diff --cached --stat
undefined
git log -20 --format="%H%n%s%n%b%n---COMMIT_END---" git diff --stat git diff --cached --stat
undefined

Step 3: Extract Action Lines

步骤3:提取操作行

From the gathered commit bodies, extract lines matching:
^(intent|decision|rejected|constraint|learned)\(
Group them by commit (preserve chronological order) and by type (for synthesis).
从收集到的提交正文中,提取匹配以下规则的行:
^(intent|decision|rejected|constraint|learned)\(
按提交分组(保留时间顺序),同时按类型分组(用于后续合成)。

Step 4: Synthesize Output

步骤4:合成输出

Signal density over narrative flow. The output should be compact, scannable, and grounded entirely in what the commits and diffs show. Every line should be actionable information. No fluff, no conversational padding.
优先保证信息密度,而非叙事流畅性。 输出应当紧凑、易读,完全基于提交和diff的实际内容,每一行都应当是可落地的信息,没有废话,没有口语化填充内容。

For Scenario A (branch with commits):

场景A(有提交的分支):

Output the branch state, then synthesize the contextual action lines into a dense briefing organized by what matters most for continuing work.
Example output:
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).
When branched from a non-default branch:
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.
Priority order:
  1. Active intent (what we're building and why)
  2. Current approach (decisions made)
  3. Rejected approaches (what NOT to re-explore — critical)
  4. Constraints (hard boundaries)
  5. Learnings (things that save time)
  6. In-progress work (unstaged/staged changes)
If intent evolved during the branch (a pivot), show both the original and current intent to make the pivot visible.
先输出分支状态,再将上下文操作行合成高密度简报,按对后续工作的重要程度排序。
输出示例:
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.
优先级顺序:
  1. 活跃意图(我们正在构建的内容及原因)
  2. 当前方案(已做出的决策)
  3. 被否决的方案(不要重复探索的内容——核心价值)
  4. 约束(硬性边界)
  5. 经验总结(能节省时间的内容)
  6. 进行中的工作(未暂存/已暂存更改)
如果分支开发过程中意图发生了变化(方向调整),请同时展示原始和当前意图,让方向调整清晰可见。

For Scenario B (branch with no commits):

场景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)
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)

For Scenario C (default branch, no changes):

场景C(默认分支,无更改):

Synthesize recent merged work from the last 20 commits. Group by area of activity. Surface any active constraints or learnings that apply broadly.
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?
合成最近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?

For Scenario D (default branch with uncommitted changes):

场景D(默认分支有未提交更改):

Same as Scenario C, with uncommitted changes noted at the top.
同场景C,在顶部标注未提交更改。

When there are no contextual commits at all

完全没有上下文提交时

If the history contains conventional commits but no contextual action lines, still produce useful output from what exists:
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.
This is honest about the signal quality while still providing useful orientation. The suggestion to adopt the skill is a natural next step, not a sales pitch.
如果历史记录包含常规提交,但没有上下文操作行,仍然要基于现有内容生成有用的输出
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.
这既如实反映了信号质量,同时也提供了有用的方向指引,建议使用该技能是自然的下一步,而非推销话术。

Guidelines

指导原则

  • Dense over conversational. Every line should carry information. No "Here's what's been happening" or "Let me tell you about."
  • Grounded in data. Only report what the action lines, commit subjects, and diffs actually show. Do not infer, speculate, or fill gaps.
  • Surface rejections prominently. Rejected approaches are the highest-value signal — they prevent wasted exploration.
  • Group by scope when multiple scopes exist. On the default branch with broad history, organize by domain area rather than chronologically.
  • End with a prompt. Close with "What do you want to work on?" or similar. Keep it short.
  • Scale to the data. If there are 2 contextual commits, the output is 3-4 lines. If there are 20, it's a few grouped paragraphs. Never pad thin data into a long output.

  • 高密度优先于口语化:每一行都要承载信息,不要出现「以下是最近发生的事」或「我来给你介绍下」这类表述。
  • 基于实际数据:仅报告操作行、提交主题和diff实际展示的内容,不要推断、猜测或填补空白。
  • 突出展示被否决的方案:被否决的方案是价值最高的信号——能避免无效探索。
  • 多范围时按范围分组:默认分支历史内容广泛时,按领域组织,而非按时间顺序。
  • 末尾添加引导:以「你想开展什么工作?」或类似内容收尾,保持简短。
  • 输出适配数据量:如果只有2条上下文提交,输出就只有3-4行;如果有20条,就输出几个分组段落,不要为了撑长内容填充无用信息。

Scope Query (
recall <scope>
)

范围查询(
recall <范围>

Targeted query across full repo history for a given scope. Prefix matching:
auth
matches
auth
,
auth-tokens
,
auth-library
, etc.
针对给定范围查询整个仓库历史,前缀匹配:
auth
会匹配
auth
auth-tokens
auth-library
等。

Step 1: Query

步骤1:查询

bash
git log --all --grep="(${SCOPE}" --format="%H%n%s%n%b%n---COMMIT_END---"
bash
git log --all --grep="(${SCOPE}" --format="%H%n%s%n%b%n---COMMIT_END---"

Step 2: Extract

步骤2:提取

From the gathered commit bodies, extract lines matching:
bash
grep -E "^(intent|decision|rejected|constraint|learned)\(${SCOPE}"
This captures all action lines whose scope starts with the query term.
从收集到的提交正文中,提取匹配以下规则的行:
bash
grep -E "^(intent|decision|rejected|constraint|learned)\(${SCOPE}"
这会捕获所有范围以查询词开头的操作行。

Step 3: Output

步骤3:输出

Group by action type, chronological within each group. Show which sub-scopes were found.
Example (
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
If no matches are found, say so plainly and suggest checking the scope name.

按操作类型分组,每组内按时间顺序排列,展示找到的所有子范围。
示例(
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
如果没有找到匹配项,如实说明并建议检查范围名称。

Action+Scope Query (
recall <action>(<scope>)
)

操作+范围查询(
recall <操作>(<范围>)

Query a specific action type for a scope across full repo history.
针对指定范围查询特定操作类型的全仓库历史。

Step 1: Query

步骤1:查询

bash
git log --all --grep="${ACTION}(${SCOPE}" --format="%H%n%s%n%b%n---COMMIT_END---"
bash
git log --all --grep="${ACTION}(${SCOPE}" --format="%H%n%s%n%b%n---COMMIT_END---"

Step 2: Extract

步骤2:提取

bash
grep "^${ACTION}(${SCOPE}"
bash
grep "^${ACTION}(${SCOPE}"

Step 3: Output

步骤3:输出

Flat chronological list with commit subject for provenance.
Example (
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
If no matches are found, say so plainly.

按时间顺序平铺展示,附带提交主题作为来源依据。
示例(
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
如果没有找到匹配项,如实说明。

Proactive Usage

主动使用建议

Before making a significant decision in any scope area, check
rejected
and
constraint
lines for that scope first:
bash
git log --all --grep="rejected(${SCOPE}" --format="%b" | grep "^rejected(${SCOPE}"
git log --all --grep="constraint(${SCOPE}" --format="%b" | grep "^constraint(${SCOPE}"
If a previous commit recorded a
rejected
line for the approach you're about to propose, surface the rejection reason to the user before re-proposing it. The rejection may still stand, or circumstances may have changed — but the user should make that call with full context, not rediscover the same dead end.
Similarly, check
constraint
lines before proposing an approach that might violate a known boundary.
This check is lightweight and should become habitual for any scope you're actively working in.
在任何范围领域做出重大决策前,先查询该范围的
rejected
constraint
行:
bash
git log --all --grep="rejected(${SCOPE}" --format="%b" | grep "^rejected(${SCOPE}"
git log --all --grep="constraint(${SCOPE}" --format="%b" | grep "^constraint(${SCOPE}"
如果之前的提交记录了你即将提议的方案对应的
rejected
行,在重新提议之前先向用户展示否决原因。否决可能仍然有效,也可能情况已经发生了变化——但用户应该在掌握完整上下文的情况下做出决定,而不是重新踩一遍同样的坑。
同理,在提议可能违反已知边界的方案前,先检查
constraint
行。
这种检查成本很低,应当成为你在任何活跃工作范围内的习惯操作。