CodeCharter reads a single configuration file, .codecharter/config.yml, from your
repository. It controls which rule profiles apply, the values of tunable rule
parameters, per-rule severities, which findings are switched on or off, and
which paths are analysed. One file covers the whole repository, and path
scopes let you vary the configuration for individual folders.
Location and discovery
Place the file at .codecharter/config.yml in your repository. When CodeCharter
analyses a file, it looks for .codecharter/config.yml starting at the file's
directory and walking up to the repository root, so a config at the root
applies to everything beneath it.
config.yml itself is a checked-in file, not a local one. Only two paths
under .codecharter/ are meant to be ignored:
.codecharter/cache/
.codecharter/config.local.yml
Do not .gitignore the whole .codecharter/ folder. A blanket ignore quietly
drops config.yml from version control, so profiles, overrides, and
exclusions never make it into a commit and every teammate — and CI — silently
falls back to no configuration at all. Only cache/ (downloaded rule bundles)
and config.local.yml (below) are machine-local; config.yml is the shared,
committed source of truth.
An optional .codecharter/config.local.yml sits next to it for personal,
machine-local overrides. It is never committed (it is covered by the
.gitignore entry above) and takes precedence over config.yml. Use it to
float your local rule versions or to quiet a rule on your machine without
changing the shared configuration. CI, which never has this file, stays
reproducible.
A complete example
version: 1
# Rule profiles to apply, newest-first. A bare slug or @latest floats to the
# newest published version; an exact version pins it. Platform profiles use the
# org/slug form. Use { path: ... } to load a local bundle instead of the portal.
profiles:
- dotnet-base@1.4.2
- security@latest
- acme/house-style@^2.1.0
- { path: ./bundles/internal-rules.cgbundle }
# Values for tunable rule parameters, keyed by rule-slug.paramName.
params:
cyclomatic-complexity.max: "15"
method-length.maxLines: "60"
# Per-rule severity. Only severity can be overridden here.
overrides:
magic-number:
severity: warning
empty-catch-block:
severity: error
# Switch findings off. Optionally limit to a namespace (in:) or to entities
# whose reported name matches a glob (match:) — fully qualified for types and
# members, plain for events and occurrence-level entities.
ignore:
- rule: namespace-distance
in: Acme.Generated
- rule: todo-comment
- rule: const-naming
match: "*InstanceMemberBindingFlags"
# Switch a rule back on after it was ignored more broadly (e.g. in a scope).
include:
- rule: todo-comment
# Paths excluded from analysis entirely (glob patterns).
exclude:
- "**/tests/**"
- "**/obj/**"
- "**/Migrations/**"
# The test-coverage gate: threshold, report snippet size, test parallelism, the
# files left out of the coverage number and the directories never searched for
# test projects. Repository-wide, never per scope.
coverage:
minimum-percent: 99.5
snippet-context-lines: 3
max-parallel-test-projects: 4
exclude:
- "**/*.Designer.cs"
excluded-directories:
- "vendor/**"
# Folder-specific overrides. Each scope matches one or more path globs and may
# set any of the sections above; settings apply only to files the scope matches.
scopes:
- match:
- "src/Legacy/**"
overrides:
magic-number:
severity: info
ignore:
- rule: cyclomatic-complexity
Sections
version
Required. The configuration format version. Use version: 1.
org
Optional. Names the organization the CLI acts as, needed only when your
license covers more than one. In the common single-organization case, leave
it out entirely — the CLI resolves the acting organization automatically and
org adds nothing.
org: acme
profiles:
- dotnet-base@1.4.2
org is resolved hierarchically like every other key in this file: the
value closest to the analyzed file wins. It takes precedence over the
CODECHARTER_ORG environment variable. Naming an organization your license
does not cover exits with code 6; if your license covers more than one
organization and neither org nor CODECHARTER_ORG names one, the CLI
exits with code 64. See
Choosing an Organization in the CLI.
profiles
The rule profiles to apply. Each entry is either a slug reference or a local bundle path:
dotnet-base@1.4.2— an exact published version.security@latestor a baresecurity— floats to the newest published version, re-resolved when you runcodecharter update.security@^2.1.0/security@2.1.*— a version range.acme/house-style@1.0.0— a platform profile, addressed asorg/slug.{ path: ./bundles/rules.cgbundle }— a local.cgbundle, not fetched from the portal.
params
Values for rule parameters that a rule exposes, keyed by rule-slug.paramName.
Values are written as strings; CodeCharter validates them against each
parameter's declared type and range. A rule that exposes no parameters, or a
parameter name that does not exist, is reported by codecharter config validate.
overrides
Changes a rule's severity. The only field is severity, one of error,
warning (or warn), or info. To switch a rule off entirely, use ignore
rather than overrides.
ignore and include
ignore switches findings off; include switches them back on. Each entry
targets a rule by slug and may narrow the target:
in: Acme.Core— applies only to findings in that namespace or a namespace beneath it.match: "*Dto"— applies only to entities whose reported name matches the glob. For a type, method, property, or field that name is fully qualified (namespace plus simple name, e.g.Acme.Core.OrderDto), so a pattern without a leading*must start at the namespace root — a bare simple name such asmatch: "OrderDto"matches nothing unless the type is declared at the global namespace. Events and occurrence-level entities (parameters, member accesses, literals, and the like) are reported under their plain, unqualified name instead, so a bare simple name matches those directly.
ignore and include share one activation signal that is evaluated in order:
the base layer first, then each matching scope top to bottom. The last
matching entry wins, so you can ignore a rule broadly and re-include it for a
narrower path or namespace.
exclude
Glob patterns for paths that are dropped from analysis before any rule runs.
exclude is additive: the base patterns and the patterns of every matching
scope all apply.
coverage
Settings for the test-coverage gate run by
codecharter coverage:
minimum-percent— the required line coverage, 0 to 100. Default: 100.snippet-context-lines— how many lines of context the report prints around each uncovered region.max-parallel-test-projects— how many test projects run at once after the shared build, 1 or more. Default: the processor count, capped at 4.exclude— globs for source files that are left out of the coverage number.excluded-directories— globs for directory trees that test-project discovery skips entirely.
The last two are easy to confuse. exclude works at measurement time: the
tests still run and the matching files simply stop counting. excluded-directories
works at discovery time: the tree is never walked, so a test project inside it
is never found and never run. Reach for the first when generated code drags the
number down, and for the second when a vendored tree brings tests you do not
own.
This section is repository-wide and cannot be set inside a scope. Its
exclude list is independent of the top-level exclude above: a folder you
drop from rule analysis still counts towards coverage unless you exclude it
here as well.
A coverage key in config.local.yml replaces the committed value rather than
merging with it, which for both glob lists means the local list replaces the
whole committed list. --min-coverage and --max-parallel on the command line
beat both layers.
scopes
Folder-specific configuration. Each scope has a match list of path globs and
may contain any of params, overrides, ignore, include, and exclude.
A scope's settings apply only to files it matches. Resolution is
last-match-wins for params, overrides, and rule activation, anchored on
the source file of the entity being evaluated; exclude is additive across all
matching scopes.
Inspecting and validating the configuration
Three commands help you work with the file:
codecharter config explain <path>shows the effective configuration for a given source file, including which layer (base or which scope) each value came from. Add--jsonfor machine-readable output.codecharter config validatechecks the file for structural errors, unknown rule ids, invalid parameter values, and entries that never match anything.codecharter config schemaemits a JSON Schema for.codecharter/config.ymlthat editors can use for completion and validation. Pass--out <file>to write it to disk.
To edit the file from the command line instead of by hand — set parameters
and severities, manage profiles and exclusions, scaffold the file, and sync the
local overlay — use the config write commands. Every edit preserves your
comments and formatting and is validated before it is written. See
codecharter config.
Relationship to suppressions
ignore/exclude operate at the repository or folder level. To silence a
single finding at the point in the code where it occurs, use an inline
suppression comment instead — see
Suppressions.