Skip to main content
tally can apply fixes automatically. Fixes are designed to be:
  • Atomic — a fix applies fully or not at all.
  • Conflict-aware — overlapping edits are skipped rather than producing a corrupted file.
  • Configurable — per-rule fix modes let you control exactly which fixes run and when.

Basic usage

Apply all safe fixes:
tally lint --fix Dockerfile
Apply unsafe fixes too (includes AI-powered fixes when enabled):
tally lint --fix --fix-unsafe Dockerfile
Limit fixes to specific rules:
tally lint --fix --fix-unsafe \
  --fix-rule hadolint/DL3008 \
  --fix-rule tally/prefer-copy-heredoc \
  Dockerfile
Use --fix-rule to limit the blast radius when applying fixes for the first time. Start with one rule at a time to review changes before committing.

Safe vs. unsafe fixes

ModeFlagDescription
Safe--fixApplies mechanical rewrites with high confidence (🔧 in RULES.md)
Unsafe--fix + --fix-unsafeAlso applies riskier fixes that may change semantics, including AI-powered fixes
The 🔧 marker in the rules reference indicates a rule has auto-fix support. Safe fixes are things like adding a missing newline, reordering instructions, or converting RUN echo to a COPY heredoc. Unsafe fixes may restructure stages or change command arguments.

Per-rule fix modes

Control when fixes are allowed per rule in .tally.toml:
[rules.tally.prefer-copy-heredoc]
fix = "always"          # Apply whenever --fix is set (default)

[rules.tally.prefer-multi-stage-build]
fix = "explicit"        # Only when --fix-rule includes this rule explicitly

[rules.tally.no-trailing-spaces]
fix = "unsafe-only"     # Only when --fix-unsafe is also set

[rules.tally.eol-last]
fix = "never"           # Never auto-fix this rule
Valid fix mode values:
ValueBehavior
alwaysApply whenever --fix is passed (default)
neverNever auto-fix, even when --fix is set
explicitOnly when --fix-rule <this-rule> is explicitly specified
unsafe-onlyOnly when --fix-unsafe is also set

How conflict resolution works

When two fixes would modify overlapping lines, tally skips the conflicting fix rather than applying a partial or corrupted change. The skipped fix is reported to stderr:
Skipped 1 fixes
note: skipped fix tally/prefer-copy-heredoc (Dockerfile): overlapping edit at line 14
Fix skips are informational — linting continues and the violation is still reported so you can address it manually.

Examples of fixable rules

Rules marked 🔧 in the rules reference support auto-fix. Some notable examples:
RuleFix typeWhat it does
tally/prefer-copy-heredocSafeConverts RUN echo/cat/printf to COPY heredoc
tally/prefer-copy-chmodSafeConverts COPY + RUN chmod to COPY --chmod
tally/no-trailing-spacesSafeRemoves trailing whitespace
tally/eol-lastSafeAdds missing newline at end of file
tally/sort-packagesSafeSorts package lists alphabetically
tally/epilogue-orderSafeReorders STOPSIGNAL, HEALTHCHECK, ENTRYPOINT, CMD
tally/curl-should-follow-redirectsSafeAdds -L to curl commands
tally/prefer-multi-stage-buildUnsafe (AI)Converts single-stage builds to multi-stage
tally/prefer-package-cache-mountsUnsafe (AI)Adds BuildKit cache mounts for package installs

AI AutoFix

Some fixes are too complex to implement deterministically. For those, tally supports an opt-in AI resolver via ACP (Agent Client Protocol). AI fixes are marked unsafe and require both --fix and --fix-unsafe. See the AI AutoFix (ACP) guide for setup instructions.