Skip to main content
ClaudeWave
Instalar en Claude Code
Copiar
git clone --depth 1 https://github.com/berserkdisruptors/contextual-commits /tmp/recall && cp -r /tmp/recall/skills/recall ~/.claude/skills/recall
Después abre una sesión nueva de Claude Code; el skill carga automáticamente.

SKILL.md

# 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**.

---

## Default Mode (no arguments)

### Step 1: Detect Branch State

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")

# 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` 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`.

### Step 2: Gather Raw Material

#### Scenario A — On a feature branch with commits

This is the richest scenario. Gather:

```bash
# 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
```

#### Scenario B — On a feature branch with no commits yet

```bash
# 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---"
```

#### Scenario C — On the default branch

```bash
# Recent commit history with contextual action lines
git log -20 --format="%H%n%s%n%b%n---COMMIT_END---"
```

#### Scenario D — On the default branch with uncommitted changes

```bash
# 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
```

### Step 3: Extract Action Lines

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).

### Step 4: Synthesize Output

**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.

#### For Scenario A (branch with commits):

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.

#### For Scenario B (branch with no commits):

```
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):

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