Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Configuration

Most of Clover’s behavior lives in the annotations themselves, so configuration is deliberately small. Clover reads from two layers that share the same keys:

  • A user config at clover/config.yaml under your XDG config directory. This is typically ~/.config/clover/config.yaml, or $XDG_CONFIG_HOME/clover/config.yaml when that variable is set. Use it for personal defaults that should apply everywhere.
  • A project .clover.yaml at a repository’s root, for settings that travel with the project.

The project config overlays the user one field by field: a key set in the project file wins, and anything it leaves unset falls back to the user value. Both files are optional, and both validate against the same schema.

# yaml-language-server: $schema=https://raw.githubusercontent.com/gechr/clover/main/internal/config/schema.json

required-version: ">=0.1.0"

paths:
  exclude:
    - vendor/**
    - "**/testdata/**"

global:
  output: wide # shared default for run and lint

run:
  verify: true # verify secure pins by default
  output: github # overrides global.output for `clover run`

fmt:
  prune: true

annotate:
  write: true # apply proposed annotations by default

Options

Settings are grouped by the command they configure, with a global block for cross-command defaults. See .clover.reference.yaml for every key with its default.

KeyDescription
required-versionA version constraint the running clover binary must satisfy (e.g. ">=0.1.0", "~>0.1"). Clover refuses to run if its own version falls outside the range.
paths.excludeDoublestar globs that are excluded from scanning. Everything else under the scanned paths is searched for annotations.
global.outputDefault output detail (text, wide, or github) shared by run and lint
run.verifyVerify secure pins against their upstream tags by default (implies a deep lookup)
run.cooldownDefault minimum age before a version is eligible, for directives that set no cooldown of their own (e.g. 72h, 2w)
run.prereleaseAllow selecting prerelease versions by default
run.downgradeAllow selecting versions older than the current one by default
run.deepFollow pagination to fetch every version by default (more accurate, but slower)
run.forceRe-pin followed digests by default, even when the version they follow is unchanged
run.cachePersist cacheable HTTP responses across runs and revalidate them with conditional requests (see Caching). On by default. Set false to fetch everything fresh each run
run.outputOutput detail for clover run (overrides global.output)
run.rulesScoped defaults that apply only to matching markers (see Scoped rules)
lint.outputOutput detail for clover lint (overrides global.output)
fmt.pruneRemove unknown directive keys instead of erroring on them by default
annotate.writeApply proposed annotations by default instead of previewing them
annotate.checkReport proposed annotations and exit non-zero by default instead of writing
annotate.sidecarGenerate sidecars for comment-less targets. On by default. Set false to leave such targets untouched

Precedence, highest first: an explicit CLI flag, then the per-command key, then global, then the built-in default. For the per-marker toggles (verify, prerelease, downgrade), a CLI flag wins over both the config and the directive. Otherwise the config supplies the default, which a directive can still override. run.cooldown follows the latter model: a directive’s own cooldown always wins over the config default, while the --cooldown flag overrides both.

annotate.write and annotate.check are mutually exclusive.

An unknown key is reported as a warning (with a “did you mean?” hint for a likely typo) and otherwise ignored, so a config written for a newer Clover still loads on an older one. Values are validated against the schema and a malformed one is rejected.

Scoped rules

run.rules narrows the run defaults to just the markers you choose, so one project can hold Docker images back for a week while everything else updates freely. Each rule pairs selectors with settings. The selectors are paths (Doublestar globs matched against the file’s path relative to its repository root), providers (provider names), and tags (tags the marker’s directive must all carry). A rule needs at least one selector, and a marker must satisfy every selector the rule sets.

run:
  cooldown: 3d
  rules:
    - providers: [docker]
      cooldown: 1w
    - paths: [experiments/**]
      tags: [canary]
      prerelease: true

A rule can scope verify, prerelease, downgrade, deep, force, and cooldown. For each setting, the first matching rule that sets it wins, and markers no rule matches fall back to the plain run defaults. Rules slot into the usual precedence between the CLI and the run block: an explicit flag still overrides every rule, and a directive’s own cooldown still wins over any configured default.

Environment variables

Clover also reads process-wide settings from CLOVER_* environment variables. Set CLOVER_NO_CACHE=1 to disable the cross-run HTTP cache for a run, overriding run.cache. An explicit --[no-]cache flag wins over both.

To make file and line hyperlinks open in an editor, set CLOVER_HYPERLINK_FORMAT to one of the supported editor presets:

export CLOVER_HYPERLINK_FORMAT=vscode

For fish:

set -gx CLOVER_HYPERLINK_FORMAT vscode

Supported presets include cursor, kitty, macvim, subl, textmate, vscode, vscode-insiders, and vscodium. Individual format variables such as CLOVER_HYPERLINK_LINE_FORMAT can override a single hyperlink shape when a preset is not specific enough.

Schema

The # yaml-language-server comment on the first line wires the file up to its JSON schema, so editors with the YAML language server give you completion and validation as you type.

Selecting the config

By default Clover loads the user config and overlays the nearest .clover.yaml. Override that per run:

# replace the project config with an explicit file (the user layer still applies)
clover run --config path/to/.clover.yaml

# ignore both layers for a fully unconfigured run
clover run --no-config

Run clover init to create a starter config interactively.