Install Agent Code Guard as an isolated CLI tool with pipx:
pipx install agent-code-guard
Inside an activated Python virtual environment, use:
python -m pip install agent-code-guard
An isolated uv tool installation is also available:
uv tool install agent-code-guard
For source or repository development installs, run one of the following from a checkout:
python -m pip install .
python -m pip install -e .
The checkout runner at skills/code-guard/scripts/code_guard.py exists for
repository and skill compatibility; it is not the primary installed command.
The public command is code-guard. With no paths, it defaults to ., but
normal development should select current work explicitly.
Report the installed distribution identity without configuration, scope, Git, provider, skill, or guard work:
$ code-guard --version
agent-code-guard <version>
For machine-readable output:
$ code-guard --version --json
{
"distribution": "agent-code-guard",
"version": "<version>"
}
The value is read from installed metadata for the canonical
agent-code-guard distribution. --version may be combined only with
--json. Both successful version forms exit 0; incompatible arguments or
unavailable metadata exit 3. Human errors use standard error and JSON errors
use an error object on standard output. If distribution metadata is
unavailable, the error is
installed distribution metadata is unavailable for agent-code-guard.
Inspect the active installation and its immediate local capabilities without running project analysis:
code-guard doctor
code-guard doctor --json
The human and JSON reports cover the active distribution, Python process,
invoked entry point, bundled skill, current-directory configuration and Git
context, and all supported parser providers. A healthy report exits 0; a
completed unhealthy report exits 1; invocation or internal failures that
prevent a report exit 3. Completed reports use standard output only.
doctor is reserved only as the exact first token. Analyze a file or directory
with that name through a qualified spelling such as ./doctor, .\doctor, or
an absolute path. Doctor is read-only: it does not analyze source, repair or
install dependencies, export skills, modify configuration or Git state, access
the network, or persist diagnostics.
Diagnostic output includes resolved launcher, interpreter, skill, Git, and configuration paths. Treat those paths and other environment details as potentially sensitive before sharing a report.
code-guard . --changed-only
This selects staged, unstaged, and untracked files known to the current Git worktree, then intersects them with positional file or directory bounds.
code-guard . --staged
This selects only index changes. Unstaged and untracked files are excluded.
code-guard . --base-ref origin/main --ci
This selects added, copied, modified, or renamed files from the merge-base
comparison <ref>...HEAD. The ref must exist and resolve in the environment;
fetch the intended base before running in shallow or isolated CI checkouts.
Only one of --changed-only, --staged, and --base-ref may be used at a
time. Positional paths bound the Git-selected candidates; they do not add files
outside that selection.
Without Git, pass the exact files owned by the current change:
code-guard src/Foo.py src/Bar.ts docs/guide.md
Git selectors require a Git repository and fail rather than falling back to a recursive audit. Do not create a manifest merely to provide scope.
code-guard .
A directory without a Git selector is a recursive audit. In a Git repository,
directory discovery respects Git tracking and ignore rules. Outside Git, it
walks the directory while pruning .git, node_modules, bin, and obj.
Changed work and a full audit are intentionally different operations.
Recursive discovery does not follow symlinks. An explicitly supplied file symlink expresses caller intent and is inspected at its resolved target. An explicit directory symlink is rejected rather than traversed recursively.
Missing explicit paths, incompatible selectors, unavailable base refs, invalid scope, and Git selectors outside a repository are tool errors. Git-derived paths that no longer exist are ignored.
Established repositories may adopt LOC policy without accepting further growth.
The default guards.loc.ratchetAt: "fail" records files above effective
failAt. Use "review" when existing files above effective warnAt may remain
but must not grow. Create the
canonical source-controlled ratchet over an intentionally bounded scope:
code-guard src/legacy --create-loc-baseline
git add .agent-tools/code-guard.loc-baseline.json
git diff --cached
The file is always
<analysis-root>/.agent-tools/code-guard.loc-baseline.json, where the root is
the enclosing Git top-level or, outside Git, the resolved invocation directory.
Normal analysis reads it automatically and never writes it. Under fail, a file
at its allowance, or reduced while still above failAt, becomes grandfathered
REVIEW. Under review, a file within its allowance keeps ordinary REVIEW
between warnAt and failAt, and is grandfathered only above failAt. Growth
above either allowance is FAIL. At or below the selected policy threshold,
the entry is reported as no longer needed.
After reducing or deleting legacy code, explicitly lower and prune entries:
code-guard src/legacy --update-loc-baseline
Update bounds come only from the positional paths. Update lowers existing allowances, removes entries that are missing, excluded, inapplicable, or no longer above the selected policy threshold, and leaves entries outside the bounds unchanged. It never adds a newly oversized path or raises an allowance; any attempted growth aborts the entire update. A rename is an old-path deletion plus a new, ungrandfathered destination—Git history is not consulted. Manual JSON edits are ordinary source-control changes and require review.
This ratchet differs from LOC exclusions, threshold overrides, and
allowedLargeFiles: exclusions skip LOC evaluation, overrides change ordinary
thresholds, and allowedLargeFiles is a reasoned static exemption without a
size-regression check. A ratchet entry may not overlap allowedLargeFiles.
This workflow is only for adopting established legacy repositories. New projects, including Agent Code Guard itself, should meet policy directly and must not create a LOC ratchet baseline.
Do not switch between fail and review, raise thresholds, add exclusions or
exemptions, or edit allowances merely to silence a growth failure. Those are
source-controlled policy changes and require their own substantive justification.
After reviewing an oversized, cohesive Markdown document, explicitly record its accepted physical-line count over a deliberately bounded scope:
code-guard docs/architecture.md --create-markdown-baseline
git add .agent-tools/code-guard.markdown-baseline.json
git diff --cached
This creates <analysis-root>/.agent-tools/code-guard.markdown-baseline.json.
The analysis root is the enclosing Git top-level or, outside Git, the resolved
invocation directory. Creation requires an enabled markdownDocumentSize guard
and records only selected .md files strictly above its effective reviewAt.
An existing baseline is never overwritten by create. Review and commit the
baseline as the explicit acceptance decision; it is not part of ordinary setup.
Normal analysis reads the baseline automatically without writing it. With the default 800-line threshold and an accepted allowance of 845 document lines:
| Current document | Document-size result |
|---|---|
| Same path, 845 lines | PASS, within allowance |
| Same path, 840 lines | PASS, within allowance |
| Same path, 846 lines | REVIEW, allowance exceeded |
| New or renamed path, 845 lines | REVIEW, no allowance |
| Any document at or below 800 lines | PASS, no allowance needed |
This ratchet applies only to markdownDocumentSize. It does not change the
threshold, exclude Markdown from analysis, or suppress markdownSectionSize.
An accepted document can still have section REVIEW findings. Growth remains
REVIEW (exit 1, or 0 with --ci), not FAIL.
After shortening or deleting documents, explicitly lower or prune entries:
code-guard docs --update-markdown-baseline
Update requires an existing baseline and an enabled document guard. It lowers existing allowances within positional bounds, removes deleted or scope-excluded paths and entries at or below the effective threshold, and preserves entries outside those bounds. It never adds an entry or increases an allowance. Growth in a retained entry aborts the entire update without changing the baseline. A rename is a deletion plus an unaccepted new path. Manual baseline changes require source-control review; do not rebaseline merely to hide growth.
Both write modes accept paths, --config, and repeated --scope-exclude.
They reject other baseline modes, LOC counting/threshold options, Git selectors,
JSON/CI analysis options, diagnostics, version reporting, and skill management.
Writes do not run normal analysis. Successful writes exit 0; invalid inputs
or unsafe baselines produce tool errors (exit 3, stderr, no completed report).
Normal analysis and creation do not grant allowances through an explicitly
supplied file symlink; updates reject symlink bounds. Baseline storage and
entries must not traverse symlinks, and baseline-enabled scopes must stay
inside the analysis root.
Human output shows the accepted allowance and within, exceeded, or
no longer needed. Full/debug JSON retains document measurements and the
unchanged thresholds.reviewAt; entries matched by path add baselineLines
and ratchetStatus (within, exceeded, or notNeeded). Unmatched findings
retain their original shape. Compact JSON omits accepted PASS findings like
other passes. Accepted documents do not require the document-size policy;
independent section findings still require their own policy.
See the persisted schema.
PASS means no special action and exits 0.REVIEW means inspect findings and apply judgment; normal invocation exits 1.FAIL blocks normal completion and exits 2.INCOMPLETE retains independent completed evidence when known per-file
syntax/provider evidence is unavailable and exits 3.3 without a completed report.--ci changes a REVIEW-only result to exit 0. It does not suppress FAIL,
INCOMPLETE, or tool errors. REVIEW is not automatic refactoring, and metrics
must never be gamed.
Human output is the default and emphasizes actionable findings. Every completed analysis starts with the aggregate state and exact scope counts:
PASS: 3 selected; 2 analyzed; 1 inapplicable; 0 excluded.
The labels do not pluralize. An empty valid selection is
PASS: 0 selected; 0 analyzed; 0 inapplicable; 0 excluded. and exits 0.
Existing finding and required-policy lines follow this summary unchanged.
The counts have these meanings:
selected: files remaining after discovery, bounds, normalization,
deduplication, absent Git-derived entries, and all-guard exclusions;analyzed: selected files applicable to at least one enabled guard;inapplicable: selected files applicable to no enabled guard;excluded: existing normalized files removed specifically by
scope.exclude or --scope-exclude.Therefore analyzed + inapplicable == selected, and an excluded file belongs
to none of the other sets. All values are non-negative integers. Git-ignored
files never discovered, paths outside positional bounds, and absent Git-derived
files are not counted as exclusions.
Add --json for the stable, compatible full machine-readable output, including
all passing and actionable findings. Completed PASS, REVIEW, and FAIL
results include exactly one top-level summary alongside the existing overall,
requiredPolicies, and guards values:
"scope": {
"selected": 3,
"analyzed": 2,
"inapplicable": 1,
"excluded": 0
}
Counts do not change aggregate state, findings, required policies, or exit
codes. Tool errors retain their existing human or JSON error form and do not
include a successful scope object.
When a known per-file syntax or provider failure occurs, the headline is
INCOMPLETE, followed by ordered unavailable context and the incomplete syntax
guard identifiers before ordinary findings. JSON uses overall: "incomplete",
adds the authoritative completed aggregate as completedOverall, and includes
ordered top-level unavailable records containing path, embedded language,
kind, and the exact provider message. scope.unavailable overlaps
analyzed, so analyzed + inapplicable == selected remains true. Every guard
adds complete only on incomplete runs; incomplete syntax guards also add
ordered unavailablePaths. Guard states, findings, and requiredPolicies
continue to describe only completed evidence.
Choose a completed-analysis serialization mode explicitly when needed:
code-guard . --json --json-mode compact
code-guard . --json --json-mode debug
compact is intended for routine agent checks. It preserves overall, the
complete scope, requiredPolicies, every guard and guard state, and existing
guard and retained-finding ordering. It omits each finding whose normalized
state is pass and retains unchanged findings whose state is review or
fail. This includes omitting LOC exemptions: their native status is exempt,
but their normalized state is pass. debug is an explicit name for the full
output and is byte-for-byte identical to bare --json for the same completed
analysis.
For incomplete output, full and debug retain identical unavailable records;
compact filters only ordinary passing findings and also retains those records
unchanged. All three JSON modes, human output, normal invocation, and --ci
exit 3.
Both named modes require --json and apply only to completed analysis output.
They do not change analysis, scope, policies, ordering, aggregate or guard
states, exit codes, or error shapes and channels. Version JSON supports only
bare --version --json; skill-management modes are also incompatible with JSON
analysis options. Values are exact and case-sensitive. There is no detail mode.
requiredPolicies lists the policy identifiers needed for actionable findings.
An agent should load only those referenced policies, preserve project intent,
and decide whether a REVIEW warrants meaningful improvement. A passing result
has no required policy work.
After a meaningful editing turn in Git, the normal structured agent command is:
code-guard . --changed-only --json --json-mode compact
Outside Git, pass the exact edited paths instead. An optional, user-authorized
platform hook may add --ci; this changes REVIEW’s process exit from 1 to
0 without hiding its findings or changing FAIL and tool-error exits.
Agent Code Guard does not install hooks.
See the human and agent workflow for the repeated manual and hook-assisted loop. Installed distributions also carry a version-matched skill payload; skill distribution documents discovery, export, and platform activation.
Performance changes can be measured against the fixed Wayfarer workload with
tools/benchmark_wayfarer.py. The caller supplies a disposable checkout at
commit 679ddae9717bf78681a2cfbf794f687127b23b5d, its exact project config, and
an output directory outside that checkout:
python tools/benchmark_wayfarer.py --wayfarer-path C:\bench\Wayfarer --config-path C:\bench\wayfarer-code-guard.config.json --output-directory C:\bench\results\after --installation-mode "editable wheel from issue 122 branch"
The script validates the source commit, records Python and Code Guard versions, the configuration hash, exact commands, three fresh sequential warm-process samples and medians for LOC-only, syntax-only, and normal six-guard scans, plus a normal-run cProfile file. It requires successful complete Git-status checks before and after the run, and fails if verification fails or analysis creates repository metadata. It rejects output paths equal to or beneath the target, never clones or writes to the target checkout, and is intentionally not a CI test. Run the same script and installation mode against the before and after revisions, retaining both result directories for comparison.