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:
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=rootoption.
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#):
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 }}
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:
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 }}
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:
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:
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 }}
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.
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:
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
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:
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:
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 }}
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
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:
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:
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:
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:
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:
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 }}
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:
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 }}
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
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.
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:
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:
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 }}
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:
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 }}
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 }}
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 }}
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 }}
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:
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 }}
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:
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 }}
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 }}
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 }}
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:
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 }}
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:
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:
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:
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.
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.
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:
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:
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
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:
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