Zum Inhalt springen

How a CodeCharter rule set is structured in your repo

How a CodeCharter rule set is laid out in your repository, the rules directory, config.yml, suppressions, and platform profiles.

Without --rules, the CLI looks for a rules/ directory in the current working directory. Use the --rules <dir> option to point to any other directory.

A local rules/ directory is the legacy path. The recommended way to manage a rule set is platform profiles declared in .codecharter/config.yml. Profiles and an auto-discovered rules/ folder are mutually exclusive: once profiles are configured, the run uses only the profile rules and any local rules/ directory is ignored, unless you pass an explicit --rules <dir>, which always wins. Running with only built-in or local rules and no profiles configured prints a deprecation notice pointing you to platform profiles. The layout below still applies to custom rules you keep in the repo, whether you load them via --rules or bundle them into a local profile.

rules/
├── architecture/
│   ├── domain-must-not-reference-web.ccr
│   └── repository-naming.ccr
├── naming/
│   ├── no-manager-suffix.ccr
│   ├── no-manager-suffix.spec.md
│   └── async-suffix.ccr
└── team-conventions/
    └── controller-action-limit.ccr
.codecharter/config.yml

Subdirectories under rules/ are freely chosen. CodeCharter reads all .ccr files recursively. Older .cgr files from before the rename from CodeGuard to CodeCharter are still read for backward compatibility, so existing repositories keep working without changes.

The rule ID is the file name without the .ccr extension; subdirectory names carry no meaning. These IDs are what .codecharter/config.yml entries and suppression comments reference, so avoid using the same file name in different folders.

Spec tests live as <rule-name>.spec.md next to the .ccr file and are discovered recursively by codecharter test.

Initializing rules/

codecharter init

Creates a rules/ directory with two example rules that you can grow from.

.codecharter/config.yml

The repository configuration lives at .codecharter/config.yml. Among other sections, ignore switches rules off (optionally limited to a namespace or matching entity names) and exclude removes whole paths from analysis:

version: 1
ignore:
  - rule: namespace-distance
    in: Acme.Generated
  - rule: async-suffix
exclude:
  - "**/tests/**"
  - "**/obj/**"

See Configuration file for all sections (profiles, parameters, severities, rule activation, and path scopes).

Inline Suppressions

Per location in code:

// codecharter-disable-next-line datetime-direct-usage
var migrationTimestamp = DateTime.UtcNow;

The rule ID in the comment must match the rule's file name exactly, including casing. See Suppressions for all variants.

Platform Profiles in the Repo

When you use platform profiles, you list them in .codecharter/config.yml; codecharter.lock.json (pinning each profile by content hash) and the downloaded rule bundles both live under .codecharter/:

.codecharter/
├── config.yml
├── codecharter.lock.json
└── cache/

Commit config.yml and codecharter.lock.json; cache/ is a local download cache and should stay out of version control (see Configuration file).

Multi-Repo and Monorepo

In a monorepo you can have rules/ directories per sub-project and point to them with --rules. CodeCharter finds .codecharter/config.yml by walking up from the file being analysed, so a config at the repository root applies everywhere beneath it.