Ameba 1.7.0 has been released
This release is a milestone — 37 new rules, major internal rewrites, and a wave of quality-of-life features. Check out the release notes to see the full scope of changes.
Crystal compatibility
Ameba 1.7 requires Crystal 1.19.0 or newer to build.
Windows compatibility
With Crystal nearing tier 1 Windows support, Ameba 1.7.0 makes sure it runs equally well on Windows as on other platforms. This effort was tracked in #668.
Distribution binaries
Binaries for Linux, macOS, and Windows are being built in CI upon release (#789).
Breaking changes ⚠️
This release contains a fair number of breaking changes. Here’s what to watch out for:
Removed auto-compilation (bin/ameba)
Ameba no longer builds a bin/ameba binary automatically on shards install/update — the postinstall script has been dropped. The recommended way to run Ameba going forward is via the GitHub Action, which uses a precompiled binary (~1s per run) instead of building from source (~1+ min). Alternatively, add an ameba target to your shard.yml and run shards build ameba.
The bin/ameba.cr executable is no longer copied into your project’s bin/ directory either — use lib/ameba/bin/ameba.cr directly or copy it over for local modification if needed.
CLI: --fail-level replaced by --min-severity
The --fail-level switch has been replaced with --min-severity. The new flag filters which issues get reported based on their severity, instead of just affecting the exit code. This aligns Ameba more closely with tools like Credo (--min-priority).
Project root detection
Invoking Ameba from outside the project directory now correctly discovers the project root and respects the Excluded paths from the closest .ameba.yml. The default exclusion of the lib folder was moved from globs (as !lib) to Excluded (as lib) — which may affect custom .ameba.yml configurations.
Unknown config attributes are now silently ignored
Previously, Ameba would raise on unknown attributes in .ameba.yml. Now they are silently ignored, making it easier to share config across Ameba versions.
Renamed rules
Documentation/DocumentationAdmonition→Documentation/AdmonitionLint/DuplicatedRequire→Lint/DuplicateRequire
Update your .ameba.yml config and # ameba:disable directives if you reference these rules by name.
Documentation/Admonition is now disabled by default
This rule checks for NOTE/TODO/WARNING markers in documentation comments. It’s now disabled by default because it’s a subjective style preference and may be too noisy for many projects.
Lint/Typos is now disabled by default
Due to performance limitations and file-scoping issues, Lint/Typos is no longer active out of the box. Enable it explicitly in .ameba.yml if you still want to use it.
Versioned documentation
Documentation URLs now include the version. If you link to Ameba documentation, the URL structure has changed: crystal-ameba.github.io/ameba -> crystal-ameba.org/api/<version>. Rule presenter output also now includes the versioned documentation URL.
Other breaking changes
Lint/UselessAssign—ExcludeTypeDeclarationsoption was removed without replacementLint/SpecFilename—IgnoredDirsandIgnoredFilenamesoptions were replaced withIgnoredPathsPerformance/AnyInsteadOfEmpty— this rule has been deprecated- Ameba now raises on invalid file paths instead of silently skipping them
All of the breaking changes are documented in the migration guide.
37 new rules
This release adds the largest batch of new rules ever.
Lint
Lint/AssignmentInCallArgument— detects assignments used as call arguments (e.g.foo(x = 1))Lint/DeprecatedRule— reports deprecated rulesLint/DuplicateBranch— flagswhenbranches containing the same codeLint/DuplicateEnumValue— warns on enum members with duplicate valuesLint/DuplicateMethodSignature— flags methods with identical signaturesLint/DuplicateWhenCondition— detects duplicate conditions inwhenbranchesLint/ElseNil— reportselse nilin constructs where returningnilis already implicitLint/EnumMemberNameConflict— warns when an enum member name clashes with a methodLint/NonExistentRule— flags references to rules that don’t existLint/RequireParentheses— enforces parentheses around method callsLint/SelfInitializeDefinition— flagsself.initializedefinitionsLint/SignalTrap— warns onSignal.trapusageLint/SpecEqWithBoolOrNilLiteral— flagsshould eq(true / false / nil)in specsLint/TopLevelOperatorDefinition— warns on operator definitions at the top levelLint/TrailingRescueException— flags trailingrescueclauses that include exception typesLint/UnusedExpression— flags unused expressionsLint/UnusedRescueVariable— flags unused rescue variablesLint/UselessVisibilityModifier— warns on redundantprotectedvisibility modifierLint/VoidOutsideLib— flagsVoidtype usage outsidelibdeclarationsLint/WhitespaceAroundMacroExpression— enforces whitespace around{{ }}macro expressions
Style
Style/CallParentheses— flags unnecessary parentheses on method callsStyle/Elsif— encourages the use ofcase/whensyntax overif/elsifStyle/HeredocEscape— flags unnecessary escapes in heredocsStyle/HeredocIndent— enforces consistent heredoc indentationStyle/MultilineCurlyBlock— recommendsdo ... endover{ ... }for multiline blocksStyle/MultilineStringLiteral— flags multiline string literals that could use heredocsStyle/PercentLiteralDelimiters— enforces consistent delimiters in percent literalsStyle/RedundantNilInControlExpression— flags redundantnilin control expressionsStyle/RedundantSelf— flags unnecessaryselfreceiverStyle/VerboseNilType— suggestsT?instead ofT | NilStyle/ArrayLiteralSyntax— enforcesArray(Type).newover[] of Typefor array instantiationsStyle/HashLiteralSyntax— enforcesHash(K, V).newover{} of K => Vfor hash instantiations
Typing
Typing/MacroCallArgumentTypeRestriction— enforces type restrictions on macro call argumentsTyping/MethodParameterTypeRestriction— enforces type restrictions on method parametersTyping/MethodReturnTypeRestriction— enforces return type restrictions on methodsTyping/ProcLiteralReturnTypeRestriction— enforces return type restrictions on proc literals
Performance
Performance/TimesMap— suggests usingArray.new(n) { ... }overn.times.map { ... }
Rule deprecation mechanism
Ameba now supports marking rules as deprecated. Deprecated rules are still available but will emit a warning when used. Performance/AnyInsteadOfEmpty was the first rule to be deprecated in this release.
Rule versioning
Rules can now declare a since_version — the Ameba version in which they were introduced. Use --up-to-version <version> to exclude rules added after a given version, or --rule-versions to display version info alongside each rule. You can also set Version in .ameba.yml to automatically limit rules to those available at that version.
JSON Schema for .ameba.yml
Ameba now ships with a JSON Schema for its configuration file, along with a generator that keeps it up-to-date as rules change. This enables autocompletion and inline documentation when editing .ameba.yml in compatible editors.
GitHub Actions formatter
A new github-actions formatter produces annotations compatible with GitHub Actions, making it easy to see issues inline in PR checks.
Liveness analysis rewrite
Three rules (Lint/UselessAssign, Lint/ShadowedArgument, Lint/SharedVarInFiber) were rewritten using backward dataflow liveness analysis. This replaces the old branch-consumption heuristic with a sound algorithm that:
- Improves accuracy — eliminates false positives from imprecise branch handling
- Improves performance —
Lint/UselessAssignon the Crystal compiler source went from ~4.5s to under 1s - Handles loops correctly — fixed-point iteration replaces the conservative
referenced_in_loop?flag - Handles flow control —
break/next/returnpropagate to the correct target live set
These changes also allowed the removal of the AST::Branch and AST::Branchable modules, simplifying the codebase significantly.
ECR file linting
Ameba can now lint .ecr files (Embedded Crystal) by default — no configuration needed. This makes it easy to catch issues in templates right from the command line.
Autocorrect additions
Several more rules now support autocorrect: Lint/RedundantStringCoercion (new), and existing rules gained broader autocorrect coverage through the work in #796.
New rule options
Documentation/Documentation— addedRequireExampleoptionLint/SpecFilename— addedIgnoredPathsoption (replacingIgnoredDirsandIgnoredFilenames)Naming/BinaryOperatorParameterName— addedAllowedNamesoptionStyle/ParenthesesAroundCondition— addedExcludeMultilineoption
Other highlights
Style/RedundantBegin,Style/RedundantNext, andStyle/RedundantReturnwere extended to report inside blocks andif/unlessbranches- Issue locations were improved across 14 rules for more precise error highlighting
--ignore-configCLI flag added to skip reading.ameba.ymlentirely- Version output now includes the Git SHA for non-release builds
- Rule documentation URLs are now included in rule presenter output
- Docker images are now built with
--release - Windows CI support was added (see Windows compatibility)
Full Changelog: https://github.com/crystal-ameba/ameba/compare/v1.6.4...v1.7.0