Skip to content

Repository files navigation

Repo2Repro

Paste the failing command. Get a smaller repo that still fails the same way.

繁體中文 · Advisor protocol · Limitations

CI GitHub release License: MIT Node.js 20+

You already found a real bug. Now the maintainer wants a minimal reproduction, and the repo has 1,000 files. Repo2Repro does the boring part in a disposable copy:

npx github:leavemagic-cyber/repo2repro --output ../issue-repro --match "Expected 2.*Received 3" -- npm test -- --run src/failing.test.ts

It keeps deleting files and npm dependencies only when the chosen failure still reproduces. Then it removes node_modules, performs a clean install, and verifies the reduced failure again.

Repo2Repro produces a reduced, verified reproduction. It does not claim a mathematically minimal result.

What it actually proves

For each run, Repo2Repro:

  1. Copies Git-tracked and non-ignored untracked files to a new directory. The source command is never run in your original repo.
  2. Excludes Git-ignored files and common credential paths such as .env, .npmrc, private keys, and credential JSON files.
  3. Captures the same non-zero failure three times. By default, normalized output must be identical; --match handles noisy test runners.
  4. Tests candidate file groups, individual files, and npm dependency groups against that failure oracle.
  5. Optionally asks any AI CLI for likely removal groups. AI suggestions get no special trust: every group must pass the same oracle.
  6. Removes node_modules, performs npm ci, and reproduces the failure three more times.
  7. Writes REPRO.md and repo2repro-report.json beside the reduced project.

The report records the command, failure signal, exit code, reduction attempts, removed files and dependencies, final verification count, whether a clean install occurred, and safety settings.

Why not just use a reducer?

C-Reduce and Shrink Ray are serious general-purpose reducers. They are the right tools when you already have a carefully written interestingness test and a reducible test case.

Repo2Repro targets an earlier, messier moment: “this whole npm repo fails when I run this command.” It derives a conservative oracle from the repeated failure, reduces both repository files and package dependencies, and leaves a clean-install evidence report. The scope is narrower; the setup is shorter.

Install and run

The first release is distributed from GitHub:

npx github:leavemagic-cyber/repo2repro --help

Run it from the Git repository root, or pass --source:

repo2repro --source ./my-app --output ../my-app-repro -- npm test -- --run tests/bug.test.ts

The output directory must not exist. Repo2Repro refuses to overwrite it.

Reduction can take time: the upper bound is roughly --max-attempts × --timeout, plus package installs. The CLI reports every accepted or reverted attempt so a slow reducer does not look hung.

The command after -- is an executable plus arguments, not a shell expression. Put pipes, redirects, environment assignments, or compound commands in a package script first. The command is copied into REPRO.md and the JSON report, so never put a credential in a command argument.

Choosing the failure signal

Use the default exact fingerprint when output is deterministic:

repo2repro --output ../repro -- npm test -- --run tests/bug.test.ts

The automatic fingerprint assumes the Git-visible copy contains everything needed to reach the intended bug. If Repo2Repro detects an excluded sensitive-path file, it requires --match so a “missing configuration” error cannot silently replace your real failure. Use --match whenever ignored runtime data may affect the command.

Use a narrow regular expression when timestamps, ports, ordering, or timing make the full output noisy:

repo2repro --output ../repro --match "TypeError: Cannot read properties of undefined" -- npm test

A generic signal such as error is dangerous: an unrelated failure may match it. Prefer the failing test name plus its distinctive error text.

Optional AI advisor — any provider

Repo2Repro does not require a model. If you already use an AI CLI, --advisor-command lets it inspect the disposable copy and suggest deletion groups:

repo2repro --output ../repro --advisor-command "my-repro-advisor" -- npm test

The advisor receives JSON on stdin and must return strict JSON on stdout. It can be backed by a local model, a hosted model, or deterministic code. Repo2Repro validates every suggestion before accepting it; an advisor cannot declare success. See the provider-neutral protocol.

Safety model

Repo2Repro protects the source repository, not the machine:

  • The failing command runs only in a newly created disposable copy, and command-created files are removed between attempts.
  • Existing project files modified by the command make the run fail rather than silently contaminating the oracle.
  • npm lifecycle scripts are disabled by default. --allow-scripts is an explicit opt-in.
  • The source manifest is hashed before and after reduction. A concurrent source change aborts the result.
  • The output is never overwritten.

This is not a sandbox. The command and optional advisor still have your user permissions and network access. Never use Repo2Repro to run an untrusted command. It also cannot prove that an ordinary tracked source file contains no secret; run your normal secret scanner before sharing the result.

Current scope

v0.1 intentionally supports the narrow path we can verify well:

  • Git repository root
  • JavaScript or TypeScript project with package.json
  • npm installs and dependency reduction
  • deterministic command-line failures
  • Node.js 20 or newer

pnpm, Yarn, symbolic links, Git submodules, commands that rewrite existing project files, GUI failures, login-dependent flows, flaky network failures, and hardware-specific failures are not yet supported. See all limits and non-goals.

Options

--source <path>           Git repository root (default: current directory)
--output <path>           Required new directory for the reproduction
--match <regex>           Explicit failure signal for noisy output
--baseline-runs <n>       Runs before reduction (default: 3)
--verify-runs <n>         Clean verification runs (default: 3)
--timeout <ms>            Per-command timeout (default: 120000)
--max-attempts <n>        Reduction attempt budget (default: 80)
--advisor-command <cmd>   Optional provider-neutral advisor
--skip-dependencies       Keep package dependencies unchanged
--skip-install            Skip npm install and dependency reduction
--allow-scripts           Allow npm lifecycle scripts

Develop

git clone https://github.com/leavemagic-cyber/repo2repro.git
cd repo2repro
npm test
npm run check

The end-to-end test builds a real temporary Git/npm project, reduces unused source and a local dependency, verifies the exact failure after a clean install, and checks that the original repo and ignored .env remain untouched.

Found a repo Repo2Repro cannot shrink without changing the bug? Open an issue with the generated report after removing anything private. Counterexamples are more useful than applause.

About

Turn a failing JavaScript or TypeScript repository into a smaller, verified reproduction.

Topics

Resources

Contributing

Security policy

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages