Skip to main content

vulkro ai

Advisory only, opt-in, local by default

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:

  1. Probes the machine and recommends a model for it.
  2. 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-install to print the official install command and stop instead (locked-down or CI machines).
  3. Offers to start the daemon (ollama serve) if it is not running.
  4. Pulls the chosen model if it is not installed, with the consent rules below.
  5. 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
ModelSizeLicenseNote
qwen2.5-coder:7b4.7 GBApache-2.0The default: best commercial-safe code model that is still laptop-friendly.
phi4-mini:3.8b2.5 GBMITLight fallback for weak, CPU-only, or 8 GB machines.
qwen2.5-coder:1.5b1.0 GBApache-2.0Tiny: 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

FlagDescription
--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.
--yesAnswer yes to any prompt (start the daemon, pull a missing Tier-1 model). Never auto-pulls a bring-your-own model.
--byokSet 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-installDo 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.

FlagDescription
--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).

FlagDescription
--url <URL>Point at a different OpenAI-compatible runtime while switching.
--pullPull the model if it is not installed, without a prompt.
--yesAnswer 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.

FlagDescription
--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.

FlagDescription
--explainPrint 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.

FlagDescription
--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.

FlagDescription
--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.

FlagDescription
--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.

FlagDescription
--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:

  1. Per-run flags: --ai-model, --ai-url, --no-ai (or --model / --url on the vulkro ai subcommands).
  2. Environment variables: VULKRO_AI_MODEL, VULKRO_AI_URL, VULKRO_AI_KEY.
  3. The saved selection from vulkro ai use / vulkro ai setup.
  4. The smart default: qwen2.5-coder:7b (Apache-2.0), falling back to phi4-mini:3.8b (MIT) on a constrained machine. The smart default never selects the non-commercial qwen2.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

NameEffect
VULKRO_AI_MODELModel tag override. Beaten only by a per-run flag.
VULKRO_AI_URLOpenAI-compatible base-url override.
VULKRO_AI_KEYBring-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_OFFLINEThe 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.

CommandFlagsWhat the overlay adds
vulkro explain--aiA 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-urlThe 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-urlA security-delta narrative on the surface diff: new unauthenticated routes, removed auth checks, new or regressed findings.
vulkro inspect--aiA per-capability explanation of why a flagged shape is suspicious and what to check.
vulkro respond--aiA reachability / relevance judgement per matched package, grounded in the project's own call sites. Never flips the Clean / Exposed outcome.
vulkro slopcheck--aiA 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-budgetA 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-aiAn 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
  • 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 --ai tier 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.