What you’ll build
By the end of this tutorial you’ll have VulnHunter’s scanner skill installed locally, a completed /vulnhunt run against a real repository, and a results directory containing a written report, proof-of-concept exploits, and proposed fixes for whatever it finds — without VulnHunter having touched a single line of your actual source.
This walkthrough covers the “Hunt” half of VulnHunter’s hunt-fix-verify loop, since that’s the part every new user runs first. It stops short of /vulnhunter-fix and /vulnhunt-fix-verify, which apply and verify the fixes — those require GitHub CLI auth and extra Python setup that’s out of scope here, but the same install gets you all three.
VulnHunter matters if you’ve ever had a traditional SAST scanner bury a handful of real issues in hundreds of pattern-matched false positives. It’s built to do the opposite: it reasons forward from attacker-reachable inputs, tries to disprove its own findings before you see them, and only surfaces what survives that adversarial pass with an executable proof-of-concept attached.
Step 1: Clone the repository
git clone https://github.com/capitalone/vulnhunter.git
cd vulnhunter
This gives you the installer script plus all three skills (vulnhunt, vulnhunter-fix, vulnhunt-fix-verify) and the batch-scanning harness in one checkout.
Step 2: Install the skills
./install.sh
install.sh copies the skill files directly into ~/.claude/skills/ — it doesn’t symlink them, because symlinks can break find/glob calls that run inside Claude Code subagents. That also means if you pull a newer version of VulnHunter later, you need to re-run ./install.sh to refresh what’s actually installed; editing files in your cloned checkout alone won’t change the running skill.
Verify it worked: run ls ~/.claude/skills/ and confirm vulnhunt, vulnhunter-fix, and vulnhunt-fix-verify all appear as directories. If any are missing, re-run the installer and check its output for a permissions error on ~/.claude/skills/ — that’s the most common failure at this step.
Step 3: Point Claude Code at a target and run the scanner
Change into the codebase you want scanned — VulnHunter runs against whatever directory you launch Claude Code from — then start a session with the vulnhunt skill directories added:
cd /path/to/your/target-repo
claude --model opus \
--add-dir ~/.claude/skills/vulnhunt \
--add-dir ~/.claude/skills/vulnhunt/phases
Inside the Claude Code session, invoke:
/vulnhunt
This kicks off a multi-phase run: a recon pass builds an inventory of every user-controllable input, parallel class agents (injection, navigation/access, logic/crypto) trace those inputs forward toward dangerous sinks, an adversarial verification pass tries to disprove each candidate finding, and a final phase writes proof-of-concept exploits and fix strategies for whatever survives.
Scan time scales with codebase size and how many candidate findings make it past recon — expect anywhere from several minutes on a small service to considerably longer on a large monorepo.
Step 4: Review the results
When the run finishes, look for a new *_VULNHUNT_RESULTS_* directory in your target repo:
ls -d *_VULNHUNT_RESULTS_*
cat *_VULNHUNT_RESULTS_*/README.md
What a successful run looks like: the results directory contains a README.md summarizing each finding, alongside executable proof-of-concept exploits and exploit tests for every issue that survived the falsification pass. Each finding should read as a specific, traceable path — a named entry point, the intermediate logic it flows through, and the sink it reaches — not a generic “possible injection” flag. If the report only lists zero findings, that’s a valid outcome too; VulnHunter is tuned to discard anything it can’t back with a working PoC rather than pad the report.
Confirm VulnHunter didn’t modify your source: git status in the target repo should show no changes to tracked files, only the new, untracked results directory. VulnHunter is read-only over the target codebase by design — it documents fix strategies rather than applying them at this stage.
Step 5 (optional): Apply and verify a fix
If a finding warrants fixing immediately, the remediation skill picks up from the results directory. It requires git, a GitHub CLI (gh) authenticated against your target repo, and its Python helpers installed:
cd vulnhunter-fix && pip install -e ".[dev]"
claude --model opus --add-dir ~/.claude/skills/vulnhunter-fix
Then invoke /vulnhunter-fix inside the session. It writes a failing security test that reproduces the exploit (red), implements the fix (green), confirms the exploit is now blocked without breaking existing tests, and opens a reviewable PR. A separate, strictly read-only agent (/vulnhunt-fix-verify) can then independently confirm the fix actually closed the gap, rather than trusting the fixer’s own claim.
Troubleshooting
/vulnhunt isn’t recognized inside the Claude Code session. The skill directories weren’t added to this session — exit and relaunch with both --add-dir flags from Step 3. Skills added via --add-dir only apply to the session they’re passed to.
The results directory is empty or missing a README.md. The run likely didn’t complete a full pass — check your terminal output for an error from one of the phase subagents. Re-run /vulnhunt; if it fails at the same phase repeatedly, it’s worth checking whether your Claude Code session actually has Opus access, since VulnHunter’s low false-positive rate depends on frontier-class reasoning and phases can behave unpredictably on a weaker model.
Every finding gets discarded and the report comes back empty. This is expected behavior on a codebase with genuinely no exploitable issues VulnHunter’s adversarial pass can back with a PoC — it’s not a bug. If you expected findings on a known-vulnerable target, confirm you’re scanning the intended directory (pwd before launching Claude Code) and not a subdirectory that excludes the vulnerable code path.
vulnhunter-fix fails with a gh authentication error. The fixer shells out to the GitHub CLI to open the remediation PR. Run gh auth status to confirm you’re logged in and have write access to the target repository, then gh auth login if not.
Scans behave inconsistently between runs on the same codebase. VulnHunter is read-only by default and doesn’t cache results between invocations, so re-running /vulnhunt performs recon from scratch each time. Some variance in exactly which findings survive the falsification pass is expected given the adversarial reasoning involved — a finding that barely survives one run isn’t guaranteed to survive the next.
Where to go next
Once you’re comfortable with a single-repo scan, harness/ in the same repository adds batch scanning across a list of repos plus a benchmarking mode for evaluating detection accuracy against a known-vulnerable corpus — useful if you’re rolling VulnHunter out across more than one team’s codebase. For unattended CI/CD use, vulnhunter-agent/ wraps the scanner into a headless workflow that opens GitHub issues for confirmed findings automatically.

