bisect
Skill8 starsChanged 3 months agoMITView on GitHub
Use when hunting a regression, phrases like "bisect", "find the commit that broke X", "this used to work", "regression in test Y", "when did <symptom> start". Also use when escalated from ci-debug-loop because log analysis can't pinpoint the offending change, or when a previously-passing test/build/behavior is now failing and the cause isn't obvious from the recent diff. Drives `git bisect run` against a user-provided reproducer command, isolates the offending commit, and reports it with diff and metadata. Does not auto-fix.
We split this skill into the rules it gives an agent
10 rules. 0 are common, 7 are distinctive, and 3 are very specific to this project.
0
Common
Most of the 7 edited versions we read keep these.
7
Distinctive
This author's own choices. Worth a look.
3
Very specific
Tied to their project's names, files or tools. Probably skip.
- Common
- Distinctive
- Very specific
- Distinctive: line 16
Do not use when the bug is obviously in the most recent commit (inspect it), or when the reproducer is too fragile/flaky to drive an …
- Very specific: line 24
Known-bad ref: default HEAD.
- Distinctive: line 25
Known-good ref: default oldest commit within the last 2 weeks:
- Distinctive: line 29
If the user has a tag, branch, or specific date in mind, use it instead.
- Distinctive: line 48
If none of the three apply, bisect is the wrong tool.
- Very specific: line 71
Build the wrapper script: Write to $TMPDIR/bisect-wrapper.sh:
- Distinctive: line 101
If git bisect log doesn't have it (older git), parse the run output instead.
- Distinctive: line 109
Flaky reproducer: If the same commit returns different exit codes on repeat runs, bisect is unreliable.
- Very specific: line 110
Stale generated files: after git checkout between steps.
- Distinctive: line 139
Do not auto-revert, auto-fix, or push anything.
“Common” is measured: kept by at least 6 in 10 of the 7 edited versions of this file we could read. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.
Files
Bisect
Drive git bisect to isolate the first commit that introduced a bug, then report it. The skill stops at the report. Fixing belongs to the user with full context.
When to use
- User asks to "bisect", "find the commit that broke X", says "this used to work", or names a regression in a specific test/build target.
ci-debug-loopexhausted log analysis without identifying a clear cause.- A behavior, test, or build that was green at a known earlier point is now red.
Do not use when the bug is obviously in the most recent commit (inspect it), or when the reproducer is too fragile/flaky to drive an automated bisect (fix the flake first).
Inputs (confirm before starting)
Per confirm-before-implementing, gather these before touching git bisect:
- Symptom: one-line description of what's broken (e.g. "TestExchangeToken fails with
unauthorized"). - Reproducer: a shell command that exits 0 when the bug is absent, 1 when present. If the user can't supply one, build it together (see Reproducer strategy).
- Known-bad ref: default
HEAD. - Known-good ref: default oldest commit within the last 2 weeks:
If the user has a tag, branch, or specific date in mind, use it instead.git rev-list --since='2 weeks ago' --reverse HEAD | head -1
Reproducer strategy
The reproducer must work at every commit in the bisect range. The reproducer that exists today often won't: APIs change, test files don't yet exist on old commits, etc. Pick the highest-applicable strategy:
- External reproducer (preferred). A self-contained shell script in
$TMPDIR(e.g./tmp/repro.sh) that builds and exercises the project from outside the source tree. Hits a stable surface (CLI flag, HTTP endpoint, exported function with stable signature) that survived the bisect range. Examples:
This survives any in-tree changes because the reproducer doesn't live in the tree.# CLI: build and check observable behavior go build -o /tmp/foo ./cmd/foo && /tmp/foo --some-flag | grep -q expected # HTTP: spin up server, hit endpoint, kill go run ./cmd/server & PID=$!; sleep 1; curl -fsS localhost:8080/health; kill $PID - Carry an in-tree reproducer file across checkouts. Stash the reproducer test file,
git stash applyit at each step, run, undo. Workable but brittle; checkouts during bisect can conflict with the stash. Use only when an external reproducer is impossible. - Narrow the range first. If the reproducer fundamentally requires an API that didn't exist before commit X, set the known-good to X and bisect within the API-stable window. The bisect then can't find regressions older than X. Accept that as a scope limit, don't fight it.
If none of the three apply, bisect is the wrong tool. Read the diff manually instead.
Workflow
- Resolve refs and reproducer. Confirm the reproducer exits 1 at HEAD (bug present) and 0 at known-good (bug absent). If either fails, the inputs are wrong. Stop and re-gather.
- Estimate cost. Count commits in range:
Steps ≈git rev-list --count <good>..<bad>log2(N). If more than ~8 steps (>256 commits), ask the user to narrow the known-good; bisect time grows quickly. - Snapshot working state. Auto-stash uncommitted changes including untracked files:
The trap restores state on success, error, or interrupt.STASH_REF="" if ! git diff --quiet || ! git diff --cached --quiet || [ -n "$(git ls-files --others --exclude-standard)" ]; then git stash push -u -m "bisect-auto-$(date +%s)" && STASH_REF=$(git rev-parse stash@{0}) fi ORIG_HEAD=$(git rev-parse --abbrev-ref HEAD) trap 'git bisect reset >/dev/null 2>&1; git checkout "$ORIG_HEAD" 2>/dev/null; [ -n "$STASH_REF" ] && git stash pop 2>/dev/null' EXIT INT TERM - Build the wrapper script. Write to
$TMPDIR/bisect-wrapper.sh:#!/bin/sh set -e # Skip commits explicitly marked as intentionally broken. if git log -1 --format=%B | grep -qF '[skip-bisect]'; then exit 125 fi # Optional project regen, uncomment per project needs. # task generate || exit 125 # buf generate || exit 125 # Run the reproducer. Exit 0 = good, 1 = bad, 125 = skip. <USER REPRODUCER COMMAND HERE>chmod +xthe wrapper. Compile errors and missing-tool failures from the reproducer should propagate as exit codes the wrapper passes through; commits that can't even build typically return non-zero from the build step. Convert those to 125 by guarding with|| exit 125if the user wants to skip them rather than treat them as bad. - Run bisect.
git bisect start <bad> <good> git bisect run "$TMPDIR/bisect-wrapper.sh"git bisect rundrives to completion automatically. Capture the output. - Read the result. The last line of
git bisect runoutput is<sha> is the first bad commit. Capture the SHA:
IfFIRST_BAD=$(git bisect log | awk '/first bad commit/ {print $2}' | head -1)git bisect logdoesn't have it (older git), parse the run output instead. - Reset state.
git bisect resetreturns HEAD to the original ref. The trap will fire on exit and restore the stash. - Generate report (see Output).
Edge cases
- Flaky reproducer. If the same commit returns different exit codes on repeat runs, bisect is unreliable. Loop the reproducer N times (e.g. 5) and treat any failure as bad. Wrap the user's command in
for i in 1 2 3 4 5; do <repro> || exit 1; done; exit 0. If still flaky, fix the flake first. - Stale generated files after
git checkoutbetween steps. Add a regen step at the top of the wrapper (task generate,buf generate,npm run generate) before the reproducer. [skip-bisect]commits. Wrapper greps the message and exits 125. This relies on thecommit-per-phaserule's marker convention; assume well-formed history.- Compile/setup failures on old commits often surface as non-zero exits. By default
git bisect runtreats those as "bad". If they're really "can't tell", convert to 125 by guarding setup with|| exit 125in the wrapper. - Working tree dirt. Handled by step 3's auto-stash + trap. Don't skip the trap; Ctrl-C without it leaves the user mid-bisect.
- Merges in the range.
git bisecthandles them by linearizing via the commit graph. No special action. - Refactor renames. The offending commit may be a rename or move that exposes a latent bug elsewhere. Note this in the report; don't claim the rename is the root cause.
Output
Produce a single Markdown report:
## Offending commit
**<sha7>** — <subject>
Author: <name> | Date: <YYYY-MM-DD>
PR: <url if found via `gh pr list --search "<sha>" --state merged`>
## Diff
<output of `git show --stat <sha>` followed by `git show <sha>`>
## Commit message
<full body from `git log -1 --format=%B <sha>`>
## Suggested next step
- [ ] Write a regression test that reproduces <symptom> at HEAD (so the bisect is repeatable)
- [ ] Revert + reimplement, OR fix forward (user's call)
- [ ] Open issue / PR comment if the offending commit was already merged and shippedDo not auto-revert, auto-fix, or push anything. The skill ends at the report.
Cross-references
commit-per-phaserule defines the[skip-bisect]marker the wrapper looks for.ci-debug-loopskill is the typical escalation source. When log analysis stalls, hand the failing test/command to this skill as the reproducer.verify-when-completeskill produces good reproducer one-liners (task test -- -run '^TestX$').
Anti-patterns
- Running bisect without a deterministic reproducer. Guesses propagate exponentially.
- Skipping the auto-stash and trap. Leaves the user mid-bisect on Ctrl-C.
- Treating compile-error commits as "bad" without checking. That's a setup failure, not the bug.
- Auto-fixing the offending commit. Out of scope for this skill.
- Per
~/.claude/rules/probe-not-assume.md: confirm via tool/command before recommending; do not infer.
Other versions8 projects use a version of this.
Word for word · 0
None found.
Edited · 0
None found.
Wrote their own version · 8
- ClickHouse/ClickHouse★ 51ksame name
- sirius-db/sirius★ 1.1ksame name
- ohm41321/luciazero★ 6same name
- Pradnyeshp/Claude-Skills★ 2same name
- anuq/my-claude-skills★ 1same name
- lkc-studio/claude-skill-bisect★ 1same name
- tejastn10/workbench★ 1same name
- tokyubevoxelverse/bisect★ 1same name
How matches are found. Word for word: the exact same text. Edited: shares passages with this file (“99% same” means 99% of its five-word phrases also appear here; 10% or more counts). Their own version: similar meaning, or, weakest, the same name. We can’t tell which project had it first. Projects are counted among the 200 most-starred candidates, and mentions are links to the repository we found, up to 50 per site, so both counts are a floor.
In this repository38 other files it gives its agents.
- CLAUDE.mdCLAUDE.md
- active-readSkill
- active-reviewSkill
- analyze-knowledgeSkill
- audit-accomplishmentsSkill
- audit-historySkill
- ci-debug-loopSkill
- create-decision-documentSkill
- create-jira-itemSkill
- create-prSkill
- create-ruleSkill
- create-skillSkill
- discover-patternsSkill
- evaluate-dependencySkill
- fix-pr-conflictSkill
- implement-planSkill
- match-voiceSkill
- push-and-watchSkill
- rebase-pr-chainSkill
- review-allSkill
- review-api-compatSkill
- review-ciSkill
- review-codeSkill
- review-coverageSkill
- review-databaseSkill
- review-documentationSkill
- review-infrastructureSkill
- review-observabilitySkill
- review-performanceSkill
- review-planSkill
- review-reliabilitySkill
- review-securitySkill
- review-trajectorySkill
- set-session-contextSkill
- ship-itSkill
- simplify-proseSkill
- start-daySkill
- verify-when-completeSkill
Does it work?
Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.
No reviews yet
People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.
- It worked
- Partly
- It didn't
Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.
Your trail
Files you open will collect here, so you can find them again.
Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.
Now do this for your own.
Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.

