# Assay
Incremental Dialyzer for modern Elixir tooling. Assay reads Dialyzer settings
directly from your host app’s `mix.exs`, runs the incremental engine, filters
warnings via `dialyzer_ignore.exs`, and emits multiple output formats suited
for humans, CI, editors, and LLM-driven tools.
## Features
* Incremental Dialyzer runs via `mix assay`
* Watch mode (`mix assay.watch`) with debounced re-analysis
* JSON/CLI formatters (`text`, `github`, `sarif`, `lsp`, `ndjson`, `llm`)
* `dialyzer_ignore.exs` filtering with per-warning decorations
* Igniter-powered installer (`mix assay.install`) that configures apps/
warning_apps in the host project
* JSON-RPC daemon (`mix assay.daemon`) plus an MCP server (`mix assay.mcp`)
for editor/LSP/agent integrations
## Installation
Add Assay as a dev/test dependency (local path while developing, Hex release
once published):
```elixir
def deps do
[
{:assay, "~> 0.1", runtime: false, only: [:dev, :test]}
]
end
```
From the host project, run:
```bash
mix assay.install --yes
```
This detects project/dep apps and injects:
```elixir
assay: [
dialyzer: [
apps: [...],
warning_apps: [...]
]
]
```
## Usage
### One-off analysis
```bash
mix assay
mix assay --print-config
mix assay --format github --format sarif
```
Exit codes: `0` (clean), `1` (warnings), `2` (error).
### Watch mode
```bash
mix assay.watch
```
Re-runs incremental Dialyzer on file changes and streams formatted output.
### JSON-RPC daemon
```bash
mix assay.daemon
```
Speaks JSON-RPC over stdio. Supported methods:
* `assay/analyze` – run incremental Dialyzer
* `assay/getStatus`, `assay/getConfig`, `assay/setConfig`
* `assay/shutdown`
### MCP server
```bash
mix assay.mcp
```
Implements the Model Context Protocol (`initialize`, `tools/list`, `tools/call`)
and exposes a single tool, `assay.analyze`, which returns the same structured
diagnostics as the daemon. Requests/responses use the standard MCP/LSP framing:
each JSON payload must be prefixed with `Content-Length: <bytes>\r\n\r\n`.
### Pretty-printing Dialyzer terms
Add [`erlex`](https://hexdocs.pm/erlex) to your host project's deps (e.g.
`{:erlex, "~> 0.2", optional: true}`) and pass `--format elixir` to `mix assay`
to render Dialyzer's Erlang detail blocks as Elixir-looking maps/structs (e.g.
`%Ecto.Changeset{}`) while keeping plain output available when the default
`text` format is used.
## Development
* `mix test` – unit tests (including daemon + MCP simulations)
* `mix credo` – linting/style checks
* `mix format` – formatter
* `mix assay.watch` – dogfooding watch mode on the library itself
## Status
Assay currently focuses on incremental Dialyzer runs, watch mode, the Igniter
installer, and daemon/MCP integrations. Future milestones include richer
pass-through Dialyzer flag support, additional output formats, and expanded
editor tooling.