Skip to content

Automatic Fixes

MAKI includes a powerful autofix engine that can automatically correct many linting violations. This guide explains how autofixes work, their safety classifications, and how to use them effectively.

Autofixes allow you to automatically correct common FSH issues without manual intervention. MAKI classifies fixes by safety level and provides multiple modes for applying them.

MAKI classifies all fixes into two safety levels:

No semantic changes - These fixes only modify formatting, add required metadata, or remove redundant code without changing the meaning of your FSH.

Examples:

  • Adding missing Id, Title, or Description fields
  • Removing unused aliases
  • Fixing whitespace and indentation
  • Correcting punctuation

Applied with: --fix flag (default)

Semantic changes - These fixes modify the meaning or behavior of your FSH code and should be reviewed carefully.

Examples:

  • Converting identifier naming conventions (e.g., bad_nameBadName)
  • Adding FHIR constraints (cardinality, binding strength)
  • Adding extension contexts
  • Swapping reversed min/max in cardinality

Applied with: --unsafe flag

The safest way to use autofixes is to apply only safe fixes:

Terminal window
maki lint --fix input/fsh/

This applies all safe fixes only, leaving unsafe fixes for manual review.

To apply all fixes including semantic changes:

Terminal window
maki lint --fix --unsafe input/fsh/

For maximum control, use interactive mode to review each unsafe fix:

Terminal window
maki lint --fix --interactive input/fsh/

Interactive mode will:

  1. Automatically apply all safe fixes without prompting
  2. Prompt for confirmation on each unsafe fix
  3. Show a detailed preview with context
  4. Allow you to accept, skip, or quit
🔧 Unsafe autofix suggested
────────────────────────────────────────────────────────────────────────────
Rule: style/naming-convention
Location: profiles/Patient.fsh:5:1
Safety: unsafe (semantic changes, requires review)
Description: Convert Profile name to PascalCase
Changes:
3 │ ValueSet: MyValueSet
4 │
- 5 │ Profile: bad_name
+ 5 │ Profile: BadName
6 │ Parent: Patient
7 │
────────────────────────────────────────────────────────────────────────────
Apply this fix? [y/N/q]

Options:

  • y - Apply this fix
  • N - Skip this fix (default)
  • q - Quit and cancel all remaining fixes

Preview what would change without modifying files:

Terminal window
# Preview safe fixes
maki lint --fix --dry-run input/fsh/
# Preview all fixes (safe + unsafe)
maki lint --fix --unsafe --dry-run input/fsh/

Dry-run mode shows:

  • Which files will be modified
  • Detailed diff for each fix
  • Total number of fixes by safety level

MAKI automatically detects when multiple fixes would modify overlapping text and resolves conflicts using priority-based selection:

  1. Detects overlapping ranges - Identifies fixes that would conflict
  2. Prioritizes by safety - Safe fixes have higher priority than unsafe fixes
  3. Selects best fix - Chooses the highest-priority fix and skips conflicting ones

Fixes are applied in reverse offset order (from end of file to beginning) to preserve text positions as fixes are applied.

After applying fixes, MAKI validates the modified FSH syntax to ensure:

  • Balanced brackets and braces
  • Valid FSH structure
  • No syntax errors introduced

If validation fails, changes are rolled back and an error is reported.

RuleFixSafety
required-idAdd missing Id fieldSafe
required-titleAdd missing Title fieldSafe
required-descriptionAdd missing Description fieldSafe
extension-context-requiredAdd extension ^contextUnsafe
code-system-content-requiredAdd ^content fieldSafe
value-set-compose-requiredAdd ^compose fieldSafe
RuleFixSafety
profile-namingConvert Profile ID to PascalCaseUnsafe
extension-namingConvert Extension ID to PascalCaseUnsafe
value-set-namingConvert ValueSet ID to kebab-caseUnsafe
code-system-namingConvert CodeSystem ID to kebab-caseUnsafe
RuleFixSafety
cardinality-min-max-swappedSwap reversed min/max valuesSafe
RuleFixSafety
binding-strength-requiredAdd missing binding strengthUnsafe
RuleFixSafety
redundant-aliasRemove unused alias definitionsSafe

Configure autofix behavior in your .makirc.json or .makirc.toml:

{
"autofix": {
"default_safety": "safe",
"interactive": false,
"create_backups": true,
"backup_extension": ".bak",
"max_fixes_per_file": 100
}
}
  • default_safety - Default safety level for --fix flag

    • "safe" (default) - Only apply safe fixes
    • "unsafe" - Apply all fixes
  • interactive - Enable interactive mode by default

    • false (default) - Apply fixes automatically
    • true - Prompt for confirmation on unsafe fixes
  • create_backups - Create backup files before modifying

    • true (default) - Create .bak files
    • false - Don’t create backups
  • backup_extension - File extension for backups

    • ".bak" (default)
  • max_fixes_per_file - Limit fixes per file

    • 100 (default)
    • Prevents excessive modifications in a single pass

Always start with safe-only fixes to catch low-hanging fruit:

Terminal window
maki lint --fix input/fsh/

For unsafe fixes, use interactive mode to review each change:

Terminal window
maki lint --fix --unsafe --interactive input/fsh/

Preview changes before applying to understand their impact:

Terminal window
maki lint --fix --unsafe --dry-run input/fsh/

Combine autofixes with git for safety:

Terminal window
# Commit your work first
git add .
git commit -m "Before autofixes"
# Apply fixes
maki lint --fix input/fsh/
# Review changes
git diff
# Commit if satisfied, or revert
git add . && git commit -m "Apply safe autofixes"
# or
git restore .

Use autofixes in CI/CD to enforce code quality:

.github/workflows/lint.yml
- name: Check for fixable issues
run: |
maki lint --fix --dry-run input/fsh/
if [ $? -ne 0 ]; then
echo "Fixable issues found. Run 'maki lint --fix' locally."
exit 1
fi

After applying fixes, MAKI displays comprehensive statistics:

═══════════════════════════════════════════════════════════════════════════
📊 Autofix Statistics
═══════════════════════════════════════════════════════════════════════════
📈 Overall:
Total fixes: 24
✅ Applied (safe): 17
⚠️ Applied (unsafe): 5
❌ Failed: 2
⏭️ Skipped: 0
📁 Files modified: 8
📋 By Rule:
✅ required-id
Applied: 8 | Failed: 0
⚠️ naming-convention
Applied: 5 | Failed: 0
✅ redundant-alias
Applied: 4 | Failed: 0

Check safety level: Ensure you’re using the correct flag:

  • --fix applies safe fixes only
  • --fix --unsafe applies all fixes

Check configuration: Verify your config doesn’t disable autofixes for specific rules.

File a bug report: If autofixes introduce syntax errors, this is a bug. Please report it with:

  • The original FSH file
  • The command you ran
  • The error message

MAKI automatically resolves conflicts, but if fixes are skipped:

  • Review the diagnostic output
  • Apply fixes in multiple passes if needed
  • Consider manual intervention for complex cases

Apply fixes to multiple directories:

Terminal window
for dir in input/fsh/*; do
maki lint --fix "$dir"
done

Disable specific rules and their fixes:

{
"rules": {
"style/naming-convention": "off"
}
}

Then apply only remaining fixes:

Terminal window
maki lint --fix --unsafe input/fsh/

Combine MAKI with custom scripts for complex workflows:

apply-fixes.sh
#!/bin/bash
# Apply safe fixes
maki lint --fix input/fsh/
# Apply specific unsafe fixes interactively
maki lint --fix --unsafe --interactive \
--config unsafe-fixes-only.json \
input/fsh/
# Run final validation
maki lint input/fsh/

MAKI’s autofix engine is highly optimized:

  • Conflict detection: O(n²) worst case, typically O(n log n) with smart grouping
  • Fix application: O(n) per file with reverse-order optimization
  • Typical performance: <100ms for 50 fixes per file

For large codebases (1000+ files), consider:

  • Processing files in parallel using GNU parallel or similar
  • Using --max-fixes-per-file to limit single-pass changes
  • Running multiple targeted passes for different rule categories

MAKI’s autofix engine provides:

Safety-first approach - Safe fixes by default, unsafe with explicit flag ✅ Interactive review - Control over semantic changes ✅ Conflict resolution - Automatic handling of overlapping fixes ✅ Dry-run preview - See changes before applying ✅ Comprehensive statistics - Detailed reporting of applied fixes ✅ High performance - Fast processing even for large codebases

By following these guidelines, you can safely automate most FSH code corrections while maintaining control over semantic changes.