vulkro ai
The AI layer is opt-in and advisory. It never changes a deterministic
finding, its severity, the JSON / SARIF / SBOM output, or an exit code, and
the published benchmark is AI-free. The default model is a local
qwen2.5-coder:7b served by Ollama on your own machine, so nothing leaves
the box.
The vulkro ai command group configures and drives Vulkro's local-AI layer:
pick a model, point at a runtime, self-test it, and use the advisory surfaces
(chat, one-shot questions, second-pass target selection, the AI memory log,
and agent-context exports).
There are no config files. The selection is CLI-only and is persisted in the
settings key-value table of the same ~/.vulkro/scans.db every other
subsystem uses (schema migration V011). A cloud API key is never persisted:
it is read from the VULKRO_AI_KEY environment variable only.
Usage
vulkro ai <SUBCOMMAND> [FLAGS]
Configuration subcommands (setup, list, use, pull, status, test,
off) never scan your code. The grounded subcommands (targets, chat,
ask, export, skill) run the normal deterministic scan first and
require the same verified account as vulkro scan (see
vulkro login).
Getting started: vulkro ai setup
One command sets up the whole path:
vulkro ai setup
The wizard:
- Probes the machine and recommends a model for it.
- Installs Ollama if it is missing. The install is always explicit: from the
official source, only after a y/N confirmation, never a hidden
curl | sh. Pass--no-installto print the official install command and stop instead (locked-down or CI machines). - Offers to start the daemon (
ollama serve) if it is not running. - Pulls the chosen model if it is not installed, with the consent rules below.
- Runs a canned self-test and saves the selection.
Interactive prompts appear only on a TTY. In CI or any non-TTY context the wizard is fully scriptable and never blocks on a prompt:
vulkro ai setup --model qwen2.5-coder:7b --yes
Recommended models
| Model | Size | License | Note |
|---|---|---|---|
qwen2.5-coder:7b | 4.7 GB | Apache-2.0 | The default: best commercial-safe code model that is still laptop-friendly. |
phi4-mini:3.8b | 2.5 GB | MIT | Light fallback for weak, CPU-only, or 8 GB machines. |
qwen2.5-coder:1.5b | 1.0 GB | Apache-2.0 | Tiny: runs anywhere, simple single-function fixes only. |
These are Tier 1 (Apache-2.0 / MIT): no license obligation flows to you, so
Vulkro may default to them and auto-pull them after consent (--yes, or an
interactive yes). Every other model is Tier 2 (bring-your-own): it is never
auto-pulled, and you accept its license when you pull it explicitly.
The smart default never selects qwen2.5-coder:3b: that 3B sibling ships
under a non-commercial license and is unsuitable for commercial use. On a
constrained machine (fewer than 4 physical cores) the smart default falls
back to phi4-mini:3.8b instead.
Setup flags
| Flag | Description |
|---|---|
--model <MODEL> | Model tag to use; skips the interactive picker. Example: qwen2.5-coder:7b. |
--url <URL> | OpenAI-compatible runtime base url. Default: http://127.0.0.1:11434/v1 (local Ollama). For --byok, a cloud url such as https://api.openai.com/v1. |
--yes | Answer yes to any prompt (start the daemon, pull a missing Tier-1 model). Never auto-pulls a bring-your-own model. |
--byok | Set up bring-your-own-key cloud mode instead of a local model. The key is read from VULKRO_AI_KEY only and never written to disk. Cloud means code context leaves the machine, and it is refused under VULKRO_OFFLINE. |
--no-install | Do not install Ollama even if it is missing: print the official install command and stop. |
Exit code: 0 saved, 2 error (Ollama missing and not installed, runtime
unreachable, model missing and declined, bad args).
The other configuration subcommands
vulkro ai list
Lists the installed models plus the Tier-1 recommended set with size and license; the current model is marked.
| Flag | Description |
|---|---|
--format <FMT> | table (default, human) or json (a single-line object with installed, recommended, default, and constrained_default, for tooling such as an editor settings UI). |
vulkro ai use <MODEL>
Sets the active model. Validates that the runtime is reachable and that the model is installed, and offers to pull it if not (Tier-1 models are auto-pullable; others are bring-your-own).
| Flag | Description |
|---|---|
--url <URL> | Point at a different OpenAI-compatible runtime while switching. |
--pull | Pull the model if it is not installed, without a prompt. |
--yes | Answer yes to any prompt. |
vulkro ai pull <MODEL>
Pulls a model with a progress bar (wraps the runtime's model pull). Prints the model's license tier before pulling.
vulkro ai status
Shows the current model and runtime, reachability, warm state, offline mode, and the model's license tier.
| Flag | Description |
|---|---|
--format <FMT> | table (default, human) or json (a single-line object with enabled, model, base_url, endpoint_class, reachable, warm, offline, provider, and license_tier). |
vulkro ai test
Runs a canned self-test against the active model and prints the verdict:
ok when the model answers in the expected verdict shape, weak when it
answers but not in that shape (advisory surfaces may be less reliable; a 7B
model is recommended). Exits 2 when the AI layer is off or the call fails.
vulkro ai off
Disables the AI layer (deterministic-only). The model selection is kept, so
a later vulkro ai setup restores it without re-choosing.
The json output of list and status is the contract the Vulkro VS Code
extension's settings surface consumes. The extension is built and
distributed as a .vsix; the Marketplace listing is coming soon.
The grounded subcommands
These run the normal deterministic scan first and layer the advisory AI
surface on top of it. The scan they run is the same pipeline as
vulkro scan, and its result is never mutated by anything the
AI produces.
vulkro ai targets [PATH]
Ranks the graph nodes a local-AI second pass should investigate, using only the deterministic scan. No model is called. It builds the evidence graph and data-flow graph, then promotes only the four buckets where the deterministic engine is structurally weak or deliberately silent:
- A: business-logic / money-flow intent
- B: unknown-reachability, likely-exploitable taint
- C: missing controls
- D: authorization intent
Every promotion is auditable with --explain, in the same style as
vulkro explain --risk-model.
| Flag | Description |
|---|---|
--explain | Print each target's reason codes and retrieval hints (the full audit trail behind its bucket and priority). |
--max-targets <N> | Cap the number of promoted targets (the token budget). Default: 12, sized for a local 7B context window. |
--format <FMT> | table (default) or json (the target list). |
Exit codes follow the deterministic scan and are never affected by target
selection: 0 no findings, 1 findings reported, 2 error.
vulkro ai chat [PATH]
Interactive advisory chat grounded in the project's scan. Runs the
deterministic scan once, then opens a REPL: type a question, get an advisory
answer anchored to that scan's endpoints, findings, and vulnerable
dependencies. Type exit (or press Ctrl-D) to quit.
The answers are advisory only: they never change a deterministic finding, a severity, or the exit code. A disabled or unreachable AI layer prints an actionable note as the answer rather than failing.
| Flag | Description |
|---|---|
--model <MODEL> | Model tag override for this session. |
--url <URL> | OpenAI-compatible runtime base url override for this session. |
Exit code: 0 on a clean session, 2 on error (bad path, scan failure).
The advisory chat never sets exit 1.
vulkro ai ask <QUESTION> [PATH]
One-shot advisory answer: scan the project, answer the question grounded in
that scan, print the answer, and exit. The answer is the only stdout output,
so it pipes cleanly. Same grounding and offline gating as ai chat.
| Flag | Description |
|---|---|
--model <MODEL> | Model tag override for this answer. |
--url <URL> | OpenAI-compatible runtime base url override for this answer. |
Exit code: 0 success, 2 error.
vulkro ai log [PATH]
Lists the project-local AI memory records at .vulkro/ai/sessions.jsonl:
the advisory triage, fix, hunt, and chat interactions recorded for this
project, newest first. Read-only: it never scans and never calls a model.
| Flag | Description |
|---|---|
--limit <N> | Cap the number of records shown (newest first). |
--format <FMT> | table (default) or json (the record list). |
Exit code: 0 success, 2 error.
vulkro ai export [PATH]
Exports a portable skill bundle (a zip): a Markdown security digest, the
advisory AI analysis reconstructed from the memory store, and a copy of
.vulkro/ai/sessions.jsonl. Use it to hand this project's security context
to an external agent. Additive and advisory: nothing in the bundle changes a
deterministic result.
| Flag | Description |
|---|---|
--output, -o <FILE> | Output zip path. Default: ./vulkro-skill-bundle.zip. |
Exit code: 0 success, 2 error.
vulkro ai skill [PATH]
Writes (or updates) the agent-context files external AI agents read:
AGENTS.md, a managed section inside CLAUDE.md, and
.cursor/rules/vulkro.mdc, each carrying this project's findings digest and
advisory AI analysis. Idempotent: only the marker-delimited vulkro block is
touched, your own content is preserved, and re-running with an unchanged
scan rewrites nothing.
Exit code: 0 success, 2 error.
How the model is resolved
Every AI-capable command resolves its model and runtime in the same order, highest priority first:
- Per-run flags:
--ai-model,--ai-url,--no-ai(or--model/--urlon thevulkro aisubcommands). - Environment variables:
VULKRO_AI_MODEL,VULKRO_AI_URL,VULKRO_AI_KEY. - The saved selection from
vulkro ai use/vulkro ai setup. - The smart default:
qwen2.5-coder:7b(Apache-2.0), falling back tophi4-mini:3.8b(MIT) on a constrained machine. The smart default never selects the non-commercialqwen2.5-coder:3b.
An explicit --no-ai always wins and disables the layer for that run. After
vulkro ai off, the layer stays off unless a per-run flag or environment
override explicitly re-enables it.
Environment variables
| Name | Effect |
|---|---|
VULKRO_AI_MODEL | Model tag override. Beaten only by a per-run flag. |
VULKRO_AI_URL | OpenAI-compatible base-url override. |
VULKRO_AI_KEY | Bring-your-own cloud API key. Env-only: it is never written to disk, and it is only sent to a cloud endpoint (a local endpoint never carries a key). |
VULKRO_OFFLINE | The air-gap switch. A loopback (local Ollama) model is still allowed, because nothing leaves the machine. A cloud endpoint is refused. |
Where the settings live
The vulkro ai group stores its state in the settings key-value table of
~/.vulkro/scans.db, added by schema migration V011. The keys are the
active model (ai.model), the runtime base url (ai.base_url), and the
on/off state (ai.enabled). There is no config file to edit or check in,
and no API key on disk: VULKRO_AI_KEY lives only in your environment.
The Salesforce CLI shares this exactly: vulkro-sf ai is a thin mirror of
the same command group and reads and writes the same V011 settings, so a
model configured with either binary serves both.
AI never changes scan results
The deterministic scan is the product; the AI layer is an advisory overlay on top of it. Concretely:
- Enabling AI changes no deterministic finding, no severity, and no exit code. The machine-readable outputs a pipeline consumes (JSON, SARIF, SBOM) are unchanged by it.
- Every AI-produced surface is labelled advisory, non-deterministic, and excluded from the benchmark. The published benchmark runs with the AI layer off.
- Advisory output is kept structurally separate: an additive field, a labelled block, or a separate report, never merged into the deterministic findings.
- Where AI proposes code fixes (
vulkro fix --ai), the judge is deterministic: a proposed fix counts as verified only when a fresh deterministic re-scan no longer reports the finding, no new finding appears, and the file still parses. That claim is deliberately narrow: it does not claim the build compiles or that tests pass. Everything else is refused with a reason, and a refusal is not an error. - Local by default: the default runtime is loopback Ollama, so code context
stays on the machine even with AI on. Cloud (BYOK) is a separate,
explicit opt-in and is refused under
VULKRO_OFFLINE.
The --ai flags on other commands
Several commands accept a per-run AI overlay. All of them resolve the model the same way (flags, then env, then the saved selection, then the smart default), and none of them changes the command's deterministic output or exit code.
| Command | Flags | What the overlay adds |
|---|---|---|
vulkro explain | --ai | A plain-language narrative for the matched finding: what it is, why it matters in this code, how to fix it here. |
vulkro fix | --ai, --ai-model, --ai-url | The AI fix tier for findings no deterministic template covers. --ai alone is read-only; --ai --write applies only verified diffs (see the definition above), after the deterministic templates run. |
vulkro diff | --ai, --ai-model, --ai-url | A security-delta narrative on the surface diff: new unauthenticated routes, removed auth checks, new or regressed findings. |
vulkro inspect | --ai | A per-capability explanation of why a flagged shape is suspicious and what to check. |
vulkro respond | --ai | A reachability / relevance judgement per matched package, grounded in the project's own call sites. Never flips the Clean / Exposed outcome. |
vulkro slopcheck | --ai | A per-name explanation of why a dependency name is risky and what to verify before installing. |
vulkro triage | --ai-model, --ai-url, --no-ai (plus the legacy --model alias) | Selects the model for the advisory triage verdicts. |
vulkro analyze | --ai, --ai-model, --ai-url, --no-ai, --ai-max-targets, --ai-budget | A graph-guided AI second pass over the ai targets buckets. Candidates are never merged into the deterministic findings. |
vulkro hunt | --ai-model, --ai-url, --no-ai | An AI-driven hunt that calls Vulkro's deterministic checks as tools. A finding is confirmed only when a deterministic oracle grounds it; everything else is a labelled advisory lead. |
vulkro scan itself has no --ai flag. Its --ai-pr flag is unrelated to
the AI layer: it is a deterministic calibration heuristic over the git diff
shape and calls no model.
Examples
# One-time setup: install Ollama (consented), pull the default model, self-test.
vulkro ai setup
# Scriptable setup for CI or provisioning: never prompts.
vulkro ai setup --model qwen2.5-coder:7b --yes
# What is configured right now, and is the runtime up?
vulkro ai status
vulkro ai status --format json
# Switch models, pulling if needed.
vulkro ai use phi4-mini:3.8b --pull
# What would an AI second pass look at? Deterministic, no model called.
vulkro ai targets . --explain
# Ask one grounded question and pipe the answer.
vulkro ai ask "Which endpoints accept file uploads without auth?" .
# Interactive advisory chat over the scan.
vulkro ai chat .
# Review what the advisory layer has done in this project.
vulkro ai log . --limit 20
# Hand the project's security context to an external agent.
vulkro ai export . -o context.zip
vulkro ai skill .
# Turn the layer off; the model selection is kept.
vulkro ai off
Related
vulkro scan- the deterministic, offline scan every grounded subcommand runs first.vulkro triage- the advisory triage lens that uses the model configured here.vulkro fix- fix suggestions; the--aitier is validated by a deterministic re-scan.vulkro login- the verified account the scanning subcommands require.- Air-gap: offline mode -
VULKRO_OFFLINE, and why a loopback model is still allowed under it.