Qodana 2026.2 Help

Configuration reference

Introduction

You can configure Qodana using YAML or CLI options.

Configuring Qodana via a YAML-formatted file typically named qodana.yaml and contained in the root directory of your project is suitable for settings that require lengthy commands. For example, inspection configuration, bootstrap, other settings that are not convenient to configure otherwise. Once a YAML configuration is saved, you can reuse it across different instances of Qodana.

CLI options are suitable for immediate configuration of applications that run Qodana like the Docker engine, Qodana CLI, IDEs, and CI/CD tools. Besides that, some CLI options do not have any YAML equivalents.

Settings like linter or quality gates can be set up using both YAML and CLI methods. In such cases, CLI options take precedence over their YAML equivalents if both methods are used.

YAML configuration

By default, this configuration capability will be referred to as the qodana.yaml configuration. To start, in the root directory of your project save the qodana.yaml file.

To override the qodana.yaml filename and its location, follow the recommendations of the Override YAML configuration file chapter.

The JSON schema for qodana.yaml is published in the SchemaStore project, which provides completion and basic validation in IDEs.

CLI options

You can configure Qodana using three types of CLI options as shown below.

Option type

Example

Requires the equal sign (=) between the option name and its argument

--property=idea.log.config.file=info.xml

Requires the space character ( ) between the option name and its argument

--baseline /path/to/sarif/file

Requires no argument

--apply-fixes

Here are the examples that invoke all these option types:

docker run \ -v $(pwd):/data/project/ \ -e QODANA_TOKEN="<cloud-project-token>" \ <image-name> \ --property=idea.log.config.file=info.xml \ --baseline <baseline-path> \ --apply-fixes
qodana scan \ -e QODANA_TOKEN="<cloud-project-token>" \ --property=idea.log.config.file=info.xml \ --baseline <baseline-path> \ --apply-fixes
name: Qodana on: workflow_dispatch: pull_request: push: branches: # Specify your branches here - main # The 'main' branch - master # The 'master' branch - 'releases/*' # The release branches jobs: qodana: runs-on: ubuntu-latest permissions: contents: write pull-requests: write checks: write steps: - uses: actions/checkout@v3 with: ref: ${{ github.event.pull_request.head.sha }} # to check out the actual pull request commit, not the merge commit fetch-depth: 0 # a full history is required for pull request analysis - name: 'Qodana Scan' uses: JetBrains/qodana-action@v2026.1 with: args: | --property=idea.log.config.file=info.xml --baseline <baseline-path> --apply-fixes env: QODANA_TOKEN: ${{ secrets.QODANA_TOKEN }}
pipeline { environment { QODANA_TOKEN=credentials('qodana-token') } agent { docker { args ''' -v "${WORKSPACE}":/data/project --entrypoint="" ''' image 'jetbrains/qodana-<image>' } } stages { stage('Qodana') { steps { sh ''' qodana \ --property=idea.log.config.file=info.xml \ --baseline <baseline-path> \ --apply-fixes ''' } } } }
include: - component: $CI_SERVER_FQDN/qodana/qodana/qodana-gitlab-ci@v2026.1 inputs: args: | --property=idea.log.config.file=info.xml --baseline <baseline-path> --apply-fixes --image <image>

In the runner configuration, find the Additional Qodana arguments field and specify the path to the plugin file:

--property=idea.log.config.file=info.xml --baseline <baseline-path> --apply-fixes

Run custom commands

During analyses, Qodana linters may report that some inspections cannot find classes, packages, files or cannot resolve references, although linters related to JVM, .NET, and Golang try to figure out the build system and project structure automatically. In these cases, Qodana needs a bit of help:

  • Install third-party packages or libraries

  • Run a program that sets up the build environment

These actions are carried out using the bootstrap key:

version: "1.0" linter: <linter> bootstrap: |+ set -eu # For PHP projects that use Laravel: #composer require --dev barryvdh/laravel-ide-helper # For JavaScript projects that use Node.js: #npm install # For Python projects #pip install -r requirements.txt

To be able to use syntax highlighting and validation in your IDE, you can create the prepare-qodana.sh shell script and save it in the root directory of your project:

#! /bin/sh set -eu # For PHP projects that use Laravel: #composer require --dev barryvdh/laravel-ide-helper # For JavaScript projects that use Node.js: #npm install

Run the script in a Qodana Docker container using the bootstrap key:

bootstrap: sh ./prepare-qodana.sh

To run Qodana as the root user, you may need to invoke the --user=root option.

In CI/CD environments like GitLab CI/CD, you may need to prepare a complex environment before the analysis starts. Here is an example of a monorepo setup with a frontend folder (Node.js) and a backend folder (C#):

version: "1.0" linter: qodana-dotnet bootstrap: |+ set -eu # Install frontend dependencies echo "Installing frontend dependencies..." cd frontend && npm install && cd .. # Build backend C# projects echo "Building C# projects..." dotnet restore backend/MySolution.sln dotnet build backend/MySolution.sln --no-restore

You can also see the Monorepo projects section.

Specify a linter

Using the linter YAML key, you can specify a linter that you are going to employ. For example:

version: "1.0" linter: qodana-jvm-android

Alternatively, you can use the --linter CLI option as shown below:

docker run \ -v $(pwd):/data/project/ \ -e QODANA_TOKEN="&lt;cloud-project-token&gt;" \ jetbrains/qodana-&lt;image&gt; \ --linter <linter>
qodana scan \ -e QODANA_TOKEN="&lt;cloud-project-token&gt;" \ --linter <linter>
name: Qodana on: workflow_dispatch: pull_request: push: branches: # Specify your branches here - main # The 'main' branch - master # The 'master' branch - 'releases/*' # The release branches jobs: qodana: runs-on: ubuntu-latest permissions: contents: write pull-requests: write checks: write steps: - uses: actions/checkout@v3 with: ref: ${{ github.event.pull_request.head.sha }} # to check out the actual pull request commit, not the merge commit fetch-depth: 0 # a full history is required for pull request analysis - name: 'Qodana Scan' uses: JetBrains/qodana-action@v2026.1 with: args: --linter <linter> env: QODANA_TOKEN: ${{ secrets.QODANA_TOKEN }}
pipeline { environment { QODANA_TOKEN=credentials('qodana-token') } agent { docker { args ''' -v "${WORKSPACE}":/data/project --entrypoint="" ''' image 'jetbrains/qodana-&lt;image&gt;' } } stages { stage('Qodana') { steps { sh ''' qodana \ --linter <linter> ''' } } } }
include: - component: $CI_SERVER_FQDN/qodana/qodana/qodana-gitlab-ci@v2026.1 inputs: args: | --linter <linter>

In the runner configuration, find the Additional Qodana arguments field and specify the script:

--linter <linter>

Configure native mode

The native mode lets you run Qodana without the Docker engine and is available for the following linters:

Linter name

Description

qodana-jvm

Qodana for JVM

qodana-jvm-community

Qodana Community for JVM

qodana-php

Qodana for PHP

qodana-js

Qodana for JS

qodana-dotnet

Qodana for .NET

qodana-go

Qodana for Go

qodana-python

Qodana for Python

qodana-python-community

Qodana Community for Python

You can configure native mode by specifying a linter, as well as set the withinDocker setting to false.

In case of a YAML configuration, this may look as follows:

version: "1.0" linter: <linter-name> withinDocker: false # Setting Docker mode to false

The --linter and --within-docker false CLI options also let you configure the native mode:

qodana scan \ -e QODANA_TOKEN="<cloud-project-token>" \ --linter <linter> \ --within-docker false
name: Qodana on: workflow_dispatch: pull_request: push: branches: # Specify your branches here - main # The 'main' branch - master # The 'master' branch - 'releases/*' # The release branches jobs: qodana: runs-on: ubuntu-latest permissions: contents: write pull-requests: write checks: write steps: - uses: actions/checkout@v3 with: ref: ${{ github.event.pull_request.head.sha }} # to check out the actual pull request commit, not the merge commit fetch-depth: 0 # a full history is required for pull request analysis - name: 'Qodana Scan' uses: JetBrains/qodana-action@v2026.1 with: args: | --linter <linter> --within-docker false env: QODANA_TOKEN: ${{ secrets.QODANA_TOKEN }}

Override YAML configuration file

Your project can have several Qodana configurations contained in YAML-formatted files. This comes in handy if you analyze monorepo projects or run a single CI job.

You can use the --config CLI option and a path to a file relatively to the project root:

docker run \    -v $(pwd):/data/project \    -e QODANA_TOKEN="<cloud-project-token>" \    jetbrains/qodana-<image> \    --config relative/path/to/config.yaml
qodana scan \    -e QODANA_TOKEN="<cloud-project-token>" \    --config relative/path/to/config.yaml
name: Qodana on: workflow_dispatch: pull_request: push: branches: # Specify your branches here - main # The 'main' branch - master # The 'master' branch - 'releases/*' # The release branches jobs: qodana: runs-on: ubuntu-latest permissions: contents: write pull-requests: write checks: write steps: - uses: actions/checkout@v3 with: ref: ${{ github.event.pull_request.head.sha }} # to check out the actual pull request commit, not the merge commit fetch-depth: 0 # a full history is required for pull request analysis - name: 'Qodana Scan' uses: JetBrains/qodana-action@v2026.1 with: args: --config relative/path/to/config.yaml env: QODANA_TOKEN: ${{ secrets.QODANA_TOKEN }}
pipeline { environment { QODANA_TOKEN=credentials('qodana-token') } agent { docker { args ''' -v "${WORKSPACE}":/data/project --entrypoint="" ''' image 'jetbrains/qodana-<image>' } } stages { stage('Qodana') { steps { sh ''' qodana \ --config relative/path/to/config.yaml ''' } } } }
include: - component: $CI_SERVER_FQDN/qodana/qodana/qodana-gitlab-ci@v2026.1 inputs: args: | --config relative/path/to/config.yaml --linter <linter>

In the runner configuration, find the Additional Qodana arguments field and specify the path to your custom configuration file:

--config relative/path/to/config.yaml

Inspection profile

By default, Qodana analyzes your code using the qodana.starter profile. You can switch to another existing profile using the recommendations from the Existing Qodana profiles chapter. To set up your own profile, use available configuration options described in the Custom profiles chapter.

YAML configuration

Using the profile YAML key, you can set up an existing profile, configure your own profile from scratch, or import an existing configuration from a dedicated YAML-formatted file:

You can writer your profile configuration directly in the qodana.yaml file:

version: "1.0" linter: <linter> profile: inspections: — group: "category:Java/Probable bugs" enabled: true — inspection: RedundantIf enabled: true

Use the profile.path key to invoke an existing profile by its name, for example:

version: "1.0" linter: <linter> profile: name: qodana.recommended

After you set up a profile in a dedicated file as described in the Inspection profiles section, you can invoke it in the qodana.yaml file using the profile.path key, for example:

version: "1.0" linter: <linter> profile: path: .qodana/profiles/<custom-profile.yaml>

CLI options

You can use the following profile-related CLI options:

Option

Description

Default setting

--disable-sanity

Skip running the inspections configured by the qodana.sanity profile

Enabled

-n, --profile-name

The profile name from the list of existing Qodana profiles.

Alternatively, you can use a profile name from a custom profile file. To do it, you will need to mount a profile file to Qodana.

qodana.starter

-p, --profile-path

The absolute path to the profile file.

None

--run-promo

Run promo inspections as a part of the qodana.starter profile

Enabled only if Qodana is configured for the qodana.starter profile, and the --run-promo true option is invoked

Below are the configuration snippets containing the -profile-name option for invoking a profile by its name, as well as the --profile-path CLI option for invoking a profile configuration from a dedicated file:

docker run \ -v $(pwd):/data/project/ \ -e QODANA_TOKEN="<cloud-project-token>" \ jetbrains/qodana-<image> \ -v <path-to-profile-file> \ # Mount the file containing custom profile --profile-name qodana.recommended | <profile-name-from-file> \ # Existing profile name | Name from mounted file --profile-path /data/project/myprofiles/<file-name> # Importing profile file
qodana scan \ -e QODANA_TOKEN="<cloud-project-token>" \ -v <path-to-profile-file> \ # Mount the file containing custom profile --profile-name qodana.recommended | <profile-name-from-file> \ # Existing profile name | Name from mounted file --profile-path /data/project/myprofiles/<file-name> # Importing profile file
name: Qodana on: workflow_dispatch: pull_request: push: branches: # Specify your branches here - main # The 'main' branch - master # The 'master' branch - 'releases/*' # The release branches jobs: qodana: runs-on: ubuntu-latest permissions: contents: write pull-requests: write checks: write steps: - uses: actions/checkout@v3 with: ref: ${{ github.event.pull_request.head.sha }} # to check out the actual pull request commit, not the merge commit fetch-depth: 0 # a full history is required for pull request analysis - name: 'Qodana Scan' uses: JetBrains/qodana-action@v2026.1 with: args: | -v <path-to-profile-file> # Mount the file containing custom profile --profile-name qodana.recommended | <profile-name-from-file> # Existing profile name | Name from mounted file --profile-path /data/project/myprofiles/<file-name> # Importing profile file env: QODANA_TOKEN: ${{ secrets.QODANA_TOKEN }}
pipeline { environment { QODANA_TOKEN=credentials('qodana-token') } agent { docker { args ''' -v "${WORKSPACE}":/data/project -v <path-to-profile-file> // Mount the file containing custom profile --entrypoint="" ''' image 'jetbrains/qodana-<image> } } stages { stage('Qodana') { steps { sh ''' qodana \ --profile-name qodana.recommended | <profile-name-from-file> // Existing profile name | Name from mounted file --profile-path /data/project/myprofiles/<file-name> // Importing profile file ''' } } } }
include: - component: $CI_SERVER_FQDN/qodana/qodana/qodana-gitlab-ci@v2026.1 inputs: args: | --linter <linter> -v <path-to-profile-file> \ # Mount the file containing custom profile --profile-name qodana.recommended | <profile-name-from-file> \ # Existing profile name | Name from mounted file --profile-path /data/project/myprofiles/<file-name> # Importing profile file

Configure the runner as described in the Basic configuration chapter.

Disable unexpected problems

By default, unexpected problems are enabled in Qodana. You can disable them using this snippet:

version: "1.0" linter: <linter> disableSanityInspections: true

Inspections

Including inspections

You can tell Qodana to analyze files of a certain directory using an inspection that is not contained in the selected profile. This can be done on a per-analysis basis. To include all paths in a project into the inspection scope, omit the paths node. Information about inspection IDs is available on the Inspectopedia website.

In this YAML configuration example, the empty profile, which contains no inspections, is specified, and the SomeInspectionId inspection is explicitly included in the analysis scope for the tools directory. As a result, only the analysis performed by the SomeInspectionId inspection the tools directory contents will be included in the Qodana analysis scope.

version: "1.0" linter: <linter> profile: name: empty include: - name: SomeInspectionId paths: - tools

Here, each include entry should reference an inspection registered in an active inspection profile, either enabled or disabled. If an inspection ID is not registered, the ìnclude entry becomes silently ignored and no inspection is added.

For example, the profile.name: empty configuration implies that plugin-provided inspections like CppClangTidy* are not registered. To enable specific plugin inspections, you can start from an existing inspection profile like qodana.starterand use exclude to suppress inspections that you do not need. Also, add inspections using plugin-specific config like .clang-tidy in case of the C / C++ linter.

Excluding inspections

To disable inspections for a specific file, use the following YAML configuration:

version "1.0" linter: <linter> exclude: - name: <inspection-name> paths: - <path/to/the/file/from/project/root>

You can also suppress the inspection only for a class by adding the noinspection comment above the class:

// noinspection <inspection-name> export class WorkflowJobSubject { private static subject: Observable<GithubEvent<WorkflowJobEvent>> | null = null; private static GithubWebhookEventSubject: any;

Linter paths

This table lists the paths available in Qodana linters.

Path

Description

/data/project

Root directory of the project

/data/results

Directory to store analysis reports. It should be empty before running Qodana

/opt/idea

IDE distributive directory

/root/.config/idea

IDE configuration directory

/data/profile.xml

The default profile file containing the qodana.starter profile configuration. This file is used if a profile was not previously configured either via the CLI or the qodana.yaml file. See Order of resolving a profile for details

/data/project/.idea/inspectionProfiles/

Directory for binding profile files

/data/cache/.m2

Maven project dependencies

/root/.m2/

Directory for overriding the settings.xml configuration file for Maven

/data/cache/gradle

Gradle project dependencies

/data/cache/nuget

NuGet project dependencies

/data/coverage

Directory for mapping code coverage files

You can find below several examples of how these paths can be applied.

Configure Maven

In Maven, you can configure the source and target versions of the Java compiler. Qodana compares these values and selects the latest version. This version of the JDK is then searched in the list of available versions. If found, Qodana will download and use it. Otherwise, Qodana will download the subsequent version from this list.

You can specify the path to a custom Maven settings file, which lets you use custom repositories, mirrors, credentials, and local repository settings:

version: "1.0" linter: <linter> mavenSettingsPath: /path/to/settings.xml
qodana scan \ -e QODANA_TOKEN="&lt;cloud-project-token&gt;" \ --maven-settings-path /path/to/settings.xml

This setting lets Qodana parse the path, resolve relative paths against the project root, expose it in the YAML schema, and apply the configured settings.xml file prior to Maven project import or reimport. It also ensures the correct workflow order: Maven reimport (if requested) runs only after Maven settings are configured, which then updates module dependencies.

Override Gradle settings

For JVM linters, you can override the default Gradle settings:

docker run \ -v $(pwd):/data/project/ \ -v $(pwd)/gradle.properties:/data/cache/gradle/gradle.properties \ -e QODANA_TOKEN="<cloud-project-token>" \ jetbrains/qodana-<image>
qodana scan \ -v $(pwd)/gradle.properties:/data/cache/gradle/gradle.properties \ -e QODANA_TOKEN="<cloud-project-token>"
name: Qodana on: workflow_dispatch: pull_request: push: branches: # Specify your branches here - main # The 'main' branch - master # The 'master' branch - 'releases/*' # The release branches jobs: qodana: runs-on: ubuntu-latest permissions: contents: write pull-requests: write checks: write steps: - uses: actions/checkout@v3 with: ref: ${{ github.event.pull_request.head.sha }} # to check out the actual pull request commit, not the merge commit fetch-depth: 0 # a full history is required for pull request analysis - name: 'Qodana Scan' uses: JetBrains/qodana-action@v2026.1 with: args: -v gradle.properties:/data/cache/gradle/gradle.properties env: QODANA_TOKEN: ${{ secrets.QODANA_TOKEN }}
pipeline { environment { QODANA_TOKEN=credentials('qodana-token') } agent { docker { args ''' -v "${WORKSPACE}":/data/project -v "${WORKSPACE}"/gradle.properties:/data/cache/gradle/gradle.properties --entrypoint="" ''' image 'jetbrains/qodana-<image>' } } stages { stage('Qodana') { steps { sh '''qodana''' } } } }
include: - component: $CI_SERVER_FQDN/qodana/qodana/qodana-gitlab-ci@v2026.1 inputs: args: | -v gradle.properties:/data/cache/gradle/gradle.properties --linter <linter>

In the runner configuration, find the Additional Docker arguments field and specify the path to the file containing new Gradle settings:

-v gradle.properties:/data/cache/gradle/gradle.properties

Mount JDK

You can mount JDK from your local filesystem to the /root/.jdks folder of the Qodana Docker image:

$ docker run \ -v /path/to/jdk:/root/.jdks/jdk \ jetbrains/qodana-<linter>

View Qodana logs

Depending on the tool, you can view log files generated by Qodana:

You can mount the $(pwd)/.qodana/results/ directory to the /data/results directory of the Docker image:

docker run \ -v $(pwd):/data/project/ \ -v $(pwd)/.qodana/results/:/data/results \ -e QODANA_TOKEN="<cloud-project-token>" \ jetbrains/qodana-<image>

Once the Qodana run is complete, you can view log files in the $(pwd)/.qodana/results/ directory.

After running Qodana, in the project root run the $ qodana show -d command for opening the directory containing log files.

There are several options for examining Qodana behavior using the /data/results directory:

  • The /data/results/projectStructure directory.

    The Modules.json file in this directory contains a list of all modules detected by Qodana. It should be identical to the list that you expect to see while opening your project in IntelliJ IDEA. If this is no longer the case, check pom.xml for Maven or the build.gradle file for Gradle configurations.

    The SDKs.json file in this directory contains the interpreter paths in case of Python.

  • In the /data/results/ directory, each inspection that detected a possible problem creates its own file named ID.json, where ID is the inspection name that can be used in qodana.yaml for including or excluding inspections. You can find the complete list of inspection IDs in the /data/results/.descriptions.json file using the /groups/*/inspections/*/shortName pattern.

  • In /data/results/log/idea.log, you can investigate suspicious warnings.

Analysis directories

Using these options, you can override the paths described in the Linter paths section.

Option

Default setting

--repository-root <string>

Specify the VCS root directory for your project. This option is required for Git-related operations

None

-i, --project-dir

Root directory of the inspected project can be either a subdirectory of --repository-root or identical to it.

Files and directories contained in the outside directory are not used while running Qodana

/data/project

-o, --results-dir

Directory to save Qodana inspection results to

/data/results

-r, --report-dir

Directory for saving the generated HTML report. To open the report, you will need to add the --save-report option

/data/results/report

--cache-dir

Directory to store cache

/data/cache

-d, --source-directory

Directory inside --project-dir. If missing, the whole project is inspected.

Files and directories contained in the outside directory like .git and build.gradle are used by Qodana while inspecting code

None

--only-directory <string>

Specify the directory inside the project-dir directory that must be analyzed. If not specified, the whole project will be analyzed

Files and directories contained in the outside directory like .git and build.gradle are used by Qodana while inspecting code

None

Override the report directory

This Docker command overrides the default report directory using the --report-dir option, and saves the generated report to the local filesystem using the --save-report option:

docker run \ -v $(pwd):/data/project/ \ -v <html-report-directory>:/data/results/newreportdir/ \ -e QODANA_TOKEN="<cloud-project-token>" \ jetbrains/qodana-<image> \ --report-dir /data/results/newreportdir/ \ --save-report

The generated report is saved to the local filesystem as configured by the -v <html-report-directory>:/data/results/newreportdir/ line in this command.

Analyze a specific project directory within a repository

A typical project structure can have a directory structure similar to this:

repo/ .git/ project/ ...

Here, the repo/.git directory contains information that should be accessible to Qodana, and the repo/project directory contains the project that needs to be inspected by Qodana. All these samples mount the repo/project directory using the --project-dir option, while the QODANA_TOKEN variable refers to the Qodana Cloud project token:

docker run \ -v repo/:/data/project/ \ -e QODANA_TOKEN="<cloud-project-token>" \ jetbrains/qodana-<image> \ --project-dir=/data/project/project/
qodana scan \ -e QODANA_TOKEN="<cloud-project-token>" \ --project-dir=/data/project/project/
name: Qodana on: workflow_dispatch: pull_request: push: branches: - main - 'releases/*' jobs: qodana: runs-on: ubuntu-latest permissions: contents: write pull-requests: write checks: write steps: - uses: actions/checkout@v3 with: ref: ${{ github.event.pull_request.head.sha }} # to check out the actual pull request commit, not the merge commit fetch-depth: 0 # a full history is required for pull request analysis - name: 'Qodana Scan' uses: JetBrains/qodana-action@v2026.1 with: args: --project-dir project env: QODANA_TOKEN: ${{ secrets.QODANA_TOKEN }}

Exclude paths from the analysis scope

You can exclude files and paths from analyses on a per-analysis basis and for all inspections at once. Information about inspection IDs is available on the Inspectopedia website.

To exclude all paths in a project from the analysis scope, omit the paths node.

Exclude all inspections for specified project paths using the following YAML configuration:

version: "1.0" linter: <linter> exclude: - name: All paths: - asm-test/src/main/java/org - asm/Visitor.java - benchmarks

Exclude inspections specified by ID for specified project paths:

version: "1.0" linter: <linter> exclude: - name: Annotator - name: AnotherInspectionId paths: - relative/path - another/relative/path - name: All paths: - asm-test/src/main/java/org - asm - benchmarks - tools

You can find specific inspection IDs in the Profile settings in the HTML report or in the .xml file with your inspection profile.

Specify directory in your project

Use the onlyDirectory option to specify a directory inside your project that has to be analyzed. This has to be specified relatively to the project root, for example:

version: "1.0" linter: <linter> onlyDirectory: project-a

This is useful while analyzing monorepo projects.

Cache dependencies

You can improve Qodana performance by persisting cache between analyses. For example, package and dependency management tools such as Maven, Gradle, npm, Yarn, and NuGet keep a local cache of downloaded dependencies.

By default, Qodana save caches to the /data/cache directory inside a container. You can override this location using the --cache-dir option. This data is per-repository, so you can pass cache from branch-a to build checking branch-b. In this case, only new dependencies would be downloaded if they were added.

In a GitHub workflow, you can use dependency caching. GitLab CI/CD also has the cache that can be stored only inside the project directory. In this case, you can exclude the cache directory from inspection via qodana.yaml.

This command maps the local directory with the /data/cache directory of the Docker image, which saves cache to your local filesystem:

docker run \ -v $(pwd):/data/project/ \ -v <local-cache-directory>:/data/cache/ \ -e QODANA_TOKEN="<cloud-project-token>" \ jetbrains/qodana-<image>

Using the --cache-dir option, you can override the cache directory:

docker run \ -v $(pwd):/data/project/ \ -v <local-cache-directory>:/data/newcachedir/ \ -e QODANA_TOKEN="<cloud-project-token>" \ jetbrains/qodana-<image> \ --cache-dir /data/newcachedir
qodana scan \ -e QODANA_TOKEN="<cloud-project-token>" \ --cache-dir /opt/newcachedir
name: Qodana on: workflow_dispatch: pull_request: push: branches: # Specify your branches here - main # The 'main' branch - master # The 'master' branch - 'releases/*' # The release branches jobs: qodana: runs-on: ubuntu-latest permissions: contents: write pull-requests: write checks: write steps: - uses: actions/checkout@v3 with: ref: ${{ github.event.pull_request.head.sha }} # to check out the actual pull request commit, not the merge commit fetch-depth: 0 # a full history is required for pull request analysis - name: 'Qodana Scan' uses: JetBrains/qodana-action@v2026.1 with: args: --cache-dir /data/newcachedir env: QODANA_TOKEN: ${{ secrets.QODANA_TOKEN }}
pipeline { environment { QODANA_TOKEN=credentials('qodana-token') } agent { docker { args ''' -v "${WORKSPACE}":/data/project --entrypoint="" ''' image 'jetbrains/qodana-<image>' } } stages { stage('Qodana') { steps { sh ''' qodana \ --cache-dir /data/newcachedir ''' } } } }
include: - component: $CI_SERVER_FQDN/qodana/qodana/qodana-gitlab-ci@v2026.1 inputs: args: | --cache-dir /data/newcachedir --linter <linter>

In the runner configuration, find the Additional Qodana arguments field and specify the path to the cache directory:

--cache-dir /data/newcachedir

Analysis reports

Qodana provides the following CLI options for managing reports:

Option

Description

-s, --save-report

Generate and save HTML-formatted reports

-w, --show-report

Serve HTML-formatted reports. By default, port 8080 is used

The --save-report option in the Docker command lets you save the generated HTML report to your local filesystem:

docker run \ -v $(pwd):/data/project/ \ -v <directory-to-save-report-to>:/data/results/report \ -e QODANA_TOKEN="<cloud-project-token>" \ jetbrains/qodana-<image> \ --save-report

This command runs the web server on port 4040 of a host machine, so your report will be available on http://localhost:4040:

docker run \ -p 4040:8080 \ -v $(pwd):/data/project/ \ -e QODANA_TOKEN="<cloud-project-token>" \ jetbrains/qodana-<image> \ --show-report
qodana scan \ -e QODANA_TOKEN="<cloud-project-token>" \ --port 4040 \ --show-report

Alternatively, in the project root you can run the qodana show command.

To stop the web server, press Ctrl-C in the Docker console.

Qodana features

Quality gates

You have several options to configure quality gates.

In your YAML configuration, you can add a fail threshold to control the total number of problems in a project, which is supported by all linters:

version: "1.0" linter: <linter> failThreshold: <number>

All linters except Qodana Community for .NET and Qodana Community for C/C++ let you use the following configuration:

version: "1.0" linter: <linter> failureConditions: severityThresholds: any: <number> # Total problems critical: <number> # Critical and other severities high: <number> moderate: <number> low: <number> info: <number> testCoverageThresholds: fresh: <number> # Fresh code coverage total: <number> # Total code coverage dependencyLicenses: failOnProhibited: <true|false> # Prohibited licenses failOnUnknown: <true|false> # Unknown licenses

In this configuration, exceeding just one setting limitation will make the build fail.

The severityThresholds:any key lets you configure the total number of problems. The severityThresholds:critical key lets you configure quality gates for each problem severity. The testCoverageThresholds:fresh and testCoverageThresholds:total keys let you configure the total and fresh code coverage supported by several linters. The dependencyLicenses key lets you configure quality gates for prohibited or unknown licenses.

Also, you can configure quality gates for the total number of problems using the --fail-threshold CLI option. Here is the command that tells Qodana to fail the build in case the number of problems exceeds 10:

docker run \ -v $(pwd):/data/project/ \ -e QODANA_TOKEN="<cloud-project-token>" \ jetbrains/qodana-<image> \ --fail-threshold 10
qodana scan \ -e QODANA_TOKEN="<cloud-project-token>" \ --fail-threshold 10
name: Qodana on: workflow_dispatch: pull_request: push: branches: # Specify your branches here - main # The 'main' branch - master # The 'master' branch - 'releases/*' # The release branches jobs: qodana: runs-on: ubuntu-latest permissions: contents: write pull-requests: write checks: write steps: - uses: actions/checkout@v3 with: ref: ${{ github.event.pull_request.head.sha }} # to check out the actual pull request commit, not the merge commit fetch-depth: 0 # a full history is required for pull request analysis - name: 'Qodana Scan' uses: JetBrains/qodana-action@v2026.1 with: args: --fail-threshold 10 env: QODANA_TOKEN: ${{ secrets.QODANA_TOKEN }}
pipeline { environment { QODANA_TOKEN=credentials('qodana-token') } agent { docker { args ''' -v "${WORKSPACE}":/data/project --entrypoint="" ''' image 'jetbrains/qodana-<image>' } } stages { stage('Qodana') { steps { sh ''' qodana \ --fail-threshold 10 ''' } } } }
include: - component: $CI_SERVER_FQDN/qodana/qodana/qodana-gitlab-ci@v2026.1 inputs: args: | --fail-threshold 10 --linter <linter>

In the runner configuration, find the Additional Qodana arguments field and specify a quality gate:

--fail-threshold 10

If you run Qodana with the baseline mode enabled, a threshold is calculated as the sum of new and absent problems. The unchanged results are ignored.

Baseline

In the baseline run mode, each new Qodana run is compared to some initial run. This can help in situations when you have no possibility to fix old problems and rather want to prevent the appearance of new ones.

To use the baseline feature, first run Qodana, and in the report UI select the problems that will be considered as baseline. Finally, save the SARIF-formatted file containing the baseline problems.

This is the list of baseline-related options:

Option

Description

-b, --baseline

Run Qodana in the baseline mode. Provide the path to an existing SARIF report to be used in the baseline state calculation

--baseline-include-absent

Include in the output report the results from the baseline run that are absent during the current analysis

This command invokes all baseline options:

docker run \ -v $(pwd):/data/project/ \ -e QODANA_TOKEN="<cloud-project-token>" \ jetbrains/qodana-<image> \ --baseline <path-to-the-SARIF-file> \ --baseline-include-absent
qodana scan \ -e QODANA_TOKEN="<cloud-project-token>" \ --baseline <path-to-the-SARIF-file> \ --baseline-include-absent
name: Qodana on: workflow_dispatch: pull_request: push: branches: # Specify your branches here - main # The 'main' branch - master # The 'master' branch - 'releases/*' # The release branches jobs: qodana: runs-on: ubuntu-latest permissions: contents: write pull-requests: write checks: write steps: - uses: actions/checkout@v3 with: ref: ${{ github.event.pull_request.head.sha }} # to check out the actual pull request commit, not the merge commit fetch-depth: 0 # a full history is required for pull request analysis - name: 'Qodana Scan' uses: JetBrains/qodana-action@v2026.1 with: args: | --baseline <path-to-the-SARIF-file> --baseline-include-absent env: QODANA_TOKEN: ${{ secrets.QODANA_TOKEN }}
pipeline { environment { QODANA_TOKEN=credentials('qodana-token') } agent { docker { args ''' -v "${WORKSPACE}":/data/project --entrypoint="" ''' image 'jetbrains/qodana-<image>' } } stages { stage('Qodana') { steps { sh ''' qodana \ --baseline <path-to-the-SARIF-file> \ --baseline-include-absent ''' } } } }
include: - component: $CI_SERVER_FQDN/qodana/qodana/qodana-gitlab-ci@v2026.1 inputs: args: | --baseline <path-to-the-SARIF-file> --baseline-include-absent --linter <linter>

In the runner configuration, find the Additional Qodana arguments field and configure a baseline:

--baseline <path-to-the-SARIF-file> --baseline-include-absent --linter <linter>

Here, the <path-to-the-SARIF-file> is the path to a qodana.sarif.json file relative to the project root and taken from a previous Qodana run. If --baseline-include-absent is invoked, the inspection results will include absent problems or the problems detected only in the baseline run but not in the current run.

Based on this run, the SARIF output report will contain the per-problem information on the baseline state.

License audit

The license audit feature is enabled by default. You can disable it by excluding the CheckDependencyLicenses inspection:

version: "1.0" linter: <linter> exclude: - name: CheckDependencyLicenses

Ignore a dependency

Ignore a dependency to hide the related problems from the report:

version: "1.0" linter: <linter> dependencyIgnores: - name: "enry"

where name is the dependency name to ignore.

In the example above, the enry dependency is completely excluded from the analysis. Because any possible license-related problems are dismissed, the dependency won't be included in the report at all. This is useful to quickly hide internal dependencies that do not need to be mentioned in the report.

Allow or prohibit a license

Override the predefined license compatibility matrix:

version: "1.0" linter: <linter> licenseRules: - keys: - "PROPRIETARY-LICENSE" - "MIT" prohibited: - "BSD-3-CLAUSE-NO-CHANGE" allowed: - "ISC" - keys: [ "Apache-2.0" ] prohibited: - "MIT"

In this configuration, keys is the project license(s) and the dependency licenses identifiers are specified in allowed or prohibited.

Override a dependency license

Override a dependency license identifier:

version: "1.0" linter: <linter> dependencyOverrides: - name: "jaxb-runtime" version: "2.3.1" url: "https://github.com/javaee/jaxb-v2" licenses: - key: "CDDL-1.1" url: "https://github.com/javaee/jaxb-v2/blob/master/LICENSE" - key: "GPL-2.0-with-classpath-exception" url: "https://github.com/javaee/jaxb-v2/blob/master/LICENSE"

where name is the dependency name, version is the dependency version, and licenses is the list of redefined dependency licenses.

In the example above, you 'tell' Qodana to detect CDDL-1.1, GPL-2.0-with-classpath-exception, and no other licenses for jaxb-runtime (only 2.3.1). This is useful when a dependency is dual-licensed, and you want to omit some license or when it's not possible to detect the license from the dependency sources correctly.

Custom dependencies

Currently, the license audit with Qodana is possible only for JPS, Maven, Gradle, npm, yarn, and composer projects. To include the dependency that should be mentioned in the report but is impossible to detect from the project sources, use customDependencies to specify it:

version: "1.0" linter: <linter> customDependencies: - name: ".babelrc JSON Schema (.babelrc-schema.json)" version: "JSON schema for Babel 6+ configuration files" licenses: - key: "Apache-2.0" url: "https://github.com/SchemaStore/schemastore/blob/master/LICENSE"

Quick-Fixes

This table describes the available Quick-Fix strategies:

CLI option / YAML key

Description

--apply-fixes / apply

Apply all available Quick-Fix strategies including cleanup, see the Quick-Fix section for details

--cleanup / cleanup

Run the CLEANUP Quick-Fix strategy, see the Quick-Fix for details

Using the fixesStrategy YAML key, you can choose among the available strategies:

version: "1.0" linter: <linter> fixesStrategy: cleanup/apply

Alternatively, you can employ the --apply-fixes or --cleanup command-line options:

docker run \ -v $(pwd):/data/project/ \ -e QODANA_TOKEN="<cloud-project-token>" \ jetbrains/qodana-<image> \ --apply-fixes/cleanup
qodana scan \ -e QODANA_TOKEN="<cloud-project-token>" \ --apply-fixes/cleanup
name: Qodana on: workflow_dispatch: pull_request: push: branches: # Specify your branches here - main # The 'main' branch - master # The 'master' branch - 'releases/*' # The release branches jobs: qodana: runs-on: ubuntu-latest permissions: contents: write pull-requests: write checks: write steps: - uses: actions/checkout@v3 with: ref: ${{ github.event.pull_request.head.sha }} # to check out the actual pull request commit, not the merge commit fetch-depth: 0 # a full history is required for pull request analysis - name: 'Qodana Scan' uses: JetBrains/qodana-action@v2026.1 with: args: --apply-fixes/cleanup env: QODANA_TOKEN: ${{ secrets.QODANA_TOKEN }}
pipeline { environment { QODANA_TOKEN=credentials('qodana-token') } agent { docker { args ''' -v "${WORKSPACE}":/data/project --entrypoint="" ''' image 'jetbrains/qodana-<image>' } } stages { stage('Qodana') { steps { sh ''' qodana \ --apply-fixes/cleanup ''' } } } }
include: - component: $CI_SERVER_FQDN/qodana/qodana/qodana-gitlab-ci@v2026.1 inputs: args: | --apply-fixes/cleanup --linter <linter>

In the runner configuration, find the Additional Qodana arguments field and specify the option:

--apply-fixes

Taint analysis

In the qodana.yaml file, include the PhpVulnerablePathsInspection inspection into the analysis scope:

version "1.0" linter: qodana-php include: - name: PhpVulnerablePathsInspection

In the qodana.yaml file, include the JvmTaintAnalysis inspection into the analysis scope:

version "1.0" linter: qodana-jvm include: - name: JvmTaintAnalysis

Vulnerability checker

To start using the Vulnerability checker feature, enable the VulnerableLibrariesGlobal inspection:

version "1.0" linter: <linter> include: - name: VulnerableLibrariesLocal

Code coverage

By default, code coverage is enabled in Qodana.

Using the coverage.reportProblems key, you can configure it in a YAML file. The codeCoverageLocations key lets you override the default code coverage directories, for example:

version: "1.0" linter: <linter> coverage: reportProblems: true # Code coverage is enabled codeCoverageLocations: # Directories containing coverage reports - "custom-directory-1" - "custom-directory-2"

You can run the code coverage by mapping the directory containing code coverage files to the /data/coverage directory of a Qodana linter image:

docker run \ -v /my/dir/with/coverage:/data/coverage \ -e QODANA_TOKEN="<cloud-project-token>" \ jetbrains/qodana-<image>
qodana scan \ -v /my/dir/with/coverage:/data/coverage \ -e QODANA_TOKEN="<cloud-project-token>"
name: Qodana on: workflow_dispatch: pull_request: push: branches: # Specify your branches here - main # The 'main' branch - master # The 'master' branch - 'releases/*' # The release branches jobs: qodana: runs-on: ubuntu-latest permissions: contents: write pull-requests: write checks: write steps: - uses: actions/checkout@v3 with: ref: ${{ github.event.pull_request.head.sha }} # to check out the actual pull request commit, not the merge commit fetch-depth: 0 # a full history is required for pull request analysis - name: 'Qodana Scan' uses: JetBrains/qodana-action@v2026.1 with: args: -v /my/dir/with/coverage:/data/coverage env: QODANA_TOKEN: ${{ secrets.QODANA_TOKEN }}
pipeline { environment { QODANA_TOKEN=credentials('qodana-token') } agent { docker { args ''' -v "${WORKSPACE}":/data/project --entrypoint="" ''' image 'jetbrains/qodana-<image>' } } stages { stage('Qodana') { steps { sh ''' qodana \ -v /my/dir/with/coverage:/data/coverage ''' } } } }
include: - component: $CI_SERVER_FQDN/qodana/qodana/qodana-gitlab-ci@v2026.1 inputs: args: | -v /my/dir/with/coverage:/data/coverage --linter <linter>

In the runner configuration, find the Additional Docker arguments field and specify the path the file containing code coverage results:

-v /my/dir/with/coverage:/data/coverage

Override the run scenario

You can use the following run scenarios:

Scenario name

Description

default

The default Qodana scenario, enabled by default

php-migration

PHP version migration scenario

local-changes

Analyze only uncommitted changes. You can see the Incremental analysis section to learn more about incremental analysis

Using the script of a YAML configuration, you can specify a run scenario:

version: "1.0" linter: <linter> script: name: <script-name> parameters: <parameter>: <value>

By default, Qodana employs the default scenario, which means the normal Qodana run equivalent to this setting:

version: "1.0" linter: <linter> script: name: default

You can also use the --script CLI option to configure a run scenario:

docker run \ -v $(pwd):/data/project/ \ -e QODANA_TOKEN="<cloud-project-token>" \ jetbrains/qodana-<image> \ --script default
qodana scan \ -e QODANA_TOKEN="<cloud-project-token>" \ --script default
name: Qodana on: workflow_dispatch: pull_request: push: branches: # Specify your branches here - main # The 'main' branch - master # The 'master' branch - 'releases/*' # The release branches   jobs: qodana: runs-on: ubuntu-latest permissions: contents: write pull-requests: write checks: write steps: - uses: actions/checkout@v3 with: ref: ${{ github.event.pull_request.head.sha }} # to check out the actual pull request commit, not the merge commit fetch-depth: 0 # a full history is required for pull request analysis - name: 'Qodana Scan' uses: JetBrains/qodana-action@v2026.1 with: args: --script default env: QODANA_TOKEN: ${{ secrets.QODANA_TOKEN }}
pipeline { environment { QODANA_TOKEN=credentials('qodana-token') } agent { docker { args ''' -v "${WORKSPACE}":/data/project --entrypoint="" ''' image 'jetbrains/qodana-<image>' } } stages { stage('Qodana') { steps { sh ''' qodana \ --script default ''' } } } }
include: - component: $CI_SERVER_FQDN/qodana/qodana/qodana-gitlab-ci@v2026.1 inputs: args: | --script default --linter <linter>

In the runner configuration, find the Additional Qodana arguments field and specify the script:

--script default

JDK version

You can configure the JDK version for these linters:

Use the projectJDK key to specify the JDK version, for example:

version: "1.0" linter: <linter> projectJDK: 11

or:

version: "1.0" linter: <linter> projectJDK: 1.8

You can also specify JDK using the name:

version: "1.0" linter: <linter> projectJDK: corretto-19

To learn more about configuring JDK, see the Configuring the JDK section.

PHP version

You can configure the PHP version before running the Qodana for PHP linter:

version: "1.0" linter: qodana-php php: version: "X.x"

Properties

Using the --property= option, you can override various Qodana parameters:

Option

Description

--property=

Set a JVM property using this notation:

--property=property.name=value1,...,valueN

This option can be repeated multiple times for setting multiple JVM properties.

Log INFO messages to STDOUT

The default log level for STDOUT is WARN. You can override it using the idea.log.config.file property.

docker run \ -v $(pwd):/data/project/ \ -e QODANA_TOKEN="<cloud-project-token>" \ jetbrains/qodana-<image> \ --property=idea.log.config.file=info.xml
qodana scan \ -e QODANA_TOKEN="<cloud-project-token>" \ --property=idea.log.config.file=info.xml
name: Qodana on: workflow_dispatch: pull_request: push: branches: # Specify your branches here - main # The 'main' branch - master # The 'master' branch - 'releases/*' # The release branches jobs: qodana: runs-on: ubuntu-latest permissions: contents: write pull-requests: write checks: write steps: - uses: actions/checkout@v3 with: ref: ${{ github.event.pull_request.head.sha }} # to check out the actual pull request commit, not the merge commit fetch-depth: 0 # a full history is required for pull request analysis - name: 'Qodana Scan' uses: JetBrains/qodana-action@v2026.1 with: args: --property=idea.log.config.file=info.xml env: QODANA_TOKEN: ${{ secrets.QODANA_TOKEN }}
pipeline { environment { QODANA_TOKEN=credentials('qodana-token') } agent { docker { args ''' -v "${WORKSPACE}":/data/project --entrypoint="" ''' image 'jetbrains/qodana-<image>' } } stages { stage('Qodana') { steps { sh ''' qodana \ --property=idea.log.config.file=info.xml ''' } } } }
include: - component: $CI_SERVER_FQDN/qodana/qodana/qodana-gitlab-ci@v2026.1 inputs: args: | --property=idea.log.config.file=info.xml --linter <linter>

In the runner configuration, find the Additional Qodana arguments field and specify the preferred Quick-Fix strategy:

--property=idea.log.config.file=info.xml

Disable user statistics

To disable reporting of usage statistics, adjust the idea.headless.enable.statistics value of the --property option:

docker run \ -v $(pwd):/data/project/ \ -e QODANA_TOKEN="<cloud-project-token>" \ jetbrains/qodana-<image> \ --property=idea.headless.enable.statistics=false
qodana scan \ -e QODANA_TOKEN="<cloud-project-token>" \ --property=idea.headless.enable.statistics=false
name: Qodana on: workflow_dispatch: pull_request: push: branches: # Specify your branches here - main # The 'main' branch - master # The 'master' branch - 'releases/*' # The release branches jobs: qodana: runs-on: ubuntu-latest permissions: contents: write pull-requests: write checks: write steps: - uses: actions/checkout@v3 with: ref: ${{ github.event.pull_request.head.sha }} # to check out the actual pull request commit, not the merge commit fetch-depth: 0 # a full history is required for pull request analysis - name: 'Qodana Scan' uses: JetBrains/qodana-action@v2026.1 with: args: --property idea.headless.enable.statistics=false env: QODANA_TOKEN: ${{ secrets.QODANA_TOKEN }}
pipeline { environment { QODANA_TOKEN=credentials('qodana-token') } agent { docker { args ''' -v "${WORKSPACE}":/data/project --entrypoint="" ''' image 'jetbrains/qodana-<image>' } } stages { stage('Qodana') { steps { sh ''' qodana \ --property=idea.headless.enable.statistics=false ''' } } } }
include: - component: $CI_SERVER_FQDN/qodana/qodana/qodana-gitlab-ci@v2026.1 inputs: args: | --property idea.headless.enable.statistics=false --image <image>

In the runner configuration, find the Additional Qodana arguments field and specify the required property:

--property=idea.headless.enable.statistics=false

Configure plugins

Using the idea.required.plugins.id and idea.suppressed.plugins.id properties, you can specify the plugins required for a specific run, and the list of plugins that will be suppressed:

docker run \ -v $(pwd):/data/project/ \ -e QODANA_TOKEN="<cloud-project-token>" \ jetbrains/qodana-<image> \ --property=idea.required.plugins.id=JavaScript,org.intellij.grails \ --property=idea.suppressed.plugins.id=com.intellij.spring.security
qodana scan \ -e QODANA_TOKEN="<cloud-project-token>" \ --property=idea.required.plugins.id=JavaScript,org.intellij.grails \ --property=idea.suppressed.plugins.id=com.intellij.spring.security
name: Qodana on: workflow_dispatch: pull_request: push: branches: # Specify your branches here - main # The 'main' branch - master # The 'master' branch - 'releases/*' # The release branches jobs: qodana: runs-on: ubuntu-latest permissions: contents: write pull-requests: write checks: write steps: - uses: actions/checkout@v3 with: ref: ${{ github.event.pull_request.head.sha }} # to check out the actual pull request commit, not the merge commit fetch-depth: 0 # a full history is required for pull request analysis - name: 'Qodana Scan' uses: JetBrains/qodana-action@v2026.1 with: args: | --property=idea.required.plugins.id=JavaScript,org.intellij.grails --property=idea.suppressed.plugins.id=com.intellij.spring.security env: QODANA_TOKEN: ${{ secrets.QODANA_TOKEN }}
pipeline { environment { QODANA_TOKEN=credentials('qodana-token') } agent { docker { args ''' -v "${WORKSPACE}":/data/project --entrypoint="" ''' image 'jetbrains/qodana-<image>' } } stages { stage('Qodana') { steps { sh ''' qodana \ --property=idea.required.plugins.id=JavaScript,org.intellij.grails \ --property=idea.suppressed.plugins.id=com.intellij.spring.security ''' } } } }
include: - component: $CI_SERVER_FQDN/qodana/qodana/qodana-gitlab-ci@v2026.1 inputs: args: | --property=idea.required.plugins.id=JavaScript,org.intellij.grails --property=idea.suppressed.plugins.id=com.intellij.spring.security --image <image>

In the runner configuration, find the Additional Qodana arguments field and specify the required properties:

--property=idea.required.plugins.id=JavaScript,org.intellij.grails \ --property=idea.suppressed.plugins.id=com.intellij.spring.security

Setting up configuration timeout

Using the following properties, you can configure the configuration stage timeout:

Property

Available for the linters

qd.cpp.startup.timeout.minutes

Qodana for C/C++ and Qodana Community for C/C++

qd.rust.configuration.timeout.minutes

Qodana for Rust

Here are the examples of property usage:

name: Qodana on: workflow_dispatch: pull_request: push: branches: # Specify your branches here - main # The 'main' branch - 'releases/*' # The release branches jobs: qodana: runs-on: ubuntu-latest permissions: contents: write pull-requests: write checks: write steps: - uses: actions/checkout@v3 with: ref: ${{ github.event.pull_request.head.sha }} # to check out the actual pull request commit, not the merge commit fetch-depth: 0 # a full history is required for pull request analysis - name: 'Qodana Scan' uses: JetBrains/qodana-action@v2026.1 with: args: --property qd.<cpp|rust>.startup.timeout.minutes=10 env: QODANA_TOKEN: ${{ secrets.QODANA_TOKEN }}
qodana scan \    -e QODANA_TOKEN="<cloud-project-token>" \    --linter <linter> \    --property qd.<cpp|rust>.configuration.timeout.minutes=10
docker run \    -v $(pwd):/data/project/ \    -e QODANA_TOKEN="<cloud-project-token>" \    jetbrains/qodana-<image> \    --property qd.<cpp|rust>.configuration.timeout.minutes=10

Analysis of changes

Option

Description

--diff-start and --diff-end

Run incremental analysis on a change set like merge or pull requests

If you just finished work and would like to analyze the changes, you can employ the --diff-start option and specify a hash of the commit that will act as a base for comparison, see the Incremental analysis section for details:

docker run \    -v $(pwd):/data/project/ \    -e QODANA_TOKEN="<cloud-project-token>" \    jetbrains/qodana-<image> \    --diff-start=<GIT_START_HASH>
qodana scan \    -e QODANA_TOKEN="<cloud-project-token>" \    --diff-start=<GIT_START_HASH>
name: Qodana on: workflow_dispatch: pull_request: push: branches: # Specify your branches here - main # The 'main' branch - master # The 'master' branch - 'releases/*' # The release branches jobs: qodana: runs-on: ubuntu-latest permissions: contents: write pull-requests: write checks: write steps: - uses: actions/checkout@v3 with: ref: ${{ github.event.pull_request.head.sha }} # to check out the actual pull request commit, not the merge commit fetch-depth: 0 # a full history is required for pull request analysis - name: 'Qodana Scan' uses: JetBrains/qodana-action@v2026.1 with: args: --diff-start=<GIT_START_HASH> env: QODANA_TOKEN: ${{ secrets.QODANA_TOKEN }}
pipeline { environment { QODANA_TOKEN=credentials('qodana-token') } agent { docker { args ''' -v "${WORKSPACE}":/data/project --entrypoint="" ''' image 'jetbrains/qodana-<image>' } } stages { stage('Qodana') { steps { sh ''' qodana \ --diff-start=<GIT_START_HASH> ''' } } } }
include: - component: $CI_SERVER_FQDN/qodana/qodana/qodana-gitlab-ci@v2026.1 inputs: args: | --diff-start=<GIT_START_HASH> --image <image>

In the runner configuration, find the Additional Qodana arguments field and specify the commit hash:

--diff-start=<GIT_START_HASH>

To analyze a set of changes between two commits, employ both --diff-start and --diff-end options:

docker run \    -v $(pwd):/data/project/ \    -e QODANA_TOKEN="<cloud-project-token>" \    jetbrains/qodana-<image> \    --diff-start=<GIT_START_HASH> \    --diff-end=<GIT_END_HASH>
qodana scan \    -e QODANA_TOKEN="<cloud-project-token>" \    --diff-start=<GIT_START_HASH> \    --diff-end=<GIT_END_HASH>
name: Qodana on: workflow_dispatch: pull_request: push: branches: # Specify your branches here - main # The 'main' branch - master # The 'master' branch - 'releases/*' # The release branches jobs: qodana: runs-on: ubuntu-latest permissions: contents: write pull-requests: write checks: write steps: - uses: actions/checkout@v3 with: ref: ${{ github.event.pull_request.head.sha }} # to check out the actual pull request commit, not the merge commit fetch-depth: 0 # a full history is required for pull request analysis - name: 'Qodana Scan' uses: JetBrains/qodana-action@v2026.1 with: args: | --diff-start=<GIT_START_HASH> --diff-end=<GIT_END_HASH> env: QODANA_TOKEN: ${{ secrets.QODANA_TOKEN }}
pipeline { environment { QODANA_TOKEN=credentials('qodana-token') } agent { docker { args ''' -v "${WORKSPACE}":/data/project --entrypoint="" ''' image 'jetbrains/qodana-<image>' } } stages { stage('Qodana') { steps { sh ''' qodana \ --diff-start=<GIT_START_HASH> \ --diff-end=<GIT_END_HASH> ''' } } } }
include: - component: $CI_SERVER_FQDN/qodana/qodana/qodana-gitlab-ci@v2026.1 inputs: args: | --diff-start=<GIT_START_HASH> --diff-end=<GIT_END_HASH> --image <image>

In the runner configuration, find the Additional Qodana arguments field and specify the commit hashes:

--diff-start=<GIT_START_HASH> --diff-end=<GIT_END_HASH>

Change the Heap size

By default, the Heap size is set to 80% of the host RAM. You can configure this setting using the _JAVA_OPTIONS variable:

docker run \ -v $(pwd):/data/project/ \ -e _JAVA_OPTIONS=-Xmx6g \ -e QODANA_TOKEN="<cloud-project-token>" \ jetbrains/qodana-<image>
qodana scan \ -e _JAVA_OPTIONS=-Xmx6g \ -e QODANA_TOKEN="<cloud-project-token>"
name: Qodana on: workflow_dispatch: pull_request: push: branches: # Specify your branches here - main # The 'main' branch - master # The 'master' branch - 'releases/*' # The release branches jobs: qodana: runs-on: ubuntu-latest permissions: contents: write pull-requests: write checks: write steps: - uses: actions/checkout@v3 with: ref: ${{ github.event.pull_request.head.sha }} # to check out the actual pull request commit, not the merge commit fetch-depth: 0 # a full history is required for pull request analysis - name: 'Qodana Scan' uses: JetBrains/qodana-action@v2026.1 with: args: -e _JAVA_OPTIONS=-Xmx6g env: QODANA_TOKEN: ${{ secrets.QODANA_TOKEN }}
pipeline { environment { QODANA_TOKEN=credentials('qodana-token') } agent { docker { args ''' -v "${WORKSPACE}":/data/project -e _JAVA_OPTIONS=-Xmx6g --entrypoint="" ''' image 'jetbrains/qodana-<image>' } } stages { stage('Qodana') { steps { sh ''' qodana ''' } } } }
include: - component: $CI_SERVER_FQDN/qodana/qodana/qodana-gitlab-ci@v2026.1 inputs: args: | -e _JAVA_OPTIONS=-Xmx6g --image <image>

In the runner configuration, find the Additional Docker arguments field and configure the heap size using the _JAVA_OPTIONS variable:

-e _JAVA_OPTIONS=-Xmx6g

To learn more about configuring the Heap, see the Heap Tuning Parameters of the Oracle documentation.

Override the idea.properties file

The idea.properties configures the default locations of the IDE files.

You can override the idea.properties file using the IDEA_PROPERTIES variable:

docker run \ -v $(pwd):/data/project/ \ -e IDEA_PROPERTIES=/data/project/idea.properties \ -e QODANA_TOKEN="<cloud-project-token>" \ jetbrains/qodana-<image>
qodana scan \ -e IDEA_PROPERTIES=/data/project/idea.properties \ -e QODANA_TOKEN="<cloud-project-token>"
name: Qodana on: workflow_dispatch: pull_request: push: branches: # Specify your branches here - main # The 'main' branch - master # The 'master' branch - 'releases/*' # The release branches jobs: qodana: runs-on: ubuntu-latest permissions: contents: write pull-requests: write checks: write steps: - uses: actions/checkout@v3 with: ref: ${{ github.event.pull_request.head.sha }} # to check out the actual pull request commit, not the merge commit fetch-depth: 0 # a full history is required for pull request analysis - name: 'Qodana Scan' uses: JetBrains/qodana-action@v2026.1 with: args: -e IDEA_PROPERTIES=/data/project/idea.properties env: QODANA_TOKEN: ${{ secrets.QODANA_TOKEN }}
pipeline { environment { QODANA_TOKEN=credentials('qodana-token') } agent { docker { args ''' -v "${WORKSPACE}":/data/project -e IDEA_PROPERTIES=/data/project/idea.properties --entrypoint="" ''' image 'jetbrains/qodana-<image>' } } stages { stage('Qodana') { steps { sh ''' qodana ''' } } } }
include: - component: $CI_SERVER_FQDN/qodana/qodana/qodana-gitlab-ci@v2026.1 inputs: args: | -e IDEA_PROPERTIES=/data/project/idea.properties --image <image>

In the runner configuration, find the Additional Docker arguments field and configure the IDEA_PROPERTIES variable:

-e IDEA_PROPERTIES=/data/project/idea.properties

Configure root and non-root users

By default, a Docker container runs under the root user, so Qodana can read project information and write inspection results. Therefore, all files in the results/ directory are owned by the root user after the run.

To overcome this, you can run the container as a regular user:

docker run \ -u $(id -u):$(id -g) \ -v $(pwd):/data/project/ \ -v <results-directory>:/data/results/ \ -e QODANA_TOKEN="<cloud-project-token>" \ jetbrains/qodana-<image>

In this case, the results/ directory on the host should already be created and owned by you. Otherwise, Docker will create it as the root user, and Qodana will not be able to write to it.

TeamCity and Qodana CLI run Qodana using a current non-root user. This can be inconvenient if you wish to install dependencies using the apt tool invoked in the bootstrap section.

To run Qodana as a root user in TeamCity, add the -u root option in the Additional Docker arguments field of the Qodana runner configuration.

To run Qodana CLI as a root user, you can append -u root option to the qodana scan command:

qodana scan -u root
name: Qodana on: workflow_dispatch: pull_request: push: branches: # Specify your branches here - main # The 'main' branch - master # The 'master' branch - 'releases/*' # The release branches jobs: qodana: runs-on: ubuntu-latest permissions: contents: write pull-requests: write checks: write steps: - uses: actions/checkout@v3 with: ref: ${{ github.event.pull_request.head.sha }} # to check out the actual pull request commit, not the merge commit fetch-depth: 0 # a full history is required for pull request analysis - name: 'Qodana Scan' uses: JetBrains/qodana-action@v2026.1 with: args: -u root env: QODANA_TOKEN: ${{ secrets.QODANA_TOKEN }}
pipeline { environment { QODANA_TOKEN=credentials('qodana-token') } agent { docker { args ''' -v "${WORKSPACE}":/data/project -u root --entrypoint="" ''' image 'jetbrains/qodana-<image>' } } stages { stage('Qodana') { steps { sh ''' qodana ''' } } } }
include: - component: $CI_SERVER_FQDN/qodana/qodana/qodana-gitlab-ci@v2026.1 inputs: args: | -u root --image <image>

Git submodules

To analyze repositories that use Git submodules accessed via SSH, you must authenticate Git operations within the Qodana Docker container. In this case, you need to configure an SSH agent and pass an SSH key with access to the submodule into the container as shown in the snippets below:

docker run \ -v $(pwd):/data/project/ \ -v "$SSH_AUTH_SOCK:/tmp/ssh_agent.sock" \ -e SSH_AUTH_SOCK=/tmp/ssh_agent.sock \ -e GIT_SSH_COMMAND="ssh -o StrictHostKeyChecking=no" \ -e QODANA_SKIP_SUBMODULE_UPDATE=true \ jetbrains/qodana-<image> \ --diff-start=<GIT_START_HASH>

This command contains the following options:

Option

Description

-v "$SSH_AUTH_SOCK:/tmp/ssh_agent.sock"

Mount the SSH agent socket into the container

-e SSH_AUTH_SOCK=/tmp/ssh_agent.sock

Set the SSH agent socket environment variable

-e GIT_SSH_COMMAND="ssh -o StrictHostKeyChecking=no"

Disable strict host key checking for SSH operations

-e QODANA_SKIP_SUBMODULE_UPDATE=true

Skip Git submodule checkout, can be useful if the submodule checkout fails

--diff-start=<GIT_START_HASH>

Commit hash, see the Analyze pull and merge requests chapter for details

qodana scan \ -v "$SSH_AUTH_SOCK:/tmp/ssh_agent.sock" \ -e SSH_AUTH_SOCK=/tmp/ssh_agent.sock \ -e GIT_SSH_COMMAND="ssh -o StrictHostKeyChecking=no" \ -e QODANA_SKIP_SUBMODULE_UPDATE=true \ -e QODANA_TOKEN="<cloud-project-token>" \ --diff-start=<GIT_START_HASH>

This command contains the following options:

Option

Description

-v "$SSH_AUTH_SOCK:/tmp/ssh_agent.sock"

Mount the SSH agent socket into the container

-e SSH_AUTH_SOCK=/tmp/ssh_agent.sock

Set the SSH agent socket environment variable

-e GIT_SSH_COMMAND="ssh -o StrictHostKeyChecking=no"

Disable strict host key checking for SSH operations

-e QODANA_SKIP_SUBMODULE_UPDATE=true

Skip Git submodule checkout, can be useful if the submodule checkout fails

--diff-start=<GIT_START_HASH>

Commit hash, see the Analyze pull and merge requests chapter for details

jobs: qodana-job: runs-on: ubuntu-latest steps: - name: Checkout Repository uses: actions/checkout@v4 with: submodules: recursive # clones submodules recursively &nbsp; - name: Setup SSH Agent uses: webfactory/ssh-agent@v0.9.0 with: ssh-private-key: ${{ secrets.SUBMODULE_SSH_KEY }} &nbsp; - name: 'Qodana Scan' uses: JetBrains/qodana-action@v2026.1 with: args: | -v ${{ env.SSH_AUTH_SOCK }}:/tmp/ssh_agent.sock -e SSH_AUTH_SOCK=/tmp/ssh_agent.sock -e GIT_SSH_COMMAND=&quot;ssh -o StrictHostKeyChecking=no&quot; -e QODANA_SKIP_SUBMODULE_UPDATE=true upload-result: true pr-mode: 'true' env: QODANA_TOKEN: ${{ secrets.QODANA_TOKEN }}

Here, the args block contains the following options:

Option

Description

-v ${{ env.SSH_AUTH_SOCK }}:/tmp/ssh_agent.sock

Mount the SSH agent socket into the container

-e SSH_AUTH_SOCK=/tmp/ssh_agent.sock

Set the SSH agent socket environment variable

-e GIT_SSH_COMMAND=ssh -o StrictHostKeyChecking=no

Disable strict host key checking for SSH operations

-e QODANA_SKIP_SUBMODULE_UPDATE=true

Skip Git submodule checkout, can be useful if the submodule checkout fails

include: - component: $CI_SERVER_FQDN/qodana/qodana/qodana-gitlab-ci@v2026.1 inputs: image: <image> args: | -v ${{ env.SSH_AUTH_SOCK }}:/tmp/ssh_agent.sock -e SSH_AUTH_SOCK=/tmp/ssh_agent.sock -e GIT_SSH_COMMAND="ssh -o StrictHostKeyChecking=no" -e QODANA_SKIP_SUBMODULE_UPDATE=true

Here, the args block contains the following options:

Option

Description

-v ${{ env.SSH_AUTH_SOCK }}:/tmp/ssh_agent.sock

Mount the SSH agent socket into the container

-e SSH_AUTH_SOCK=/tmp/ssh_agent.sock

Set the SSH agent socket environment variable

-e GIT_SSH_COMMAND=ssh -o StrictHostKeyChecking=no

Disable strict host key checking for SSH operations

-e QODANA_SKIP_SUBMODULE_UPDATE=true

Skip Git submodule checkout, can be useful if the submodule checkout fails

Cache in Qodana CLI

Qodana CLI stores files in the <userCacheDir> directory, which is mentioned several times throughout this section. Here is the list of <userCacheDir> directory locations depending on the operating system:

Operating System

Path

macOS

~/Library/Caches/

Linux

~/.cache/

Windows

%LOCALAPPDATA%\

If you run the qodana init command in the project directory, Qodana CLI will let you choose the linter that will be run during inspection, and save the choice in qodana.yaml. Once done, you do not need to specify the linter in the commands, which is shown throughout this section.

The detailed description of the qodana init command is available in the Configure projects section.

Manage plugins

You can specify the plugins that will be downloaded and invoked during inspection using the following YAML configuration:

version: "1.0" linter: <linter> plugins: - id: <plugin.id>

Here, <plugin-id> denotes the Plugin ID from JetBrains Marketplace. For example, for Grazie Professional, the Plugin ID will be com.intellij.grazie.pro. To find the Plugin ID, on the plugin page click the Overview tab and then navigate to the Additional Information section.

Plugin cache is stored in the /data/cache/plugins directory.

To install third-party software required for your plugins, you can:

  • Use the bootstrap key.

  • Develop your custom Dockerfile that starts with FROM jetbrains/qodana.... You can use Qodana Dockerfile examples available on GitHub.

Incorrect Formatting inspection

The IncorrectFormatting inspection consolidates multiple formatting errors contained in a file into a single problem instead of listing every issue separately. Now, a single problem per file is displayed with example snippets to help you fix issues faster.

This feature is available for all linters except Qodana for C/C++, Qodana Community for C/C++, and Qodana Community for .NET.

To start using it, enable the IncorrectFormatting inspection in your Qodana inspection profile configuration, for example:

version: "1.0" linter: <linter> include: - name: IncorrectFormatting

Specify a CMake preset

Customize the Qodana for C/C++ linter by using CMake presets. Invoke presets using the cpp and cmakePreset options:

version: "1.0" linter: <linter> cpp: cmakePreset: my-qodana-preset

Configure Java and Kotlin projects in monorepo

Using the rootJavaProjects key, you can specify which projects should be included in the analysis, for example:

version: "1.0" linter: <linter> rootJavaProjects: - "./gradleProject" - "./mavenModule/pom.xml"

By default, Qodana recursively collects projects from subdirectories and imports them for analysis. This change enables incremental analysis and fixes for projects where the analyzed project and VCS root are different.

Comprehensive configuration examples

version: "1.0" linter: <linter> failThreshold: 0 profile: name: qodana.recommended include: - name: SomeInspectionId exclude: - name: Annotator - name: AnotherInspectionId paths: - relative/path - another/relative/path - name: All paths: - asm-test/src/main/java/org - benchmarks - tools

In the example above,

  • SomeInspectionId inspection is explicitly enabled for all paths, although it is disabled in the profile

  • Annotator inspection is disabled for all paths

  • AnotherInspectionId inspection is disabled for relative/path and another/relative/path

  • no inspections are conducted over these paths: asm-test/src/main/java/org, benchmarks, tools

The following example combines multiple settings, including a quality gate, inspection profile customization, and path exclusions, which are common in .NET project setups:

version: "1.0" # Run the Qodana for .NET linter in native mode linter: qodana-dotnet withinDocker: false # Set a quality gate: fail if the number of problems exceeds 10 failThreshold: 10 # Use the qodana.recommended profile profile: name: qodana.recommended # Exclude specific paths from the analysis exclude: - name: All paths: - tests/ - bin/ - obj/ # Include an inspection not contained in the qodana.recommended profile include: - name: SomeSpecificInspectionId paths: - src/ # Restore .NET dependencies bootstrap: |+ dotnet restore

Use this example while configuring the Qodana for JVM linter:

version: "1.0" # Run the Qodana for JVM linter linter: qodana-jvm # Set the JDK version jdk: version: "17" # Include Java projects for analysis rootJavaProjects: - "./gradle-project" - "./maven-module/pom.xml" # Quality gate settings failureConditions: severityThresholds: any: 50 # Fail if total number of problems exceeds 50 critical: 1 # Fail if there is at least 1 critical problem high: 2 # Fail if there are more than 2 high-severity problems testCoverageThresholds: fresh: 80 # Fail if fresh code coverage is below 80% total: 90 # Fail if total code coverage is below 90% # Disable specific inspections exclude: - name: CheckDependencyLicenses # Disable license audit if not needed # Include custom plugins plugins: - id: com.intellij.grazie.pro

Full list of CLI commands

Configure projects

You can use the following CLI options to configure Qodana projects:

Option

Description

The default value

--config <string>

Set a custom configuration file instead of qodana.yaml. Use a path relative to the project directory

None

-f, --force

Force initialization, overwrite the existing valid qodana.yaml file

None

-i, --project-dir <string>

Specify the root directory of your project

.

You can invoke these options in Qodana CLI using the qodana init <options> command.

Analyze projects

Option

Description

--image <string>

In place of <string>, specify the Qodana Docker image that you would like to employ:

Docker image

Description

jetbrains/qodana-jvm-community:2026.2

Qodana Community for JVM

jetbrains/qodana-jvm:2026.2

Qodana for JVM

jetbrains/qodana-jvm-android:2026.2

Qodana Community for Android

jetbrains/qodana-android:2026.2

Qodana for Android

jetbrains/qodana-php:2026.2

Qodana for PHP

jetbrains/qodana-python:2026.2

Qodana for Python

jetbrains/qodana-python-community:2026.2

Qodana Community for Python

jetbrains/qodana-js:2026.2

Qodana for JS

jetbrains/qodana-go:2026.2

Qodana for Go

jetbrains/qodana-dotnet:2026.2-eap

Qodana for .NET

jetbrains/qodana-cdnet:2026.2-eap

Qodana Community for .NET

jetbrains/qodana-cpp:2026.2

Qodana for C/C++

jetbrains/qodana-clang:2026.2-eap

Qodana Community for C/C++

jetbrains/qodana-ruby:2026.2-eap

Qodana for Ruby

Also, you can use any Docker image that has Qodana.

-l, --linter <string>

In place of <string>, specify the linter that you would like to employ:

Linter name

Description

qodana-jvm-community

Qodana Community for JVM

qodana-jvm

Qodana for JVM

qodana-jvm-android

Qodana Community for Android

qodana-android

Qodana for Android

qodana-php

Qodana for PHP

qodana-python

Qodana for Python

qodana-python-community

Qodana Community for Python

qodana-js

Qodana for JS

qodana-go

Qodana for Go

qodana-dotnet

Qodana for .NET

qodana-cdnet

Qodana Community for .NET

qodana-cpp

Qodana for C/C++

qodana-clang

Qodana Community for C/C++

qodana-ruby

Qodana for Ruby

--within-docker <true|false>

Define whether analysis will be performed within a Docker container.

If set to true, Qodana will employ a respective Docker image. The image for container creation will be chosen in an automated way based on the --image value. For example, the jetbrains/qodana-jvm image will be chosen in case of --linter qodana-jvm.

If set to false, Qodana will analyze your project in native mode using the current environment.

The default value is defined dynamically based on the analysis of the current environment and project.

Native mode is currently available for the following Qodana linters:

Linter name

Description

qodana-jvm

Qodana for JVM

qodana-jvm-community

Qodana Community for JVM

qodana-php

Qodana for PHP

qodana-js

Qodana for JS

qodana-dotnet

Qodana for .NET

qodana-go

Qodana for Go

qodana-python

Qodana for Python

qodana-python-community

Qodana Community for Python

-i, --project-dir <string>

Root directory of the analyzed project. The default value is .

--repository-root string <string>

Path to the root of the Git repository. This directory must be the same as --project-dir or contain the project directory inside it.

-o, --results-dir <string>

Override the directory for saving Qodana analysis reports. The default value is <userCacheDir>/JetBrains/Qodana/<linter>/results

--cache-dir <string>

Override the cache directory. The default value is <userCacheDir>/JetBrains/Qodana/<linter>/cache

-r, --report-dir <string>

Override the directory for saving Qodana HTML reports. The default value is <userCacheDir>/JetBrains/<linter>/results/report

--print-problems

Print in the CLI output all problems found by Qodana

--code-climate

Generate a SARIF-formatted Code Climate report supported by GitLab CI/CD. The report will be saved in the directory specified by the --results-dir option. By default, this option is enabled if GitLab CI/CD is running

--bitbucket-insights

Generate a Code Insights report supported by Bitbucket Cloud. By default, this option is enabled if Qodana is being run in the Bitbucket Pipelines

--clear-cache

Clear the local Qodana cache before running analyses

-w, --show-report

Serve an HTML report on the port specified by the --port option

--port <int>

Port to serve the report. The default value is 8080. This option is deprecated, use the --show-report-port option instead

--show-report-port <int>

Port to serve the report

--config <string>

Set a custom configuration file instead of qodana.yaml. Use a path relative to the project root directory

-a, --analysis-id <string>

Unique report identifier (GUID) to be used by Qodana Cloud. The default value is 2c72b6e8-f09d-472a-bb86-8a7d8e374ed1

-b, --baseline <string>

Provide the path to an existing SARIF report to be used in the baseline state calculation

--baseline-include-absent

Include baseline problems that are marked absent in the output report

--full-history [--commit <commit-hash>]

Go through the full commit history and run the analysis on each commit. If combined with --commit, the analysis will be started from the given commit

--commit <commit-hash> [--full-history]

Reset Git and run analysis only for the files modified since the given commit. If combined with the --full-history option, full history analysis will be started from the given commit

--fail-threshold <string>

Set the number of problems that will serve as a quality gate. Once the quality gate threshold is reached, the analysis will be terminated with a non-zero exit code

--disable-sanity

Skip the inspections configured by the qodana.sanity inspection profile

-d, --source-directory <string>

Specify the directory inside the project-dir directory that must be analyzed. If not specified, the whole project will be analyzed

--repository-root <string>

Specify the VCS root directory for your project. This option is required for Git-related operations

--only-directory <string>

Specify the directory inside the project-dir directory that must be analyzed. If not specified, the whole project will be analyzed

Files and directories contained in the outside directory like .git and build.gradle are used by Qodana while inspecting code

-n, --profile-name <string>

Specify the profile name

-p, --profile-path <string>

Specify the path to the profile file

--run-promo <true|false>

Set this option to true to use the promo inspections; set to false otherwise. The default value is true if Qodana is executed using the default profile

--script <string>

Override the run scenario of Qodana. Currently, the following run scenarios are available:

Scenario name

Description

default

The default Qodana scenario, enabled by default

php-migration

PHP version migration scenario

local-changes

Analyze only uncommitted changes. You can see the Incremental analysis section to learn more about incremental analysis

--coverage-dir <string>

Specify the directory that contains code coverage data for analysis

--apply-fixes

Apply all available Quick-Fix strategies including cleanup, see the Quick-Fix section for details

--cleanup

Run the CLEANUP Quick-Fix strategy, see the Quick-Fix for details

--property <stringArray>

Set a JVM property to be used while running Qodana. Use the --property property.name=value1,value2,...,valueN notation

-s, --save-report

Generate an HTML report. This option is enabled by default

--timeout int

Set Qodana analysis time limit in milliseconds. Once reached, the analysis will be terminated and the process will exit with the timeout-exit-code code. The default setting is 1

--timeout-exit-code <int>

Override the default timeout setting --timeout option. The default value set by the timeout option is 1

--diff-start <string>

Set the hash of the commit that will act as a base for comparison in a change analysis

--diff-end <string>

Set the hash of the commit that will act as an end in a change analysis. This lets you analyze only files changed between the --diff-start and --diff-end commits

--reverse

Override the default run scenario by launching incremental analysis in reverse order. This lets you skip analysis of the main codebase if the incremental analysis finds no issues.

--no-statistics

Disable sending anonymous statistics

--compile-commands <string>

Specify the path to the compile_commands.json file. The default value is ./build/compile_commands.json"

--clang-args <string>

Set additional arguments, see the C / C++ section for details

--solution <string>

Set a relative path to a solution file, see the .NET section for details

--project <string>

Set a relative path to a project file, see the .NET section for details

--configuration <string>

Specify the build configuration, see the .NET section for details

--platform <string>

Specify the build platform, see the .NET section for details

--no-build

Skip project building before analyses, see the .NET section for details

-e, --env <stringArray>

Define environment variables for the Qodana container, multiple variables can be specified. For security reasons, Qodana CLI does not read environment variables from the host operating system, so all variables required by Qodana should be specified explicitly.

-v, --volume <stringArray>

Define additional volumes for the Qodana container, multiple volumes can be specified. For example, qodana scan --volume $(pwd)/.qodana/results:/data/results/

-u, --user <string>

User to run Qodana container as. Please specify the user ID – $UID or the user ID and group ID $(id -u):$(id -g). Use root to run as the root user. By default, it is set to the current user

--skip-pull

Skip pulling the latest Qodana container

You can invoke these options in Qodana CLI using the qodana scan <options> command.

Send analysis reports to Qodana Cloud

Option

Description

-a, --analysis-id <string>

The unique report identifier (GUID) to be used by Qodana Cloud. The default value is f9d8a78f-f922-452b-8062-a64afc352537

--config <string>

Set a custom configuration file instead of qodana.yaml. Use a path relative to the project root directory

-l, --linter <string>

Override the linter which report will be used for sending to Qodana Cloud

-i, --project-dir <string>

Root directory of the project which report will be sent to Qodana Cloud. The default value is .

-r, --report-dir <string>

Override the directory for saving Qodana HTML reports. The default value is <userCacheDir>/JetBrains/<linter>/results/report

-o, --results-dir <string>

Override the directory that will be used for sending a Qodana report from. The default value is <userCacheDir>/JetBrains/<linter>/results

You can invoke these options in Qodana CLI using the qodana send <options> command.

View reports

Option

Description

--config <string>

Set a custom configuration file instead of qodana.yaml. Use a path relative to the project root directory

-d, --dir-only

Open the report directory only without serving it

-l, --linter <string>

Override the linter which report should be viewed

-p, --port <int>

Specify the port to serve a report. The default value is 8080

-i, --project-dir <string>

Root directory of the project which report should be viewed. The default value is .

-r, --report-dir <string>

Override the directory to save a Qodana HTML report. This is the directory that contains the index.html file. The default value is <userCacheDir>/JetBrains/<linter>/results/report

-o, --results-dir <string>

Override the directory for saving analysis reports. The default value is <userCacheDir>/JetBrains/<linter>/results

You can invoke these options in Qodana CLI using the qodana show <options> command.

View SARIF-formatted files

Option

Description

Default setting

-f, --sarif-file <string>

Path to the SARIF-formatted file

./qodana.sarif.json

You can invoke these options in Qodana CLI using the qodana view <options> command.

Count contributors

To collect information about contributors to your project, you can run Qodana using the following options.

Option

Description

Default setting

-d, --days <int>

The number of days in the past that should be used for calculating the number of active contributors

90

-o, --output string

The output format. Available values are tabular and json

tabular

-i, --project-dir <stringArray>

The Directory of the project that can be specified multiple times to analyze multiple projects

.

You can invoke these options in Qodana CLI using the qodana contributors <options> command.

View project statistics

You can use these options to view information about your project, such as languages and lines of code.

Option

Description

-o, --output <string>

The output format that accepts the tabular, wide, json, csv, csv-stream, cloc-yaml, html, html-table, sql, sql-insert, openmetrics values. The default setting is tabular

-i, --project-dir <stringArray>

The project directory. This option can be specified multiple times to analyze multiple projects. If not specified, the current directory will be used

You can invoke these options in Qodana CLI using the qodana cloc <options> command.

Pull a Qodana image

Using these options, you can pull the Qodana linter that you would like to employ.

Option

Description

--config <string>

Set a custom configuration file instead of qodana.yaml. Use a path relative to the project root directory

--image <string>

Specify the image that you would like to pull

-l, --linter <string>

Specify the linter that you would like to pull

-i, --project-dir <string>

The root directory of the analyzed project. If not specified, the current directory will be used

You can invoke these options in Qodana CLI using the qodana pull <options> command. Qodana CLI takes information about the linter using either the qodana.yaml file configuration or the --linter option.

Generate an autocompletion script

Using these options, you can generate an autocompletion script for a specific shell.

Command

Description

bash

Generate the autocompletion script for bash

fish

Generate the autocompletion script for fish

powershell

Generate the autocompletion script for PowerShell

zsh

Generate the autocompletion script for zsh

You can invoke these options in Qodana CLI using the qodana completion <options> command.

Configure update checking and log levels

Option

Description

--disable-update-checks

Disable checking and notification about new versions of Qodana CLI

--log-level <string>

Change log level in the output of Qodana CLI. For example, you can set --log-level debug to receive the detailed log reports. The default setting is error

23 July 2026