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
96%
Does it follow best practices?
Run evals on this skill
Adds up to 20 points to the overall score
View guide
Medium
Suggest reviewing before use
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:
/reproduce-issue <N>)gh issue view <N> --repo nrwl/nx --json number,title,body,comments,labelscreate-nx-workspace steps), the exact command(s) that show the bug, the reported vs expected behavior, and the Nx Report (nx version + Node version).nx-version = whatever the issue reports / the repo pins; default registry = public npm).The caller passes these directly:
repro — repo:<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.Run uname -s once:
--runtime=runsc to docker run (gVisor is the sandbox).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.
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.
Docker is up:
docker info >/dev/null 2>&1 && echo up || echo MISSINGMiss → Linux: sudo systemctl start docker. macOS: colima start (or open Docker Desktop). Or run setup-review-sandbox.
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).
Isolation runtime (platform-specific):
docker info --format '{{range $k,$v := .Runtimes}}{{$k}} {{end}}' | grep -q runsc && echo ok || echo MISSINGsetup-review-sandbox (installs + registers runsc).runsc.(PR-build mode ONLY) the toolchain image exists:
docker image inspect nx-review-sandbox:latest >/dev/null 2>&1 && echo ok || echo MISSINGMiss → 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.
-v a host path in. nx comes from a registry (or docker cp-ed tarballs), never a mount.--cap-drop ALL, --security-opt no-new-privileges, --memory 4g --cpus 4 --pids-limit 2048, --rm; plus --runtime=runsc on Linux.docker command per Bash call. (Chaining inside the container's bash -c '...' is one host command, which is fine.)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>.
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):
<...>PR_REPRO_PASSESPR_REPRO_FAILSPR_REPRO_FAILS_DIFFERENT (flag for human)PR_REPRO_INCONCLUSIVESETUP_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.)
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.
--rm destroys the container and everything in it on exit. Nothing persists on the host. Stray sandbox containers/images: /sandbox-prune.
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.