CtrlK
BlogDocsLog inGet started
Tessl Logo

reproduce-issue

The single skill for reproducing an nx issue. Given a GitHub issue number (human entry) OR explicit repro parameters (agent entry), it runs the reproduction ENTIRELY inside an isolated Docker sandbox — gVisor on Linux, the Docker VM on macOS — so the untrusted repro's install scripts and commands never execute on the host, then reports whether it reproduces. Called by humans via "/reproduce-issue

76

Quality

96%

Does it follow best practices?

Run evals on this skill

Adds up to 20 points to the overall score

View guide

SecuritybySnyk

Medium

Suggest reviewing before use

SKILL.md
Quality
Evals
Security

Reproduce an issue (sandboxed)

Reproduce an nx bug entirely inside an isolated container and report the outcome. The untrusted repro — its install (arbitrary postinstall scripts) and its repro command — runs only in the sandbox, never on the host. --rm destroys everything on exit; nothing touches the host filesystem.

This is the one reproduction engine in the repo. It has two front doors:

Entry A — a GitHub issue (human: /reproduce-issue <N>)

  1. Fetch the issue:
    gh issue view <N> --repo nrwl/nx --json number,title,body,comments,labels
  2. Extract from the body: the repro repo URL (or create-nx-workspace steps), the exact command(s) that show the bug, the reported vs expected behavior, and the Nx Report (nx version + Node version).
  3. Fill the parameters below and run the sandbox (default nx-version = whatever the issue reports / the repo pins; default registry = public npm).

Entry B — explicit parameters (agent: reproduce-verifier Level 2)

The caller passes these directly:

  • reprorepo:<git-url> (clone a public repo) OR create:"<create-nx-workspace args>".
  • nx-version:<version> — install this published nx and rewrite the repro's nx / @nx/* / @nrwl/* deps to it. For reproducing against a released version.
  • nx-build:<git-ref> (PR-verification mode) — instead of a published version, build nx from this nrwl/nx commit inside the sandbox and reproduce against it. Uses the nx-review-sandbox image; the skill derives the version and serves it from a localhost verdaccio in the same container. Mutually exclusive with nx-version.
  • nx-registry:<url> (optional, nx-version mode only) — registry to install from. Default public npm.
  • command:"<repro-cmd>" — the command whose output/exit code decides the verdict.
  • node-image:<img> (optional) — base image matching the issue's Node (default node:22; public images are multi-arch → native on Apple Silicon).
  • expect:<reported symptom> (optional), setup:"<files/steps>" (optional) — files to create in the workspace first.

Platform (where the sandbox boundary comes from)

Run uname -s once:

  • Linux → add --runtime=runsc to docker run (gVisor is the sandbox).
  • macOS (Darwin)omit --runtime=runsc (the Docker VM is the sandbox). Verify docker info works; if not, tell the user to colima start (or start Docker Desktop / OrbStack).

The command below shows the Linux form — on macOS drop --runtime=runsc, keep the rest.

Preflight — check the environment, fail with a FIX (not a mystery)

Before running anything, verify prerequisites in order and stop at the first miss, printing the one-line fix. Most misses point at the setup-review-sandbox skill, which installs/builds everything.

  1. Docker is up:

    docker info >/dev/null 2>&1 && echo up || echo MISSING

    Miss → Linux: sudo systemctl start docker. macOS: colima start (or open Docker Desktop). Or run setup-review-sandbox.

  2. Container networking works (the check that would have caught the veth breakage):

    docker run --rm --network none alpine true   # A: is the sandbox itself OK?
    docker run --rm alpine true                  # B: is networking OK?

    If A passes but B fails with veth ... operation not supported → networking is broken (usually a kernel update left veth unloadable). Fix: sudo modprobe veth; if that errors with a BTF/version mismatch, reboot (the running kernel no longer matches its modules).

  3. Isolation runtime (platform-specific):

    • Linux — gVisor registered as a Docker runtime?
      docker info --format '{{range $k,$v := .Runtimes}}{{$k}} {{end}}' | grep -q runsc && echo ok || echo MISSING
      Miss → run setup-review-sandbox (installs + registers runsc).
    • macOS — the Docker VM (Colima / Docker Desktop) is the sandbox; step 1 already covered it. No runsc.
  4. (PR-build mode ONLY) the toolchain image exists:

    docker image inspect nx-review-sandbox:latest >/dev/null 2>&1 && echo ok || echo MISSING

    Miss → run setup-review-sandbox (builds it from tools/review-sandbox/Dockerfile). Skip this check when reproducing against a published nx version — that path needs only steps 1–3 and a public node image.

If all needed checks pass, proceed.

Safety rails (do NOT break these)

  • The untrusted repro runs only in the container. Never -v a host path in. nx comes from a registry (or docker cp-ed tarballs), never a mount.
  • Always pass: --cap-drop ALL, --security-opt no-new-privileges, --memory 4g --cpus 4 --pids-limit 2048, --rm; plus --runtime=runsc on Linux.
  • Network is ON (clone + install need it). gVisor still protects the host kernel; on macOS the VM protects the host.
  • One docker command per Bash call. (Chaining inside the container's bash -c '...' is one host command, which is fine.)

Run

Detect platform, then a single host command does clone/create → dep-rewrite → install → repro, all inside the sandbox:

# RUNTIME="--runtime=runsc"   on Linux
# RUNTIME=""                   on macOS
docker run --rm $RUNTIME \
  --cap-drop ALL --security-opt no-new-privileges \
  --memory 4g --cpus 4 --pids-limit 2048 \
  node:22 bash -c '
    set -e
    git clone --depth 1 <GIT_URL> /repro          # repo: form
    # -- or -- npx --yes create-nx-workspace <ARGS> --directory /repro   # create: form
    cd /repro

    node -e '"'"'
      const fs=require("fs"),p=JSON.parse(fs.readFileSync("package.json","utf8")),v=process.argv[1];
      for (const s of ["dependencies","devDependencies"]) for (const n of Object.keys(p[s]||{}))
        if (n==="nx"||n.startsWith("@nx/")||n.startsWith("@nrwl/")) p[s][n]=v;
      fs.writeFileSync("package.json", JSON.stringify(p,null,2)+"\n");
    '"'"' <NX_VERSION>

    rm -f package-lock.json pnpm-lock.yaml yarn.lock
    PM=npm; test -f pnpm-workspace.yaml && PM=pnpm
    npm i -g pnpm@11 >/dev/null 2>&1 || true
    npm_config_registry=<NX_REGISTRY> $PM install

    ( timeout 300 <REPRO_COMMAND> ); echo "REPRO_EXIT=$?"
    echo "kernel: $(uname -r)"
  '

Substitute <GIT_URL>/<ARGS>, <NX_VERSION>, <NX_REGISTRY> (default https://registry.npmjs.org), and <REPRO_COMMAND>.

Classify + report

Compare output and REPRO_EXIT against the reported symptom, and return this block (verdicts match the reproduce-verifier's Level 2 vocabulary):

repro:        <repo-url | create-nx-workspace ...>
nx-version:   <version>   (registry: <url>)
command:      <verbatim>
exit code:    <N>
verdict:      <PR_REPRO_PASSES | PR_REPRO_FAILS | PR_REPRO_FAILS_DIFFERENT | PR_REPRO_INCONCLUSIVE | SETUP_FAILED>
output (tail ~20 lines):
  <...>
  • succeeded (matches the claimed fix) → PR_REPRO_PASSES
  • failed with the reported error → PR_REPRO_FAILS
  • failed with a different error → PR_REPRO_FAILS_DIFFERENT (flag for human)
  • unclear → PR_REPRO_INCONCLUSIVE
  • clone/create/install broke before the repro ran → SETUP_FAILED (say which step + tail)

(For a human /reproduce-issue run against a released version, "reproduced" vs "did not reproduce" is the plain-language answer; the verdict vocab above is for the agent.)

PR-build mode — build nx from source in the sandbox (nx-build)

When nx-build:<git-ref> is given, do everything in one nx-review-sandbox container (it carries the mise toolchain incl. java + dotnet, required by nx's @nx/dotnet/@nx/gradle graph plugins). One container, localhost throughout — no host build, no host verdaccio, no host.docker.internal, no listen-address change:

# RUNTIME="--runtime=runsc"  on Linux, ""  on macOS
docker run --rm $RUNTIME \
  --cap-drop ALL --security-opt no-new-privileges \
  --memory 20g --cpus 6 --pids-limit 8192 --tmpfs /work:rw,exec,size=16g \
  -e CI=true -e NX_DAEMON=false \
  nx-review-sandbox:latest bash -c '
    set -e
    # 1. build nx from the PR commit
    cd /work
    git clone --filter=blob:none https://github.com/nrwl/nx nx && cd nx
    git checkout <GIT_REF>
    mise install && pnpm install --frozen-lockfile
    PORT=4873
    pnpm nx local-registry @nx/nx-source --port=$PORT >/tmp/verdaccio.log 2>&1 &
    for i in $(seq 1 60); do curl -sf http://localhost:$PORT/-/ping >/dev/null 2>&1 && break; sleep 1; done
    NX_LOCAL_REGISTRY_PORT=$PORT pnpm nx populate-local-registry-storage @nx/nx-source
    NXV=$(node -p "require(\"/work/nx/dist/packages/nx/package.json\").version")

    # 2. reproduce against that build — same container, localhost registry
    cd /work
    git clone --depth 1 <GIT_URL> repro     # or: npx --yes create-nx-workspace <ARGS> --directory repro
    cd repro
    # rewrite nx/@nx/@nrwl deps to "$NXV" (same node one-liner as the Run section)
    rm -f package-lock.json pnpm-lock.yaml yarn.lock
    npm_config_registry=http://localhost:$PORT pnpm install
    ( timeout 300 <REPRO_COMMAND> ); echo "REPRO_EXIT=$?"
    echo "kernel: $(uname -r)"
  '

Because verdaccio and the repro live in the same container, the registry is plain localhost — the reachability/listen-address problems a host verdaccio would create simply don't exist. Classify the result exactly as in "Classify + report".

Prerequisite: the nx-review-sandbox image (setup-review-sandbox). The nx build is heavy (~several min + several GB) — RAM-backed via the tmpfs above so it stays off the host disk.

Cleanup

--rm destroys the container and everything in it on exit. Nothing persists on the host. Stray sandbox containers/images: /sandbox-prune.

Repository
nrwl/nx
Last updated
First committed

Is this your skill?

If you maintain this skill, you can claim it as your own. Once claimed, you can manage eval scenarios, bundle related skills, attach documentation or rules, and ensure cross-agent compatibility.