Skip to content

GritQL Custom Rules

GritQL is a powerful pattern-matching language that allows you to write custom lint rules for your FSH project.

GritQL is a query language designed for code analysis and transformation. It lets you:

  • Match code patterns using intuitive syntax
  • Capture matched values in variables
  • Apply complex predicates and conditions
  • Generate diagnostic messages and fixes

Match a profile definition:

Profile: $name

This matches any profile and captures its name in $name.

Match profiles with specific properties:

Profile: $name
Parent: Patient

Variables capture matched content:

  • $name - Captures an identifier
  • $_ - Matches anything (anonymous)
  • $...rest - Captures remaining items

Create .grit files in your custom rules directory:

custom-rules/require-ms-flag.grit
// Rule metadata
language fsh
description "Profile constraints should have MS flag"
severity warning
// Pattern to match
pattern {
Profile: $profile_name
* $path $card
}
// Condition
where {
// Check if MS flag is missing
!contains($card, "MS")
}
// Message
message "Add MS (Must Support) flag to constraint"

Configure custom rule directories in fsh-lint.json:

{
"linter": {
"ruleDirectories": [
"./custom-rules",
"./org-rules"
]
}
}
language fsh
description "Profile constraints should use MS flag"
severity warning
pattern {
Profile: $_
* $path 1..1
}
where {
!contains($path, "MS")
}
message "Add MS flag to required elements"
language fsh
description "ValueSets must end with 'VS'"
severity error
pattern {
ValueSet: $name
}
where {
!ends_with($name, "VS")
}
message "ValueSet names should end with 'VS'"
fix {
ValueSet: `${name}VS`
}
language fsh
description "Profiles must have descriptions"
severity warning
pattern {
Profile: $name
$...body
}
where {
!contains($body, "Description:")
}
message "Profile '${name}' is missing a description"
// Match any resource type
$resource_type: $name
where {
$resource_type in ["Profile", "Extension", "ValueSet"]
}
Profile: $name
* $path from $valueset (required)
where {
!exists($valueset)
}
message "ValueSet '${valueset}' not found"
Profile: $name
* $path $card
where {
$card == "1..1" and
!contains($path, "MS") and
!contains($path, "^")
}

Test your rules before deploying:

Terminal window
# Run only custom rules
fsh-lint lint --only-custom-rules **/*.fsh
# Test specific rule
fsh-lint lint --rule custom/require-ms-flag test.fsh
  1. Start Simple - Begin with basic pattern matching
  2. Test Thoroughly - Test on various FSH files
  3. Provide Clear Messages - Help users understand the issue
  4. Include Fixes - Provide automated fixes when possible
  5. Document Rules - Explain why the rule exists