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 three-step loop

1

Scan

Run charter doctor to identify fixable findings. Charter marks each finding with a fixable indicator when a deterministic remediation exists. Findings without a fixer — secrets, dangerous hook configurations — are flagged but not offered as automated fixes.
charter doctor --path .
2

Preview

Run charter fix --dry-run to see the unified diff for every proposed change. Nothing is written. The command exits with the same success or failure code that the apply step would produce, so you can use it in review scripts.
charter fix --dry-run
Every file the fixer would touch gets a before/after diff block. If you see something unexpected, stop here.
3

Apply

Run charter fix without --dry-run. Before writing a single byte, Charter copies the original file to .charter/backups/<ISO-timestamp>/. Then it writes the fix. After the run, re-scan to confirm the score improved.
charter fix
charter doctor  # verify
charter fix dry run showing unified diff for each proposed change

Fixable rules

RuleFixer actionSafety class
AE-CTX-001Creates AGENTS.md from a standard template if the file is absent✅ Create-only — never overwrites
AE-CTX-004Creates or appends .gitignore with agent artifact patterns (.aider/, .claude/, .cursor/, etc.)✅ Append-only — never removes existing entries
AE-CI-002Creates .github/workflows/charter.yaml with the standard scan workflow✅ Create-only — never overwrites
AE-MCP-001Updates an MCP server package reference to the catalog’s current stable version✅ Token replace — single version string, full diff shown
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/<ISO-timestamp>/<relative-path>
For example, if the fixer modifies .github/workflows/ci.yml, the original is preserved at:
.charter/backups/20260601T143022Z/.github/workflows/ci.yml
The backup directory is created fresh for each charter fix invocation, keyed by a UTC timestamp. Charter never deletes backup directories and never truncates existing ones. They accumulate until you choose to remove them.Add .charter/backups/ to .gitignore to keep them local:
echo ".charter/backups/" >> .gitignore
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.

Usage reference

charter fix --dry-run