ð ameba-configuration
Use when configuring Ameba rules and settings for Crystal projects including .ameba.yml setup, rule management, severity levels, and code quality enforcement.
Overview
Configure Ameba, the static code analysis tool for Crystal, to enforce consistent code style and catch code smells in your Crystal projects.
Understanding Ameba
Ameba is a static code analysis tool for the Crystal programming language that:
- Enforces consistent Crystal code style
- Catches code smells and wrong code constructions
- Provides configurable rules organized into categories
- Supports inline disabling of rules
- Offers auto-correction for many issues
- Integrates seamlessly with Crystal development workflows
Core Configuration File: .ameba.yml
Generating Default Configuration
# Generate a new configuration file with all defaults
ameba --gen-config
# This creates .ameba.yml with all available rules and their default settings
Basic Configuration Structure
# .ameba.yml - Complete example configuration
# Global source configuration
Globs:
- "**/*.cr" # Include all Crystal files
- "**/*.ecr" # Include Embedded Crystal files
- "!lib" # Exclude dependencies
Excluded:
- src/legacy/** # Exclude legacy code
- spec/fixtures/** # Exclude test fixtures
# Rule categories and individual rules
Lint/UnusedArgument:
Enabled: true
Severity: Warning
Style/RedundantReturn:
Enabled: true
Severity: Convention
Performance/AnyInsteadOfEmpty:
Enabled: true
Severity: Warning
Source File Configuration
Globs: Defining What to Analyze
# Include specific patterns
Globs:
- "**/*.cr" # All Crystal source files
- "**/*.ecr" # All Embedded Crystal templates
- "!lib/**" # Exclude lib directory
- "!vendor/**" # Exclude vendor directory
# Common patterns
# - "src/**/*.cr" # Only src directory
# - "spec/**/*.cr" # Only spec directory
# - "!**/*_test.cr" # Exclude test files
Excluded: Fine-Grained Exclusions
# Global exclusions (applied to all rules)
Excluded:
- src/compiler/** # Exclude specific directories
- src/legacy/**
- spec/fixtures/**
- db/migrations/** # Often excluded from style checks
# Real-world example
Globs:
- "**/*.cr"
- "!lib"
Excluded:
- src/external/generated/** # Generated code
- src/legacy/** # Legacy code being refactored
- spec/support/fixtures/** # Test data
Source Configuration Examples
# Example 1: Standard web application
Globs:
- "src/**/*.cr"
- "spec/**/*.cr"
- "!lib"
Excluded:
- src/assets/**
- spec/fixtures/**
# Example 2: Library/Shard
Globs:
- "src/**/*.cr"
- "spec/**/*.cr"
- "examples/**/*.cr"
- "!lib"
Excluded:
- spec/support/**
# Example 3: Monorepo
Globs:
- "apps/**/src/**/*.cr"
- "apps/**/spec/**/*.cr"
- "packages/**/src/**/*.cr"
- "!lib"
- "!**/node_modules/**"
Excluded:
- apps/legacy/**
Rule Categories
Lint Rules (Code Correctness)
Lint rules catch potential bugs and incorrect code:
# Unused variables and arguments
Lint/UnusedArgument:
Enabled: true
Severity: Warning
# Catches: def process(data, unused_param)
Lint/UselessAssign:
Enabled: true
Severity: Warning
# Catches: x = 5; x = 10 # First assignment never used
# Shadowed variables
Lint/ShadowingOuterLocalVar:
Enabled: true
Severity: Warning
# Catches: x = 1; proc { |x| x } # x shadows outer x
# Unreachable code
Lint/UnreachableCode:
Enabled: true
Severity: Error
# Catches: return x; do_something() # Never executes
# Syntax issues
Lint/Syntax:
Enabled: true
Severity: Error
# Catches syntax errors before compilation
# Empty blocks
Lint/EmptyBlock:
Enabled: true
Severity: Warning
ExcludeEmptyBlocks: false
# Catches: items.each { }
# Debugger statements
Lint/DebuggerStatement:
Enabled: true
Severity: Warning
# Catches: debugger; pp value
Style Rules (Code Conventions)
Style rules enforce Crystal code conventions:
# Naming conventions
Style/ConstantNames:
Enabled: true
Severity: Convention
# Enforces: CONSTANT_NAME not Constant_Name
Style/MethodNames:
Enabled: true
Severity: Convention
# Enforces: method_name not methodName
Style/TypeNames:
Enabled: true
Severity: Convention
# Enforces: ClassName not Class_Name
# Predicate methods
Style/PredicateName:
Enabled: true
Severity: Convention
# Enforces: empty? not is_empty
# Redundant code
Style/RedundantReturn:
Enabled: true
Severity: Convention
AllowMultipleReturnValues: true
# Catches: def foo; return 42; end
# Prefers: def foo; 42; end
Style/RedundantBegin:
Enabled: true
Severity: Convention
# Catches: def foo; begin; 42; end; end
# Prefers: def foo; 42; end
# Large numbers
Style/LargeNumbers:
Enabled: true
Severity: Convention
IntMinDigits: 5
# Enforces: 100_000 not 100000
# Parentheses
Style/ParenthesesAroundCondition:
Enabled: true
Severity: Convention
# Enforces: if x > 5 not if (x > 5)
# String literals
Style/StringLiterals:
Enabled: true
Severity: Convention
# Catches inconsistent quote usage
# Variable names
Style/VariableNames:
Enabled: true
Severity: Convention
# Enforces: snake_case not camelCase
Performance Rules
Performance rules identify inefficient code patterns:
# Inefficient any? usage
Performance/AnyInsteadOfEmpty:
Enabled: true
Severity: Warning
FilterFirstNegativeCondition: true
# Catches: array.any?
# Prefers: !array.empty?
# Size after filter
Performance/SizeAfterFilter:
Enabled: true
Severity: Warning
FilterNames: [select, reject]
# Catches: items.select(&.active?).size
# Prefers: items.count(&.active?)
# Compact after map
Performance/CompactAfterMap:
Enabled: true
Severity: Warning
# Catches: items.map(&.value?).compact
# Prefers: items.compact_map(&.value?)
# Flatten after map
Performance/FlattenAfterMap:
Enabled: true
Severity: Warning
# Catches: items.map(&.children).flatten
# Prefers: items.flat_map(&.children)
Rule Configuration Options
Per-Rule Configuration
# Enable/disable individual rules
Style/LargeNumbers:
Enabled: true # or false to disable
# Set severity levels
Style/RedundantReturn:
Enabled: true
Severity: Warning # Error, Warning, Convention
# Configure rule-specific options
Style/LargeNumbers:
Enabled: true
Severity: Convention
IntMinDigits: 5 # Minimum digits before requiring underscores
Lint/UnusedArgument:
Enabled: true
IgnoreTypeDeclarations: false
IgnoreParameterNames: [] # Parameter names to ignore
# Exclude files from specific rules
Style/RedundantBegin:
Enabled: true
Excluded:
- src/server/processor.cr
- src/server/api.cr
Advanced Rule Configuration Examples
# Custom severity levels
Lint/UselessAssign:
Enabled: true
Severity: Error # Make this an error, not warning
Style/RedundantReturn:
Enabled: true
Severity: Convention
AllowMultipleReturnValues: true # Allow: return x, y
# Ignore specific parameter patterns
Lint/UnusedArgument:
Enabled: true
IgnoreParameterNames:
- "_*" # Ignore params starting with underscore
- "unused_*" # Ignore params prefixed with unused_
# Configure numeric formatting
Style/LargeNumbers:
Enabled: true
IntMinDigits: 5 # 10000 requires underscores
# 1000 is fine, 10000 should be 10_000
# Performance tuning
Performance/SizeAfterFilter:
Enabled: true
FilterNames:
- select
- reject
- filter
Severity Levels
Understanding Severity
# Error: Must be fixed (blocks CI typically)
Lint/Syntax:
Severity: Error
# Warning: Should be fixed (important issues)
Lint/UnusedArgument:
Severity: Warning
# Convention: Style preference (less critical)
Style/RedundantReturn:
Severity: Convention
Severity Configuration Strategy
# Conservative approach (CI-friendly)
# Only errors block builds
Lint/Syntax:
Severity: Error
Lint/UnreachableCode:
Severity: Error
Style/RedundantReturn:
Severity: Warning
Style/LargeNumbers:
Severity: Convention
# Strict approach (enforce everything)
# All issues treated as errors
Lint/UnusedArgument:
Severity: Error
Style/RedundantReturn:
Severity: Error
Style/VariableNames:
Severity: Error
# Progressive approach (gradually increase strictness)
# Start with warnings, move to errors over time
Lint/UselessAssign:
Severity: Warning # Will become Error after cleanup
Style/RedundantBegin:
Severity: Convention # Will become Warning after team adapts
Inline Rule Control
Disabling Rules in Code
# Disable single rule for one line
time = Time.epoch(1483859302) # ameba:disable Style/LargeNumbers
# Disable multiple rules for one line
result = calculate() # ameba:disable Style/RedundantReturn, Lint/UselessAssign
# Disable rule categories
# ameba:disable Style, Lint
def legacy_method
# Old code with known issues
end
# ameba:enable Style, Lint
# Disable specific rule for block
# ameba:disable Style/RedundantBegin
def process
begin
perform_operation
rescue
handle_error
end
end
# ameba:enable Style/RedundantBegin
# Common patterns
class LegacyService
# ameba:disable Lint/UnusedArgument
def process(data, context)
# Only using data for now
data.process
end
# ameba:enable Lint/UnusedArgument
end
Inline Disable Best Practices
# GOOD - Specific and temporary
def parse_timestamp(value)
Time.epoch(1483859302) # ameba:disable Style/LargeNumbers
end
# GOOD - With explanation
# This API requires exact numeric format
# ameba:disable Style/LargeNumbers
LEGACY_TIMESTAMP = 1483859302
# ameba:enable Style/LargeNumbers
# BAD - Too broad
# ameba:disable Style
# Disables all style rules - too permissive
def messy_method
# ...
end
# BAD - Never re-enabled
# ameba:disable Lint/UselessAssign
# Disables for rest of file
# GOOD - Scoped to minimum area
def external_api_call
# ameba:disable Style/VariableNames
responseData = call_api() # External API uses camelCase
# ameba:enable Style/VariableNames
response_data = responseData # Convert to Crystal convention
end
Complete Configuration Examples
Minimal Configuration (Permissive)
# .ameba.yml - Minimal setup for new projects
Globs:
- "**/*.cr"
- "!lib"
# Only enable critical rules
Lint/Syntax:
Enabled: true
Severity: Error
Lint/UnreachableCode:
Enabled: true
Severity: Error
Standard Configuration (Balanced)
# .ameba.yml - Standard configuration for most projects
Globs:
- "**/*.cr"
- "**/*.ecr"
- "!lib"
Excluded:
- spec/fixtures/**
# Lint rules (errors and warnings)
Lint/Syntax:
Enabled: true
Severity: Error
Lint/UnusedArgument:
Enabled: true
Severity: Warning
Lint/UselessAssign:
Enabled: true
Severity: Warning
Lint/UnreachableCode:
Enabled: true
Severity: Error
# Style rules (conventions)
Style/RedundantReturn:
Enabled: true
Severity: Convention
Style/RedundantBegin:
Enabled: true
Severity: Convention
Style/LargeNumbers:
Enabled: true
Severity: Convention
IntMinDigits: 5
Style/VariableNames:
Enabled: true
Severity: Warning
# Performance rules
Performance/AnyInsteadOfEmpty:
Enabled: true
Severity: Warning
Performance/SizeAfterFilter:
Enabled: true
Severity: Warning
Strict Configuration (Comprehensive)
# .ameba.yml - Strict configuration for production code
Globs:
- "src/**/*.cr"
- "spec/**/*.cr"
- "!lib"
Excluded:
- spec/fixtures/**
- spec/support/mocks/**
# All lint rules enabled as errors
Lint/Syntax:
Enabled: true
Severity: Error
Lint/UnusedArgument:
Enabled: true
Severity: Error
Lint/UselessAssign:
Enabled: true
Severity: Error
Lint/UnreachableCode:
Enabled: true
Severity: Error
Lint/ShadowingOuterLocalVar:
Enabled: true
Severity: Error
Lint/DebuggerStatement:
Enabled: true
Severity: Error
# Style rules as warnings or errors
Style/RedundantReturn:
Enabled: true
Severity: Error
Style/RedundantBegin:
Enabled: true
Severity: Error
Style/LargeNumbers:
Enabled: true
Severity: Error
IntMinDigits: 4
Style/VariableNames:
Enabled: true
Severity: Error
Style/MethodNames:
Enabled: true
Severity: Error
Style/ConstantNames:
Enabled: true
Severity: Error
Style/PredicateName:
Enabled: true
Severity: Warning
# Performance rules as warnings
Performance/AnyInsteadOfEmpty:
Enabled: true
Severity: Warning
Performance/SizeAfterFilter:
Enabled: true
Severity: Warning
Performance/CompactAfterMap:
Enabled: true
Severity: Warning
Performance/FlattenAfterMap:
Enabled: true
Severity: Warning
When to Use This Skill
Use the ameba-configuration skill when:
- Setting up Ameba for a new Crystal project
- Configuring code quality standards for a team
- Customizing rule severity levels for CI/CD
- Excluding legacy code or generated files from analysis
- Troubleshooting rule conflicts or false positives
- Migrating from one Ameba version to another
- Establishing project-specific coding standards
- Balancing code quality with development velocity
- Integrating Ameba into existing Crystal projects
- Creating configuration templates for multiple projects
Best Practices
- Start with generated config - Run
ameba --gen-configto see all available rules and their defaults - Use version control - Commit
.ameba.ymlso team members share the same configuration - Enable incrementally - Start permissive, gradually enable more rules as team adapts
- Set appropriate severities - Use Error for blocking issues, Warning for important, Convention for style
- Document exceptions - Add comments explaining why specific rules are disabled or configured differently
- Scope exclusions narrowly - Exclude specific files/directories rather than disabling rules globally
- Use inline disables sparingly - Prefer fixing issues over disabling rules; when necessary, be specific
- Review generated config - Don't blindly use default config; review and customize for your project
- Separate concerns - Use different severity levels for different types of issues (bugs vs style)
- Test configuration changes - Run
amebalocally before committing configuration changes - Keep config maintainable - Group related rules together and use comments to explain sections
- Align with team standards - Configuration should reflect team consensus, not individual preferences
- Update regularly - Review and update configuration when upgrading Ameba versions
- Use rule-specific exclusions - Exclude files from specific rules rather than globally when possible
- Monitor false positives - Adjust rules that generate too many false positives for your codebase
Common Pitfalls
- Too strict initially - Enabling all rules at maximum severity in existing projects creates overwhelming technical debt
- Too permissive permanently - Never tightening rules means missing valuable code quality improvements
- Excluding too broadly - Using
Excluded: ["**/*"]defeats the purpose of static analysis - Inconsistent severity - Mixing up severity levels (making style issues errors, making bugs conventions)
- Not using version control - Team members using different configurations causes confusion
- Ignoring upgrade guides - New Ameba versions may change rule names or behaviors
- Disabling without understanding - Turning off rules that flag legitimate issues
- Overusing inline disables - Littering code with
ameba:disablecomments instead of fixing issues - Not excluding generated code - Wasting time analyzing auto-generated files
- Forgetting about ECR files - Not including
**/*.ecrin Globs for web applications - Conflicting with formatter - Enabling rules that conflict with
crystal tool format - Missing test files - Not including
spec/**/*.crin Globs - Global disables in code - Using
ameba:disableat file level without re-enabling - Not testing CI integration - Configuration works locally but fails in CI environment
- Ignoring performance impact - Enabling every rule without considering analysis time on large codebases