> ## Documentation Index
> Fetch the complete documentation index at: https://trunk-4cab4936-sam-gutentag-analytics-cli-troubleshooting.mintlify.app/llms.txt
> Use this file to discover all available pages before exploring further.

# CLI Reference

> CLI tool for uploading test results to Trunk from CI, enabling flaky test detection and quarantining.

Trunk detects and tracks flaky tests in your repos by receiving uploads from your test runs in CI, uploaded from the Trunk Analytics CLI. These uploads happen in the CI jobs used to run tests in your nightly CI, post-commit jobs, and PR checks.

### Guides

If you're setting up Trunk Flaky Tests for the first time, you can follow the guides for your CI provider and test framework.

<Columns cols={2}>
  <Card title="Guides by Test Frameworks" href="/flaky-tests/get-started/frameworks/" />

  <Card title="Guides by CI Provider" href="/flaky-tests/get-started/ci-providers/" />
</Columns>

The CLI should be **downloaded as part of your test workflow** in your CI system. You can download the appropriate binary for your platform directly from the [GitHub releases page](https://github.com/trunk-io/analytics-cli/releases).

<Warning>
  Install `trunk-analytics-cli` from [github.com/trunk-io/analytics-cli/releases](https://github.com/trunk-io/analytics-cli/releases/latest), not from `get.trunk.io` or `trunk.io/releases`. Those URLs install the legacy `trunk` launcher used by Code Quality, which is in maintenance mode and is not the recommended path for Flaky Tests.
</Warning>

### Manual Download

You can find the list of releases on [the GitHub release page](https://github.com/trunk-io/analytics-cli/releases). We provide executables for Linux and OS X. It’s a single file inside a tar and upon downloading the tar you will find a single binary - `trunk-analytics-cli` to use.

<CodeGroup>
  ```bash Linux (x64) theme={null}
  SKU="trunk-analytics-cli-x86_64-unknown-linux.tar.gz"
  curl -fL --retry 3 \
    "https://github.com/trunk-io/analytics-cli/releases/latest/download/${SKU}" \
    | tar -xz

  chmod +x trunk-analytics-cli
  ```

  ```bash Linux (arm64) theme={null}
  SKU="trunk-analytics-cli-aarch64-unknown-linux.tar.gz"
  curl -fL --retry 3 \
    "https://github.com/trunk-io/analytics-cli/releases/latest/download/${SKU}" \
    | tar -xz

  chmod +x trunk-analytics-cli
  ```

  ```bash macOS (arm64) theme={null}
  SKU="trunk-analytics-cli-aarch64-apple-darwin.tar.gz"
  curl -fL --retry 3 \
    "https://github.com/trunk-io/analytics-cli/releases/latest/download/${SKU}" \
    | tar -xz

  chmod +x trunk-analytics-cli
  ```

  ```bash macOS (x64) theme={null}
  SKU="trunk-analytics-cli-x86_64-apple-darwin.tar.gz"
  curl -fL --retry 3 \
    "https://github.com/trunk-io/analytics-cli/releases/latest/download/${SKU}" \
    | tar -xz

  chmod +x trunk-analytics-cli
  ```
</CodeGroup>

### Organization Slug and Token

The CLI requires your Trunk organization slug and token passed through `--org-url-slug` and `--token` to upload results to the correct organization. They can alternatively be set via environment variables, `TRUNK_ORG_URL_SLUG` and `TRUNK_API_TOKEN`, respectively.

You can find your organization slug and token by going to **Settings** > **Manage** > **Organization**.

<Tabs>
  <Tab title="Slug">
    <Frame caption="Make sure you are getting your Organization Slug, not the Organization Name.">
      <img className="block dark:hidden" src="https://mintcdn.com/trunk-4cab4936-sam-gutentag-analytics-cli-troubleshooting/S7VBJuMrEqCwGnb0/assets/org-slug-light.png?fit=max&auto=format&n=S7VBJuMrEqCwGnb0&q=85&s=1c877a6ac5227888713030ea50a46002" alt="" width="5632" height="1804" data-path="assets/org-slug-light.png" />

      <img className="hidden dark:block" src="https://mintcdn.com/trunk-4cab4936-sam-gutentag-analytics-cli-troubleshooting/S7VBJuMrEqCwGnb0/assets/org-slug-dark.png?fit=max&auto=format&n=S7VBJuMrEqCwGnb0&q=85&s=9123865be1b68113d3f0f30b5003e959" alt="" width="5632" height="1804" data-path="assets/org-slug-dark.png" />
    </Frame>
  </Tab>

  <Tab title="Token">
    <Frame caption="Ensure you get your Organization API Token, not your repo token.">
      <img className="block dark:hidden" src="https://mintcdn.com/trunk-4cab4936-sam-gutentag-analytics-cli-troubleshooting/S7VBJuMrEqCwGnb0/assets/org-token-light.png?fit=max&auto=format&n=S7VBJuMrEqCwGnb0&q=85&s=7ee7f2eee97d8b4dbd5efc58f7c6b487" alt="" width="5632" height="1420" data-path="assets/org-token-light.png" />

      <img className="hidden dark:block" src="https://mintcdn.com/trunk-4cab4936-sam-gutentag-analytics-cli-troubleshooting/S7VBJuMrEqCwGnb0/assets/org-token-dark.png?fit=max&auto=format&n=S7VBJuMrEqCwGnb0&q=85&s=8c0767428116dba3763f3a5e1ec4412f" alt="" width="5632" height="1420" data-path="assets/org-token-dark.png" />
    </Frame>
  </Tab>
</Tabs>

### Uploading Test Results

<Info>
  The uploaded tests are processed by Trunk periodically, not in real-time. Wait for at least an hour after the initial upload before they’re displayed in the [Uploads tab](/flaky-tests/get-started/#id-4.-confirm-your-configuration-analyze-your-dashboard). Multiple uploads are required before a test can be accurately detected as flaky.
</Info>

Trunk accepts uploads in three main report formats, [XML](https://github.com/testmoapp/junitxml), [Bazel Event Protocol JSONs](https://bazel.build/remote/bep#consuming-bep-text-json), and XCode XCResult paths. You can upload each of these test report formats using the `./trunk-analytics-cli upload` command like this:

<Tabs>
  <Tab title="XML">
    Trunk can accept JUnit XMLs through the `--junit-paths` argument:

    ```
    ./trunk-analytics-cli upload --junit-paths "test_output.xml" \
       --org-url-slug <TRUNK_ORG_SLUG> \
       --token $TRUNK_API_TOKEN
    ```
  </Tab>

  <Tab title="Bazel">
    Trunk can accept Bazel through the `--bazel-bep-path` argument:

    ```
    ./trunk-analytics-cli upload --bazel-bep-path <BEP_JSON_PATH> \
       --org-url-slug <TRUNK_ORG_SLUG> \
       --token $TRUNK_API_TOKEN
    ```
  </Tab>

  <Tab title="XCode">
    Trunk can accept XCode through the `--xcresult-path` argument:

    ```
    ./trunk-analytics-cli upload --xcresult-path <XCRESULT_PATH> \
       --org-url-slug <TRUNK_ORG_SLUG> \
       --token $TRUNK_API_TOKEN
    ```
  </Tab>
</Tabs>

### Variants

If you run the same tests across different environments or architectures, you can use variants to separate these runs into distinct test cases. This allows Trunk to detect environment-specific flakes.

For example, a test for a mobile app might be flaky on iOS but stable on Android. Using variants, Trunk can isolate flakes on the iOS variant instead of marking the test as flaky across all environments.

You can specify a variant during upload using the `--variant` option:

```sh Upload an iOS variant theme={null}
./trunk-analytics-cli upload --junit-paths "test_output.xml" \
   --org-url-slug <TRUNK_ORG_SLUG> \
   --token $TRUNK_API_TOKEN \
   --variant ios
```

Variant names are displayed in brackets next to test names in your dashboard:

<Frame caption="The same test, but the first is a macOS variant.">
  <img className="block dark:hidden" src="https://mintcdn.com/trunk-4cab4936-sam-gutentag-analytics-cli-troubleshooting/9xEdY06ZQpuEPcoq/assets/variants-light-border.png?fit=max&auto=format&n=9xEdY06ZQpuEPcoq&q=85&s=8b85da0414c9e9576f7371f3f85b5c73" alt="" width="5600" height="1524" data-path="assets/variants-light-border.png" />

  <img className="hidden dark:block" src="https://mintcdn.com/trunk-4cab4936-sam-gutentag-analytics-cli-troubleshooting/9xEdY06ZQpuEPcoq/assets/variants-dark-border.png?fit=max&auto=format&n=9xEdY06ZQpuEPcoq&q=85&s=57f75b5eb6f5ba1c3eab735ac3806459" alt="" width="5600" height="1524" data-path="assets/variants-dark-border.png" />
</Frame>

### Running and Quarantining Tests

You can also execute tests and upload results to Trunk in a single step using the `test` command to **wrap** your test command.

This is especially useful for [Quarantining](../quarantining/), where the Trunk Analytics CLI will **override the exit code** of the test command if all failures can be quarantined, **preventing** flaky tests from failing your builds in CI.

<Info>
  **When to use `upload` vs `test`**

  Use `test` when you want Trunk to run your test command directly and set the build exit code based on quarantine status.

  Use `upload` when an external runner (or a post-processing step) has already produced JUnit XML and you only need to ship the results. `upload` will not re-run tests; it ingests the report and sets the exit code based on quarantine status. This is the right command when your test framework's JUnit reporter can't be configured for Trunk's needs and you have to post-process the XML before uploading.
</Info>

<Tabs>
  <Tab title="XML">
    Trunk can accept JUnit XMLs through the `--junit-paths` argument:

    ```
    ./trunk-analytics-cli test --junit-paths "test_output.xml" \
       --org-url-slug <TRUNK_ORG_SLUG> \
       --token $TRUNK_API_TOKEN \
       <YOUR_TEST_COMMAND>
    ```
  </Tab>

  <Tab title="Bazel">
    Trunk can accept Bazel through the `--bazel-bep-path` argument:

    ```
    ./trunk-analytics-cli test --bazel-bep-path <BEP_JSON_PATH> \
       --org-url-slug <TRUNK_ORG_SLUG> \
       --token $TRUNK_API_TOKEN \
       <YOUR_TEST_COMMAND>
    ```
  </Tab>

  <Tab title="XCode">
    Trunk can accept XCode through the `--xcresult-path` argument:

    ```
    ./trunk-analytics-cli test --xcresult-path <XCRESULT_PATH> \
       --org-url-slug <TRUNK_ORG_SLUG> \
       --token $TRUNK_API_TOKEN \
       <YOUR_TEST_COMMAND>
    ```
  </Tab>
</Tabs>

<Info>
  #### Service Availability and Graceful Degradation

  Trunk Analytics CLI is designed to fail safe when our quarantine service is unavailable. Read more at [Quarantine Service Availability](../quarantining/quarantine-service-availability)
</Info>

#### Upload failure vs test failure

We use the `SOFTWARE` exit code (70) if the upload fails.

If you use the `test` command and tests fail without the failures being quarantined, we return the provided exit code from the wrapped execution.

If you use the `upload` command, we return exit code `FAILURE` or the exit code provided with the `--test_process_exit_code` argument.

### Validating reports locally

You can validate the test reports produced by your test frameworks before you set up Trunk in your CI jobs. This is currently **only available for XML reports**.

You can run the validate command like this:

```
./trunk-analytics-cli validate --junit-paths "test_output.xml"
```

The `validate` command will output any problems with your reports so you can address them before setting up Trunk in CI.

```sh theme={null}
Validating the following 1 files:
  File set matching junit.xml:
    junit.xml

junit.xml - 1 test suites, 0 test cases, 0 validation errors

All 1 files are valid! ✅
Navigate to https://app.trunk.io/onboarding?intent=flaky+tests to continue using Trunk Flaky Tests! 🚀🧪
```

### Using custom CI systems

The CLI is preconfigured to work with a set [ci-providers](/flaky-tests/get-started/ci-providers/) but can be used with any CI system by passing [#environment-variables](/flaky-tests/get-started/ci-providers/otherci#environment-variables) to the uploader.

> More information on using [otherci.md](/flaky-tests/get-started/ci-providers/otherci) is documented here.

### Troubleshooting

<AccordionGroup>
  <Accordion title="&#x22;No tests were found&#x22; on upload, even though tests ran">
    This message means the CLI parsed the report inputs and found zero test cases. A few common causes:

    * **The test runner exited before writing JUnit XML.** A fatal exception in Playwright, Storybook, or any runner that produces JUnits at the end of the run will leave you with no XML file (or an empty one). Check the CI logs for an error from the runner that happened before the upload step.

    * **Bazel BEP JSON ingestion.** Trunk currently parses Bazel BEP more reliably from the binary format than from JSON. If you're passing `--bazel-bep-path` with a JSON file produced by `--build_event_json_file`, switch to the binary BEP:

      ```bash theme={null}
      bazel test //... \
        --build_event_binary_file=bep.bin

      ./trunk-analytics-cli upload --bazel-bep-path bep.bin \
         --org-url-slug <TRUNK_ORG_SLUG> \
         --token $TRUNK_API_TOKEN
      ```

    * **Globs didn't match any files.** Confirm that `--junit-paths` resolves to actual `.xml` files in the working directory the CLI is run from. Wrap globs in quotes so the shell doesn't expand them before the CLI sees them, and check that the report files contain `<testcase>` entries — not just `<testsuite>` shells.

    If you've checked all three and still see "no tests found," share a sample JUnit XML and the CI logs with Trunk support so they can look at the specific upload.
  </Accordion>

  <Accordion title="403 unauthorized on upload, but the slug and token are correct">
    The CLI infers the repository URL from the local git remote. If your remote uses an SSH host alias (for example, `git@github-most:org/repo.git` from a custom `~/.ssh/config` entry), the CLI parses the alias as the host and the upload is rejected as not belonging to a recognized GitHub or GitLab repo.

    Pass `--repo-url` explicitly with the canonical remote URL:

    ```bash theme={null}
    ./trunk-analytics-cli upload --junit-paths "test_output.xml" \
       --org-url-slug <TRUNK_ORG_SLUG> \
       --token $TRUNK_API_TOKEN \
       --repo-url git@github.com:org/repo.git
    ```

    This bypasses the inferred host and uses the value you pass directly.
  </Accordion>

  <Accordion title="&#x22;test case name too short&#x22; or &#x22;classname too short&#x22; from validate">
    These warnings come from the `validate` command (and the same checks run server-side on upload). They mean a test case has a name or classname so short it's likely to collide with another test case in your suite — Trunk uses name + classname to identify a test across runs, and very short values increase the chance of false matches.

    Today, the warning surfaces the offending value but does not name the source file. If you see these:

    * Grep your JUnit XML for the short value to find the originating test case.
    * Where possible, configure your test framework to emit fully-qualified classnames (for example, including the file path or package).

    We're tracking better source attribution for these warnings.
  </Accordion>

  <Accordion title="Wrapping an external test runner without re-running tests">
    If your test framework's JUnit reporter doesn't expose enough configuration (for example, Cypress's `mocha-junit-reporter` doesn't support `filePathPrefix`), you may need to post-process the XML before sending it to Trunk. In that case, don't use `test` — it will re-run your tests. Use `upload` instead:

    ```bash theme={null}
    # 1. Run your tests through your existing runner
    npm test

    # 2. Post-process the JUnit XML however you need to
    node scripts/fix-junit-paths.js

    # 3. Upload the corrected XML to Trunk
    ./trunk-analytics-cli upload --junit-paths "test_output.xml" \
       --org-url-slug <TRUNK_ORG_SLUG> \
       --token $TRUNK_API_TOKEN \
       --test-process-exit-code $?
    ```

    Pass `--test-process-exit-code` so Trunk knows whether the original test process succeeded or failed; this is what the upload command uses to decide whether to override the exit code based on quarantine status.
  </Accordion>
</AccordionGroup>

### Full command reference

The `trunk` command-line tool can upload and analyze test results. The `trunk-analytics-cli` command accepts the following subcommands:

| Command                              | Description                                                                                                                                                                                          |
| ------------------------------------ | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `trunk-analytics-cli upload`         | Upload data to Trunk Flaky Tests.                                                                                                                                                                    |
| `trunk-analytics-cli validate`       | Validates if the provided JUnit XML files and prints any errors.                                                                                                                                     |
| `trunk-analytics-cli test <COMMAND>` | Runs tests using the provided command, uploads results, checks whether the failures are [quarantined](../quarantining/#using-the-trunk-cli-directly) tests, and correct the exit code based on that. |

The `upload` and `test` commands accept the following options:

| Argument                                            | Description                                                                                                                                                                                                                                           |
| --------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `--junit-paths <JUNIT_PATHS>`                       | Path to the test output files. File globs are supported. Remember to wrap globs in `""` quotes                                                                                                                                                        |
| `--bazel-bep-path <BEP_JSON_PATH>`                  | Path to a JSON serialized [Bazel Build Event Protocol](https://bazel.build/remote/bep). Trunk will use the BEP file to locate test reports. Your test frameworks must still output [compatible report formats](/flaky-tests/get-started/frameworks/). |
| `--xcresult-path <XCRESULT_PATH>`                   | Path to a `.xcresult` directory, which contains test reports from `xcodebuild`.                                                                                                                                                                       |
| `--org-url-slug <ORG_URL_SLUG>`                     | Trunk Organization slug, from the Settings page.                                                                                                                                                                                                      |
| `--token <TOKEN>`                                   | Trunk Organization (not repo) token, from the Settings page. Defaults to the `TRUNK_API_TOKEN` variable.                                                                                                                                              |
| `-h, --help`                                        | Additional detailed description of the `upload` command.                                                                                                                                                                                              |
| `--repo-root`                                       | Path to the repository root. Defaults to the current directory.                                                                                                                                                                                       |
| `--repo-url <REPO_URL>`                             | Value to override URL of repository. **Optional**.                                                                                                                                                                                                    |
| `--repo-head-sha` `<REPO_HEAD_SHA>`                 | Value to override SHA of repository head. **Optional**.                                                                                                                                                                                               |
| `--repo-head-branch <REPO_HEAD_BRANCH>`             | Value to override branch of repository head. **Optional**.                                                                                                                                                                                            |
| `--repo-head-commit-epoch <REPO_HEAD_COMMIT_EPOCH>` | Value to override commit epoch of repository head. **Optional**.                                                                                                                                                                                      |
| `--codeowners-path <CODEOWNERS_PATH>`               | Value to override CODEOWNERS file or directory path. **Optional**.                                                                                                                                                                                    |
| `--allow-empty-test-results`                        | Don't fail commands if test results are empty or missing. Use it when you sometimes skip all tests for certain CI jobs. Defaults to `true`.                                                                                                           |
| `--variant <VARIANT_NAME>`                          | Upload tests to a specific variant group. **Optional**.                                                                                                                                                                                               |
| `--test-process-exit-code` `<EXIT_CODE>`            | Specify the exit code of the test previously run. This is used by the upload command to identify errors that happen outside of the context of the test execution (such as build errors).                                                              |

<Info>
  **Memory Overhead**

  Running tests via `trunk-analytics-cli test` adds negligible memory overhead.

  This subcommand is a thin wrapper around your existing test command and doesn't modify or parallelize test execution.

  During execution, it:

  * Runs your provided test command directly.
  * Records start and end times.
  * Captures the exit code for quarantine decisions.

  You can safely run the CLI even with large or memory-intensive suites, without risking additional OOMs in your CI agents.
</Info>
