A parallel code quality checker for Elixir projects that runs format, compile, credo, dialyzer, dependency checks, and tests concurrently with actionable feedback.
Perfect for iterative development: Use mix quality --quick during active coding, then mix quality for full verification before committing.
- 🚀 Fast iteration:
--quickmode skips slow checks (dialyzer, coverage) for rapid feedback - ⚡ Parallel execution: All checks run concurrently, maximizing CPU utilization
- 🔧 Auto-fix first: Automatically fixes formatting before running analysis
- 📊 Streaming output: See results as each stage completes, not after everything finishes
- 🎯 Actionable feedback: Full tool output with file:line references for easy fixing
- 🤖 Auto-detection: Automatically enables checks based on installed dependencies
- ⚙️ Configurable: Customize via
.quality.exsor CLI flags - 🧠 LLM-friendly: Includes
usage-rules.mdfor AI coding assistants
# Add to mix.exs
def deps do
[
{:ex_quality, "~> 0.2.0", only: :dev, runtime: false}
]
end# Install dependencies
mix deps.get
# Set up quality tools (interactive)
mix quality.init
# Or use defaults without prompts
mix quality.init --skip-promptsThis will:
- Detect which tools are already installed
- Prompt you to select additional tools (credo, dialyzer, excoveralls recommended)
- Add dependencies to mix.exs
- Run
mix deps.get - Set up tool configurations (.credo.exs, coveralls.json, etc.)
- Create .quality.exs for customization
Then run quality checks:
# During development - fast feedback
mix quality --quick
# Before committing - full verification
mix qualityWhen you're actively coding and want quick feedback:
mix quality --quickQuick mode skips:
- ❌ Dialyzer (type checking is slow)
- ❌ Coverage enforcement (tests run, but coverage % not checked)
Quick mode runs:
- ✅ Format (auto-fixes)
- ✅ Compilation (dev + test)
- ✅ Credo (static analysis)
- ✅ Dependencies (unused deps + security audit)
- ✅ Tests (must pass)
- ✅ Doctor (if installed)
- ✅ Gettext (if installed)
Use this when: Making frequent changes, implementing features, fixing bugs.
Before committing, pushing, or opening a PR:
mix qualityFull mode runs everything:
- ✅ Format
- ✅ Compilation
- ✅ Credo
- ✅ Dialyzer (comprehensive type checking)
- ✅ Dependencies (unused deps + security audit)
- ✅ Tests with coverage (enforces threshold)
- ✅ Doctor
- ✅ Gettext
Use this when: Ready to commit, opening PRs, in CI/CD.
ExQuality runs in three phases:
✓ Format: Formatted 3 files (0.2s)
Automatically fixes code formatting with mix format.
✓ Compile: dev + test compiled (warnings as errors) (2.1s)
Compiles both dev and test environments in parallel. Must pass before analysis.
✓ Doctor: 92% documented (0.4s) ← prints at 0.4s
✓ Credo: No issues (1.8s) ← prints at 1.8s
✓ Tests: 248 passed, 87.3% coverage (5.2s) ← prints at 5.2s
✓ Dialyzer: No warnings (32.1s) ← prints at 32.1s
All checks run concurrently. Results stream as each completes.
# Quick mode for iterative development
mix quality --quick
# Skip specific stages
mix quality --skip-dialyzer
mix quality --skip-credo
mix quality --skip-doctor
mix quality --skip-gettext
mix quality --skip-dependencies
# Combine flags
mix quality --quick --skip-credoExQuality automatically enables stages based on installed dependencies:
| Stage | Requires | Auto-enabled? |
|---|---|---|
| Format | (none) | Always |
| Compile | (none) | Always |
| Credo | :credo |
If installed |
| Dialyzer | :dialyxir |
If installed |
| Dependencies | (none) / :mix_audit |
Always (audit if installed) |
| Doctor | :doctor |
If installed |
| Gettext | :gettext |
If installed |
| Tests | (none) | Always |
| Coverage | :excoveralls |
If installed |
Example: If you have credo and dialyxir in deps, ExQuality will run both automatically.
Create .quality.exs in your project root to customize behavior:
[
# Override auto-detection: force disable dialyzer
dialyzer: [enabled: false],
# Credo options
credo: [
strict: true, # Use --strict mode (default: true)
all: false # Use --all flag (default: false)
],
# Doctor options
doctor: [
summary_only: true # Show only summary (default: false)
],
# Dependencies options
dependencies: [
check_unused: true, # Check for unused deps (default: true)
audit: true # Run security audit if mix_audit installed (default: :auto)
]
]Configuration is merged in this order (later wins):
- Defaults - Sensible built-in defaults
- Auto-detection - Based on installed deps
.quality.exs- Project-specific config- CLI flags - Runtime overrides (highest priority)
Example: If .quality.exs disables dialyzer, but you run mix quality (no flags), dialyzer stays disabled. However, the auto-detection still marks it as "available" internally.
Coverage threshold is NOT configured in ExQuality. It reads from your existing excoveralls configuration:
coveralls.json→minimum_coverageorcoverage_thresholdmix.exs→test_coverage: [minimum_coverage: 80.0]
This ensures a single source of truth for coverage requirements.
When checks fail, ExQuality shows the complete tool output with file:line references:
✗ Credo: 5 issue(s) (1 refactoring, 2 readability, 2 design) (0.4s)
────────────────────────────────────────────────────────────
Credo - FAILED
────────────────────────────────────────────────────────────
┃ [D] ↘ Nested modules could be aliased at the top of the invoking module.
┃ lib/mix/tasks/quality.ex:96:22 #(Mix.Tasks.Quality.run)
┃
┃ [R] ↗ Predicate function names should not start with 'is'...
┃ lib/ex_quality/stages/dialyzer.ex:92:8 #(ExQuality.Stages.Dialyzer.is_debug_info_error?)Why this matters:
- Humans can click file:line in their editor
- LLMs can see exactly what needs fixing
- No need to run individual tools to get details
For the best experience, add these to your mix.exs:
def deps do
[
# Recommended quality tools
{:credo, "~> 1.7", only: [:dev, :test], runtime: false},
{:dialyxir, "~> 1.4", only: [:dev, :test], runtime: false},
{:excoveralls, "~> 0.18", only: :test},
{:doctor, "~> 0.21", only: :dev, runtime: false},
{:mix_audit, "~> 2.1", only: [:dev, :test], runtime: false},
# If you use translations
{:gettext, "~> 0.24"},
# Quality checker
{:ex_quality, "~> 0.2.0", only: :dev, runtime: false}
]
endRun full quality checks in your CI pipeline:
# GitHub Actions
- name: Run quality checks
run: mix qualityNote: Dialyzer requires a PLT (Persistent Lookup Table). You may want to cache it:
- name: Restore PLT cache
uses: actions/cache@v3
with:
path: priv/plts
key: ${{ runner.os }}-plt-${{ hashFiles('**/mix.lock') }}Add to .git/hooks/pre-commit:
#!/bin/sh
mix quality --quickThis gives you fast feedback before committing.
During feature development:
# Make changes
vim lib/my_app/feature.ex
# Quick check (fast)
mix quality --quick
# Fix issues, repeatBefore committing:
# Full verification
mix quality
# If it passes, commit
git add .
git commit -m "Add feature"| Feature | ExQuality | ex_check | al_check |
|---|---|---|---|
| Parallel execution | ✅ | ✅ | ✅ |
| Streaming output | ✅ | ❌ | ❌ |
| Auto-fix first | ✅ | ✅ | ✅ |
| Auto-detect tools | ✅ | ✅ | ❌ |
| Quick mode | ✅ | ❌ | ✅ |
| LLM-friendly | ✅ | ❌ | ❌ |
| Config file | .quality.exs | .check.exs | alcheck.toml |
| Actionable output | ✅ Full tool output | ✅ | ✅ |
ExQuality's differentiators:
- Quick mode - Fast iteration during development
- Streaming output - See results as each check completes
- Auto-fix first - Format code before analysis
- LLM integration - Includes
usage-rules.mdfor AI assistants
Use quick mode during development:
mix quality --quickOr disable it permanently in .quality.exs:
[dialyzer: [enabled: false]]Adjust strictness in .quality.exs:
[credo: [strict: false]]Or create .credo.exs to configure credo directly.
ExQuality auto-detects and skips them. No configuration needed.
ExQuality shows the full test output with file:line references. Look for the failure details in the output.
ExQuality is designed for rapid, iterative development with confidence.
- Fast feedback loop:
--quickgives you sub-second feedback on most changes - Comprehensive verification: Full mode ensures everything is correct
- Actionable output: See exactly what needs fixing, with file:line references
- Zero configuration: Works out of the box with sensible defaults
- Progressive enhancement: Add tools as you need them
MIT
Issues and pull requests welcome at https://github.com/riddler/ex_quality