Configuration Wizards

How plugins can expose project-specific configuration through the Divekit CLI.

Configuration wizards are an experimental plugin contract. Keep the detailed schema in sync with the CLI contract and plugin template.

Plugins can expose their own CLI configuration flow with a declarative wizard. This keeps plugin-specific questions in the plugin repository while Divekit CLI provides the shared terminal UI.

The intended workflow is:

divekit plugin add jacoco-pit
divekit plugin configure jacoco-pit
divekit plugin enable jacoco-pit

divekit plugin configure <plugin> loads the configured plugin ref, reads the wizard declared by the plugin, asks for the declared values, and writes a JSON configuration file into the eval authoring tree.

Plugin Metadata

Declare the wizard path in plugin.json:

{
  "id": "divekit-plugin-example",
  "name": "Example Plugin",
  "description": "Example",
  "configuration": {
    "wizard": "configure.wizard.json"
  }
}

The path is relative to the plugin repository.

Wizard File

A minimal wizard looks like this:

{
  "version": "1.0",
  "title": "Example Plugin",
  "description": "Configure example checks.",
  "result": {
    "path": "config.json",
    "schemaVersion": 1
  },
  "steps": [
    {
      "id": "checks",
      "title": "Checks",
      "fields": [
        {
          "key": "coverage.line",
          "type": "percent",
          "label": "Line coverage",
          "description": "Required line coverage for the plugin check.",
          "default": 0.8
        },
        {
          "key": "classesToInclude",
          "type": "stringList",
          "label": "Classes to include",
          "default": ["src/main/java"]
        }
      ]
    }
  ]
}

result.path defaults to config.json. Relative paths are resolved below .divekit/plugins/<plugin-id>/. Paths that start with / are resolved from the evaluation repository root. Parent path segments such as .. are accepted and therefore allow a plugin to intentionally write elsewhere in the evaluation repository. result.schemaVersion is optional; when it is set, Divekit writes it as top-level schemaVersion in the generated JSON.

When a configuration file already exists, divekit plugin configure uses those values as editable initial values. Missing values fall back to wizard defaults or placeholders.

For repeatable setup, run the wizard with --yes:

divekit plugin configure jacoco-pit --yes

In this mode Divekit does not open the terminal UI. It preserves existing configuration values and applies wizard defaults for missing values. Required text, path, and numeric fields still need an existing value or a wizard default. Optional percent, number, and integer fields with an empty value are left unset instead of being written as zero.

The CLI stores the collected values as JSON. Dotted field keys create nested objects, so coverage.line becomes:

{
  "coverage": {
    "line": 0.8
  }
}

Supported field types are string, text, stringList, path, pathList, percent, number, integer, boolean, select, multiSelect, and objectList.

text renders a multiline prompt and stores a string. path and pathList store path-like strings. They support local tab completion for concrete paths, but glob-like patterns such as * and ** are accepted unchanged and interpreted by the plugin.

objectList renders repeatable object entries and stores an array of JSON objects. Its fields are regular wizard fields with keys relative to each list entry. Dotted child keys create nested objects inside that entry:

{
  "key": "tasks",
  "type": "objectList",
  "label": "Task",
  "required": true,
  "fields": [
    { "key": "name", "type": "string", "label": "Name", "required": true },
    { "key": "coverage.lineCoverage", "type": "percent", "label": "Line coverage" },
    { "key": "classesToInclude", "type": "stringList", "label": "Classes to include" }
  ]
}

This writes:

{
  "tasks": [
    {
      "name": "unit",
      "coverage": {
        "lineCoverage": 0.8
      },
      "classesToInclude": ["de.thkoeln.example.*"]
    }
  ]
}

fields is only valid on objectList fields. Nested objectList fields are not supported; use dotted child keys for nested objects within each entry.

When a configuration already contains an objectList, reconfiguration asks for each existing entry whether it should be edited, kept unchanged, or removed. After existing entries have been processed, the wizard can append additional entries. A required objectList must contain at least one entry.

select and multiSelect fields declare options:

{
  "key": "report.mode",
  "type": "select",
  "label": "Report mode",
  "default": "summary",
  "options": [
    { "value": "summary", "label": "Summary" },
    { "value": "detailed", "label": "Detailed" }
  ]
}

Configuration Result

With the default result.path, the plugin configuration is available inside the evaluation repository at:

.divekit/plugins/jacoco-pit/config.json

Divekit writes that file into the origin repository’s eval authoring tree:

.divekit/eval-pipeline/eval/.divekit/plugins/jacoco-pit/config.json
.divekit/distributions/<distribution>/eval-pipeline/eval/.divekit/plugins/jacoco-pit/config.json

When the eval repository is generated, the plugin can read:

.divekit/plugins/jacoco-pit/config.json

See Plugin Configuration JSON for a complete example of the generated plugin-owned configuration file.

Boundaries

The wizard describes the user interface and the JSON shape. Plugin-specific meaning stays in the plugin. For example, JaCoCo PIT decides how coverage thresholds, include paths, exclude paths, and task success rules affect its reports. Manual report overrides are Divekit-owned and are managed with divekit plugin override; they should not be modeled as plugin-owned wizard settings.

The CLI does not execute plugin code while asking questions. It only fetches the wizard from the selected plugin ref, prompts for values, and writes the result JSON.

References

Last modified July 13, 2026: docs: update CLI behavior notes (cae77c5)