Skip to main content
This guide explains how to install and use the vigolium-scanner skill with AI coding agents, Claude Code and OpenAI Codex, to operate the Vigolium CLI for web vulnerability scanning, security testing, and custom extension authoring. Skill repository: github.com/vigolium/skills — or install the copy embedded in your vigolium binary, which always matches your installed version.

Quick Install

vigolium skills install (added in v0.2.1) writes the vigolium-scanner bundle straight from the binary, so it can never drift from the CLI you’re driving. Pick the agent with --agent claude|codex|agents and the location with --scope project (current folder) or --scope global (home dir). Run vigolium skills to list what’s bundled and vigolium skills get vigolium-scanner to print a bundle without installing it. Prefer to pull the latest from the repo instead? Use the external skills installer:
Replace <agent-name> with your agent (e.g., claude-code, codex).

The three machine contracts

Whether or not you install the skill, these are the interfaces a program drives Vigolium through. They are additive — default human output is unchanged.

--events ndjson: watch a scan while it runs

Don’t poll the database and don’t invent a patience message — ask for the stream. One JSON object per line on stdout, flushed per event, while the human console stays on stderr:
Available on scan, run, scan-url, scan-request. Types: scan.started, phase.started|progress|finished, waf.block, waf.pacing, finding.new, error, scan.finished. The three you should actually branch on:
  • waf.block — the edge started filtering. Results for that host are incomplete; do not read a thin surface as a clean target.
  • error — a phase failed and the scan carried on. Non-fatal by construction, so this is never a reason to abandon a run that is still producing findings. A failure that ends the run rides on scan.finished{status:"failed"} instead.
  • scan.finished — always last, including status:"interrupted" on SIGINT/SIGTERM. Its absence means the process was killed outright (SIGKILL can’t be caught), so treat a stream that stops without it as a hard kill, not a completed scan.
Every line carries scan_uuid (a sweep is several invocations) and v, the event-schema version. This replaces scraping vigolium log for [waf-block-detected] markers. Full event table: CLI References.

-j: one envelope, every command

Parse items — it is the row array, and since v0.4.6 the only one. The historical row keys (records, findings, scans, rows, stats) are gone from the default output: they shipped a second full copy of every row, which on a 20-record compact read was 19,983 bytes against 7,884 of actual rows. --json-legacy-keys (or VIGOLIUM_JSON_LEGACY_KEYS=1) restores the alias for a caller still migrating, at that cost. Assert db_path: the database open order ends at one shared default file, so a fall-through silently mixes engagements. Run the query field rather than composing your own follow-up.
query is a ready-to-run follow-up pinned to the same store and scope, correctly shell-quoted:
Finding IDs are per-database autoincrement integers, so the --db / --stateless / --project-uuid flags inside that string are load-bearing. Under --glob-db the field is absent, because the merged source is a temporary database that no argument list can reopen.
Gate on the contract once at startup with vigolium version --json, which reports schema_version and db_schema_version.

Exit codes

0 success · 1 error · 2 usage error · 3 fuzz --fail-on-match · 4 --fail-on gate tripped. 3 and 4 are completed results, not failures: the output was written before the code was chosen. When it was not written, the run is 1 with error.code: "export_failed", and that outranks the gate. 3 and 4 are completed results, not failures. The output was written before the code was chosen. --soft-fail forces the process status to 0 for all of them while leaving the output intact — under --json the error object still reports the code that would have been used, plus "soft_fail": true. See the full table.

One document per invocation

Under --json you get exactly one document, whatever happens:
  • Flag order does not matter. traffic --bad --json and traffic --json --bad both emit one usage_error object.
  • A command that already wrote its result does not get an error object appended to it — the exit code carries the outcome.
  • Nothing else is ever written to stdout. Banners, prompts, progress, and warnings all go to stderr.
Error codes worth branching on: usage_error, source_missing, source_unreadable, source_incompatible (a valid SQLite file that is not a Vigolium store — you are pointed at the wrong file), export_failed (the run finished but a requested artifact was not written — retry the export, not the scan), gate_tripped, failed. traffic body and traffic headers add four of their own: record_not_found, body_unavailable, body_decode_failed, body_incomplete.
A requested artifact that was not written is exit 1, code export_failed (v0.5.0) — even when the scan itself ran clean, and even when it would otherwise have tripped the --fail-on gate. The gate’s whole premise is that the output was written before the code was chosen; when it wasn’t, exit 4 would send you to read a file that does not exist.Retry the export, not the scan: the findings reached the database, they just did not reach your -o. Formats are attempted independently, so with --format jsonl,sqlite one of them may well be on disk — the Exports summary on stderr lists what actually landed. Before v0.5.0 this state was exit 0 with scan.finished status=completed and no file.
A wrong --db path errors as of v0.4.7 — it no longer reads as empty. A pure read (traffic, finding, db ls, db stats, db export, export, log, traffic body/headers) against an explicitly pinned --db or $VIGOLIUM_DB_PATH that is not there now fails source_missing (exit 1) and creates nothing; another tool’s SQLite file fails source_incompatible (exit 1) without Vigolium’s tables being written into it. Before v0.4.7 both returned {"total":0,"items":[]} with exit 0, so “the path is wrong” and “nothing was captured here” were the same answer — and the wrong one looked like a finished task.The built-in default database is still created on first use, and replay/fuzz are exempt because they record the traffic they send. If you must support older builds, keep asserting db_path and sanity-check total against a query you know matches.
Confirmation for a destructive command requires a terminal. Without one it refuses immediately with exit 2 rather than blocking or reading your data stream as the answer; pass --force to authorize it non-interactively. --json is not authorization. Reading stdin is bounded by --input-read-timeout (default 3m, 0 disables), so a producer that never closes its end will not hang the process.

Discovering the interface

Don’t parse help text. Every registry that validates a flag can print itself:
strategy --json is generated from the same registries the flags are validated against, so phases[].canonical and phases[].aliases are exactly what --only, --skip, and run <phase> accept.

Credentials

auth list and config ls redact secrets by default — session tokens, auth headers, stored login requests, and login bodies. This applies under --json too, because --json output is the output most likely to end up in a transcript. --show-secrets reveals them and prints a warning to stderr. Redacted rows keep has_session_token, header_names, and a session_token_fingerprint (a short stable digest), so you can still tell two sessions apart or confirm a rotation landed without ever reading the secret.

What the Skill Does

The skill teaches the AI agent how to:
  1. Pick the right vigolium command for any security testing task
  2. Construct correct flag combinations with proper syntax
  3. Follow scanning workflows end-to-end (ingest -> scan -> triage -> export)
  4. Write custom JavaScript extensions using the vigolium.* API
  5. Operate AI agent modes (query, autopilot, swarm)
  6. Manage data: browse traffic, filter findings, export reports, clean databases
The skill uses lazy-loaded references: the main SKILL.md stays small, and detailed docs are loaded on demand when the agent needs deep flag information or extension authoring guidance.

Skill Structure

These filenames changed in v0.3.7–v0.3.9: the references were renamed to shorter stems, flags-reference.md became the generated flags.generated.md, server-and-ingestion.md split into server.md + ingest.md, and fuzzing and the Burp bridge moved out of agent-loop.md into their own files. A separate agent-browser skill was dropped. Re-run vigolium skills install to pick up the current layout.

Installation

Option A: vigolium skills install (recommended — embedded, version-matched)
The bundle ships inside the vigolium binary, so vigolium skills install can never install a stale copy — it always matches the CLI version you’re driving. --agent accepts claude, codex, or agents (an agentskills.io-compatible layout); --scope is project (current folder) or global (home dir). Inspect what’s bundled first with vigolium skills (list) and vigolium skills get vigolium-scanner (print). Option B: Install via npx / bunx (pulls the latest from the repo)
or with npx:
Replace <agent-name> with your agent (e.g., claude-code, codex). This fetches the skill from the vigolium/skills repository and registers it automatically. Option C: Clone and copy manually
Then copy the skill folder to your agent’s configuration directory:
Once installed, the skill auto-triggers when you mention keywords like scan, vigolium, agent autopilot, vulnerability scanner, openapi scan, etc. In Claude Code, you can also invoke it explicitly with /vigolium-scanner.

Usage Examples by Category

1. Scanning

Basic scan against a single target:
Multiple targets:
Targets from a file:
Do not pre-prefix a hostname list. Since v0.4.8 a schemeless target — example.com, example.com:8443, or a whole -T file of bare hostnames — is normalized to http:// at every entry point (CLI, REST API, agent swarm, scan-url), before the dedup, so example.com and http://example.com count as one target. Before v0.4.8 such lists scanned fine under probe, discovery and known-issue-scan but silently produced zero spidering records, and --only spidering --soft-fail still exited 0. See Schemeless targets.
Scan with a specific strategy:
Scan a single URL with custom method, headers, and body:
Scan a raw HTTP request from a file:
Scan a raw request from stdin:
Scan with a proxy (e.g., Burp Suite):
High-speed scan with tuned concurrency:
Scan and output results as JSONL:
Scan and generate an HTML report:
Scan to a standalone SQLite file:
--format sqlite (aliases sqlite3, db) requires -S/--stateless + -o; reopen it with vigolium finding -S --db scan.sqlite. Scan to a browsable filesystem tree (no DB needed):
--format fs writes two sibling dirs off the -o base — run-traffic/ and run-findings/ — so you can investigate with plain ls/grep/jq. Each <host>/<id>.req is the raw, replayable request (strip the leading @target line), <id>.resp.headers/<id>.resp.body hold the gzip-decoded response, and <id>.md under -findings/ is the finding cross-linked to its .req. Start from index.json in each dir — jq it to map every id to its url/status/severity. Works with or without -S; honors --omit-response. See Output and Reporting for the full layout. Scan to SARIF (for GitHub code scanning / DefectDojo):
--format sarif writes a SARIF 2.1.0 log; it also works on vigolium export --format sarif and vigolium import --format sarif (the path for publishing an agentic source audit). Code findings anchor to file:line so a consumer can annotate a diff; HTTP findings anchor to their URL and carry the evidence exchange in webRequest/webResponse. See Output and Reporting. Scan with custom scanning profile:
Scan with strict origin scope:

2. Input Formats

OpenAPI 3.x spec with explicit base URL:
OpenAPI spec using servers from the spec:
OpenAPI with auth header and parameter values:
Swagger 2.0 spec:
Burp Suite XML export:
HAR (HTTP Archive) file:
cURL commands file:
Postman collection:
Nuclei templates:
Piped URLs from stdin:

3. Phase Control

Run only discovery (content enumeration):
Run only spidering (headless browser crawling):
Run only audit (vulnerability scanning):
Run only the Nuclei known-issue scan (critical/high only):
Run a whitebox source-code audit (SAST):
Run only external harvest (Wayback, Common Crawl, OTX):
Skip specific phases:
Run only JavaScript extensions:
Phase aliases reference:

4. Module Filtering

List all available scanner modules:
Filter modules by keyword:
List only active modules with verbose details:
Scan with specific modules only:
Filter modules by tags (OR logic):
Combine module IDs and tags:
Enable/disable modules persistently:
Enable by exact module ID:

5. Server & Ingestion

Start the API server (default port 9002):
Start server on custom port without auth:
Start server with scan-on-receive (auto-scan ingested traffic):
Start server with transparent proxy for recording:
Mirror ingested traffic to files in real time:
Every saved HTTP record and finding is written to ./mirror/traffic/<host>/… and ./mirror/findings/<host>/… as it lands in the DB — the same layout as --format fs, except the indexes are append-only index.jsonl (one object per line — tail/grep it live) and per-host ids resume across restarts. Point your agent at ./mirror to read ingested Burp/proxy traffic as files while it streams in. High-concurrency server:
Ingest an OpenAPI spec locally:
Ingest and auto-scan:
Ingest Burp export:
Remote ingest to a running server:
Ingest without fetching responses:

6. AI Agent Modes

Agent (Template-Based)

Security code review:
Endpoint discovery from source:
Review specific files only:
Append extra instructions to a template:
Use a custom prompt file:
Select a specific olium provider:
Dry-run to preview the rendered prompt:
Save agent output to a file:
List available templates and providers:
Built-in templates include:
  • security-code-review: Comprehensive security review
  • injection-sinks: Find injection sinks
  • auth-bypass: Auth bypass vectors
  • secret-detection: Hardcoded secrets
  • endpoint-discovery: API endpoints from source
  • api-input-gen: Generate test inputs
  • curl-command-gen: Generate cURL commands
  • attack-surface-mapper: Map attack surface
  • nextjs-security-audit: Next.js security review
  • react-xss-audit: React XSS audit
  • cors-csrf-review: CORS/CSRF config audit

Agent Query (Freeform Prompt)

Inline prompt:
Named prompt flag:
Pipe prompt from stdin:
Custom prompt file with a specific provider:
Pick a different model:

Agent Autopilot (Autonomous Scanning)

Basic autonomous scan:
With source code context and focus area:
Custom limits (lighter intensity, shorter wall-clock):
Preview the system prompt (dry run):
Custom system prompt:
Start from project traffic, Burp history, and app docs:
Resume a durable run:
Use a different olium provider:
Autopilot security model:
  • Yolo-mode Bash — autopilot runs the model’s bash calls without an approval prompt. Common scanner, record, replay, finding, OAST, auth-session, and Burp operations are also first-class tools; the model can still shell out for uncovered CLI operations.
  • The engine only hard-rejects catastrophic patterns (rm -rf /, dd to block devices, fork bombs, mkfs against real devices). There is no vigolium-only command allowlist.
  • Per-tool timeout: 5 minutes (ToolTimeout).
  • Intensity-driven defaults: quick=150 / balanced=500 / deep=1500 commands (MaxCommands), browser enabled at every intensity.
  • In legacy/shadow mode, report_finding soft-warns at 50 findings and hard-caps at 200. In enforced mode, propose_candidate routes claims through fresh-context verification before promotion.
  • Run autopilot in a disposable container or VM scoped to in-scope targets — see Security Warning.

Agent Swarm (AI-Guided Multi-Phase Scan)

Basic swarm scan with discovery (all phases):
The swarm runs ten phases in order (most are conditional — see Swarm for full detail):
  1. native-normalize — parse --input/stdin/record-uuid into HTTP records
  2. auth (optional) — browser-driven login, writes auth headers/cookies
  3. source-analysis (if --source) — 4-call wave that emits routes, session-config, and source extensions
  4. code-audit (if --code-audit) — code-level security audit, findings → DB
  5. native-discover (if --discover) — crawl/spider/JS-scan
  6. plan — master agent picks modules and writes an extensions spec
  7. native-extension — compile/validate generated JS extensions (Sobek)
  8. native-scanrunner.RunNativeScan() with the planned modules + extensions
  9. triage (if --triage) — AI verifies findings, may request targeted rescans
  10. native-rescan — targeted rescan loop, bounded by --max-iterations
Swarm with focus area and source code:
Control rescan iterations:
Skip discovery and start from planning (use existing DB data):
Skip triage (just discover -> plan -> scan):
Use a scanning profile:
Preview agent prompts (dry run):
Specific source files for agent context:
Use a different agent backend:

7. Traffic & Results Browsing

Browse all stored HTTP traffic:
Fuzzy search traffic:
Tree view (hierarchical URL structure):
Burp-style colored output:
Filter by host, method, status:
Filter by date range:
Search in request/response body:
Since v0.4.7, --body searches only the body and --header only the header block; --search is the one that spans the whole exchange. Terms are matched literally, so % and _ are ordinary characters (--body 'api_key' no longer also matches api-key). --host/--path stay patterns, where * is the wildcard.
Select one exact URL (not a substring):
--url is equality, repeatable and OR-ed, and applied before pagination — the positional term is a substring search, and --uuid is identity. Extract one message without re-sending it:
This is the answer to a decoder_capped: true body: pull it whole in one call rather than concluding a string is absent. Four failure states are distinguishable — record_not_found, body_unavailable (that side was never captured), body_decode_failed, body_incomplete (a prefix; --allow-incomplete writes it anyway) — and a captured, genuinely empty body succeeds with empty: true. Keep a large result out of your context:
-o works on traffic, finding and db ls under -j. The file is byte-identical to what would have been printed; stdout gets {"artifact":"json_result","output":…,"bytes":…,"sha256":…,"complete":true}. complete: false means it holds one page. Search in headers:
Custom columns:
Watch mode (auto-refresh):
View raw HTTP request/response:
Browse findings:
Filter findings by severity:
Search findings:
Watch findings in real-time:
Render a finding as Markdown (evidence + request/response):
Read a standalone export without a project DB:
-S/--stateless + --db reads a --format jsonl export or a standalone .sqlite directly with project scoping off, writing nothing to your project DB. Replay stored traffic (re-send requests):
Replay and replace stored responses:

8. Data Management

Database statistics:
Detailed stats with host breakdown:
Stats for a specific host:
Live-updating stats:
List database records with filters:
List available tables and columns:
Clean records by hostname:
Clean old records with dry-run preview:
Clean only findings (keep HTTP records):
Clean orphaned findings:
Reset entire database:
Reclaim disk space after deletion:

9. Export & Reports

Full JSONL export:
Export only findings:
Export findings and HTTP records:
HTML report:
Lightweight export (omit raw HTTP request/response bytes):
Export with search filter:
Database-level export as CSV:
Export as Markdown:
Export raw requests only:
Export filtered by host and date:
Export a single record by UUID:
Export module registry:

10. Whitebox / Source-Aware Scanning

Source-aware scanning runs through the agent modes via the --source flag — the native vigolium scan does not take source code. Use agent swarm for an AI-driven source-aware DAST scan, or agent audit for a source-only (SAST) review. Source-aware scan with local source code:
--target is required whenever --source is given. The source-analysis and code-audit phases run automatically when --source is present. Scan with source cloned from Git:
Run a source-code audit (SAST) only:
Deeper multi-phase audit:

11. JavaScript Extensions

Install preset examples:
View the extension API reference:
List loaded extensions:
Quick-test JS code inline:
Evaluate a JS file:
Run a custom extension against a target:
Run extension alongside built-in modules:
Run only extensions (skip built-in modules):
Load multiple extensions:
Load all extensions from a directory:
Ask the agent to write an extension:
The agent will generate a JS file like:
Ask the agent to write an AI-augmented extension:
The agent will generate a JS file using vigolium.agent.generatePayloads() and vigolium.agent.analyzeResponse(). YAML extension (simple pattern matching):

12. Configuration & Projects

View all configuration:
View a specific config section:
Set configuration values:
Set scope mode:
Enable extensions globally:
View scope rules:
View scanning strategies:
Create and manage projects:
Scope CLI operations to a project:
Project-scoped database access:

Natural Language Examples

These are examples of natural language prompts you can give to Claude Code or Codex with the skill installed. The agent will translate them into the correct vigolium commands.

Tips & Best Practices

  1. Start with scan -t: It’s the most common command. Add flags incrementally.
  2. Use strategies: lite for quick checks, balanced for most cases, deep for full coverage, whitebox when you have source code.
  3. Phase isolation: Use --only or vigolium run <phase> to iterate on a single phase without re-running the entire pipeline.
  4. Module tags: Filter modules by technology (spring, nodejs) or vulnerability class (xss, injection) to reduce noise.
  5. Watch mode: Add --watch 5s to traffic, finding, or db stats for real-time monitoring during long scans. Under --json it switches to NDJSON — one compact document per line, no clear-screen, no heading — and it is rejected on a command that writes.
  6. Triage at scale first: vigolium run probe -T hosts.txt sweeps thousands of hosts with one request each. Rank by surface_score, then point a real scan at the top of that list — don’t send a full scan at a list you haven’t triaged.
  7. Count, don’t dump: vigolium traffic --group-by status_code runs the same filters the listing would and returns buckets. Never pull rows into your context just to count them.
  8. Route bulk output to disk: -o findings.json on a -j read puts the document in a file and a receipt on stdout. For one message, traffic body/traffic headers beat exporting a whole record tree.
  9. Dry-run agents: Always --dry-run first for agent commands to preview prompts before spending AI tokens.
  10. Swarm over autopilot: Use agent swarm --discover for structured scans (lower cost, reproducible). Use agent autopilot for exploratory, creative scanning.
  11. Extensions for custom logic: Write JS extensions instead of modifying core modules. They run alongside built-in modules with --ext.
  12. Projects for isolation: Use vigolium project create to keep scan data separate across engagements.
  13. Export early: Run vigolium export --format html -o report.html to share results as interactive reports.