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.yamlunder your XDG config directory. This is typically~/.config/clover/config.yaml, or$XDG_CONFIG_HOME/clover/config.yamlwhen that variable is set. Use it for personal defaults that should apply everywhere. - A project
.clover.yamlat 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.
| Key | Description |
|---|---|
required-version | A 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.exclude | Doublestar globs that are excluded from scanning. Everything else under the scanned paths is searched for annotations. |
global.output | Default output detail (text, wide, or github) shared by run and lint |
run.verify | Verify secure pins against their upstream tags by default (implies a deep lookup) |
run.cooldown | Default minimum age before a version is eligible, for directives that set no cooldown of their own (e.g. 72h, 2w) |
run.prerelease | Allow selecting prerelease versions by default |
run.downgrade | Allow selecting versions older than the current one by default |
run.deep | Follow pagination to fetch every version by default (more accurate, but slower) |
run.force | Re-pin followed digests by default, even when the version they follow is unchanged |
run.cache | Persist 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.output | Output detail for clover run (overrides global.output) |
run.rules | Scoped defaults that apply only to matching markers (see Scoped rules) |
lint.output | Output detail for clover lint (overrides global.output) |
fmt.prune | Remove unknown directive keys instead of erroring on them by default |
annotate.write | Apply proposed annotations by default instead of previewing them |
annotate.check | Report proposed annotations and exit non-zero by default instead of writing |
annotate.sidecar | Generate 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.