# `Whiff`
[🔗](https://github.com/SinAnima/whiff-elixir/blob/main/lib/whiff.ex#L1)

Elixir wrapper around the Rust [whiff](https://github.com/baoulo/whiff) crate.

Returns idiomatic `{:ok, report}` / `{:error, %Whiff.Error{}}` results where
`report` is a **string-keyed** map conforming to schema `whiff/1`.

## Examples

    iex> is_binary(Whiff.schema_version())
    true

Native identification/extraction is the default. Elixir extractors
(`Whiff.Extractor`) and analyzers (`Whiff.Analyzer`) run in BEAM processes
outside the NIF.

# `report`

```elixir
@type report() :: %{optional(String.t()) =&gt; term()}
```

# `result`

```elixir
@type result() :: {:ok, report()} | {:error, Whiff.Error.t()}
```

# `extract`

```elixir
@spec extract(Path.t(), keyword()) :: result()
```

Extract a `whiff/1` report from a filesystem path.

## Options

Native: `:profile`, `:hashes`, `:privacy`, `:only`, `:skip`, `:format`,
`:provenance`, `:limits`, `:tokens` (llm only).

Pipeline: `:mode` (`:fallback` | `:augment` | `:override`), `:extractors`,
`:analyzers`, `:strict`, `:plugin_timeout_ms`, `:override_fields`.

# `extract!`

```elixir
@spec extract!(Path.t(), keyword()) :: report()
```

Same as `extract/2` but raises `Whiff.Error`.

# `extract_binary`

```elixir
@spec extract_binary(binary(), keyword()) :: result()
```

Extract from in-memory bytes.

Pass `name:` (filename) to aid detection.

# `extract_binary!`

```elixir
@spec extract_binary!(binary(), keyword()) :: report()
```

Same as `extract_binary/2` but raises `Whiff.Error`.

# `extract_many`

```elixir
@spec extract_many([Path.t()], keyword()) ::
  {:ok, [{Path.t(), result()}]} | {:error, Whiff.Error.t()}
```

Extract many paths with bounded concurrency.

Returns a list of `{path, result}` in input order.

Options: `:max_concurrency` (default 4), `:on_error` (`:collect` | `:halt`).
Other options are forwarded to `extract/2`.

# `llm`

```elixir
@spec llm(Path.t(), keyword()) :: result()
```

Compact LLM projection for a path (`Report::llm_view`).

Default token budget: `800` (override with `tokens:`).

# `llm!`

```elixir
@spec llm!(Path.t(), keyword()) :: report()
```

Same as `llm/2` but raises `Whiff.Error`.

# `schema_version`

```elixir
@spec schema_version() :: String.t()
```

Report schema version (`whiff/1`).

# `version`

```elixir
@spec version() :: String.t()
```

Library version.

---

*Consult [api-reference.md](api-reference.md) for complete listing*
