Agent Code Guard is designed for zero-config use. Start with the built-in defaults and add policy only for an immediate project need.
By default, Code Guard looks for:
.agent-tools/code-guard.config.json
relative to the current working directory. Select another file with
--config <path>; an explicitly selected missing file is an error.
The starter convention uses top-level "version": 1; the current runtime
accepts that key but does not use it for schema negotiation. A minimal
configuration is:
{
"version": 1
}
The six guard keys and their production defaults are:
| Key | Default |
|---|---|
loc |
warnAt: 400, failAt: 600, ratchetAt: "fail" |
callableSize |
enabled: true, reviewAt: 80 |
nesting |
enabled: true, reviewAt: 4 |
cyclomaticComplexity |
enabled: true, reviewAt: 15 |
markdownDocumentSize |
enabled: true, reviewAt: 800 |
markdownSectionSize |
enabled: true, reviewAt: 200 |
Every threshold comparison is strict >; a value equal to its threshold
passes. The five reviewAt guards are REVIEW-only. Only loc can FAIL.
The runner also owns policyRelaxation in Git comparison modes. It has no
configuration key: guards.policyRelaxation is rejected. There is no disable
switch, threshold, exclusion, exemption, or baseline for this guard. It reads
the active repository-owned config and three canonical baselines independently
of source bounds and exclusions. See Git policy comparison.
LOC settings below enabled are compared only when LOC is enabled in both
policies. Disabling LOC reports guardDisabled; enabling it and editing dormant
LOC settings stay quiet. Common scope.exclude declarations and persisted
baseline records remain independently compared.
Set enabled to false to disable a guard. For REVIEW-only guards, reviewAt
must be a positive integer when enabled. LOC supports its established options,
including enabled, warnAt, failAt, ratchetAt, line-count settings, extension policy,
allowed large files, and path-specific overrides.
Example with one deliberate threshold change:
{
"version": 1,
"guards": {
"callableSize": {
"reviewAt": 100
}
}
}
scope.exclude removes matching source paths before source guards run:
{
"version": 1,
"scope": {
"exclude": [
"generated/**"
]
}
}
Repeated --scope-exclude <glob> values add caller-supplied all-guard
exclusions and compose with project configuration. Only files removed by these
two all-guard forms contribute to the completed result’s excluded count.
Neither form hides policy artifacts from policyRelaxation.
guards.loc.exclude applies only to the LOC guard. The repeated CLI option
--exclude <glob> adds LOC-only exclusions. These do not remove files from
callable, nesting, complexity, or Markdown analysis, and they do not contribute
to the all-guard excluded count. A file skipped only by LOC can still be
analyzed by another enabled guard or inapplicable when none applies.
{
"version": 1,
"guards": {
"loc": {
"exclude": [
"vendor-snapshot/**"
]
}
}
}
Use scope.exclude when a path is outside every guard’s intended scope. Use
the LOC-specific forms only when the artifact should remain eligible for other
applicable guards.
The allowance data lives only in .agent-tools/code-guard.loc-baseline.json at
the owning analysis root. guards.loc.ratchetAt controls how that unchanged
version-1 data is interpreted: omitted or "fail" records and enforces files
above effective failAt; "review" starts above effective warnAt. Its complete
persisted schema is:
{
"version": 1,
"loc": {
"files": [
{
"path": "src/legacy.py",
"allowedLoc": 749
}
]
}
}
Paths are exact, normalized root-relative / paths; allowances are positive
integers. Keys are closed, entries are sorted, and unsupported, malformed,
duplicate, absolute, or unsafe paths fail closed. Writers use UTF-8, two-space
indentation, LF endings, and a final newline.
--create-loc-baseline records only selected, applicable files currently
strictly above their effective policy threshold (failAt for fail, warnAt
for review), after exclusions, line-count options,
CLI thresholds, and the last matching override. allowedLargeFiles entries are
not recorded. --update-loc-baseline can only lower or remove existing entries
within its positional bounds; it cannot add or increase one. Normal analysis
never creates, lowers, prunes, or otherwise rewrites this file.
Use exclusions when LOC should not evaluate a file, overrides when the ordinary
project threshold differs, and allowedLargeFiles for a reviewed static
exemption. The ratchet instead preserves an exact legacy maximum and rejects
growth; overlap with allowedLargeFiles is invalid. Manual ratchet edits require
normal source-control review. This facility is for established repositories,
not new projects, which should meet LOC policy directly. Choose fail to freeze
only existing hard failures; choose review when established review-level files
must also be non-increasing. Never change the policy, thresholds, exclusions,
exemptions, or stored allowances merely to silence growth.
Reviewed document allowances live separately from LOC in
<analysis-root>/.agent-tools/code-guard.markdown-baseline.json:
{
"version": 1,
"markdownDocumentSize": {
"files": [
{
"path": "docs/architecture.md",
"allowedLines": 845
}
]
}
}
The version must be integer 1. Paths are exact, normalized root-relative /
paths to .md documents (extension matching is case-insensitive); allowances
are positive integer physical-line counts, including blank and comment lines.
Keys are closed, entries must be sorted by path, and duplicate keys or paths,
non-integer values, unsafe/absolute paths, and symlink traversal fail closed.
Writers use UTF-8, two-space indentation, LF endings, and a final newline.
Creation cannot overwrite a baseline; updates replace it atomically only after
all entries in scope have been checked. A no-op update preserves the file.
There are no new guard configuration keys. markdownDocumentSize.reviewAt
remains 800 by default and markdownSectionSize.reviewAt remains 200.
guards.loc.ratchetAt has no effect on Markdown. The document-size guard accepts
an exact-path allowance while the document stays at or below that count;
growth above the allowance reviews whenever it also exceeds reviewAt.
Documents at or below reviewAt pass without needing a baseline.
--create-markdown-baseline records only selected documents above the effective
threshold. --update-markdown-baseline only lowers or prunes existing entries
within positional bounds; it never adds or increases allowances. Normal
analysis never mutates this file. Section analysis remains independent, and
section baselines are not supported. These are explicit reviewed-document
acceptances, not default setup or permission to hide growth with exclusions,
threshold changes, or replacement allowances.
See the workflow and output contract.
Human-reviewed callable ceilings live independently of LOC and Markdown in
<analysis-root>/.agent-tools/code-guard.callable-review-baseline.json:
{
"version": 1,
"callableReviews": [
{
"path": "offenders_patterns.py",
"embeddedLanguage": "python",
"callable": "offenders_patterns._auth",
"guard": "cyclomaticComplexity",
"allowedMeasured": 17,
"reason": "Reviewed cohesive authentication-format catalog; re-review on growth."
}
]
}
The schema has closed keys, integer version 1, and an array of entries. Each
entry requires a safe normalized root-relative physical path with /
separators, non-empty embedded language and lexical callable identity, a guard
ID, a positive integer guard-native measurement, and a non-blank human reason.
No range, source hash, ordinal, or alternate measurement field is supported.
Callable size counts physical lines, nesting counts structural depth, and
complexity counts baseline 1 plus normalized decisions, exactly as before.
Canonical persisted/CLI guard IDs are callableSize, nesting, and
cyclomaticComplexity. The last maps explicitly to the existing complexity
result/policy ID. complexity is rejected in this baseline and acceptance CLI;
it cannot become a separate allowance. Unknown keys/guards, duplicate JSON
properties or exact entries, invalid values/types/reasons, unsafe paths, and
symlink traversal fail closed with exit 3. Writers sort by path, embedded
language, callable, and guard and use UTF-8, two-space indentation, LF, and a
final newline. Creation and replacement reuse the baseline atomic-write helpers.
The path + embedded language + lexical identity must identify exactly one
callable in the runner’s current AnalysisFacts. Duplicate lexical identities
are tool errors when an active allowance would match; no duplicate is chosen
by source order or range. Rename, move, disappearance, and movement of a
coordinate-qualified callback can leave a stale entry. Stale entries are
harmless and require explicit pruning; unavailable, excluded, and unselected
files provide no evidence for applying or pruning an existing callable.
There are no new threshold/configuration keys. With ordinary threshold T,
accepted value A, and current measurement M, test M <= T first: PASS with
notNeeded. Otherwise M <= A passes with withinAllowance, and M > A
reviews with grown. Unmatched callables retain ordinary behavior. Threshold
changes never rewrite stored values; disabled guards do not activate because
an allowance exists. LOC and Markdown schemas and lifecycles stay independent.
See the acceptance and maintenance commands.
Malformed JSON, invalid types or thresholds, unknown top-level properties,
unknown guard names, and unknown guard properties are tool errors (exit 3).
Code Guard does not silently ignore misspelled or unsupported configuration.
Keep configuration small so policy remains visible and reviewable.