> ## Documentation Index
> Fetch the complete documentation index at: https://docs.vigolium.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Configuration Reference

> Vigolium uses a layered configuration system that merges settings from multiple sources. This document covers the config file format, environment variables, and every configurable section.

## Config File Location

The main config file is `~/.vigolium/vigolium-configs.yaml`. It is created automatically on first run with sensible defaults.

Vigolium searches for configuration in this order:

1. Path specified via the `--config` flag (error if not found)
2. `~/.vigolium/vigolium-configs.yaml`
3. `./vigolium-configs.yaml` (current working directory)

If no config file is found, built-in defaults are used.

## Config Precedence

Settings are resolved from highest to lowest precedence:

1. **CLI flags** -e.g. `--concurrency 100`, `--rate-limit 50`
2. **Environment variables** -e.g. `VIGOLIUM_API_KEY`, `VIGOLIUM_PROJECT`
3. **Scanning profile** -loaded via `--scanning-profile <name>` (from `~/.vigolium/profiles/`)
4. **Project-level config** -per-project overlay at `~/.vigolium/projects/<uuid>/config.yaml`
5. **Main config file** -`~/.vigolium/vigolium-configs.yaml`
6. **Built-in defaults** -hardcoded in the Go source

Higher-precedence sources override lower ones. Within the config file, environment variables can be referenced using `${VAR}` or `$VAR` syntax and are expanded at load time.

## Environment Variables

| Variable           | Purpose                                                                             |
| ------------------ | ----------------------------------------------------------------------------------- |
| `VIGOLIUM_API_KEY` | API key for the REST server and ingestor client authentication                      |
| `VIGOLIUM_PROJECT` | Default project UUID for CLI operations (equivalent to `--project`)                 |
| `VIGOLIUM_PROXY`   | HTTP/SOCKS proxy URL, used when `--proxy` is not set                                |
| `VIGOLIUM_HOME`    | Base directory for Vigolium data (used by the installer; defaults to `~/.vigolium`) |

Any environment variable can also be interpolated inside `vigolium-configs.yaml`:

```yaml theme={null}
database:
  postgres:
    password: ${VIGOLIUM_DB_PASSWORD}
```

## CLI Config Overrides

Use `vigolium config set` to update individual config values using dot-notation keys:

```bash theme={null}
vigolium config set scanning_pace.concurrency 100
vigolium config set database.driver postgres
vigolium config set notify.enabled true
vigolium config set notify.severities high,critical
vigolium config set server.service_port 8080
```

These commands modify the main config file directly. For one-off overrides during a scan, use CLI flags instead.

## Config Sections

### `scanning_strategy`

Controls which scan phases run for each strategy preset.

```yaml theme={null}
scanning_strategy:
  default_strategy: balanced    # lite | balanced | deep
  heuristics_check: basic
  scanning_profile: ""          # name of a profile to auto-load
  profiles_dir: ~/.vigolium/profiles/

  session:
    session_dir: ~/.vigolium/sessions/
    use_in_discovery: true       # apply session headers during discovery/spidering
    compare_enabled: true        # cross-session IDOR/BOLA replay in dynamic-assessment
    reauth_interval: ""          # e.g. "15m" to refresh tokens periodically
    reauth_on_status: []         # e.g. [401, 403]
    validate_url: ""             # URL to GET after login to verify credentials

  # Phase toggles per strategy (canonical names):
  balanced:
    discovery: true
    spidering: true
    known_issue_scan: true
    dynamic-assessment: true
    external_harvesting: false
```

Available strategies and their default phases:

| Phase                | lite | balanced | deep |
| -------------------- | ---- | -------- | ---- |
| external\_harvesting | -    | -        | yes  |
| discovery            | -    | yes      | yes  |
| spidering            | -    | yes      | yes  |
| known\_issue\_scan   | -    | yes      | yes  |
| dynamic-assessment   | yes  | yes      | yes  |

> **Phase aliases:** `dynamic-assessment` is the canonical name for active/passive vulnerability scanning. `audit`, `dast`, and `assessment` are accepted aliases on `--only` / `--skip` flags. `discovery` accepts `deparos` / `discover`; `spidering` accepts `spitolas`; `extension` accepts `ext`.

For source-aware whitebox analysis, use `vigolium agent swarm --source <path>` or `vigolium agent audit --source <path>` instead of a native scan strategy. See [Agent Mode](/agentic-scan/agent-mode).

### `scanning_pace`

Centralized speed control. Common values serve as baselines; per-phase subsections override them.

```yaml theme={null}
scanning_pace:
  concurrency: 50          # global worker count
  rate_limit: 100          # max requests/sec across all hosts
  max_per_host: 10         # max concurrent requests per host
  max_duration: 2h         # global time cap for a scan phase

  # Per-phase overrides (zero = inherit from common):
  discovery:
    concurrency: 0
    rate_limit: 0
    concurrency_factor: 0  # multiplier on common concurrency
    duration_factor: 0     # multiplier on common max_duration
  spidering:
    duration_factor: 0.15  # e.g. 2h * 0.15 = 18m
  known_issue_scan:
    duration_factor: 3.0
  external_harvester:
    duration_factor: 0.2
  audit:
    duration_factor: 1.0
    parallel_passive: true         # run passive modules in parallel
    feedback_drain_timeout: 500ms  # wait for feedback loop items
```

### `discovery`

Content discovery (directory/file brute-forcing).

```yaml theme={null}
discovery:
  mode: files_and_dirs         # files_and_dirs | files_only | dirs_only
  scope_mode: subdomain        # any | subdomain | exact
  save_response_body: true
  enable_malformed_path_probe: false
  dedup_cluster_cap: 10        # keep at most N near-identical responses per cluster (omit = 10, 0 = disabled)
  auto_fuzz_low_yield: true    # auto-enable FUZZ on the original target when spidering came up empty or hit an SSO wall (omit = on)
  enrich_targets: false        # feed paths from spidering/harvest into discovery

  recursion:
    enabled: true
    max_depth: 5

  wordlists:
    short_file_path: ""        # custom wordlist paths
    long_file_path: ""
    short_dir_path: ""
    long_dir_path: ""
    fuzz_wordlist_path: ""
    use_observed_names: true
    use_observed_paths: true
    use_observed_files: true
    enable_numeric_fuzzing: false

  extensions:
    test_custom: true
    custom_list: []
    test_observed: true
    test_backup_extensions: true
    backup_extensions: []
    test_no_extension: true

  engine:
    case_sensitivity: auto_detect  # auto_detect | sensitive | insensitive
    timeout: 10s                   # per-request timeout (1s-300s)
    custom_headers: {}
    enable_cookie_jar: false
    max_consecutive_errors: 0
    max_consecutive_waf_blocks: 0
    observed_max_items: 4000
    disable_kingfisher: false
```

### `spidering`

Browser-based crawling.

```yaml theme={null}
spidering:
  max_depth: 0               # 0 = unlimited
  max_states: 0              # 0 = unlimited
  max_duration: 30m
  max_consecutive_fails: 100
  headless: true
  browser_count: 1
  strategy: adaptive         # normal | random | oldest_first | shallow_first | adaptive
  include_response_body: true
  browser_engine: chromium   # chromium | ungoogled | fingerprint
  no_cdp: false              # disable CDP event listener detection
  no_forms: false            # disable automatic form filling

  # AI pilot mode (agent-controlled browser):
  pilot_mode: false
  pilot_auto_register: true
  pilot_username: ""
  pilot_password: ""
  pilot_screenshot: true
  pilot_max_retries: 2
  pilot_stall_timeout: 7m
```

### `dynamic-assessment`

Controls which scanner modules run and JavaScript extension settings. (Formerly `audit`.)

```yaml theme={null}
dynamic-assessment:
  max_feedback_rounds: 1            # rescan rounds for newly-discovered URLs
  max_findings_per_module: 15       # 0 = unlimited

  enabled_modules:
    active_modules: ["all"]         # ["all"] or list of module IDs
    passive_modules: ["all"]

  extensions:
    enabled: false
    extension_dir: ~/.vigolium/extensions/
    custom_dir: []                  # additional script paths
    variables: {}                   # key-value pairs passed to scripts
    limits:
      timeout: 30s
      max_memory_mb: 128
```

### `scope`

Defines what is in scope for scanning. Exclude rules take priority over include rules.

```yaml theme={null}
scope:
  applied_on_ingest: false       # enforce scope during ingestion (not just scanning)
  cli_origin_mode: relaxed       # relaxed | all | balanced | strict
  ignore_static_file: true       # skip images, fonts, video, audio, etc.
  max_request_body_size: 1048576     # 1 MB
  max_response_body_size: 524288000  # 500 MB
  body_size_exceeded_action: truncate  # truncate | drop | skip-scan

  host:
    include: ["*"]
    exclude: []
  path:
    include: ["*"]
    exclude: []
  status_code:
    include: ["*"]
    exclude: []
  request_content_type:
    include: ["*"]
    exclude: []
  response_content_type:
    include: ["*"]
    exclude: []
  request_string:
    include: []
    exclude: []
  response_string:
    include: []
    exclude: []
```

### `server`

REST API server settings.

```yaml theme={null}
server:
  auth_api_key: ""                 # auto-generated if empty; also set via VIGOLIUM_API_KEY
  service_port: 9002
  ingest_proxy_port: 0             # 0 = disabled
  mirror_fs_path: ""               # mirror ingested traffic + findings to this dir as a live filesystem tree (see --mirror-fs)
  cors_allowed_origins: reflect-origin
  enable_metrics: true
  agent_heavy_max: 5               # max concurrent autopilot/swarm runs via API
  agent_light_max: 10              # max concurrent query/chat runs via API
  agent_queue_timeout: 30s         # wait for an agent slot before returning 429
  license: ""                      # optional license tag surfaced in /server-info
```

### `agent`

AI agent integration. Every agent invocation is dispatched through the in-process **olium** runtime, there are no subprocess SDK or ACP backends.

```yaml theme={null}
agent:
  default_agent: olium
  templates_dir: ~/.vigolium/prompts/
  sessions_dir: ~/.vigolium/agent-sessions/
  stream: true                     # real-time output streaming

  # Olium engine — used by every agent subcommand
  olium:
    provider: openai-compatible    # openai-codex-oauth | anthropic-api-key | anthropic-oauth | openai-api-key | openai-responses | anthropic-cli | anthropic-claude-sdk-bridge | anthropic-compatible | anthropic-vertex | google-vertex | openai-compatible (default: openai-compatible)
    model: gemma4:latest           # empty = provider default; matches custom_provider.model_id default (openai-compatible / anthropic-compatible)
    oauth_cred_path: ~/.codex/auth.json    # openai-codex-oauth provider
    bridge_binary: ""              # anthropic-claude-sdk-bridge: path to the vigolium-audit binary hosting the SDK bridge (empty = embedded blob, then PATH)
    oauth_token: ""                # anthropic-oauth bearer token (from `claude setup-token`); supports ${ENV_VAR}
    llm_api_key: ""                # for anthropic-api-key / openai-api-key / openai-responses; supports ${ENV_VAR}; falls back to provider env
    reasoning_effort: medium       # minimal | low | medium | high | xhigh (codex)
    system_prompt: ""              # override built-in olium system prompt
    max_tokens: 1000000
    temperature: 0.0
    max_turns: 32                  # tool-loop iteration cap
    cache_size: 1024               # LRU entries; 0 disables
    max_concurrent: 4              # global cap on simultaneous in-flight provider calls
    call_timeout_sec: 600          # per-call deadline; -1 = no enforced timeout

    # Skills always loaded for autopilot/swarm regardless of planner selection.
    # Empty = built-in default [triage-finding, write-jsext]. The CLI flags
    # --skill / --skill-tag / --no-skill-filter override selection per-run.
    always_on_skills: []

    # Custom backend: used when provider == openai-compatible (OpenAI Chat
    # Completions — Ollama, OpenRouter, LM Studio, vLLM, Together, Groq, …) or
    # provider == anthropic-compatible (Anthropic Messages /v1/messages gateway).
    custom_provider:
      base_url: http://localhost:11434/v1   # e.g. http://localhost:11434/v1 (Ollama)
      model_id: gemma4:latest               # backend-specific model id
      api_key: ""                           # optional; leave empty to skip Authorization header; supports ${ENV_VAR}
      extra_headers: []                     # list of curl-style "Key: Value" strings, applied after standard headers

      # OpenRouter provider routing — typed knob for the request "provider" object.
      # Only fields you set are sent; unset fields are dropped from the wire body.
      provider_routing:
        order: []                  # upstream provider slugs in preference order
        only: []                   # restrict to these provider slugs
        ignore: []                 # exclude these provider slugs
        allow_fallbacks: true      # false = strict (only the chosen providers)
        sort: ""                   # price | throughput | latency
        quantizations: []          # e.g. [fp8, int8]
        data_collection: ""        # allow | deny
        require_parameters: false  # only providers that honour every request parameter
        zdr: false                 # Zero Data Retention providers only

      # Generic JSON-body passthrough merged into every openai-compatible request
      # (OpenRouter extensions, vLLM/Together body options, etc.). Reserved keys
      # (model, messages, tools, stream, stream_options) are rejected. Don't set a
      # `provider` key here if you also use provider_routing — use one or the other.
      extra_body: {}

    # Vertex AI (anthropic-vertex / google-vertex) — GCP project / region.
    # Credentials come from `oauth_cred_path` (service-account JSON) or
    # $GOOGLE_APPLICATION_CREDENTIALS. $GOOGLE_CLOUD_PROJECT and
    # $GOOGLE_CLOUD_LOCATION override these YAML values.
    google_cloud_project: ""       # GCP project id
    google_cloud_location: ""      # GCP region; default us-central1

  # LLM config for JavaScript extension agent API (vigolium.agent.* in extensions)
  llm:
    provider: anthropic            # anthropic | openai
    model: claude-sonnet-4-20250514
    api_key: ""                    # inline key (prefer api_key_env)
    api_key_env: ""                # env var name (default: ANTHROPIC_API_KEY or OPENAI_API_KEY)
    base_url: ""                   # custom endpoint for OpenAI-compatible providers
    max_tokens: 4096
    temperature: 0.0
    cache_size: 256                # LRU entries (0 = disabled)
    cache_ttl: 300                 # seconds

  # DB context enrichment limits for swarm/autopilot
  context_limits:
    max_findings: 50
    max_endpoints: 100
    max_high_risk: 20
    min_risk_score: 50

  # Autopilot guardrails (SDK-era; mostly informational under olium)
  guardrails:
    log_commands: false
    max_turns: 0                   # 0 = auto (MaxCommands * 3)
    disallowed_tools: []

  # Optional agent-browser integration (Bash tool can drive a real Chromium for auth-walled flows)
  browser:
    enable: true
    binary_path: agent-browser     # default: looked up on $PATH

  # Vigolium-audit integration (embedded harness)
  audit:
    enable: false                  # auto-enabled by --audit flag on autopilot/swarm
    mode: lite                     # lite | balanced | deep | mock
    sync_interval: 30              # seconds between state syncs
    # The audit driver runs the `claude` or `codex` CLI. There is no
    # platform knob here — the agent is resolved from agent.olium.provider
    # (anthropic-* → claude, openai-* → codex), overridable per-run with
    # --provider or --agent {claude|codex} on `vigolium agent audit`.
```

Provider quick reference:

| Provider                                         | Default model                                    | Credential source                                                                                                              |
| ------------------------------------------------ | ------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------ |
| `openai-codex-oauth`                             | `gpt-5.5`                                        | `oauth_cred_path` (`~/.codex/auth.json`)                                                                                       |
| `anthropic-api-key`                              | `claude-opus-4-7`                                | `llm_api_key` or `$ANTHROPIC_API_KEY`                                                                                          |
| `anthropic-oauth`                                | `claude-opus-4-7`                                | `oauth_token` (from `claude setup-token`); falls back to `$ANTHROPIC_API_KEY`                                                  |
| `openai-api-key`                                 | `gpt-5.5`                                        | `llm_api_key` or `$OPENAI_API_KEY`                                                                                             |
| `openai-responses`                               | `gpt-5.5`                                        | `llm_api_key` or `$OPENAI_API_KEY` (public OpenAI Responses API, `/v1/responses`)                                              |
| `anthropic-cli` *(alias `anthropic-claude-cli`)* | `claude-opus-4-7`                                | local `claude` binary on `$PATH`                                                                                               |
| `anthropic-claude-sdk-bridge`                    | Claude Code default                              | logged-in Claude Code subscription via the `vigolium-audit bridge` sidecar (no key); `bridge_binary` / `--bridge-bin` override |
| `anthropic-compatible`                           | via `custom_provider.model_id`                   | `agent.olium.custom_provider` (Anthropic Messages `/v1/messages` gateway or proxy)                                             |
| `anthropic-vertex`                               | `claude-opus-4-6`                                | GCP service-account JSON (or ADC) via `google_cloud_project` / `google_cloud_location`                                         |
| `google-vertex`                                  | `gemini-2.5-pro`                                 | GCP service-account JSON (or ADC) via `google_cloud_project` / `google_cloud_location`                                         |
| `openai-compatible` *(default)*                  | `gemma4:latest` (via `custom_provider.model_id`) | `agent.olium.custom_provider` (Ollama, OpenRouter, LM Studio, vLLM, …)                                                         |

CLI flags `--provider`, `--model`, `--oauth-cred`, `--oauth-token`, `--llm-api-key`, `--base-url`, `--bridge-bin` override these per-invocation. The REST API does **not** mirror these overrides, server-side workloads use the YAML config exclusively. See [Setting Up the Agent](/getting-started/setup-agent) for a step-by-step walkthrough or [Olium Agent](/agentic-scan/olium) for full provider details.

### `database`

Storage backend. SQLite is the default; PostgreSQL is supported for multi-user deployments.

```yaml theme={null}
database:
  enabled: true
  driver: sqlite                   # sqlite | postgres

  sqlite:
    path: ~/.vigolium/database-vgnm.sqlite
    busy_timeout: 15000
    journal_mode: WAL              # DELETE | TRUNCATE | PERSIST | MEMORY | WAL | OFF
    synchronous: NORMAL            # OFF | NORMAL | FULL | EXTRA
    cache_size: 10000
    max_open_conns: 8              # WAL reader pool: concurrent readers + 1 writer

  postgres:
    host: localhost
    port: 5432
    user: vigolium
    password: ""
    database: vigolium
    sslmode: disable
    max_open_conns: 25
    max_idle_conns: 5
    conn_max_lifetime: 5m
```

### `known_issue_scan`

Known-issue scanning powered by the Nuclei template engine.

```yaml theme={null}
known_issue_scan:
  tags: []                         # nuclei template tags (empty = all)
  exclude_tags: [dos]
  severities: []                   # filter: critical, high, medium, low, info
  templates_dir: ""                # custom templates path
  enrich_targets: true             # feed discovered paths into known-issue scan

  # Remap the severity a finding is recorded with, keyed by nuclei template ID.
  # Default tones down generic config.json exposure (often only public base
  # URLs / feature flags). Add your own template-ID → severity entries.
  severity_overrides:
    config-json-exposure-fuzz: medium   # critical | high | medium | low | info
```

### `mutation_strategy`

Controls how parameter values are mutated during active scanning.

```yaml theme={null}
mutation_strategy:
  default_modes: [append]

  value_aware:
    enabled: true
    max_per_intent: 5
    default_intents: [neighbor, boundary, escalation]
    enum_mappings: {}              # custom enum escalation pairs
    param_synonyms: {}             # custom param name synonyms

  field_type_defaults:
    email: ["test@example.com", "user@test.org"]
    uuid: ["550e8400-e29b-41d4-a716-446655440000"]
    integer: ["1", "100", "999"]
    # ... (all standard types have built-in defaults)
```

### `external_harvester`

Pre-scan intelligence gathering from public data sources.

```yaml theme={null}
external_harvester:
  sources: [wayback, commoncrawl, alienvault]
  # Additional sources: urlscan, virustotal (require API keys)

  api_keys:
    urlscan: ""
    virustotal: ""
```

### `oast`

Out-of-Band Application Security Testing via interactsh callbacks.

```yaml theme={null}
oast:
  enabled: true
  server_url: oast.pro
  token: ""                        # optional auth token
  poll_interval: 5                 # seconds
  grace_period: 10                 # seconds after scan for late callbacks
  oast_url: ""                     # fixed callback URL (empty = auto-generate)
  blind_xss_src: ""                # JS script src for blind XSS payloads
  enabled_blind_xss: false
```

### `source_aware`

Storage location for cloned source repositories. Used when `--source` receives a git URL (autopilot, swarm, audit, query). Static analysis tooling (ast-grep, semgrep, etc.) has been removed, for AI-driven code audit, use `vigolium agent audit` or `vigolium agent swarm --source --code-audit`.

```yaml theme={null}
source_aware:
  storage_path: ~/.vigolium/source-aware/   # base directory for cloned repos
  clone_depth: 1                            # `git clone --depth` (1 = shallow)
```

### `storage`

Cloud storage integration for source code upload/download and scan result archival. Uses an S3-compatible API, supports GCS (via HMAC), AWS S3, and MinIO.

```yaml theme={null}
storage:
  enabled: false
  driver: gcs                  # gcs | s3 | minio
  endpoint: ""                 # auto for gcs/s3; required for minio
  bucket: ${VIGOLIUM_STORAGE_BUCKET_NAME}
  region: asia-southeast1
  access_key: ${VIGOLIUM_STORAGE_ACCESS_KEY}
  secret_key: ${VIGOLIUM_STORAGE_SECRET_KEY}
  use_ssl: true
  path_style: false            # required for some MinIO deployments
```

When enabled, agent runs invoked with `--upload-results` archive their session bundle to `<bucket>/<project-uuid>/agentic-scans/<run-uuid>/results.tar.gz`. Native scans use `<bucket>/<project-uuid>/native-scans/<scan-uuid>/results.tar.gz`. See [Storage API](/api-references/storage) for upload/download endpoints.

### `notify`

Real-time finding notifications via Telegram or Discord.

```yaml theme={null}
notify:
  enabled: false
  severities: [high, critical, medium]

  telegram:
    bot_token: ""
    chat_id: ""

  discord:
    webhook_url: ""
```

## Scanning Profiles

Scanning profiles are YAML files stored in `~/.vigolium/profiles/` that override subsets of the main config. They can tune any combination of: `scanning_strategy`, `scanning_pace`, `discovery`, `spidering`, `known_issue_scan`, `audit`, `external_harvester`, `mutation_strategy`, and `scope`.

Apply a profile with:

```bash theme={null}
vigolium scan --scanning-profile aggressive
```

This loads `~/.vigolium/profiles/aggressive.yaml` and overlays it onto the active config. Only non-zero fields in the profile override the base config; unspecified fields are left unchanged.

Built-in profiles are bundled in `public/presets/profiles/`. See [native-scan/scanning-modes-overview](/native-scan/scanning-modes-overview) for details.

## Project-Level Config

Each project can have its own config overlay at `~/.vigolium/projects/<uuid>/config.yaml`. This uses the same format as scanning profiles and is automatically applied when the project is active.

Manage project configs with:

```bash theme={null}
vigolium project config set scanning_pace.concurrency 200
vigolium project config show
```

See [projects](/others/projects) for full project management documentation.
