# Elixir build insights {#elixir-build-insights}

Tuist's Hex package can send build analytics to Tuist. Build times, the dependency graph between your files, and how both evolve over time give you what you need to optimize your build graph and make the most of all the cores available in the environment where the compilation takes place.

> [!IMPORTANT] REQUIREMENTS
> - Complete <.localized_link href="/guides/get-started/elixir-project">Get started with Elixir</.localized_link>

## Report your builds {#report-your-builds}

The shared setup installs the compile integration. Keep using your usual commands:

```bash
mix compile
```

The integration covers `mix compile` and every compile that another task triggers, such as `mix test` or `mix phx.server`. A compile that finds nothing to do is not reported, so the dashboard only lists builds that did work.

## Report actor claim {#report-actor-claim}

Mix build and test report requests include the optional `x-tuist-actor-id` header only when you explicitly configure a label. Set `TUIST_ACTOR_ID` to an organization-scoped label, or add `actor_id: "developer-label"` to the project's `tuist` configuration. Resolution prefers the environment variable, then runtime `:actor_id` options, then project configuration. No label is sent by default, and the package does not detect operating-system usernames. A fixed project label applies to everyone using that configuration. Empty or invalid overrides omit the claim instead of falling back; this does not remove credential-based verified identity. If a custom proxy rejects unfamiliar headers, opt out with `TUIST_ACTOR_ID=""`.

Identifiers must be 1–128 bytes of non-space printable ASCII. Invalid overrides are omitted without falling back. Verified individual credentials take precedence; other client-reported identifiers are displayed as **Unverified**, never authorize access, and never link automatically to users. Anyone who can view the project's reports can see these identifiers, including public viewers when the project is public, and they are included in data exports, so do not include secrets. Old servers ignore the optional header, and new servers accept old clients without it. New shared-token reports with no identifier show **Unknown**, rather than the publishing organization; historical reports retain their prior attribution. Build and test reporting require authentication by default. Self-hosted installations can explicitly enable credential-free reporting as described below.

## Credential-free reporting on a private network {#network-trusted-publishing}

After an operator configures `TUIST_NETWORK_TRUSTED_REPORT_PUBLISHING=true` on the instance and restarts it as described in the <.localized_link href="/guides/server/self-host/server#network-trusted-report-publishing">self-hosting guide</.localized_link>, configure your destination. The SDK automatically discovers whether the instance permits credential-free reporting when credentials are absent. The instance setting covers every supported project and has no dashboard toggle:

```elixir
tuist: [
  url: "https://tuist.internal.example",
  project: "account/project"
]
```

`mix tuist.compile` and `mix tuist.test` publish structured reports without sign-in when credentials are genuinely absent and discovery confirms that the server permits it. No client flag or project opt-in is required. Present credentials, including supplied CI OIDC identity, are used or rejected, never ignored to downgrade to unsigned reporting. A whitespace-only `TUIST_TOKEN` is an error. An empty `TUIST_TOKEN` can fall back to valid stored credentials or supplied OIDC, and stale stored credentials can fall back to supplied OIDC; both paths remain authenticated and never enable unsigned reporting. Unusable credentials are preserved and fail when no authenticated fallback succeeds. Upgrade every server replica to a discovery-capable version before upgrading credential-free clients; older servers without discovery, disabled instances, and discovery failures still require authentication.

Unsigned runs are telemetry, not trusted flakiness, quarantine, coverage, or selective-execution evidence. Shard planning, build archives, and coverage/artifact endpoints still require credentials. Set `TUIST_ACTOR_ID=""` independently to omit the configured actor claim; verified credential identity is unaffected.

## What is tracked {#what-is-tracked}

For each build, the package collects:
- Its duration, whether it succeeded, and the Elixir, Erlang/OTP, and Mix environment it ran with
- Every warning and error, with its file and line
- How long each file took to compile, and the modules it defines
- The files each file depends on, and whether it needs them at compile time or only at runtime
- What the build did besides compiling files, such as type checking, writing to disk, and the other Mix compilers
- The processor, memory, network, and disk usage of the machine during the build
- The branch and commit, and on continuous integration, the provider and the run

## Find what slows a build down {#find-what-slows-a-build-down}

Open a build from **Builds → Build Runs** on the dashboard. Builds, their diagnostics counts, and their dependency cache summaries are also available through `tuist build mix list` and `tuist build mix show`, `GET /api/projects/{account_handle}/{project_handle}/mix/builds`, and the `list_mix_builds` and `get_mix_build` <.localized_link href="/guides/features/agentic-coding/mcp">MCP tools</.localized_link>.

The **Overview** tab lists the files the build compiled. You can group them by module, search them, and sort them by:
- **Compilation duration**, to find the files that are slow by themselves.
- **Compile-time dependents**, the number of files that cannot compile until this one has. A slow file with many dependents holds the rest of the build back, and changing it recompiles all of them.
- **Compile-time dependencies**, the number of files this one waits for.

![Overview of a Mix build of a Phoenix application](/images/guides/features/elixir/build.png)

The **Timeline** tab shows the same build over time: which files compiled in parallel, where the build type checked and wrote to disk, and how the machine was doing at each moment. A stretch with a single bar is a stretch where the build could not use the cores it had.

![Timeline of a full Mix build of a Phoenix application](/images/guides/features/elixir/build-timeline.png)

The **Warnings** and **Errors** tabs list the diagnostics of the build.

## Custom metadata {#custom-metadata}

Attach tags and key-value data to Mix builds to tell apart runs from different teams, hardware, or workflows. Both appear on each build's detail page.

Set metadata with environment variables:

```sh
export TUIST_TAGS="nightly,release"
export TUIST_VALUES="ticket=TUIST-123,runner=linux-arm64"
```

You can also configure metadata in `mix.exs`:

```elixir
tuist: [
  project: "account/project",
  tags: ["nightly", "release"],
  values: %{"ticket" => "TUIST-123", "runner" => "linux-arm64"}
]
```

Tags from both places are combined. When the same key is configured in both places, the value in the environment variable takes precedence.

Tags must contain only letters, numbers, hyphens, and underscores. A build can have up to 50 tags, and each tag can contain up to 50 characters. A build can have up to 20 key-value entries, each key can contain up to 50 characters, and each value can contain up to 500 characters. These are the same server-side limits used for Xcode build metadata. The package skips invalid tags and oversized or empty metadata entries before it sends the report, so invalid configuration cannot prevent the rest of the build insights report from being stored. Use key-value metadata for values that do not meet the tag constraint.

Custom metadata is attached to builds, not to test runs.

Custom metadata is visible to project members in the dashboard. Do not use it for credentials, access tokens, or other sensitive data. Tuist retains Mix build data, including this metadata, for 90 days. See the <.localized_link href="/guides/server/data-retention">data retention policy</.localized_link> for details.

## Troubleshooting {#troubleshooting}

Reporting never changes the result of your build: if the report cannot be sent, the build finishes as it would have and nothing is printed. To see why a report was not sent, set `TUIST_DEBUG=1`:

```bash
TUIST_DEBUG=1 mix compile --force
```
