Check by hand

Seven checks you can run right now

No tools required, nothing to install. Run these against any clone on your machine — the whole thing takes a couple of minutes. Every command is read-only; none of them change anything.

1 · Is a loader running right now?

macOS · Linux
ps -eo pid,args | grep -E "node .*-e .*global\[" | grep -v grep

No output means nothing is running. Any output is a live process — kill it.

2 · Does any file carry the operator's wallet?

working tree
grep -rn "0xa322E5f3D311D3080e6f0121063e9aDC2490Ef1a" .
and the full history — a deleted file still lives in Git
git log --all -S "0xa322E5f3" --pickaxe-regex --oneline

3 · Is a task set to run when you open the folder?

editor auto-run
grep -rn "folderOpen" .vscode/tasks.json

Any hit executes the moment the folder opens. Treat it as hostile until proven otherwise.

4 · Are your font files actually fonts?

magic bytes
head -c 4 public/fonts/*.woff2

Every real font prints wOF2. Spaces mean you are looking at a script.

5 · Do your npm scripts run something extra?

This family leaves every script you had and prefixes each one, so the file still looks like yours. The payload runs on npm run dev — no install needed, which is why --ignore-scripts does not help.

run scripts
node -e 'const s=require("./package.json").scripts||{};
for (const [k,v] of Object.entries(s)) if (/\bnode\s+\S+\.[cm]?js/.test(v)) console.log(k, "->", v)'

A build step calling your own scripts/build.js is normal. A root api.js or app.js you did not write is not — open it and look at the first line.

6 · Does your AI assistant run something at every session?

An agent's own config is an execution vector, and removing the package that delivered the hook does not remove the hook.

agent hooks
cat .claude/settings.json .claude/settings.local.json 2>/dev/null
ls -la .claude/setup.mjs .vscode/setup.mjs 2>/dev/null

A hook you wrote — a formatter, a linter — is fine. node .vscode/setup.mjs is a dropper, and the copies in .claude/ and .vscode/ re-create each other, so remove both.

7 · Has someone rewritten your remote?

The remote tip comes back with your commit's subject, author and date under a different hash. Git reports 1 ahead, 1 behind with identical messages, which reads as harmless — and then a pull merges it.

forged force-push
git fetch && git log --format='%H %cI %s' HEAD..@{u}
git log --format='%H %cI %s' @{u}..HEAD

Same message and author date on both sides, but a different hash and a committer timezone that is not yours? Do not pull.

Look for the long line

The most reliable giveaway is geometry, not content. This finds any file padded out to hide something past the edge of the screen — a hand-written config has no business being 9,000 characters wide.

hidden-payload heuristic
awk 'length > 1500 {print FILENAME": line "FNR" ("length" chars)"}' \
  $(find . \( -name "*.js" -o -name "*.mjs" -o -name "*.cjs" \) -not -path "*/node_modules/*")
What the result means

Read the outcome carefully

A clean result is narrower than it looks

Checks 2, 3 and 4 test one clone — not your other repositories, and not the branches you do not have checked out. Check 1 reports what is running right now; the loader fires when a build runs or an editor opens the folder, does its work, and exits, so a quiet process list alongside an infected repository is the expected result, not a contradiction.

These checks also key on this operator's wallet. A variant using a different address passes check 2 and is still caught by the long-line heuristic above — which is why that one matters most.