README.md

# Six

<picture>
  <img src="./assets/six.png" alt="Six">
</picture>

## Watch your Coverage

Zero-dependency Elixir coverage tool built for AI-assisted development. Wraps Erlang's `:cover` with smart defaults, function-level ignores, and a structured markdown report designed to be consumed directly by AI coding agents.

## Why Six

Erlang's `:cover` counts every executable line - including `defmodule`, `use`, `alias`, and other boilerplate that nobody considers "untested code." It also has no concept of ignoring specific functions or code blocks, and its output is designed for humans reading a terminal, not agents reading a file.

Six fixes all of that: smart defaults that exclude structural declarations, `@six :ignore` for function-level exclusions, comment directives for block-level control, and a structured markdown report at `.six/coverage.md` that tells an AI agent exactly which functions have untested branches - with source snippets and context. Zero dependencies beyond OTP.

## Installation

```elixir
# mix.exs
def project do
  [
    app: :my_app,
    test_coverage: [tool: Six],
    # ...
  ]
end

def cli do
  [preferred_envs: [six: :test, "six.detail": :test, "six.html": :test]]
end

defp deps do
  [{:six, "~> 0.1", only: :test}]
end
```

## Usage

```bash
# Run tests with coverage (terminal table + agent report)
mix test --cover

# Or use the mix task directly
mix six
mix six --threshold 90
mix six --minimum-coverage 85
mix six --skip generated/ --skip _pb.ex

# Source-level detail view
mix six.detail
mix six.detail --filter auth

# HTML report
mix six.html
mix six.html --open
```

This produces two things:

1. A terminal summary table (sorted worst-first)
2. `.six/coverage.md` - a structured report an AI agent can read and act on

## Guides

- [Reading the Output](https://hexdocs.pm/six/reading-output.html) - understanding the terminal table, columns, and colors
- [Threshold vs Minimum Coverage](https://hexdocs.pm/six/threshold-vs-minimum-coverage.html) - reporting targets vs enforcement floors
- [AI Integration](https://hexdocs.pm/six/ai-integration.html) - the agent report, Claude Code slash command, and coverage-driven test writing
- [GitHub Actions](https://hexdocs.pm/six/github-actions.html) - CI setup, failing on low coverage, and partitioned suites
- [Custom Formatters](https://hexdocs.pm/six/custom-formatters.html) - implementing the `Six.Formatter` behaviour

## Ignoring code

Three mechanisms, from automatic to explicit:

### Default pattern filters

Lines matching these patterns are automatically excluded from coverage - no configuration needed:

`defmodule`, `defprotocol`, `defimpl`, `defrecord`, `defdelegate`, `defstruct`, `defexception`, `@moduledoc`, `@doc`, `@impl`, `@behaviour`, `@callback`, `use`, `import`, `alias`, `require`, `plug`, `end`

### Function-level attribute

Add `use Six` to a module and tag functions with `@six :ignore`:

```elixir
defmodule MyApp.CoverBridge do
  use Six

  @six :ignore
  def start_cover do
    # Can't be tested during a coverage run
    :cover.start()
  end

  def normal_function do
    # This is still covered
    :ok
  end
end
```

`use Six` at the top of a file signals that the module has coverage exclusions - you know to look for `@six :ignore` tags. The attribute applies to the immediately following `def`/`defp`/`defmacro`/`defmacrop`, even with `@doc` or `@impl` in between.

### Comment directives

For quick one-offs where you don't need `use Six`:

```elixir
# six:ignore:next
def admin_only, do: System.halt(1)

# six:ignore:start
def debug_dump do
  # Everything in this block is excluded
end
# six:ignore:stop
```

Directive comments must be standalone comment lines. Six will not treat strings, heredocs, docs, or trailing inline comments that happen to contain `six:ignore:*` as coverage directives.

## Configuration

```elixir
# config/test.exs
config :six,
  # Additional patterns to ignore (beyond defaults)
  ignore_patterns: [
    ~r/^\s*@type\s/,
    ~r/^\s*defoverridable\s/
  ],

  # Set to false to ONLY use your patterns, not the built-in defaults
  default_patterns: true,

  # Fail CI if coverage drops below this
  minimum_coverage: 85.0,

  # File patterns to skip entirely
  skip_files: [
    ~r/lib\/my_app\/generated\//,
    ~r/_pb\.ex$/
  ],

  # Output directory (default: .six)
  output_dir: ".six",

  # Formatters to run (default: terminal + agent)
  formatters: [Six.Formatters.Terminal, Six.Formatters.Agent, Six.Formatters.HTML]
```

At runtime you can also override:

```bash
mix six --threshold 90
mix six --minimum-coverage 85
mix six --skip generated/ --skip _pb.ex
```

## Merging partitioned coverage

For CI setups that split tests across machines:

```bash
# Each partition exports its coverage data:
MIX_TEST_PARTITION=1 mix test --cover --export-coverage p1
MIX_TEST_PARTITION=2 mix test --cover --export-coverage p2

# Merge and generate report:
mix six --import-cover cover
```

## Acknowledgments

Six is built on top of Erlang's [:cover](https://www.erlang.org/doc/apps/tools/cover) and is inspired by [ExCoveralls](https://github.com/parroty/excoveralls) and [Coverex](https://github.com/alfert/coverex) - thank you!

## License

Copyright (c) 2026 Thomas Athanas

Licensed under the MIT License.