Skip to main content
Charter never mutates a file silently. Every fix goes through diff → review → apply — in that order, always. The alternative was a one-shot apply that minimizes output noise, but that removes the last human checkpoint between the scanner’s judgment and your codebase.

The diff-first loop

Every fix moves through the same three stages, in this order, always:
  • Scancharter doctor marks each finding with a fixable indicator when a deterministic remediation exists. Findings without a fixer (secrets, dangerous hook configurations) are flagged but never offered as automated fixes.
  • Previewcharter fix --dry-run prints the unified diff for every proposed change and writes nothing. It exits with the same code the apply step would, so it slots into review scripts.
  • Applycharter fix copies each original file to .charter/backups/<ts>/ before writing, then applies the diff.
For the exact commands, recovery steps, and a reviewer’s checklist, see Use charter fix Safely.
charter fix dry run showing unified diff for each proposed change

charter fix --dry-run — unified diff before applying

Fixable rules

These fixers are safe to automate because the correct output is fully determined by the rule specification. There is no ambiguity and no judgment call required. That is why these four — and only these four — have automated fixers in v1.

Why secrets are never auto-fixed

AE-SEC-001 and AE-SEC-002 are never auto-fixed. A fix that only removes the literal value from a file without rotating the credential is not a remediation — it is a false sense of resolution. The secret is still active, still in git history if committed, and still in any system that cached it. Charter shows you the file path and line number (never the raw value), and tells you exactly what to do. The rotation and removal steps are yours to execute.
The same logic applies to dangerous hook configurations (AE-CC-001). Rules that flag unrestricted shell execution or broad glob allowlists in agent configs require a human to evaluate the intent behind the configuration and decide on a safer alternative. Charter cannot know whether the hook is a legitimate use case that needs a narrow permission or an oversight that should be removed entirely. These are deliberate boundaries, not gaps to fill in a future release.

Backup mechanism

Before every write, Charter copies the original file to .charter/backups/<ts>/<relative-path>, where <ts> is a compact UTC timestamp such as 20260601T143022Z. If the fixer modifies .github/workflows/ci.yml, the original is preserved at:
The backup directory is created fresh for each charter fix invocation. Charter never deletes backup directories and never truncates existing ones — they accumulate until you remove them, so the AE-CTX-004 fixer adds .charter/ to .gitignore to keep them local. If a fixer produces an unexpected result, the original is always recoverable from the most recent backup directory.

MCP catalog-aware pin bumps

The AE-MCP-001 fixer has special logic for the three distinct cases it may encounter:
  • Advisory-affected version → bumps to the fixedIn version recorded in the catalog advisory. Charter will not bump to a version that is itself subject to a known advisory.
  • Unpinned or behind catalog stable → bumps to the catalog’s stableVersion for that package.
  • Deprecated or archived package → NOT auto-fixed. The package requires migration to a successor, which is a manual step. Charter provides the successor package name in the finding detail.

Next steps

Use charter fix Safely

The full recipe: dry-run, review, apply, re-scan, and recover.

charter fix

Every flag the fix command accepts.

Scoring and Caps

How a successful fix moves the score.

MCP Safety Model

Why the AE-MCP-001 fixer bumps to catalog versions, not the latest release.