> For the complete documentation index, see [llms.txt](https://docs.xygeni.io/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.xygeni.io/xygeni-products/code-quality.md).

# Code Quality

Xygeni **Code Quality** analyses your source code for **maintainability and reliability defects** — code smells, complexity violations, dead code, duplication, and patterns that cause runtime failures — and surfaces them in a dedicated **Quality** section in the web platform, separate from security findings.

Quality is delivered as its own scanner (`xygeni quality`) that shares the static-analysis engine with [SAST](/xygeni-products/code-security-cs.md) (parsers, AST, file discovery) but maintains its own rule catalog focused on quality, not security.

## Quality scanner

Run a quality scan with the dedicated command:

```bash
xygeni quality -d <directory> [options]
```

The alias `xygeni code-quality` is also accepted.

The scanner shares its option model with `xygeni sast`. The most common options are:

| Option                       | Description                                                                                                                                                                      |
| ---------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `-d`, `--dir <directory>`    | Directory to analyse. Defaults to the current working directory.                                                                                                                 |
| `-n`, `--name <name>`        | Project name to report under.                                                                                                                                                    |
| `--upload`                   | Upload results to the Xygeni platform. By default, results are not uploaded.                                                                                                     |
| `--detectors <list>`         | Comma-separated list of detector IDs to run, a severity (`critical`, `high`, `low`, `info`), or `all`. When a severity is given, that severity and any higher ones are included. |
| `--skip-detectors <list>`    | Inverse of `--detectors`.                                                                                                                                                        |
| `-i`, `--include <patterns>` | Glob patterns of files to include.                                                                                                                                               |
| `-e`, `--exclude <patterns>` | Glob patterns of files to exclude.                                                                                                                                               |
| `-o`, `--output <file>`      | Output file path. Defaults to stdout.                                                                                                                                            |
| `-f`, `--format <format>`    | Output format.                                                                                                                                                                   |
| `--fail-on <severity>`       | Exit non-zero if findings of the given severity (or higher) are produced. Useful as a CI/CD gate.                                                                                |
| `--baseline <file>`          | Compare against a baseline report and only return new findings.                                                                                                                  |

For the full option list run:

```bash
xygeni quality --help
```

### Examples

Run a quality scan on the current directory and upload the results:

```bash
xygeni quality -n MyProject --upload
```

Export critical findings to JSON:

```bash
xygeni quality -d <dir> --detectors critical --format json --output quality.json
```

### Run quality alongside a SAST scan

The SAST scanner accepts an `--include-quality` flag that runs the quality rules in the same pass. The SAST and quality rules share the parser stage, so this is more efficient than running `xygeni sast` and `xygeni quality` back to back when you want both.

```bash
xygeni sast -d <dir> --include-quality
```

The scan produces both a SAST report and a separate quality report. SAST and quality findings remain on their own report files and on their own dashboard sections — `--include-quality` only changes how the scan is executed, not how the results are surfaced.

### Upload a previously generated quality report

Quality results are normally sent to the platform during the scan with `--upload`. When the scan runs where there is no connectivity to Xygeni (an air-gapped enclave, or a CI runner without network egress), save the report and upload it later with [`report-upload`](/xygeni-products/application-security-posture-management-aspm/importing-reports-from-3rd-party-tools.md):

```bash
# 1. Scan, keep the report locally (no --upload)
xygeni quality -d <dir> -n MyProject

# 2. Later, from a host with platform connectivity, upload it
xygeni report-upload -n MyProject -r depsdoctor-quality.json
```

The findings land in the **Quality** section exactly like a native quality scan — same triage, policy, baseline, and remediation behaviour — and never in the SAST / All Risks views.

`report-upload` recognises the report from its standard file name `depsdoctor-quality.json`. If the file was renamed (for example via `--output`), pass the format explicitly so it is not mistaken for a SAST report (both share the same report shape):

```bash
xygeni report-upload -n MyProject -r my-quality-report.json --format quality-xygeni
```

Uploading a quality report requires the **Code Quality** entitlement, the same as running the scan.

## Code duplication

The quality scan also detects **duplicated code**: groups of fragments that are copies of one another, either byte-for-byte or after a consistent renaming of identifiers and literals. Each group of copies is a **clone class**.

Two fragments are compared by their **syntactic structure**, not their text. Indentation, brace style, comments and line breaks are all invisible to the comparison, and so are the names of local variables and parameters when they are renamed consistently throughout. A copied class that has since been reformatted is still found.

Only **extractable** regions are reported: a whole function, or a contiguous run of sibling statements or class members. A finding is therefore always something you can lift into a shared unit, never an arbitrary window of tokens that happens to repeat.

Duplication runs as part of both `xygeni quality` and `xygeni scan`. The `--duplication-*` options below belong to `xygeni quality`; `xygeni scan` uses the values in `xygeni.quality.yml`.

### Duplication findings

When the scan uploads, every clone class becomes a **Code Quality finding**, and so does every group of byte-identical files. They appear in the Code Quality list next to the other quality findings, with type **Duplication** and CWE-1041. Filters, sorting, CSV export, mute, snooze, triage and policies work on them as on any other quality finding.

| Detector             | One finding per                                                                     | Remedy                                                                 |
| -------------------- | ----------------------------------------------------------------------------------- | ---------------------------------------------------------------------- |
| `any.duplication`    | Clone class: two or more copies of a function, or of a run of statements or members | Extract the shared code into one unit                                  |
| `any.duplicate_file` | Group of byte-identical files                                                       | Delete the extra copies, or move the file into a module both sides use |

Byte-identical files have their own detector because the remedy is different. Without it, a copied file would show up as one clone class per method inside it.

The **severity** depends on how many lines a refactoring would remove and on how far the copies are spread:

| Severity | When                                                            |
| -------- | --------------------------------------------------------------- |
| High     | 500 or more removable lines, or copies in 3 or more directories |
| Low      | 100 to 499 removable lines                                      |
| Info     | Fewer than 100 removable lines                                  |

Duplication found only in test code is one level lower: High becomes Low, and Low becomes Info. A duplication finding is never **Critical**, so it never ranks above a real defect in the list.

The duplication detectors are in the `Very_Strict`, `Strict` and `Standard` quality policies. If your project's quality policy does not enable `any.duplication`, the scan logs that the duplication findings were not uploaded. The local duplication report is written either way.

The local quality report (`-o`) does not contain the duplication findings, and neither the baseline nor `--fail-on` counts them. Use `--fail-on-duplication-ratio` to gate a build on duplication.

### What a finding tells you

Each clone class carries the following fields, both in the duplication report and in the finding's detail panel on the platform:

| Field             | Meaning                                                                                                                                                                              |
| ----------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `kind`            | `IDENTICAL`, `RENAMED_LOCALS` (only local names differ) or `PARAMETERIZED` (identifiers or literals vary consistently).                                                              |
| `lines`, `tokens` | Size of the **smallest** fragment in the group, so a group never looks larger than its smallest copy.                                                                                |
| `count`           | How many copies exist.                                                                                                                                                               |
| `removableLines`  | Lines a refactoring would delete: every copy but one.                                                                                                                                |
| `substitutions`   | The identifiers and literals that vary between copies. These become the **parameters** of the unit you extract.                                                                      |
| `refactoring`     | The suggested technique (`extract-method`, `extract-shared-helper`, `extract-utility`), how many files and directories the copies span, and the parameters the extracted unit needs. |
| `fragments`       | Each copy: file, line range, and the enclosing type or function.                                                                                                                     |

Groups of byte-identical files are listed under `duplicateFiles` in the report, with their checksum and size.

### Options

| Option                               | Description                                                                                                                                                                                                                                                       |
| ------------------------------------ | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `--duplication` / `--no-duplication` | Detect duplicated code. Enabled by default.                                                                                                                                                                                                                       |
| `--duplication-report <path>`        | Write the report to this path. When a directory is given, it is written there as `xygeni.duplication.json` / `xygeni.duplication.md`. **Without this option no report file is written locally**, only a summary line in the log. Uploading does not depend on it. |
| `--duplication-format <list>`        | Report formats: `json`, `markdown`. Both by default.                                                                                                                                                                                                              |
| `--duplication-min-tokens <n>`       | Minimum clone size in tokens, for every language. Overrides the per-language defaults. Raising it is the main way to cut noise.                                                                                                                                   |
| `--duplication-min-lines <n>`        | Minimum clone size in lines, for every language.                                                                                                                                                                                                                  |
| `--duplication-clone-types <list>`   | Which kinds to report: `identical`, `renamed`. Both by default.                                                                                                                                                                                                   |
| `--[no-]duplication-ignore-literals` | Do not compare literal values, so differing literals are not reported as substitutions. Literals are compared by default.                                                                                                                                         |
| `--[no-]duplication-include-tests`   | Analyse test sources too. Excluded by default: test duplication is real, but usually a lower priority than production code.                                                                                                                                       |
| `--fail-on-duplication-ratio <pct>`  | Exit with an error when the percentage of duplicated tokens exceeds this value (0–100). Without it, duplication never fails the scan.                                                                                                                             |

When the scan uploads, the duplication report travels in the same bundle as the quality report, whether or not `--duplication-report` was given. This applies to `xygeni quality --upload`, to `xygeni scan`, and to `xygeni sast --include-quality --upload`.

Duplication is **not reported for an incremental scan** (`--incremental`, or a diff-mode scan). It is a whole-codebase measurement. An incremental scan analyses only the files that changed, so the ratio would be measured against a fraction of the project, and two files copied in the same commit would read as almost entirely duplicated. The scan logs that it skipped duplication and carries on.

### Examples

Scan, upload, and keep a local copy of the duplication report:

```bash
xygeni quality -d <dir> -n MyProject --upload --duplication-report /tmp/duplication
```

Report only exact copies, at least 300 tokens, and include test sources:

```bash
xygeni quality -d <dir> --duplication-clone-types identical \
  --duplication-min-tokens 300 --duplication-include-tests
```

Use duplication as a CI/CD gate:

```bash
xygeni quality -d <dir> --fail-on-duplication-ratio 15
```

### Tuning the signal

The defaults aim to report duplication that is worth reading, not as much duplication as possible:

* **Minimum size is 115 tokens and 6 lines** for Java, Go and Python. The token threshold is adjusted for each language, so that it stands for about the same amount of logic everywhere:

  | Language         | Minimum tokens |
  | ---------------- | -------------- |
  | JavaScript, PHP  | 125            |
  | C#               | 120            |
  | Java, Go, Python | 115            |
  | Kotlin, Swift    | 105            |

  These values were calibrated against established duplication tools on open-source codebases. At these values the duplication reported is in line with those tools, and almost no clones shorter than 10 lines are reported. A consistent renaming is easy to match by accident on a small fragment, so size is the main precision lever. Raise it on a large codebase. Lowering it below about 100 mostly adds small and overlapping clones. `--duplication-min-tokens` overrides every language at once.
* **Vendored code is skipped at any depth**: `**/vendor/**`, `**/vendors/**`, `**/third_party/**`, `**/third-party/**`, `**/thirdparty/**` and `**/js/libs/**`. Third-party code copied into a project duplicates itself and its other copies, and it cannot be refactored there. These excludes apply only to duplication. The scan-wide excludes are unchanged.
* **Generated code is skipped**. It is recognised by the header that generators write (`Code generated ... DO NOT EDIT`, `<auto-generated>`, `@generated`, `Generated by ...`), not by path patterns, which would also skip hand-written parsers and builders.
* **One clone is reported once.** A window shifted by a few statements over the same copies is dropped when it adds fewer than two new locations. A smaller clone that appears in more places than the larger one around it is still reported.
* **Token-dense fragments are rejected.** A short fragment packed with many tokens per line is usually a chain of assertions or builder calls, and the same shape repeats everywhere.
* **Runs of statements are considered up to 100 long.** A duplicate longer than that is a whole function or class, which is reported in its own right. The limit costs no findings and stops one very large machine-written file from dominating the scan.
* **Test sources are excluded.** When you include them, they are tagged and summarised separately.

All of these settings can be changed in `xygeni.quality.yml`, under the `duplication` key (`minTokens`, `minLines`, `languages`, `excludes`, `includeTests`, `maxDuplicatedTokensRatio`, and so on). See [Xygeni CLI Configuration options](/xygeni-scanner-cli/xygeni-cli-overview/xygeni-cli-configuration-options.md).

## Quality findings in the web platform

Quality findings are uploaded to the Xygeni platform alongside any other scan output and are displayed in a **dedicated Quality section** of the dashboard, separate from SAST and the rest of the security risks. Filtering, slide-out detail, baselines, and reports work the same way as for the other risk tables.

### Duplication in the Code Quality view

To list only duplication, open **Code Quality** and set **Type** to **Duplication**. Sort by **Severity** to see the largest or most widely spread duplication first. The **Explanation** column summarises each finding: how many copies, how many lines, and across how many files and directories.

<figure><img src="https://4096647782-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FUTz59rJLkJBjiRWAMknU%2Fuploads%2Fgit-blob-14cafcfd6b06abe2da68f57a6d31cbc677b7a99d%2Fcode-quality-duplication-list.png?alt=media" alt="Code Quality list filtered by Type = Duplication and sorted by severity, with the Statistics tab open"><figcaption><p>Duplication findings, sorted by severity. Two byte-identical file groups rank High, and the clone classes below them are Low.</p></figcaption></figure>

The **Statistics** tab shows severity, type and file totals for all the quality findings in scope. The table filters do not narrow it.

Click a finding to open its detail panel. For a clone class, the **Code duplication** section shows the clone kind, the number of copies, lines per copy, removable lines and the enclosing type. It also lists the **Substitutions**: the names and literals that differ between the copies, which become the parameters of the extracted unit. Below that are the reference code and every occurrence, each linked to its location in the repository.

<figure><img src="https://4096647782-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FUTz59rJLkJBjiRWAMknU%2Fuploads%2Fgit-blob-fe84ec2bd8a464470fd5013fa4dd4abf691a3b39%2Fcode-quality-duplication-clone-detail.png?alt=media" alt="Detail panel of a parameterized clone class, showing copies, removable lines and substitutions"><figcaption><p>A parameterized clone class: two 239-line copies that differ in three names. Extracting them needs three parameters.</p></figcaption></figure>

For a group of byte-identical files, the **Duplicate file** section shows the file size and checksum, and **Occurrences** lists every copy.

<figure><img src="https://4096647782-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FUTz59rJLkJBjiRWAMknU%2Fuploads%2Fgit-blob-c575931751f08ceacf2c46e1c7cfaf7ea1e98d1b%2Fcode-quality-duplication-file-detail.png?alt=media" alt="Detail panel of a duplicate file group, showing six identical copies of the same file"><figcaption><p>Six identical copies of the same file in six directories.</p></figcaption></figure>

## Related

* [SAST Scanner](/xygeni-products/code-security-cs/ci-cd-scanner.md) — security-focused static analysis. Quality and SAST share the engine but ship as independent scan commands and rule catalogs.
* [Xygeni CLI Configuration options](/xygeni-scanner-cli/xygeni-cli-overview/xygeni-cli-configuration-options.md) — configuration files (`xygeni.yml`, `xygeni.<command>.yml`) and `--conf-option` overrides.


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation by asking a question.

Perform an HTTP GET request on the following URL with the `ask` and `goal` query parameters:

```
GET https://docs.xygeni.io/xygeni-products/code-quality.md?ask=<question>&goal=<user_goal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is what the user is ultimately trying to achieve, the reason they need the answer. Sharing it helps GitBook give you a better, more relevant answer. A goal is most helpful when it describes the outcome the user wants rather than restating the question. For example, with `ask=how do I create an API token`, a goal like `automate deployments from our CI pipeline` lets GitBook tailor the answer to that use case.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
