> ## Documentation Index
> Fetch the complete documentation index at: https://docs.crucihil.io/llms.txt
> Use this file to discover all available pages before exploring further.

# crucihil import-results

> Import existing JUnit XML or Robot Framework results into CruciHiL

## Synopsis

```bash theme={null}
crucihil import-results <file> [options]
```

## Description

`crucihil import-results` is the lowest-friction adoption tier: import results from your **current** test runner — history, trends, and MCP querying work before any rig integration.

It parses a JUnit XML file (pytest, Jenkins, GitLab, CruciHiL's own reporter) or a Robot Framework `output.xml` into CruciHiL test results. When `CRUCIHIL_BASE_URL` and `CRUCIHIL_API_KEY` are set, the batch is synced to the cloud through the same idempotent path the agent uses; otherwise a local summary is printed.

The status mapping keeps blocked≠fail intact across the import boundary — see [Blocked status mapping](#blocked-status-mapping) below.

## Supported formats

| Format          | Value   | Detected from                                | Sources                                                                      |
| --------------- | ------- | -------------------------------------------- | ---------------------------------------------------------------------------- |
| JUnit XML       | `junit` | root element `<testsuites>` or `<testsuite>` | pytest, Jenkins, GitLab, CruciHiL's own reporter                             |
| Robot Framework | `robot` | root element `<robot>`                       | RF 7 (`start`/`elapsed` ISO 8601) and legacy (`starttime`/`endtime`) formats |

The format is auto-detected from the document's root element when `--format` is omitted. If the root element is not recognized, the command exits with an error asking for an explicit `--format junit|robot`.

## Options

<ParamField path="FILE" type="path" required>
  Positional argument. JUnit XML or Robot Framework `output.xml` from your current runner. The file must exist.
</ParamField>

<ParamField path="--format" type="string">
  Result format: `junit` or `robot`. Auto-detected from the root element when omitted.
</ParamField>

<ParamField path="--suite-name" type="string">
  Override the suite name recorded on every imported result. Defaults to the suite name found in the file (or the file's stem if none is present).
</ParamField>

<ParamField path="--rig-name" type="string" default="&#x22;imported&#x22;">
  Rig name recorded on the synced run. Informational — the server attributes the run to the authenticated rig.
</ParamField>

<ParamField path="--json" type="path">
  Also write the parsed test results as JSON to this path. Parent directories are created if needed.
</ParamField>

## Blocked status mapping

The blocked≠fail distinction survives the import in both formats:

| Source                                                                        | Imported status                                                |
| ----------------------------------------------------------------------------- | -------------------------------------------------------------- |
| JUnit `<skipped message="blocked: ...">` (CruciHiL's own reporter convention) | `blocked` — the text after the colon becomes the error message |
| JUnit `<skipped>` with any other message                                      | `skip`                                                         |
| JUnit `<failure>`                                                             | `fail`                                                         |
| JUnit `<error>`                                                               | `error`                                                        |
| RF `FAIL` whose message contains `BlockedError`                               | `blocked` — never `fail`                                       |
| RF `FAIL` (any other message)                                                 | `fail`                                                         |
| RF `SKIP` / `NOT RUN`                                                         | `skip`                                                         |
| RF `PASS` / JUnit passing testcase                                            | `pass`                                                         |

<Info>
  A JUnit `skipped` message is matched case-insensitively — any message starting with `blocked` maps to `blocked`. The RF convention matches the live Robot listener: a test failing with a `BlockedError` message imports as `blocked`.
</Info>

Additional data is preserved where the source format provides it: JUnit `classname` and `system-out` are kept on each result (as metadata and logs respectively), and Robot test names are recorded alongside the normalized test ID.

## Cloud sync

Set both environment variables to sync the imported batch to the cloud:

```bash theme={null}
export CRUCIHIL_BASE_URL=https://cloud.example
export CRUCIHIL_API_KEY=chk_...

crucihil import-results build/junit.xml
```

The API key is exchanged for a JWT, then the batch is pushed through `POST /api/v1/results/sync` — the same endpoint the agent uses. The sync is idempotent per run: results are upserted with `ON CONFLICT (test_id, run_id) DO NOTHING`, so a replayed or retried batch never duplicates results. Each `import-results` invocation records a new run.

If either environment variable is unset, the command prints the local summary only and exits `0`:

```
CRUCIHIL_BASE_URL / CRUCIHIL_API_KEY not set — local summary only.
```

## Output format

```
Parsed : build/junit.xml  (format: junit)
Suite  : engine_validation
5 run · 4 passed · 0 failed · 1 blocked · 0 errored  (12.480s total)
Synced : 5 new results → https://cloud.example  (run 7f3a…)
```

## Exit codes

| Code | Meaning                                                       |
| ---- | ------------------------------------------------------------- |
| `0`  | Results parsed (and synced, if configured)                    |
| `2`  | Parse error, unknown format, nothing to sync, or sync failure |

## Examples

### Import a pytest JUnit report

```bash theme={null}
crucihil import-results build/junit.xml
```

### Import a Robot Framework output.xml with an explicit suite name

```bash theme={null}
crucihil import-results output.xml --format robot --suite-name bench_regression
```

### Import, sync to the cloud, and keep a local JSON copy

```bash theme={null}
export CRUCIHIL_BASE_URL=https://cloud.example CRUCIHIL_API_KEY=chk_...
crucihil import-results build/junit.xml --json results/imported.json
```

## See also

* [Bring your pytest & Robot suites](/guides/frameworks) — the full framework adoption guide
* [`crucihil run`](/cli/run) — run suites natively (or foreign suites via `--framework`)
* [`crucihil verify`](/cli/verify) — mutation-verify a suite, including imported frameworks
