Code Archaeology skill for Claude Code
Learn why code exists before you delete it. Claude finds the commit that actually introduced a behavior, not the last formatter run, using blame that ignores whitespace and moves plus pickaxe and line-range history. It reads the PR discussion, linked issues and ADRs, quotes the original reason, checks whether that reason still holds against today's code, dependencies and data, and ends with a provenance note and a recommendation backed by evidence.
- name
code-archaeology - size136 lines · ≈1,650 tokens
- files1
- licenseMIT
- updated
What Claude sees before loading it
This description is the only part of the skill that sits in context all the time. Claude reads it to decide when to load the full playbook below.
description: Finds out why code exists before it is changed or deleted, by tracing its origin with git blame (ignoring whitespace, moves, and formatting commits), git log -S, -G, -L and --follow, the pull requests and issues behind each commit, ADRs, changelogs, and runtime usage evidence, then writes a short provenance note with a keep, change, or delete recommendation. Use when the user asks why something is done this way, whether code is still needed, who added it, what breaks if it is removed, or before touching weird-looking code. Try asking
- Why does this function sleep for 7 seconds before retrying? Find out where it came from
- Is this weird special case for customer 4021 still needed, or can we delete it?
- Who added this config flag and what was it for?
Use it when
- Code looks wrong or odd and you are about to change it
- You want to delete something but do not know why it was added
- Blame points at a refactor or formatting commit
- A reviewer asks for the history behind a decision
Skip it when
- You already know the code is unused and need to remove it safely — use dead-code-removal instead
- You need to rewrite or repair git history itself — use git-history-surgery instead
How to check the result
The note names the introducing commit and PR, quotes the stated reason, and shows a concrete check of whether that reason still applies today.
The common mistake it prevents
Running plain git blame, landing on a bulk formatting or file-move commit, and attributing the code to the wrong author and reason.
An archaeology answer is done when it names the commit that introduced the behavior, the reason (from a PR, issue, ADR, or commit message, quoted), whether that reason still holds today, and a recommendation with the evidence for it. “Probably legacy” is not an answer; neither is the last commit that reformatted the line.
Workflow
- [ ] 1. Pin the target: exact lines, symbol, config key, or behavior
- [ ] 2. Find the introducing commit (not the last toucher)
- [ ] 3. Read the context: full commit, PR discussion, linked issues, ADRs
- [ ] 4. Check whether the reason still holds (code, tests, data, traffic)
- [ ] 5. Recommend keep / change / delete, with risk and verification plan
1. Pin the target
Write the question precisely: “Why does retryPayment() sleep 7 seconds before the
second attempt (src/billing/retry.ts:48)?” Note the symbol names, string literals, and
config keys involved; they are your search terms.
2. Find the introducing commit
Start with blame that sees through noise:
git blame -w -C -C -M -L 40,60 -- src/billing/retry.ts
git blame --ignore-revs-file .git-blame-ignore-revs -L 40,60 -- src/billing/retry.ts
-wignores whitespace;-Mdetects moved lines within a file;-C -Cdetects lines copied or moved from other files in the same or any commit.- If the repo has a
.git-blame-ignore-revs(bulk formatting commits), use it; set it permanently withgit config blame.ignoreRevsFile .git-blame-ignore-revs. - If blame lands on a refactor, rename, or formatting commit, re-blame its parent:
git blame -w -C -C <sha>^ -L 40,60 -- <old-path>.
When blame keeps hitting refactors, search history by content instead:
| Question | Command |
|---|---|
| When did this string/symbol appear or disappear? | git log -S'sleep(7000)' --oneline -- src/ |
| When did lines matching a regex change? | `git log -G’retry(Count |
| Full history of one function | git log -L :retryPayment:src/billing/retry.ts |
| History of a line range | git log -L 40,60:src/billing/retry.ts |
| History across renames | git log --follow --oneline -- src/billing/retry.ts |
| Who touched this area most (expertise) | git shortlog -sn -- src/billing/ |
| When did a file get deleted / where did it go | git log --diff-filter=D --summary -- '**/oldname.ts' |
-S finds commits that change the number of occurrences (introductions and removals);
-G finds any commit whose diff lines match. Use --all to include other branches, and
--reverse to see the earliest first.
3. Read the context
git show --stat <sha> # the whole change, not just your line
git show <sha> -- src/billing/ # what else changed with it
gh pr list --state merged --search "<sha>" --json number,title,url
gh api repos/{owner}/{repo}/commits/<sha>/pulls --jq '.[].html_url'
gh pr view <n> --comments # review discussion often holds the real reason
Then follow links: issue numbers in the commit or PR (#123, JIRA-456), incident or
postmortem references, ADRs (docs/adr/, docs/decisions/), CHANGELOG entries, and code
comments near the line (git log -S on a comment’s text finds when it was written).
Record quotes, not paraphrases. A commit message like “fix” is weak evidence; a PR description saying “provider rate-limits retries within 5 s (see incident 2023-04-11)” is strong.
Squash-merged repos: the PR is the unit of history; the squash commit body often lists the original commit messages. Rebased or vendored code: look for “imported from” notes or an upstream repo and continue there.
4. Does the reason still hold?
| Reason type | How to check today |
|---|---|
| Workaround for a dependency bug | Find the upstream issue; is it fixed in the version we use? (npm ls, lockfile) |
| External constraint (rate limit, API quirk) | Current provider docs; integration tests; ask the owner |
| Data shape (legacy rows, old clients) | Query production-like data: SELECT count(*) WHERE legacy_flag ; client version metrics |
| Feature flag or experiment | Flag state in the flag service; last evaluation time |
| Performance fix | Benchmark or trace with and without |
| Unknown | Treat as load-bearing until proven otherwise |
Usage evidence for “is anything still calling this?”: references in the repo
(rg -n symbolName), other repos that depend on it, logs/metrics for the endpoint or
code path, and feature-flag evaluations. Absence in one repo is not absence everywhere.
5. Recommend
| Finding | Recommendation |
|---|---|
| Reason documented and still true | Keep; add a comment linking the PR/issue so the next person does not repeat this |
| Reason gone (upstream fixed, flag at 100% for months, no traffic) | Delete, behind a test or flag if risky; see dead-code-removal |
| Reason partly true | Change: narrow the workaround, parameterize, add a test that encodes the constraint |
| Reason unknown after search | Keep, add a characterization test, ask the listed owners; do not delete on a hunch |
If the code survives, leave a breadcrumb at the site:
// Provider rejects retries within 5 s of a failure (PR #812, incident 2023-04-11).
// Keep >= 5000 ms unless the provider contract changes.
Gotchas
- Blaming without
-w -C -C -Musually lands on a formatter or file move, sending you to the wrong author and the wrong reason. - Shallow clones (CI, some containers) have truncated history:
git rev-parse --is-shallow-repository; rungit fetch --unshallowif true. - The person who wrote it may have only moved it. Check
git showfor a move before asking them. - Old code with tests that assert the odd behavior is strong evidence it is intentional; read those tests before concluding it is a bug.
- Do not post speculation as fact in PRs; label hypotheses and show the evidence trail.
Output
**Question:** Why does retryPayment() wait 7 s before the second attempt? (src/billing/retry.ts:48)
**Introduced:** 3f2a9c1 (2023-04-12, @dkim) "Delay payment retry past provider window" via PR #812
**Reason (quoted):** "Stripe returns rate_limit when the same card is retried within 5 s; incident 2023-04-11 double-declined 300 orders."
**Still holds?** Yes — provider docs still describe per-card retry throttling; integration test `retry_respects_window` encodes it
**History:** moved from payments/legacy.ts in 9b01de4 (refactor, no behavior change); delay raised 5 s -> 7 s in 1c77e02 for clock skew
**Recommendation:** Keep. Add comment linking #812; extract 7000 to `PROVIDER_RETRY_WINDOW_MS` About this skill
Written and maintained by the Claude Skills editors to the same editorial standard as every skill in the directory: a selective trigger, a real workflow, known pitfalls and a verification step. First published , last updated . MIT licensed.