# Create application Source: https://docs.qlty.sh/api-reference/applications/create-application https://api.qlty.sh/openapi.json post /gh/{ownerKeyOrId}/applications Create an Application for a Workspace. The Workspace must have Applications enabled. # Delete application Source: https://docs.qlty.sh/api-reference/applications/delete-application https://api.qlty.sh/openapi.json delete /gh/{ownerKeyOrId}/applications/{applicationIdOrName} Permanently delete an Application. Every Project assigned to it must be unassigned first. The Workspace must have Applications enabled. # Get an application Source: https://docs.qlty.sh/api-reference/applications/get-an-application https://api.qlty.sh/openapi.json get /gh/{ownerKeyOrId}/applications/{applicationIdOrName} Retrieves details about a specific Application # List applications Source: https://docs.qlty.sh/api-reference/applications/list-applications https://api.qlty.sh/openapi.json get /gh/{ownerKeyOrId}/applications Retrieve the Applications defined for a Workspace. Supports JSON, newline-delimited JSON (`application/x-ndjson`), and CSV (`text/csv`) response formats via the `Accept` header. # Update application Source: https://docs.qlty.sh/api-reference/applications/update-application https://api.qlty.sh/openapi.json patch /gh/{ownerKeyOrId}/applications/{applicationIdOrName} Update an Application's name and description. Omitted fields keep their current values; pass `description: null` to clear it. The Workspace must have Applications enabled. # Create component Source: https://docs.qlty.sh/api-reference/components/create-component https://api.qlty.sh/openapi.json post /gh/{ownerKeyOrId}/projects/{projectKeyOrId}/components Create a Component for a Project. Requires admin access to the Project, and the Project must have Components enabled. # Delete component Source: https://docs.qlty.sh/api-reference/components/delete-component https://api.qlty.sh/openapi.json delete /gh/{ownerKeyOrId}/projects/{projectKeyOrId}/components/{componentIdOrName} Permanently delete a Component from a Project. Requires admin access to the Project, and the Project must have Components enabled. # List components Source: https://docs.qlty.sh/api-reference/components/list-components https://api.qlty.sh/openapi.json get /gh/{ownerKeyOrId}/projects/{projectKeyOrId}/components Retrieve all Components defined for a Project. Supports JSON, newline-delimited JSON (`application/x-ndjson`), and CSV (`text/csv`) response formats via the `Accept` header. # Update component Source: https://docs.qlty.sh/api-reference/components/update-component https://api.qlty.sh/openapi.json put /gh/{ownerKeyOrId}/projects/{projectKeyOrId}/components/{componentIdOrName} Replace a Component's definition. Takes the same fields as create and fully replaces the existing definition; the Component's id and creator are preserved. Requires admin access to the Project, and the Project must have Components enabled. # Get file coverage Source: https://docs.qlty.sh/api-reference/coverage/get-file-coverage https://api.qlty.sh/openapi.json get /gh/{ownerKeyOrId}/projects/{projectKeyOrId}/coverage/file Retrieve line-by-line test coverage data for a file at a specific Git reference or commit SHA # List issues Source: https://docs.qlty.sh/api-reference/issues/list-issues https://api.qlty.sh/openapi.json get /gh/{ownerKeyOrId}/projects/{projectKeyOrId}/issues Retrieves a list of Issues associated with a Project. Supports JSON, newline-delimited JSON (`application/x-ndjson`), and CSV (`text/csv`) response formats via the `Accept` header. # Get component metric series Source: https://docs.qlty.sh/api-reference/metrics/get-component-metric-series https://api.qlty.sh/openapi.json get /gh/{ownerKeyOrId}/projects/{projectKeyOrId}/components/{componentIdOrName}/metrics/series Retrieve each metric's history for a specific Component on the Project's default branch as a time series over the requested window. Returns one series per metric — covering maintainability, reliability, security, size, coverage, and quality indicators — each with the metric's descriptor and one value per interval; narrow the result with the `metric` and `category` query parameters. Available as JSON, newline-delimited JSON (`application/x-ndjson`), or CSV (`text/csv`) via the `Accept` header. Buckets are UTC-aligned and labeled with the inclusive end of each interval; a bucket with no measurement carries the most recent prior value forward, and the final bucket (the one containing `to`) may be labeled later than `to` — including the future for an interval still in progress — with its value reflecting only measurements within the window. # Get component metrics Source: https://docs.qlty.sh/api-reference/metrics/get-component-metrics https://api.qlty.sh/openapi.json get /gh/{ownerKeyOrId}/projects/{projectKeyOrId}/components/{componentIdOrName}/metrics Retrieve the latest value of every metric for a specific Component on the Project's default branch, covering maintainability, reliability, security, size, coverage, and quality indicators. # Get file metrics Source: https://docs.qlty.sh/api-reference/metrics/get-file-metrics https://api.qlty.sh/openapi.json get /gh/{ownerKeyOrId}/projects/{projectKeyOrId}/files Retrieve the latest values of all metrics for a file in a Project's default branch # Get project metric series Source: https://docs.qlty.sh/api-reference/metrics/get-project-metric-series https://api.qlty.sh/openapi.json get /gh/{ownerKeyOrId}/projects/{projectKeyOrId}/metrics/series Retrieve each metric's history on a Project's default branch as a time series over the requested window. Returns one series per metric — covering maintainability, reliability, security, size, coverage, and quality indicators — each with the metric's descriptor and one value per interval; narrow the result with the `metric` and `category` query parameters. Available as JSON, newline-delimited JSON (`application/x-ndjson`), or CSV (`text/csv`) via the `Accept` header. Buckets are UTC-aligned and labeled with the inclusive end of each interval; a bucket with no measurement carries the most recent prior value forward, and the final bucket (the one containing `to`) may be labeled later than `to` — including the future for an interval still in progress — with its value reflecting only measurements within the window. # Get project metrics Source: https://docs.qlty.sh/api-reference/metrics/get-project-metrics https://api.qlty.sh/openapi.json get /gh/{ownerKeyOrId}/projects/{projectKeyOrId}/metrics Retrieve the latest value of every metric on a Project's default branch, covering maintainability, reliability, security, size, coverage, and quality indicators. # Get a project Source: https://docs.qlty.sh/api-reference/projects/get-a-project https://api.qlty.sh/openapi.json get /gh/{ownerKeyOrId}/projects/{keyOrId} Retrieves details about a specific Project # List projects Source: https://docs.qlty.sh/api-reference/projects/list-projects https://api.qlty.sh/openapi.json get /gh/{ownerKeyOrId}/projects Retrieves a list of Projects associated with a Workspace. Supports JSON, newline-delimited JSON (`application/x-ndjson`), and CSV (`text/csv`) response formats via the `Accept` header. # Update a project Source: https://docs.qlty.sh/api-reference/projects/update-a-project https://api.qlty.sh/openapi.json patch /gh/{ownerKeyOrId}/projects/{keyOrId} Assign a Project to an Application, or pass `applicationId: null` to unassign it. The Workspace must have Applications enabled. # Get rate limit status Source: https://docs.qlty.sh/api-reference/service/get-rate-limit-status https://api.qlty.sh/openapi.json get /rate_limit Retrieve the rate limit status for the authenticated token. Rate limits use a one-hour window; the current limit and usage are also reported on every response via the `x-ratelimit-*` headers. # Get authenticated user Source: https://docs.qlty.sh/api-reference/user/get-authenticated-user https://api.qlty.sh/openapi.json get /user Get the authenticated User based on the provided access token # Get a workspace Source: https://docs.qlty.sh/api-reference/workspaces/get-a-workspace https://api.qlty.sh/openapi.json get /workspaces/{keyOrId} Retrieve a single Workspace by its ID or key # List workspaces Source: https://docs.qlty.sh/api-reference/workspaces/list-workspaces https://api.qlty.sh/openapi.json get /workspaces List Workspaces accessible to the authenticated token. Supports JSON, newline-delimited JSON (`application/x-ndjson`), and CSV (`text/csv`) response formats via the `Accept` header. # Introduction Source: https://docs.qlty.sh/api/introduction The Qlty API is currently in an early access period and subject to change without warning. The Qlty API is organized around REST. The API provides predictable, resource-oriented URLs, accepts JSON-encoded request bodies, and returns JSON-encoded responses. We strive to make use of standard HTTP response codes, authentication, and verbs. ## Authentication The Qlty API uses tokens to authenticate requests. You can generate an API token through your user settings at [https://qlty.sh/user/settings/tokens](https://qlty.sh/user/settings/tokens) Authentication is performed by passing the token as a Bearer token in the `Authorization` header: ```bash lines theme={"system"} curl -H "Authorization: Bearer " https://api.qlty.sh/... ``` All API requests must be made over HTTPS. Calls made over plain HTTP or without authentication will fail. ## Errors Qlty uses conventional HTTP response codes to indicate the success or failure of an API request. Codes in the 2xx range indicate success. Codes in the 4xx range indicate an error that failed given the information provided (e.g., a required parameter was omitted). Codes in the 5xx range indicate an error with Qlty's server. | Code | Status | Description | | ------------------ | ----------------- | -------------------------------------------------------------- | | 200 | OK | The request was successful. | | 400 | Bad Request | The request was invalid, often due to a missing input. | | 401 | Unauthorized | Authentication failed. | | 403 | Forbidden | The API token does not have permission to access the resource. | | 404 | Not Found | The requested resource was not found. | | 429 | Too Many Requests | Too many API requests were sent in too short of a period. | | 500, 502, 503, 504 | Server Error | An unexpected error occurred on the server. | Errors are returned in the `errors` key of the response. ```json Error response lines theme={"system"} { "errors": [ { "status": "400", "title": "Bad Request", "detail": "The request was invalid." } ] } ``` ## Pagination Many list API endpoints return paginated results. The Qlty API uses offset-based pagination. The `page[limit]` query parameter specifies the number of items to return per page. It defaults to `20` and may not exceed `100`. The `page[offset]` query parameter specifies the offset of the first item to return, and defaults to `0`. When additional records are available, the response will include a `meta` key with a `hasMore: true` property. ```bash lines theme={"system"} curl -X GET "https://api.qlty.sh/workspaces?page[limit]=2&page[offset]=0" \ -H "Authorization: Bearer " ``` ```json Pagination response lines theme={"system"} { "data": [ { "id": "01998c1e-0000-7000-8000-000000000001", "key": "acme" }, { "id": "01998c1e-0000-7000-8000-000000000002", "key": "globex" } ], "meta": { "hasMore": true } } ``` ## Rate Limiting Qlty uses rate limiting to ensure that the API is not overwhelmed by too many requests. If you exceed the rate limit, you will receive a `429 Too Many Requests` response. The rate limit is measured in units, not raw request counts. Most requests cost a single unit, but some endpoints that return larger or more expensive results cost more. By default, the limit is 5,000 units per hour, applied as a fixed window. Requests to workspace and project endpoints count against a per-workspace limit, and requests to user endpoints count against a per-user limit. Contact support if you need a higher rate limit. Responses include headers reporting your current rate limit usage: | Header | Description | | ----------------------- | ------------------------------------------------------------- | | `x-ratelimit-limit` | Maximum number of units allowed in the current window | | `x-ratelimit-remaining` | Number of units remaining in the current window | | `x-ratelimit-used` | Number of units used in the current window | | `x-ratelimit-reset` | Unix timestamp (in seconds) when the rate limit window resets | You can also check your current rate limit status without consuming any of your limit by calling the `GET /rate_limit` endpoint. ## Versioning The Qlty API does not currently have a versioning scheme. Today, all endpoints are available at `https://api.qlty.sh/`. Prior to the general availability of the API, we are evaluating a versioning scheme that will allow us to make breaking changes without affecting existing users. # Auto-formatting Source: https://docs.qlty.sh/auto-formatting Auto-formatting is the practice of using automated tools to rewrite source code files into a consistent format. These tools ensure that your code adheres to predefined styling and formatting guidelines, removing the need for manual adjustments and maintaining uniformity across the codebase. Popular auto-formatting tools include [`go fmt`](https://go.dev/blog/gofmt) for Go, [Prettier](https://prettier.io/) for JavaScript, and [Black](https://github.com/psf/black) for Python. Auto-formatting is provided by [Qlty CLI](/cli/quickstart). ## Why is Auto-Formatting Useful? Auto-formatting offers several key benefits that can enhance your development workflow and code quality: 1. **Consistency**: Auto-formatting enforces a consistent style across the entire codebase, making the code easier to read and understand. 2. **Productivity**: By automating the formatting process, developers can focus on writing code rather than spending time on manual formatting. 3. **Faster Code Review**: Consistent formatting results in clean diffs and reduces the number of stylistic comments during code reviews, allowing reviewers to focus on the logic and functionality of the code. ## How Auto-Formatting Works Auto-formatting tools analyze your code and apply a set of formatting rules to transform it into a standard format. These rules cover various aspects of code style, including indentation, spacing, line breaks, and more. The tools can typically be configured to match the specific style guide of your development team or project. Here’s a simple example in Go using `go fmt`: ### Before Auto-Formatting ```go lines theme={"system"} package main import "fmt" func main() { fmt.Println("Hello, world!") } ``` ### After Auto-Formatting ```go lines theme={"system"} package main import "fmt" func main() { fmt.Println("Hello, world!") } ``` In this example, `go fmt` adjusts the import statement and function definition to follow Go's standard formatting rules. ## Integrating Auto-Formatting into Your Workflow Qlty supports auto-formatting tools as part of its comprehensive code quality toolkit via the Qlty CLI. 1. **On Demand:** By configuring auto-formatters and running `qlty fmt` regularly, you can ensure consistent code style. 2. **Pre-commit Hooks**: Adding `qlty fmt` as a Git pre-commit hook to ensure every correct formatting of every commit. 3. **Continuous Integration (CI)**: You can set up an automated job to run `qlty fmt` nightly and commit the results. ## Recommended Auto-Formatters by Language | Language | Auto-Formatter | | ---------- | -------------------- | | Go | go fmt | | GraphQL | Prettier | | HTML | Prettier | | Java | google-java-format | | JavaScript | Prettier | | JSON | Prettier | | Kotlin | ktfmt | | Markdown | Prettier | | PHP | @prettier/plugin-php | | Python | Black | | Ruby | standardrb | | Rust | rustfmt | | Shell | shfmt | | TypeScript | Prettier | | YAML | Prettier | ## See Also * [Qlty CLI](/cli/quickstart) * [`qlty fmt`](/cli/commands/fmt) * [Available Plugins](/plugins) * [Analysis Configuration](/cli/analysis-configuration) # Changelog Source: https://docs.qlty.sh/changelog New features, improvements, and fixes across Qlty Cloud and the Qlty CLI ## Is the code your team is shipping well covered? Most coverage trend charts plot a Project's total coverage over time. That's valuable, but on a large project total coverage is a lagging metric: a real change in how a team tests takes a long time to make a meaningful mark on the total. Diff coverage — the coverage of the lines a change touches — is a leading one. If your team is covering the code it ships, diff coverage is high now, and total coverage trends upward over time. Every Project's **Trends** page now includes a **Diff Coverage** chart, showing how well tested the code you merged was, week by week. Diff coverage is plotted as a line, with the executable lines changed in each period as bars behind it, so you can tell a meaningful week from a quiet one. Ranges run from 1 month to 3 years. There's nothing to configure — the chart is built from the coverage you already upload on your default branch. See [Diff Coverage Over Time](/coverage/diff-coverage-trends) for details. ## Build Secrets (beta) Some linters need a credential to do their job: an API token to reach a private package registry, a license key for a commercial tool. Until now, there was no way to hand one to a cloud build without committing it to your repository. **Build Secrets** are encrypted environment variables you set per project. Open **Project Settings → Secrets**, add a name and a value, and it's available to that project's builds. Values are write-only — once saved, a secret is encrypted and can never be read back, only rotated or deleted. The list shows names and timestamps, and only project admins can see or change it. Adding a secret doesn't hand it to every plugin. The Qlty CLI runs each plugin in a subprocess with a restricted environment and passes through only the variables that plugin's definition names, so you opt each plugin in from your `qlty.toml`: ```toml theme={"system"} [[plugins.definitions.foo.environment]] name = "BAR" value = "${env.BAR}" ``` Secrets reach your plugins only while Qlty installs and runs them, and never reach builds for pull requests from forks. Build Secrets are in beta and rolled out per workspace — [contact Qlty Support](https://qlty.sh/contact/support) to request access. See [Build Secrets](/cloud/build-secrets) for details. ## Selective Coverage on pull requests (beta) Qlty has always supported partial test runs through [tags](/coverage/tags). Publish your unit tests as `units` and that suite is tracked on its own, because a tag runs a predictable set of tests each time and every report for it is comparable to the last. Test optimization tools break that assumption. To keep pull request builds fast on a large codebase, they choose a different subset of tests for every build based on what the change touched. Each report covers a unique slice of the codebase, comparable to nothing before it, and to a coverage tool it looks like a sudden, dramatic drop. The coverage such a run reports would be misleading, so our recommendation has been not to publish it at all. **Selective Coverage** makes those runs usable by overlaying the selected report on the pull request's diff. Add `--selection` to `qlty coverage publish` in the builds that run a dynamically selected subset of your tests: ```bash Qlty CLI lines theme={"system"} qlty coverage publish --selection coverage/lcov.info ``` ```yaml GitHub Action lines theme={"system"} - uses: qltysh/qlty-action/coverage@v2 with: token: ${{ secrets.QLTY_COVERAGE_TOKEN }} files: coverage/lcov.info selected: true ``` Qlty trusts a selected report for the lines it does cover — exactly what diff coverage needs — so the Diff Coverage commit status and PR comments work as usual. The Total Coverage status passes with "Not computable for select coverage" rather than a misleading percentage; total coverage metrics, component coverage, trends, and the file explorer are untouched; and a selected report is never used as the comparison base for another pull request. Selective Coverage is in beta and requires Qlty CLI v0.633.0, GitHub Action `qltysh/qlty-action` v2.3.0, or CircleCI orb `qltysh/qlty-orb` 0.1.2 — or newer. Publish full-suite coverage on your default branch to keep totals and baselines accurate. See [Selective Coverage](/coverage/selective-coverage) for details. ## Seat-based licensing Qlty Cloud now licenses Workspaces by **seats** instead of active contributors. A new **Seat Management** settings page lets admins assign seats to contributors and see how many are in use. See [Seats](/cloud/billing/seats) for details. ## Verified seat assignment When you assign a seat on the Seat Management page, Qlty now verifies the GitHub username exists before granting the seat. A confirmation dialog shows the account's avatar, name, and whether they belong to your GitHub organization, so you can catch typos and confirm you're assigning the right person. Non-existent accounts are rejected before any seat is used. ## Search when adding projects The Add Projects page now has a search box that filters across all accessible repositories server-side, so you no longer have to page through every repo to find one in a large Workspace. ## `--skip-source-fetch` for `qlty coverage publish` `qlty coverage publish` now accepts `--skip-source-fetch`, matching `qlty check` and `qlty fmt`. When set, the command skips fetching remote sources and falls back to the default configuration if a source is not cached locally. See [coverage publish](/cli/commands/coverage-publish) for details. ## VB.NET maintainability analysis The Qlty CLI now analyzes `.vb` files for maintainability — complexity, duplication, and code smells — with VB.NET's case-insensitive member semantics handled correctly. ## Scala maintainability analysis The Qlty CLI now analyzes Scala (including Scala 3) source files for maintainability — complexity, duplication, and code smells. ## Knip honors `.qlty/configs/` Fixed Knip not picking up a configuration file placed under `.qlty/configs/` in nested-package layouts. Qlty now passes the config path to Knip explicitly. ## RuboCop `AllCops: Exclude` now respected Qlty now passes `--force-exclusion` to RuboCop, so `AllCops: Exclude` patterns in your `.rubocop.yml` are honored even though Qlty invokes RuboCop with explicit file targets. ## editorconfig-checker findings no longer dropped Fixed a bug where `editorconfig-checker` results were silently discarded when the tool reported a `-1` line number for an issue it couldn't locate. All findings are now reported. ## Verified CLI downloads in GitHub Actions The Qlty GitHub Actions now verify the Qlty CLI's Sigstore attestation before running it. Each action checks the downloaded archive against its signed provenance using the GitHub CLI, giving your workflows tamper-evident assurance that the binary came from Qlty. Verification is automatic and uses your existing `${{ github.token }}`. See [Integrity Verification](/cli/integrity-verification) for details. ## More coverage formats in the GitHub Action The Qlty coverage GitHub Action now accepts `dotcover` and `xccov-json` as `format` values, so you can upload JetBrains dotCover and Xcode `xccov` JSON reports directly from your workflow without converting them first. See [Generating Coverage Data](/coverage/generating-data) for details. ## Node 24 runtime for GitHub Actions The Qlty GitHub Actions now run on the Node 24 runtime, clearing the deprecation warning GitHub showed for the older Node 20 runtime and keeping the actions on a supported runtime ahead of GitHub's automatic migration. ## Windows support for the fmt action The Qlty `fmt` GitHub Action now runs on Windows runners in addition to Linux and macOS, so Windows-based CI pipelines can auto-format code with Qlty. ## C and C++ language support Qlty now provides maintainability analysis for C and C++. This includes complexity, duplication, and code smells, available in both the Qlty CLI and Qlty Cloud. See [C / C++](/languages/c-cpp) for details. ## Travis CI push branch detection Travis CI users no longer need to set the branch name manually when uploading coverage. The Qlty CLI now detects the branch automatically on Travis push builds, the same way it already does for other CI providers. ## editorconfig-checker plugin We've added a plugin for [editorconfig-checker](https://github.com/editorconfig-checker/editorconfig-checker), which verifies that your codebase follows the rules defined in `.editorconfig`. ```bash lines theme={"system"} qlty plugins enable editorconfig-checker ``` ## Spectral plugin We've added a plugin for [Spectral](https://github.com/stoplightio/spectral), a linter for OpenAPI and AsyncAPI specifications. ```bash lines theme={"system"} qlty plugins enable spectral ``` ## golangci-lint v2 support The Qlty plugin for [golangci-lint](https://golangci-lint.run/) now supports the v2 output format in addition to v1, so you can upgrade golangci-lint without losing report parsing. ## Client-side coverage summing The Qlty CLI can now sum multiple coverage reports on the client before upload, complementing our existing server-side coverage merging. This is useful in CI workflows that already collect multiple coverage files on a single machine. ## Resync renamed repositories When a GitHub repository is renamed, you can now click a **Resync** button on the Add Project page to update Qlty's reference to the new repository name, keeping the Project's existing history and settings instead of having to re-add it from scratch. ## Python 3.13+ support The Qlty CLI now supports multiple Python runtime releases, enabling Python 3.13 and newer for plugins that require recent Python versions. ## On-demand source fetching You now have precise control over when private sources are loaded — useful in offline or air-gapped environments, and for pre-fetching sources once in CI before running multiple analyses. A new `qlty sources fetch` command fetches the sources defined in `qlty.toml` without running analysis, and a new `--skip-source-fetch` flag tells `qlty check` and `qlty fmt` to use what's already on disk. ```bash lines theme={"system"} qlty sources fetch qlty check --skip-source-fetch qlty fmt --skip-source-fetch ``` ## SLSA provenance for installers and upgrades Qlty CLI installer scripts are now published with [SLSA](https://slsa.dev/) attestations, and the `qlty upgrade` command verifies SLSA provenance for new releases using the `gh` CLI. This adds an extra layer of supply-chain integrity to installations and upgrades. ## Improved SAML re-authentication When a user accessing a Workspace with SAML enabled needs to re-authenticate, Qlty Cloud now surfaces a clearer re-authentication page with explicit instructions, rather than a generic error. ## Always-available PR Coverage tab The Pull Request Coverage tab now renders even when a base coverage report is missing, so reviewers always have a coverage view to work from. When there is no base report, diff coverage is displayed as "N/A" rather than blocking the page. ## Better missing coverage data messaging When a Project is missing expected coverage data, the Coverage page now displays a clearer message explaining what's missing and how to resolve it. ## HTTPS required for all outgoing requests The Qlty CLI now requires HTTPS for all outgoing HTTP requests, including source fetching and tool downloads. All network activity from the CLI is encrypted in transit. ## Jenkins CI auto-detection We now support automatic detection of build metadata from Jenkins. Uploading coverage from a Jenkins build only requires the path to the coverage data file. See [setting up coverage with Jenkins](/coverage/ci) for the full walkthrough. ```shell lines theme={"system"} qlty coverage publish coverage.lcov ``` ## Coverage page redesign A clearer view of how a pull request moves your coverage. The Project Coverage page has been rebuilt from the ground up, with: * Improved stats cards * A Files Changed tab with rendered file diffs * A Components tab showing per-Component coverage for the pull request * A collapsible sidebar with coverage comparison details ## Coverage summary comment improvements Coverage summary comments on pull requests have been redesigned. The new comment includes: * An updated rating display * A **Modified Components** section showing which Components changed in the pull request * An **AI prompt** section with a ready-to-paste prompt for your AI coding agent to write the missing tests * The Qlty header image and clearer formatting ## More coverage formats supported The Qlty CLI now ingests two more coverage report variants without any conversion step: * Apple's `xccov-json` format produced by `xccov` from Xcode coverage data * JaCoCo reports containing `` elements, the standard output for multi-module Maven and Gradle projects ## Coverage Report page Full visibility into how each commit's coverage report was built — and a way to clean it up when something goes wrong. Qlty Cloud now includes a Coverage Report details page for each commit, showing summary metrics and every upload that contributed to the report. Project admins can also delete individual reports or uploads from Coverage Settings when a bad upload needs to be removed. ## Maintainability shown as effort duration Maintainability is now displayed as estimated remediation effort (e.g. "2h 30m") in addition to issue counts, making it easier to compare projects and plan remediation work. ## Bitrise CI auto-detection We now support automatic detection of build metadata from Bitrise. Uploading coverage from a Bitrise build only requires the path to the coverage data file. ```shell lines theme={"system"} qlty coverage publish coverage.lcov ``` ## Configuration typo warnings The Qlty CLI now emits warnings when your `qlty.toml` contains unexpected attributes, helping you catch typos and outdated configuration syntax before they silently change your analysis. ## API rate limiting Qlty API requests are now rate limited to protect service availability for all users. Clients that exceed the limit receive a `429 Too Many Requests` response with standard rate-limit headers, so your client can back off cleanly. ## Automatic path fixing for coverage `qlty coverage publish` now automatically detects and corrects common path mismatches between coverage reports and the repository, including paths produced inside Docker containers and CI runners. This works in addition to the explicit `--add-prefix` and `--strip-prefix` options. See [Path Fixing](/coverage/path-fixing) for details. ## Install-only mode `qlty check` now supports an `--install-only` flag that installs the plugins required by your configuration without running them. Use it to warm caches in CI so the analysis step runs faster on every build. ## Onboarding flow We've shipped an updated onboarding flow for new users and new Workspaces, walking through GitHub installation, Project selection, and coverage setup. ## Coding with AI agents We've published a new guide on [coding with AI agents](/cli/coding-with-ai-agents) that documents recommended patterns for using the Qlty CLI with Claude Code, Cursor, GitHub Copilot, OpenAI Codex, and other agents that can run shell commands. ## Applications For teams that ship a single product across several repositories, Applications give you one view of code quality at the product level. Group related Projects together at the Workspace level and see aggregated maintainability, duplication, security, and coverage metrics across all of them. Enable Applications from **Settings > Features**, then assign Projects from each Project's **Settings > General**. See the [Applications documentation](/cloud/applications) for details. ## Churn view in Project Hotspots The Project Hotspots page now includes a churn view that combines maintainability issues with file change frequency to surface the files most likely to benefit from refactoring. ## Self-service Workspace deletion Workspace Owners can now delete their own Workspace directly from Workspace Settings, without needing to contact support. ## Improved Projects index The Workspace Projects page now supports server-side sorting, a column picker, and shows the timestamp of the last build for each Project. ## Components Track per-team or per-service code quality without splitting your repo. Qlty Cloud now supports Components, which let you group files inside a Project (for example, by service, package, or directory) and view maintainability metrics for each group independently. Components are particularly useful for monorepos and modular codebases. Configure them from your Project's settings. ## Workspace Activation page A new Activation page in Workspace Settings shows which Projects are activated, with sorting, filtering, and pagination — making it easier to manage Qlty across large organizations. ## ktlint plugin We've added a plugin for [ktlint](https://github.com/pinterest/ktlint), an anti-bikeshedding Kotlin linter and formatter. ```bash lines theme={"system"} qlty plugins enable ktlint ``` ## Delegated billing Delegated billing lets a single Workspace manage payment and subscription for one or more other Workspaces. This is useful for agencies, consultancies, and parent organizations that pay for multiple Workspaces. ## JaCoCo source path override Java and Kotlin projects with non-standard source layouts can now point JaCoCo coverage uploads at the right directories by setting the `JACOCO_SOURCE_PATH` environment variable before running `qlty coverage publish`. ## Workspace Manager permissions A new Workspace Manager role lets you delegate workspace-level administration to specific users without granting them GitHub Organization Owner permissions. See [User Permissions](/cloud/permissions) for the full permissions matrix. ## GitHub Merge Queue support The Qlty CLI now has initial support for GitHub Merge Queues. We also detect merge groups across any CI provider that listens to GitHub push events (#2320). ## Analysis Minutes progress bar Workspace billing pages now show an Analysis Minutes progress bar and a usage breakdown table so you can see at a glance how your build minutes are being consumed. ## Workspace pausing You can now pause a Workspace from its settings page. While paused, Qlty stops running analysis and coverage reporting — useful while a repository is dormant or when you need to temporarily halt billable usage without deleting the Workspace. ## Default coverage validation `qlty coverage publish` now validates coverage reports by default, catching path mismatches and malformed reports before they corrupt your metrics. If you need to temporarily disable validation while fixing a report, use `--no-validate`: ```bash lines theme={"system"} qlty coverage publish --no-validate coverage.lcov ``` See [Path Fixing](/coverage/path-fixing) for details. ## zizmor plugin We've added a plugin for [zizmor](https://github.com/woodruffw/zizmor), a security analyzer for GitHub Actions workflows. ```bash lines theme={"system"} qlty plugins enable zizmor ``` ## Coverprofile parser The Qlty CLI now parses Go's native `cover.out` (Coverprofile) format. You can upload Go coverage data without converting to another format first. ```bash lines theme={"system"} qlty coverage publish cover.out ``` ## Faster debugging of plugin install failures When a plugin fails to install, the Qlty CLI now surfaces the installation log directly in the main build log and points you to the full debug log on disk. No more guessing why a CI build broke during plugin setup. ## Project Hotspots Qlty Cloud now includes a Hotspots page on every Project. Hotspots highlight the files most likely to need attention by combining maintainability, duplication, and (in later updates) churn data. ## Named API access tokens API access tokens now have a name, description, and optional expiration date. You can manage your tokens from your user settings page. Existing tokens will continue to work — you can add metadata to them or rotate them at any time. ## Project Trends Qlty Cloud now includes a Trends tab on every Project. The Trends view visualizes how key quality metrics — including maintainability, duplication, and code coverage — change over time on your default branch. ## Qlty API (beta) Pull Qlty data into your own tools. The Qlty API is now in beta, with endpoints for listing and reading Projects and for reading analysis Issues for a Project. Authenticate with a personal access token from your user settings to query any Workspace you can access. See the [API Reference](/api/introduction) for details. ## Coverage Diff commit status setting A new workspace-level setting controls whether Qlty posts a separate **Coverage Diff** commit status to GitHub (in addition to the existing Coverage status). Toggle it from Workspace Settings if your branch protection rules don't expect this status. ## Git-free coverage publishing You can now publish coverage from environments that don't have a Git working directory — for example, containers that only carry the test artifacts. Pass `--override-commit-time` to `qlty coverage publish` to skip Git detection. ## dotCover format support The Qlty CLI now parses [dotCover](https://www.jetbrains.com/dotcover/) reports for .NET projects, in addition to the formats we already supported. ```bash lines theme={"system"} qlty coverage publish coverage.dcvr ``` ## SARIF output for `qlty smells` `qlty smells` now supports the `--sarif` flag, joining `qlty check` in producing standardized [SARIF](https://sarifweb.azurewebsites.net/) output for integration with other tools. ```bash lines theme={"system"} qlty smells --sarif ``` ## Qlty Cloud Enterprise plan We've added a new Enterprise plan for Qlty Cloud, tailored for organizations with advanced needs. This plan includes everything in our Pro plan, plus more analysis minutes and additional features to enhance your experience: * Priority support with a SLA * Named account manager available through a private Slack channel * Consolidated billing for multiple GitHub organizations * Payment via invoices (including ACH and wire transfer) * Migration assistance * Terms of Service customization Learn more about the [Enterprise plan](https://qlty.sh/pricing) and how it can benefit your organization. ## Server-side coverage merging We're proud to announce a long-requested feature: Server-side coverage merging! In testing workflows which involve multiple test suites, parallelization, or multiple programming languages it is common to produce multiple code coveragate data files. Previously, we only offered client-side coverage merging which required that all of the coverage data was available on the same filesystem and sent to the server as a single upload. In many scenarios, client-side merging was cumbersome and required uploading and downloading files from shared storage (like S3 or GitHub Actions artifacts). Also, visibility into the process was limited, resulting in a poor debugging experience if something went wrong. The addition of server-side merging significantly simplifies the set up of code coverage reporting in complex CI workflows, and enabled full visibility into the process from Qlty Cloud. To ensure accurate reporting, we delay posting coverage reports to GitHub until all of the coverage data is received. ```yaml GitHub Action lines theme={"system"} # Upload each coverage file separately - uses: qltysh/qlty-action/coverage@v1 with: oidc: true files: coverage/coverage1.lcov incomplete: true - uses: qltysh/qlty-action/coverage@v1 with: oidc: true files: coverage/coverage2.lcov incomplete: true # Tell Qlty all parts have been uploaded $ qlty coverage complete ``` ```bash Qlty CLI lines theme={"system"} # Upload each coverage file separately qlty coverage publish --incomplete coverage/coverage1.lcov qlty coverage publish --incomplete coverage/coverage2.lcov # Tell Qlty all parts have been uploaded qlty coverage complete ``` We support Learn more about [coverage merging](/coverage/merging) in our documentation. ## Qlty Cloud is out of beta We're excited to announce that we have completed our beta phase for Qlty Cloud and have advanced it to GA status! Thank you to everyone who provided feedback and helped us improve the product during the beta period. We are proud to have made significant improvements based on your input, including: * Server-side coverage merging * OpenID Connect (OIDC) authentication for easier coverage setup * Expanded support for programming languages like C# and Swift * Additional plugins, bringing our total to 70+ * Significant performance improvements to the Qlty Cloud website * Many bug fixes and improvements to the debugging experience With Qlty Cloud now in GA, we'll be activating our billing system for all users by the end of the month. We offer a plan which is free for unlimited, private contributors and have paid plans with additional features and build minutes. Learn more on our [pricing page](https://qlty.sh/pricing). We look forward to continuing to iterate Qlty rapidly to deliver code quality and coverage done right. ## StringsLint plugin We've added a plugin for [StringsLint](https://github.com/dral3x/StringsLint) which is ensures that localized strings in a Swift project are complete and never unused. StringsLint runs on macOS and targets files with the extensions `*.strings`, `*.stringsdict`, `*.swift`, `*.m`, `*.xib`, and `*.storyboard`. You can enable it using the Qlty CI: ```bash lines theme={"system"} qlty plugins enable stringslint ``` StringsLint only runs on macOS and is not available on Qlty Cloud which runs on Linux. ## SwiftFormat plugin We've added a plugin for [SwiftFormat](https://github.com/swiftlang/swift-format), the official auto-formatter for Swift. This auto-formatter targets Swift files, runs on macOS, and can be enabled using the Qlty CI: ```bash lines theme={"system"} qlty plugins enable swiftformat ``` SwiftFormat only runs on macOS and is not available on Qlty Cloud which runs on Linux. ## Cloud authentication improvements We've significantly improved the latency of most web pages by using a short-lived caching strategy for our GitHub authorization checks. Navigating around the website should feel faster. (The exception is the Dashboard, which we will be optimizing soon.) Also, for organizations that use SAML on GitHub, we now detect when GitHub requires SAML re-authorization and use that information to render better error messages. Users accessing a GitHub organization with SAML enabled need to re-authorize occasionaly, and we now show a message with instructions on how to do that. ## Out-of-the-box linter configs The Qlty CLI now provides out-of-the-box linter configurations for several popular linters. These linter configuration files are copied into your project when you run `qlty init` or `qlty plugins enable PLUGIN`. This allows you to quickly set up your project with sensible defaults without needing to create a configuration file manually. Once the configuration files are in place, you can customize them to fit your project's needs. ## Swift maintainability analysis Qlty now provides maintainability analysis for Swift. This includes duplication and complexity metrics as well as code smells. The maintainability analysis is available in the Qlty CLI and Qlty Cloud. ## ast-grep plugin We've added a plugin for [ast-grep](https://ast-grep.github.io/) (sg), a fast polyglot structural search and linting tool supporting 20+ languages. ast-grep offers a pattern language to support writing your own [custom checks](/custom-checks) or adopting checks provided by the ast-grep community. ```bash lines theme={"system"} qlty plugins enable ast-grep ``` ## Improved coverage uploader output We've updated the output from `qlty coverage publish` to include more information to improve the setup an debugging experience. ```toml lines theme={"system"} SETTINGS cwd: /home/runner/work/qlty/qlty add-prefix: src/ METADATA CI: GitHub Commit: c6dc5239a9e011e55ebdd598e35ce5700dc29741 Branch: main Build ID: 14975425147:1 COVERAGE FILES: 1 Coverage File Format Size remix/api-coverage/lcov.info lcov 2.32 KiB COVERAGE DATA 5 unique code file paths All code files in the coverage data were found on disk. Covered Lines: 57 Uncovered Lines: 24 Omitted Lines: 161 Line Coverage: 70.37% EXPORTING... Exported: tmp/qlty-coverage/coverage.zip AUTHENTICATION Auth Method: OIDC Token: *** PREPARING TO UPLOAD... Upload ID: 0efcc860-ede8-4466-9170-038cee46ccd1 UPLOADING... Uploaded 2.34 KiB in 0.28s! View report: https://qlty.sh/gh/qltysh/projects/qlty/settings/coverage/uploads/0efcc860-ede8-4466-9170-038cee46ccd1 ``` ## Package lockfiles The Qlty CLI now uses package lockfiles (e.g. `package-lock.json`, `yarn.lock`, `Gemfile.lock`) when they are available and the `package_file` directive is specified in the `qlty.toml` configuration file. This ensures the exact same linter versions are used across all machines, including Qlty Cloud. ## V1 of Coverage GitHub Action We've release v1.0.0 of our reusable GitHub Action for coverage uploading. We adhere to [semantic versioning](https://semver.org/) so going forward breaking changes will be represented with a bump in the major version. To use the latest version on the v1 line, pin your CI workflows to `@v1` like this: ```yaml lines theme={"system"} - uses: qltysh/qlty-action/coverage@v1 with: oidc: true files: coverage/lcov.info ``` ## BuildKite support We now support automatic detection of build metadata from BuildKite. Therefore, uploading code coverage data from BuildKite only requires executing the Qlty CLI with the path to the coverage data file. ```shell lines theme={"system"} qlty coverage publish coverage.lcov ``` ## OpenID Connect (OIDC) We now support OpenID Connect (OIDC) authentication for code coverage uploads from GitHub Actions. OIDC allows us to authenticate the repository running a GitHub Actions workflow with a short-lived token. This enables coverage uploading without needing to manage a long-lived token, providing better security and easier coverage setup. ```yaml lines theme={"system"} permissions: contents: read id-token: write # IMPORTANT # ... Later in a workflow job: ... - uses: qltysh/qlty-action/coverage@v1 with: oidc: true files: coverage/lcov.info ``` ## dockerfmt plugin We've add a plugin for [dockerfmt](https://github.com/reteps/dockerfmt), a tool for automatically formatting Dockerfiles. ```bash lines theme={"system"} qlty plugins enable dockerfmt ``` ## Support Linux Arm64 Musl The Qlty CLI now supports Linux systems using Arm64 architecture with Musl. We're now compiling binaries for these target systems with each release. To install the Qlty CLI on an Arm64 Linux system using Musl, use our installer: ```shell lines theme={"system"} curl https://qlty.sh | sh ``` ## SARIF output from Qlty CLI The Qlty CLI now supoprts [SARIF](https://sarifweb.azurewebsites.net/) output format. This is a standardized format for static analysis results, making it easier to integrate with other tools and platforms. To use the SARIF output format, simply add the `--sarif` flag to your Qlty CLI command. For example: ```bash lines theme={"system"} qlty check --sarif ``` ## Code coverate tags (beta) Qlty Cloud now offers support for Coverage Tags in beta. Coverage Tags are a powerful feature that allow you to group, upload, and report on coverage data with more granularity. Coverage Tags are particularly useful to track coverage by suite independently. For example, you can track unit test coverage separately from integration test coverage. They can also be used in monorepos to make it easy to upload and report on coverage by service. In addition to providing clear, independent reporting of coverage metrics, Coverage Tags also allow you to carry forward coverage data from previous runs. This means that you can maintain a complete picture of your code coverage over time, even if you only run a subset of all of your tests on each commit. To use Coverage Tags, you can add the `--tag` flag to the `qlty coverage publish` command. For example: ```bash lines theme={"system"} qlty coverage publish --tag unit coverage/unit.lcov qlty coverage publish --tag integration coverage/integration.lcov ``` ## php-cs-fixer plugin plugin We've added support for [php-cs-fixer](https://cs.symfony.com/), a tool that fixes your PHP code to follow standards including the PHP coding standards as defined in the PSR-1, PSR-2, etc., or other community driven standards from organizations like Symfony. ```bash lines theme={"system"} qlty plugins enable php-cs-fixer ``` ## Checkstyle plugin Qlty now supports [Checkstyle](https://checkstyle.sourceforge.io/), a tool that helps programmers write Java code that adheres to a coding standard. ```bash lines theme={"system"} qlty plugins enable checkstyle ``` ## Improved coverage comments We've made significant improvements to the code coverage summary comments from Qlty Could. The new comments include more information about the coverage impact of your pull request, including diff coverage and a breakdown of coverage changes by file. We've also added a "Help" section with definitions for the coverage metrics to help make it easier to interpret the results. ## Support for more SimpleCov formats We have added support for additional SimpleCov formats to make it easier to get your code coverage data from SimpleCov ingested into Qlty Cloud. We now support the simplecov-json and simplecov-merged formats. ## Negated exclusion patterns The Qlty CLI now supports negated exclusion patterns. Exclusion patterns are processed in order, matching the way that Git processes them. This means that if you have a negated pattern that matches a file, it will override any previous exclusion patterns that match the same file. You can use negated exclusion patterns in your `qlty.toml` file by prefixing the pattern with an exclamation mark (`!`). ```toml lines theme={"system"} exclude_patterns = [ "**/ignores/**.sh", "!**/dont_ignore/**", "**/ignores/dont_ignore/ignore_this_one.sh" ] ``` ## SempahoreCI support We now support automatic detection of build metadata from SemaphoreCI. Therefore, uploading code coverage data from SemaphoreCI only requires executing the Qlty CLI with the path to the coverage data file. ```shell lines theme={"system"} qlty coverage publish coverage.lcov ``` ## Coverage example repositories We now provide code coverage example repositories for many of the programming languages we support. These repositories are designed to help you get started with Qlty Cloud and provide a reference for how to set up code coverage reporting in your own projects. You can find links to all of the example repositories in our [documentation](https://docs.qlty.sh/coverage/example-repositories). ## Docker images for Qlty CLI We now build and publish Docker images for the Qlty CLI. This distribution format is an alternative to our native binaries and enables the use of the Qlty CLI on operating systems that are not natively supported. The Docker images are available on [GitHub Container Registry](https://github.com/qltysh/qlty/pkgs/container/qlty). ```shell lines theme={"system"} docker pull ghcr.io/qltysh/qlty:main ``` ## Pull request coverage tab Qlty Cloud has a new Coverage sub-tab on the Pull Request page. This tab provides a summary of the code coverage for the pull request, including a breakdown of coverage changes by file and their impact on your overall coverage. We also show the diff of the pull request with coverage annotations in the left gutter. ## Workspace-level coverage tokens Qlty Cloud now offers Workspace-level coverage tokens in order to simplify the seet up of uploading code coverage data. This feature is particularly useful for organizations that have multiple repositories and want to use the same coverage token across all of them. ## Code coverage debugging information We have significantly expanded the amount of debugging information available for code coverage uploads in the Qlty Cloud web app. Navigate the the "Code Covearge" section of Project Settings and you will be able to find a record of every code coverage upload, including the metadata and coverage metrics. We also provide a link to download the coverage information as a Zip file for easy inspeciton if something goes wrong. ## SOC 2 Type II certification Qlty Software Inc. is proud to announce that we have achieved SOC 2 Type II certification. You can find our full announcement on our [blog](https://qlty.sh/blog/qlty-achieves-soc-2-type-ii-certification). Additional information about our security and compliance program can be found in our [Trust Center](https://trust.qlty.sh/). ## C# maintainability analysis Qlty now provides maintainability analysis for C#. This includes duplication and complexity metrics as well as code smells. The maintainability analysis is available in the Qlty CLI and Qlty Cloud. ## Qlty CLI is now Fair Source The Qlty CLI is now released under a Fair Source license. This means that you can use the Qlty CLI for free including in commercial projects, as long as you are not using it to provide a competing service. After a delay, the Qlty CLI code reverts to an OSI-approved Open Source license, also known as delayed Open Source publication (DOSP). Read the full announcement on our [blog](https://qlty.sh/blog/qlty-cli-is-fair-source). # Qlty CLI vs. Qlty Cloud Source: https://docs.qlty.sh/cli-vs-cloud Qlty is available as a command line interface (CLI) that you can run on your machine, as well as a complete, hosted Code Health Platform. You can use either Qlty CLI or Qlty Cloud alone, or you can use them together. Your local Code Quality Toolkit Hosted Cloud Health Platform Here are some of the key differences. #### Qlty CLI * Qlty CLI makes it fast and easy to run 50+ linters locally * Qlty CLI supports multi-language auto-formatting * Qlty CLI offers the fastest feedback loop * Qlty CLI can automatically fix issues * Qlty CLI is available for Mac, Linux, and Windows #### Qlty Cloud * Qlty Cloud provides automated code review of pull requests * Qlty Cloud runs static analysis with no setup required * Qlty Cloud offers automated security scanning * Qlty Cloud tracks code coverage * Qlty Cloud provides quality visualizations and trends * Qlty Cloud works with repositories hosted on GitHub Cloud # Analysis Configuration Source: https://docs.qlty.sh/cli/analysis-configuration Qlty's static analysis is highly configurable to maximize the relevancy of your results. Project configuration is through a `qlty.toml` file which is committed into your Git repository as `.qlty/qlty.toml`. If your repository does not have a `.qlty/qlty.toml` file, Qlty Cloud will automatically generate a basic configuration before analysis. However, we strongly recommend checking in a `.qlty/qlty.toml` to enable customization. If you have the Qlty CLI installed, you can generate an initial configuration by running `qlty init`. This will look at the file types and configuration files in your repository to generate a baseline configuration. ```bash Generate a Qlty config for the current repository lines theme={"system"} qlty init ``` Alternatively, you can write your `.qlty/qlty.toml` file by hand. Here is a minimal starting point that you can check in: ```toml .qlty/qlty.toml lines theme={"system"} config_version = "0" exclude_patterns = ["**/node_modules/**"] test_patterns = ["**/test/**"] [[source]] name = "default" default = true ``` This configuration will analyze all [supported languages](/languages) for maintainability using the default thresholds. ## Excluding files and paths Qlty is Git-aware and honors `.gitignore` files. Additional exclude patterns can be specified using glob syntax: ```toml .qlty/qlty.toml lines theme={"system"} # ... exclude_patterns = [ "path/to/file.py", # Ignore a specific file "**/generated/**", # Ignore generated files "**/*.css" # Ignore all CSS files ] # ... ``` ## Maintainability checks and thresholds Qlty evaluates code maintainability using a set of static analysis checks implemented for all supported programming languages. These checks have reasonable defaults, and can be customized further. For example: ```toml .qlty/qlty.toml lines theme={"system"} # Disable the "too many return statements" check [smells.return_statements] enabled = false # Allow functions with 6 params (all languages) [smells.function_parameters] threshold = 6 # For Python, allow 7 params [language.python.checks] function_parameters.threshold = 7 ``` ## Linting and SAST plugins Plugins extend Qlty with thousands of checks from linters and security scanning tools. Plugin definitions are stored in a Git repository called a Source. Qlty provides a default source which should be included in your `.qlty/qlty.toml` as follows. (This is automatically generated if you used `qlty init`.) ```toml .qlty/qlty.toml lines theme={"system"} # ... [[source]] name = "default" default = true # ... ``` With your Source specified, you can list available plugins: ```bash List all available plugins with the CLI lines theme={"system"} qlty plugins list ``` Then, you can activate any [available plugin](/plugins) as follows. ```shell Qlty CLI lines theme={"system"} qlty plugins enable rubocop ``` ```toml qlty.toml lines theme={"system"} [[plugin]] name = "rubocop" version = "1.64.1" # Optionally, lock to a version ``` ## Plugin configurations When running Qlty, plugins are configured using their own analysis configuration files (e.g. `.eslintrc`). Plugin configuration files can be stored in the `.qlty/configs/` directory in order to keep the root of the repository tidy. Qlty will automatically make them available to plugins when it runs analysis. ## Check modes Qlty's maintinability analysis, linters, and security scanning plugins run Checks which emit findings called Issues. By configuring the *Mode*, you keep developer workflows streamlined while preserving issues for later review. Qlty Cloud uses the Mode to determine the behavior for handling issues. The Mode can be configured at a Plugin level to one of four options: | Mode | Behavior | | ---------- | --------------------------------------------------------------------- | | `disabled` | This plugin will not be run. | | `monitor` | Issues are browseable on Qlty.sh, but not annotated on GitHub | | `comment` | Issues generate code review comments but do not fail the Quality Gate | | `block` | This issue may cause the Quality Gate to fail. | ```toml .qlty/qlty.toml lines theme={"system"} [[plugin]] name = "osv-scanner" mode = "monitor" ``` ## Complete example ```toml .qlty/qlty.toml lines theme={"system"} config_version = "0" exclude_patterns = ["**/fixtures/**", "**/generated/**", "*.css"] # Code maintainability (structure and duplication) issues # are posted as comments but do not fail Quality Gates [checks] mode = "comment" [[source]] name = "default" default = true [[plugin]] name = "rubocop" version = "1.64.1" [[plugin]] name = "hadolint" [[plugin]] name = "shellcheck" [[plugin]] name = "osv-scanner" mode = "monitor" ``` ## More information * [Available Plugins](/plugins) * [Supported Languages](/languages) * [Project Configuration (`qlty.toml`) reference](/cli/qlty-toml) # Continuous Integration Source: https://docs.qlty.sh/cli/ci Most Qlty users user [Qlty Cloud](https://qlty.sh), our fully automated Code Health Platform, to run static analysis in the cloud, making CI setup unnecessary. However, there are a few use cases where running Qlty CLI in your continuous integration (CI) pipeline is useful. ## Auto-formatting your code nightly Qlty Cloud does not currently support auto-formatting your code. However, you can run `qlty fmt` in your CI pipeline to automatically format your code nightly. Here is an example GitHub Actions workflow: ```yml .github/workflows/fmt.yml lines theme={"system"} name: fmt on: workflow_dispatch: schedule: - cron: "0 6 * * *" permissions: contents: write jobs: format: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 with: ref: ${{ github.head_ref }} - uses: qltysh/qlty-action/fmt@main - name: Commit changes uses: stefanzweifel/git-auto-commit-action@v5 with: commit_message: qlty fmt --all branch: ${{ github.head_ref }} commit_user_name: qltysh[bot] commit_user_email: 168846912+qltysh[bot]@users.noreply.github.com commit_author: qltysh[bot] <168846912+qltysh[bot]@users.noreply.github.com> ``` ## Publishing code coverage data to Qlty Cloud Qlty CLI is used to publish code coverage data to Qlty Cloud. Please see our documentation for [setting up code coverage](/coverage/quickstart) for more information. # Coding with AI Agents Source: https://docs.qlty.sh/cli/coding-with-ai-agents # Use Qlty CLI with AI Coding Agents Qlty CLI gives your AI coding tools a universal "quality gate" for code linting, auto-formatting, and maintainability checks. When you let your coding agent run Qlty as part of its workflow, it can automatically clean up code, catch issues early, and ship changes that pass the same standards you expect from human contributors. ## Requirements * Qlty CLI installed and available on `$PATH`. * A Qlty analysis config (`.qlty/qlty.toml`) tailored to your project. ## Compatibility Qlty can be integrated with most AI coding agents that can run shell commands. Popular options include: * Claude Code * GitHub Copilot * Cursor IDE * OpenAI Codex * Other agents that can run shell commands Network access must be available from the agent environment. ## Integration methods Because `qlty` is a command-line tool, it can be integrated into your AI agent's workflow in several ways: 1. Project memory/instructions (simplest) -- e.g. `CLAUDE.md` 2. Git hooks -- This method works automatically for both humans and agents. 3. Agent-specific hooks -- e.g. Claude Code [hooks](https://docs.anthropic.com/en/docs/claude-code/hooks) The `qlty` command is run with CLI arguments and reads code files from the local filesystem. Output is printed to standard out, and exit codes indicate success or failure. This simple interface avoids the need for Model Context Protocol (MCP) server or API integration. ### Project memory integration Each AI Agent offer ways to integrate custom instructions. When coding, agents read these instructions and follow them as part of their workflow. You can add instructions to run the `qlty` command at the right time. The necessary instructions can be as simple as the following: ```md lines theme={"system"} - Before committing, ALWAYS run auto-formatting with `qlty fmt` - Before finishing, ALWAYS run `qlty check --fix --level=low` and fix any lint errors ``` You can customize these instructions to fit the particulars of your desired workflow. Each AI coding agent has different paths that it will check for instructions files. Some examples include: * Claude Code: `CLAUDE.md` * Cursor: `AGENTS.md` * OpenAI Codex: `AGENTS.md` * GitHub Copilot: `.github/copilot-instructions.md` Please refer to the documentation of your chosen agent for details on how to add custom instructions. ### Git hooks integration The Qlty CLI can be run through Git hooks to enforce quality gates for both human and AI commits. This method works with any AI agent that can commit code via Git. The typical configuration is to set up a pre-commit hook to run `qlty fmt` and a pre-push hook to run `qlty check`. See [Qlty Git Hooks](/cli/git-hooks) for more details. # cache clean Source: https://docs.qlty.sh/cli/commands/cache-clean ```bash lines theme={"system"} qlty cache clean [OPTIONS] ``` Delete the cache for the current project This will remove all cached results, logs, and debugging files for the current repository. It can be useful when debugging or to reclaim disk space. Stored files that are shared by the Qlty CLI between repositories, like installed plugins, are not affected by this command. ## Examples ```bash Clean the cache for the current repository lines theme={"system"} qlty cache clean ``` ## See Also * [`cache dir`](/cli/commands/cache-dir) * [`cache status`](/cli/commands/cache-status) * [Global Options](/cli/global-options) # cache dir Source: https://docs.qlty.sh/cli/commands/cache-dir ```bash lines theme={"system"} qlty cache dir [OPTIONS] ``` Print the cache directory for the current project The Qlty CLI creates symlinks from within the *repository's* top-level `.qlty/` folder into a global `~/.qlty/` directory within the home directory. This command retrieves the *global* filesystem path to where those files are stores (a non-symlink path). For example: ``` /Users/username/.qlty/cache/repos/da4c81b6f6ee723c7f3c1490954ac29e ``` ## Examples ```bash Print the cache directory for the current repository lines theme={"system"} qlty cache dir ``` ## See Also * [`cache clean`](/cli/commands/cache-clean) * [`cache status`](/cli/commands/cache-status) * [Global Options](/cli/global-options) # cache status Source: https://docs.qlty.sh/cli/commands/cache-status ```bash lines theme={"system"} qlty cache status [OPTIONS] ``` Print the status of the cache directory for the current project The printed information includes file counts and sizes for the cached analysis results, project logs, and debug files. ## Examples ```bash Print the cache status for the current repository lines theme={"system"} qlty cache status ``` ## See Also * [`cache clean`](/cli/commands/cache-clean) * [`cache dir`](/cli/commands/cache-dir) * [Global Options](/cli/global-options) # check Source: https://docs.qlty.sh/cli/commands/check ```bash lines theme={"system"} qlty check [OPTIONS] [PATHS]... ``` Run linters By default, only changed files are analyzed. Use `--all` or specify paths to override this behavior. Installs plugins and their required runtimes as needed before analyzing. By default, issues are cached locally to speed up subsequent runs. Must be run within a Git repository with Qlty initializd. ## Arguments Files to analyze Check all files, not just changed Apply all auto-fix suggestions automatically. When combined with `--ai`, AI-generated fixes are applied without prompting for review. See [AI Autofixes Security Considerations](/cloud/ai-autofixes#security-considerations) for important guidance when using this flag. Do not apply auto-fix suggestions Generate AI-powered fixes using a large language model (requires Qlty Cloud authentication). AI fixes should be reviewed before applying. Using `--ai` with `--fix` applies AI suggestions automatically without review—see [Security Considerations](/cloud/ai-autofixes#security-considerations). Allow fixes for rules that may produce incorrect results and require careful human review. By default, fixes for certain rules are blocked because they are more likely to need manual judgment. This flag removes those restrictions. Disable formatter checks Disable progress bar Exit successfully regardless of what issues are found Exit successfully regardless of linter errors Sample results from a number of files for each linter Minimum level of issues to show \[default: note] \[possible values: note, fmt, low, medium, high] Maximum number of concurrent jobs Filter by plugin or check Print verbose output Print a summary of issues Upstream base ref to compare against Disable caching issues Print errors to stderr Minimum level of issues to fail on \[default: fmt] \[possible values: note, fmt, low, medium, high] SARIF output ## Examples ```bash Run linters on changed files on your current branch lines theme={"system"} qlty check ``` ```bash Run linters on all files lines theme={"system"} qlty check --all ``` ```bash Run only ESLint on all files lines theme={"system"} qlty check --all --filter=eslint ``` ```bash Run linters on the web/ folder lines theme={"system"} qlty check web/ ``` ## See Also * [`init`](/cli/commands/init) * [`fmt`](/cli/commands/fmt) * [Available Plugins](/plugins) * [Excluding Files](/cli/excluding-files) * [Ignoring Checks and Issues](/cli/ignoring-issues) * [Global Options](/cli/global-options) # completions Source: https://docs.qlty.sh/cli/commands/completions ```bash lines theme={"system"} qlty completions [OPTIONS] ``` Generate or install Qlty CLI shell completions When the `--shell` argument is omitted, it will attempt to detect the current shell using the `$SHELL` environment variable (or an operating system check for PowerShell on Windows). When the `--install` argument is specified, it will attempt to update the current user's shell configuration to include the tab completions. This operation involves *writing* to files like `.zshrc` but should generally be safe. ## Arguments Shell to generate completions for \[possible values: bash, elvish, fish, powershell, zsh] Install completions for the given shell ## Examples ```bash Install Qlty CLI completions for the current shell lines theme={"system"} qlty completions --install ``` ```bash Generate completions for Bash (no install) lines theme={"system"} qlty completions --shell bash ``` ## See Also * [`init`](/cli/commands/init) * [Global Options](/cli/global-options) # config migrate Source: https://docs.qlty.sh/cli/commands/config-migrate ```bash lines theme={"system"} qlty config migrate [OPTIONS] ``` Update qlty.toml with settings from .codeclimate.yml Qlty’s [default thresholds for Code Smells](https://docs.qlty.sh/qlty-toml#smellsnamethreshold) differ from the [default thresholds](https://docs.codeclimate.com/docs/default-analysis-configuration#default-thresholds) in Quality Classic. Because of this, maintainability ratings in Qlty may differ from those seen in Classic. For repos with a committed `.codeclimate.yml` file, `qlty config migrate` will adjust your Qlty configuration to more closely align with your configuration in Quality Classic. For example: * If your `.codeclimate.yml` specifies a custom threshold for the `return-statements` check, `qlty config migrate` will copy this threshold into your `qlty.toml` * If your `.codeclimate.yml` does not specify a custom threshold for the `return-statements` check, `qlty config migrate` will copy the default threshold for Quality Classic’s `return-statements` check into your `qlty.toml` Additionally, `qlty config migrate` will copy any existing `prepare` statements which exist in your `.codeclimate.yml`. ## Arguments Prints the migrated version of qlty.toml to the console without saving it to disk ## Examples ```bash Migrate configuration from .codeclimate.yml into qlty.toml lines theme={"system"} qlty config migrate ``` ```bash Preview the migration without making changes lines theme={"system"} qlty config migrate --dry-run ``` ## See Also * [`config show`](/cli/commands/config-show) # config show Source: https://docs.qlty.sh/cli/commands/config-show ```bash lines theme={"system"} qlty config show [OPTIONS] ``` Print the full, merged configuration Qlty uses a strategy of merging layered configuration in this order: 1. Global defaults 2. Any Sources declared in the project's `qlty.toml` 3. Configuration from the `qlty.toml` Each layer is able to override the earlier layers using a deep merge. The result of this process is a single, merged configuration with all of the configuration that Qlty uses. This command prints that configuration in YAML format to aid with debugging. If the configuration is missing or invalid, the command will exit with an error. ## Examples ```bash Print the current project's full, merged configuration lines theme={"system"} qlty config show ``` ## See Also * [`config validate`](/cli/commands/config-validate) * [Global Options](/cli/global-options) # config validate Source: https://docs.qlty.sh/cli/commands/config-validate ```bash lines theme={"system"} qlty config validate [OPTIONS] ``` Validate the current project's configuration If the configuration is valid, the command will exit successfully with no output. If the configuration is missing or invalid, the command will exit with an error. ## Examples ```bash Validate the current project's configuration lines theme={"system"} qlty config validate ``` ## See Also * [`config show`](/cli/commands/config-show) * [Global Options](/cli/global-options) # coverage publish Source: https://docs.qlty.sh/cli/commands/coverage-publish ```bash lines theme={"system"} qlty coverage publish [OPTIONS] [PATHS]... ``` Upload coverage reports to the Qlty Cloud The `qlty coverage publish` command uploads code coverage reports to Qlty Cloud for analysis. It supports multiple report formats to ensure compatibility with various programming languages, including `simplecov`, `clover`, `cobertura`, `coverprofile`, `lcov`, `jacoco`, and the generic `qlty` format. Beyond uploading reports, this command allows the addition or removal of file path prefixes, tagging uploads for easier identification, and overriding the value of certain git-related variables. It integrates code coverage data into Qlty Cloud, offering a comprehensive view of your codebase's coverage. ## Arguments One or more paths to the coverage reports to be uploaded Do not upload the coverage report, only export it to the output directory The format of the coverage report to transform. If not specified, the format will be inferred from the file extension or contents \[possible values: simplecov, clover, cobertura, coverprofile, lcov, jacoco, qlty] A tag to associate with this coverage report upload Override the build identifier from the CI environment Override the branch from the CI environment Override the commit SHA from the CI environment Override the pull request number from the CI environment Override the git tag from the CI environment Do not validate coverage data before publishing Skip fetching remote sources before publishing. When set and a remote source is not cached locally, publishing warns and falls back to the default configuration instead of fetching. Useful in CI where source fetching is unwanted or unavailable The prefix to add to file paths in coverage payloads, to make them match the project's directory structure The prefix to remove from absolute paths in coverage payloads to make them relative to the project root. This is usually the directory in which the tests were run. Defaults to the root of the git repository The token to use for authentication when uploading the report. By default, it retrieves the token from the QLTY\_COVERAGE\_TOKEN environment variable The name of the project to associate the coverage report with. Only needed when coverage token represents a workspace and if it cannot be inferred from the git origin Print coverage Verbose Suppress all output except for errors The total number of parts that qlty cloud should expect. Each call to qlty publish will upload one part. (The total parts count is per coverage tag e.g. if you have 2 tags each with 3 parts, you should set this to 3) ## Example Upload a [Cobertura](https://cobertura.github.io/cobertura/) report to Qlty Cloud: ```sh lines theme={"system"} qlty coverage publish cobertura.xml ``` ## See Also * [`(Qlty Cloud) Setting up Code Coverage`](/coverage/quickstart) # dashboard Source: https://docs.qlty.sh/cli/commands/dashboard ```bash lines theme={"system"} qlty dashboard [OPTIONS] ``` Open the Qlty Cloud dashboard in the browser ## Examples ```bash Open the Qlty Cloud dashboard lines theme={"system"} qlty dashboard ``` ## See Also * [Global Options](/cli/global-options) # deinit Source: https://docs.qlty.sh/cli/commands/deinit ```bash lines theme={"system"} qlty deinit [OPTIONS] ``` Remove Qlty from the current repository This command has the effect of removing the `.qlty/` directory at the root of the repository. All cached analysis results, logs, and debugging files will be lost. Because this is a destructive operation, the command will prompt for interactive confirmation. The `--yes` argument can be used to skip the confirmation step. If Qlty is not initialized in the current repository, this command will exit with an error. ## Arguments Proceed without confirmation ## Examples ```bash Remove the Qlty configuration from the current project lines theme={"system"} qlty deinit ``` ## See Also * [`init`](/cli/commands/init) * [Global Options](/cli/global-options) # discord Source: https://docs.qlty.sh/cli/commands/discord ```bash lines theme={"system"} qlty discord [OPTIONS] ``` Join our Discord server (opens in the browser) ## Examples ```bash Open the Qlty Discord server lines theme={"system"} qlty discord ``` ## See Also * [Global Options](/cli/global-options) # docs Source: https://docs.qlty.sh/cli/commands/docs ```bash lines theme={"system"} qlty docs [OPTIONS] ``` Open the docs website in the browser ## Examples ```bash Open the Qlty documentation lines theme={"system"} qlty docs ``` ## See Also * [Global Options](/cli/global-options) # fmt Source: https://docs.qlty.sh/cli/commands/fmt ```bash lines theme={"system"} qlty fmt [OPTIONS] [PATHS]... ``` Auto-format files by rewriting them By default, only changed files are auto-formatted. Use `--all` or specify paths to override this behavior. Installs plugins and their required runtimes as needed before analyzing. Must be run within a Git repository with Qlty initializd. ## Arguments Files to analyze Check all files, not just changed Disable progress bar Exit successfully regardless of linter errors Sample results from a number of files for each linter Maximum number of concurrent jobs Filter by plugin or check \[default: manual] \[possible values: manual, pre-commit, pre-push, build] Print verbose output Upstream base ref to compare against Format files in the Git index Format files in the specified Git index file ## Examples ```bash Auto-format changed files on your current branch lines theme={"system"} qlty fmt ``` ```bash Auto-format all files with prettier lines theme={"system"} qlty fmt --all --filter=prettier ``` ```bash Auto-format files in a directory lines theme={"system"} qlty fmt web/ ``` ## See Also * [`init`](/cli/commands/init) * [`check`](/cli/commands/check) * [Available Plugins](/plugins) * [Excluding Files](/cli/excluding-files) * [Global Options](/cli/global-options) # help Source: https://docs.qlty.sh/cli/commands/help ```bash lines theme={"system"} qlty help [SUBCOMMAND]... ``` Print this message or the help of the given subcommand(s) Example output: ```plain lines theme={"system"} Usage: qlty [OPTIONS] [COMMAND] Commands: cache Manage cache check Run linters completions Generate shell completions config Print current version coverage View, transform, and publish code coverage dashboard Open the Qlty Cloud dashboard deinit Remove Qlty from the repository discord Join our Discord server docs Open the docs website fmt Auto-format init Set up Qlty in the repository install Install linters and formatters metrics Compute code metrics plugins Manage plugins smells Check code quality upgrade Upgrade Qlty to the latest version version Print current version help Print this message or the help of the given subcommand(s) Options: --debug Log with more information --no-upgrade-check Do not check for updates -h, --help Print help -V, --version Print version ``` ## Examples ```bash Show top-level subcommands lines theme={"system"} qlty help ``` ```bash Show auth subcommands lines theme={"system"} qlty help auth ``` ## See Also * [`version`](/cli/commands/version) * [Global Options](/cli/global-options) # init Source: https://docs.qlty.sh/cli/commands/init ```bash lines theme={"system"} qlty init [OPTIONS] ``` Set up Qlty in the current repository This command will generate an initial project configuration file based on the contents of the repository and write it to `.qlty/qlty.toml` at the repository root. When run without the `--skip-plugins` command, initialization will try to determine a reasonable set of linters and formatters to enable. Certain linters and formatters are enabled based on the detection of a linter configuration file. Others are enabled just based on the presence of target files of the programming language. Following initialization, the command will print a summary of the configuration. After generating a configuration file, the command will ask if you want to *sample* the results of the enabled plugins. Sampling runs each plugin against a small set of targets. If Qlty is already initialized in the current repository, this command will exit with an error. ## Arguments Answer yes to all prompts Answer no to all prompts Skip enabling plugins Print the generated configuration to stdout instead of saving to disk Initialize without default source A custom source to use for plugins. This can be a URL(name=url) or a path to a local directory(name=directory) ## Examples ```bash Generate a Qlty config for the current repository lines theme={"system"} qlty init ``` ```bash Generate a Qlty config and skip prompts lines theme={"system"} qlty init --no ``` ```bash Generate a Qlty config with no plugins lines theme={"system"} qlty init --skip-plugins ``` ## See Also * [`deinit`](/cli/commands/deinit) * [Global Options](/cli/global-options) # install Source: https://docs.qlty.sh/cli/commands/install ```bash lines theme={"system"} qlty install [OPTIONS] ``` Install linters and their dependencies This command will examine the current project's configuration and install enabled plugins and any dependencies (e.g. runtimes like NodeJS). Installations are cached and re-used between runs of `qlty check` and `qlty fmt`. Under normal circumstances, running `qlty install` is not necessary, because plugins will automatically be installed as needed. However, plugin installations require an Internet connection and in some cases can be slow, so `qlty install` can be used to prepare the system for future analysis. When run without the `--filter [FILTER]` argument, only the specified plugins and their dependencies will be installed. By default *all* plugins are installed. ## Arguments Disable progress bar Maximum number of concurrent jobs Filter by plugin or check ## Examples ```bash Install all plugins lines theme={"system"} qlty install ``` ```bash Install ESLint lines theme={"system"} qlty install --filter=eslint ``` ## See Also * [Global Options](/cli/global-options) # metrics Source: https://docs.qlty.sh/cli/commands/metrics ```bash lines theme={"system"} qlty metrics [OPTIONS] [PATHS]... ``` Compute code quality metrics Calculate metrics like classes count, complexity, lines of code, and cohesion for [supported languages](/languages) using our custom built static analysis. ## Arguments Files to analyze Compute metrics for all files, not just changed Print per-directory stats Print function stats Directory depth to print, this flag will also set to print per-directory stats Sort output by column \[possible values: name, classes, functions, fields, lines, loc, complexity, lcom] Maximum rows to print Exclude tests Upstream base ref to compare against Only show results ## Examples ```bash Summarize metrics across directories lines theme={"system"} qlty metrics --all --max-depth 2 ``` ```bash Review the 10 most complex files lines theme={"system"} qlty metrics --all --sort complexity --limit 10 ``` ```bash View function-level metrics for a file lines theme={"system"} qlty metrics --functions remix/app/root.tsx ``` ## See Also * [`qlty init`](/cli/commands/init) * [`qlty smells`](/cli/commands/smells) * [Support Languages](/languages) * [Excluding Files](/cli/excluding-files) * [Global Options](/cli/global-options) # plugins disable Source: https://docs.qlty.sh/cli/commands/plugins-disable ```bash lines theme={"system"} qlty plugins disable [OPTIONS] [PLUGINS]... ``` Disable plugins for the current project The command edits the current project's `qlty.toml` file to disable plugins. ## Arguments Plugins to disable by name ## Examples ```bash Disable the latest version of shellcheck lines theme={"system"} qlty plugins disable shellcheck ``` ```bash Disable rubocop and eslint lines theme={"system"} qlty plugins disable rubocop eslint ``` ## See Also * [`plugins enable`](/cli/commands/plugins-enable) * [`plugins upgrade`](/cli/commands/plugins-upgrade) * [`plugins list`](/cli/commands/plugins-list) * [Global Options](/cli/global-options) # plugins enable Source: https://docs.qlty.sh/cli/commands/plugins-enable ```bash lines theme={"system"} qlty plugins enable [OPTIONS] [PLUGINS]... ``` Enable plugins for the current project The command edits the current project's `qlty.toml` file to enable plugins. ## Arguments Plugins to enable specified as name=version ## Examples ```bash Enable the latest version of shellcheck lines theme={"system"} qlty plugins enable shellcheck ``` ```bash Enable shellcheck version 1.2.3 lines theme={"system"} qlty plugins enable shellcheck=1.2.3 ``` ```bash Enable rubocop and eslint lines theme={"system"} qlty plugins enable rubocop eslint ``` ## See Also * [`plugins upgrade`](/cli/commands/plugins-upgrade) * [`plugins disable`](/cli/commands/plugins-disable) * [`plugins list`](/cli/commands/plugins-list) * [Global Options](/cli/global-options) # plugins list Source: https://docs.qlty.sh/cli/commands/plugins-list ```bash lines theme={"system"} qlty plugins list [OPTIONS] ``` List all available plugins This command lists all available plugins based on the sources declared in the current project's `qlty.toml` configuration file. ## Examples ```bash List all available plugins lines theme={"system"} qlty plugins list ``` ## See Also * [`plugins enable`](/cli/commands/plugins-enable) * [`plugins upgrade`](/cli/commands/plugins-upgrade) * [`plugins disable`](/cli/commands/plugins-disable) * [Global Options](/cli/global-options) # plugins upgrade Source: https://docs.qlty.sh/cli/commands/plugins-upgrade ```bash lines theme={"system"} qlty plugins upgrade [OPTIONS] ``` Upgrade a plugin for the current project The command edits the current project's `qlty.toml` file to upgrade plugin version. ## Arguments Plugin to upgrade Optional - Specific version to upgrade to ## Examples ```bash Upgrade to the latest compatible version of shellcheck lines theme={"system"} qlty plugins upgrade shellcheck ``` ```bash Upgrade shellcheck to version 1.2.3 lines theme={"system"} qlty plugins upgrade shellcheck --version=1.2.3 ``` When specifying the version with --version option, it is responsibility of the user to make sure the version is valid and compatible with qlty. ## See Also * [`plugins enable`](/cli/commands/plugins-enable) * [`plugins disable`](/cli/commands/plugins-disable) * [`plugins list`](/cli/commands/plugins-list) * [Global Options](/cli/global-options) # smells Source: https://docs.qlty.sh/cli/commands/smells ```bash lines theme={"system"} qlty smells [OPTIONS] [PATHS]... ``` Find code smells like duplication and complexity Detect issues like duplication (copy and pasted code), high complexity, deeply nested control flows, etc. for [supported languages](/languages) using our custom built static analysis. ## Arguments Files to analyze Compute smells for all files, not just changed Don't check for duplication Include tests Don't show code snippets Upstream base ref to compare against Only show results ## Examples ```bash Analyze your current branch lines theme={"system"} qlty smells ``` ```bash Analyze your entire project for code smells lines theme={"system"} qlty smells --all ``` ```bash Analyze specific paths for code smells lines theme={"system"} qlty smells example-app/components/ui react-app/utils ``` ```bash Analyze a specific file for code smells lines theme={"system"} qlty smells example-app/components/ui/Dropdown.tsx ``` ```bash Skip duplication analysis lines theme={"system"} qlty smells --all --no-duplication ``` ```bash Analyze for code smells against a specific upstream branch lines theme={"system"} qlty smells --upstream origin/main ``` ## See Also * [Code Smells](/code-smells) * [Duplication](/duplication) * [Excluding Files](/cli/excluding-files) * [`qlty check`](/cli/commands/check) * [Global Options](/cli/global-options) # upgrade Source: https://docs.qlty.sh/cli/commands/upgrade ```bash lines theme={"system"} qlty upgrade [OPTIONS] [COMMAND] ``` Upgrade the Qlty CLI When run without a `--version` argument, this command checks if there is a newer version of the Qlty CLI available than the current version. If there is a release to install, it will download and unpack it to a tempoary directory. It will then rename the executable to replace the currently running executable, to complete the upgrade. Finally, the upgrade command will attempt to install shell completions. ## Arguments The version to upgrade to. Defaults to the latest version Run the upgrade even if the latest version is already installed Whether to perform a dry run ## Commands Upgrades the source ## Examples ```bash Upgrade to the latest Qlty CLI if one is available lines theme={"system"} qlty upgrade ``` ```bash Upgrade to version 0.299.0 lines theme={"system"} qlty upgrade --version 0.299.0 ``` ```bash Force re-installation even if no new version is available lines theme={"system"} qlty upgrade --force ``` ## See Also * [`completions`](/cli/commands/completions) * [Global Options](/cli/global-options) # version Source: https://docs.qlty.sh/cli/commands/version ```bash lines theme={"system"} qlty version [OPTIONS] ``` Print the current Qlty CLI version Example output: ```plain lines theme={"system"} qlty 0.303.0 (14cfc6e) ``` Version follow [Semantic Versioning](https://semver.org/). Following the version number is the Git commit SHA that the CLI was built from. Debug builds are indicated with the word `debug` following the Git commit SHA. Otherwise, it is a release build. ## Examples ```bash Print the current version lines theme={"system"} qlty version ``` ## See Also * [`help`](/cli/commands/help) * [Global Options](/cli/global-options) # Plugins Source: https://docs.qlty.sh/cli/concepts/plugins Qlty integrates with linters, auto-formatters, security scanners, and other static analysis tools as plugins. Looking for plugin-specific configuration options, supported versions, or invocation details? Each plugin lives in its own folder under [qltysh/qlty/qlty-plugins](https://github.com/qltysh/qlty/tree/main/qlty-plugins) on GitHub — check the plugin's `plugin.toml` and `README.md` for specifics. Each plugin consists of two components: 1. A plugin definition in a TOML configuration file 2. A results parser implemented in Rust Here is a simplified example plugin definition for [Ruff](https://github.com/astral-sh/ruff): ```toml plugin.toml for ruff lines theme={"system"} config_version = "0" [plugins.definitions.ruff] runtime = "python" package = "ruff" file_types = ["python"] version_command = "ruff version" config_files = ["ruff.toml"] issue_url_format = "https://docs.astral.sh/ruff/rules/${rule}" [plugins.definitions.ruff.drivers.lint] script = "ruff check --exit-zero --output-format sarif --output-file ${tmpfile} ${target}" success_codes = [0] output = "tmpfile" output_format = "sarif" batch = true ``` Gitleaks supports outputting results in the [SARIF](https://sarifweb.azurewebsites.net/) standard format, so a custom results parser is not needed. For tools which do not support SARIF, a results parser is implemented within the Qlty CLI and referenced by name. ## Auto-Formatters Auto-formatters are a special type of plugin because they *rewrite* files rather than outputting findings. Therefore, they do not require results parsers. Here is an example of a plugin definition for the [shfmt](https://github.com/mvdan/sh) auto-formatter: ```toml plugin.toml for shfmt lines theme={"system"} config_version = "0" [plugins.definitions.shfmt] package = "mvdan.cc/sh/v${major_version}/cmd/shfmt" runtime = "go" file_types = ["shell"] version_command = "shfmt --version" affects_cache = [".editorconfig"] [plugins.definitions.shfmt.drivers.format] script = "shfmt -w -s ${target}" success_codes = [0, 1] output = "rewrite" cache_results = true batch = true driver_type = "formatter" ``` Note the specification of `output = "rewrite"` and `driver_type = "formatter"`. # Runtimes Source: https://docs.qlty.sh/cli/concepts/runtimes For plugins which are not distributed as native binaries, Qlty supports a variety of Runtimes which are generally virtual machines: * Golang * Java * NodeJS * PHP * Python * Ruby Qlty is capable of installing packages using the package manager for each runtime (e.g. NPM for NodeJS). ## Runtime versions By default, Qlty will run the latest version of each runtime that it has been tested against as-needed in order to run plugins. It is also possible to specify the exact version of a Runtime to use with the following syntax: ```toml qlty.toml lines theme={"system"} # ... [runtimes.enabled] python = "3.10.13" # ... ``` With this configuration, Qlty will always use Python v3.10.13 when running PIP-based plugins. ## Optional runtime dependencies The PHP and Ruby runtimes have additional, optional system dependencies. Please see the [System Requirements](/cli/system-requirements#optional-dependencies) for additional information. # Sources Source: https://docs.qlty.sh/cli/concepts/sources Sources provide reusable Plugin definitions packaged as a Git repository. ## Adding Sources Sources are added to the `qlty.toml` configuration file in your repository using the following syntax: ```toml qlty.toml lines theme={"system"} [[source]] name = "default" default = true ``` Each Source declaration can point to the `default` source that comes bundled with the cli or an external repository with either a `tag` or a `branch`. If you target a tag, Qlty will fetch and checkout that tag when it first runs, and will never try to update it. If you target a branch, Qlty will check for updates to the named branch each time it runs. ```toml qlty.toml lines theme={"system"} [[source]] name = "custom" repository = "https://github.com/example/qlty-plugins.git" tag = "v1.2.3" # OR # branch = "main" ``` ## Default Source Qlty maintains a default source with linters, formatters, and security scanners which is automaticaly added to `qlty.toml` when initializing a new project: ```toml qlty.toml lines theme={"system"} # ... [[source]] name = "default" default = true # ... ``` ## Custom Sources You are not limited to the default source provided by Qlty. You can create your own custom Sources and reuse them across multiple projects. To do this, simply create a public Git repository with the following structure: ```shell lines theme={"system"} your-source-repository/ └─ linters/ └─ [linter-name]/ └─ plugin.toml ``` # Debugging Source: https://docs.qlty.sh/cli/debugging ## Plugin errors A plugin error indicates that a plugin exited with a status code that is interpretted as an error. This can occur for a number of different reasons. For example, some linters will crash if they attempt to analyze files with invalid syntax. Some linters exit with a non-zero code when they find issues. Qlty treats these exit codes as *success* to differentiate the case where a plugin ran successfully identified issues vs. a crash or unexpected failure. ### Verbose and debug output Typically the first step to investigating a plugin error is to re-run the plugin with verbose or debug output enabled. Here is an example: ```sh lines theme={"system"} qlty check --all --verbose --debug --filter=stylelint ``` The `--debug` option will increase the amount of detail in the logs going to `.qlty/logs/qlty-cli.*`. You can tail this log as you run the CLI to watch for issues with `tail -f .qlty/logs/qlty-cli.*`. The `--verbose` option will cause the CLI to print a summary of every invocation (execution) of the plugin from the run. The full details of each invocation are recorded in an output file saved to the `.qlty/out/` directory. Here is an example: ```yaml maxLines=10 lines theme={"system"} qlty_cli_version: 0.319.0 invocation_id: LaW4ba plugin_name: markdownlint driver_name: lint verb: Check config_files: - /Users/username/p/qltysh/qlty/.qlty/configs/.markdownlint.json - /Users/username/p/qltysh/qlty/.markdownlint.json script: sh -c "markdownlint --json fern-public/fern/docs/pages/cloud/additional-information/faq.mdx" env: PATH: /Users/username/.qlty/cache/tools/markdownlint/0.41.0-a8b86ee94758/node_modules/.bin:/Users/username/.qlty/cache/tools/node/19.6.0-cac67db15d71/bin:/Users/username/.qlty/cache/tools/node/19.6.0-cac67db15d71:/Users/username/.qlty/cache/tools/node/19.6.0-cac67db15d71/bin:/Users/username/.qlty/cache/tools/node/19.6.0-cac67db15d71:/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin HOME: /Users/username NODE_PATH: /Users/username/.qlty/cache/tools/markdownlint/0.41.0-a8b86ee94758/node_modules cwd: /Users/username/p/qltysh/qlty duration_secs: 0.187106333 exit_result: Success exit_code: 1 stdout: "" stderr: | [ { "fileName": "fern-public/fern/docs/pages/cloud/additional-information/faq.mdx", "lineNumber": 5, "ruleNames": [ "MD041", "first-line-heading", "first-line-h1" ], "ruleDescription": "First line in a file should be a top-level heading", "ruleInformation": "https://github.com/DavidAnson/markdownlint/blob/v0.34.0/doc/md041.md", "errorDetail": null, "errorContext": "## Can I use Qlty without the ...", "errorRange": null, "fixInfo": null } ] tmpfile_path: null tmpfile_contents: null parser_error: null ``` From this file you can see the exact command that was run, the environment variables that were set, and the output that was produced. If any errors occurred, they will be included. ### `Could not find "[package-name]"` (Missing plugin extension) A common error is that a plugin may be missing an extension references in its configuration. For example: ``` Lint error stylelint: Exited with code 78 .qlty/out/invoke-tPeFXQ.yaml Error: Could not find "@blueprintjs/stylelint-plugin". Do you need a `configBasedir`? at module.exports (/Users/username/.qlty/cache/tools/stylelint/14.6.1-a7e99b04b5e3/node_modules/stylelint/lib/utils/configurationError.js:11:49) at getModulePath (/Users/username/.qlty/cache/tools/stylelint/14.6.1-a7e99b04b5e3/node_modules/stylelint/lib/utils/getModulePath.js:28:9) at /Users/username/.qlty/cache/tools/stylelint/14.6.1-a7e99b04b5e3/node_modules/stylelint/lib/augmentConfig.js:153:60 at Array.map () at absolutizePaths (/Users/username/.qlty/cache/tools/stylelint/14.6.1-a7e99b04b5e3/node_modules/stylelint/lib/augmentConfig.js:153:44) at Object.transform (/Users/username/.qlty/cache/tools/stylelint/14.6.1-a7e99b04b5e3/node_modules/stylelint/lib/augmentConfig.js:81:27) at runLoad (/Users/username/.qlty/cache/tools/stylelint/14.6.1-a7e99b04b5e3/node_modules/cosmiconfig/dist/Explorer.js:104:49) at async cacheWrapper (/Users/username/.qlty/cache/tools/stylelint/14.6.1-a7e99b04b5e3/node_modules/cosmiconfig/dist/cacheWrapper.js:16:18) at async extendConfig (/Users/username/.qlty/cache/tools/stylelint/14.6.1-a7e99b04b5e3/node_modules/stylelint/lib/augmentConfig.js:201:24) at async augmentConfigBasic (/Users/username/.qlty/cache/tools/stylelint/14.6.1-a7e99b04b5e3/node_modules/stylelint/lib/augmentConfig.js:52:20) ``` This error indicates that the Stylelint plugin was unable to load `@blueprintjs/stylelint-plugin`. The reason that this would happen is because the Qlty CLI installs static analysis tools into sandboxes in order to create conssitent, reporducible results whereever it is run. When an erorr like this occurs, you will generally find that the references package (in this case, `@blueprintjs/stylelint-plugin`) is included in the project's `package.json` file. By default, we do not install the packages in the `package.json` file when we run analysis. There are a three ways to fix this: Specify the `extra_packages` option for the plugin in `qlty.toml`. Any listed packages will be installed into the tool's sandbox making them available. Here is an example: ```toml lines theme={"system"} [[plugin]] name = "stylelint" version = "14.16.1" extra_packages = ["stylelint-config-standard-scss@11.0.0"] ``` This tells Qlty to install `stylelint-config-standard-scss@11.0.0` into the sandbox for the `stylelint` plugin before running. This syntax works for simple cases and has the benefit of keeping the dependency declaration directly inline with the plugin configuration. This will cause Qlty to install all of the packages in the `package.json` file into the sandbox for the plugin. Here is an example: ```toml lines theme={"system"} [[plugin]] name = "stylelint" version = "14.16.1" package_file = "package.json" ``` If you are using a lot of extensions for your static analysis tools, this is a good way to get up and running quickly. The primary disadvantage is that all of the dependencies need to be installed before static analysis can be run, which can slow things down. This allows you to install all the extensions you need quickly and can allow you to de-clutter your main `package.json` file. Here is an example: ```sh lines theme={"system"} cd .qlty/configs echo '{}' > package.json npm install --save-dev stylelint-config-standard-scss ``` ```toml lines theme={"system"} [[plugin]] name = "stylelint" version = "14.16.1" package_file = ".qlty/configs/package.json" ``` You can read more about this at [linter extensions page](/cli/linter-extensions). ### `Could not find "[config file].[json]"` (Missing configuration file) If you have a static analysis configuration file that is not using one of the tool's standard configuration filenames, Qlty needs to know about it. Otherwise, you will see errors like this: ``` Error: Could not find "../../../../shared/stylelintrc.shared.json". Do you need a `configBasedir`? ``` The fix is to make the Qlty CLI aware of the configuration filename, in this case `stylelintrc.shared.json`. To do this, you need to override the *definition* of the Stylelint plugin to include all of the configuration file names you use in your project. For example, you can add this towards the top of your `.qlty/qlty.toml` file: ```toml lines theme={"system"} [plugins.definitions.stylelint] config_files = [ ".stylelintrc", ".stylelintrc.cjs", ".stylelintrc.js", ".stylelintrc.json", ".stylelintrc.yaml", ".stylelintrc.yml", "stylelintrc.shared.json", # Custom, shared configuration file ] ``` This will cause Qlty to ensure that all of those listed configuration files, including the custom, shared configuration file, are properly made available to the plugin. ## Plugin parser errors A parse error indicates that Qlty was unable to process the results output by the plugin. This can happen is a static analysis tool changes its output format. If you encounter a parse error with a plugin, please contact support for assistance. # Developing Plugins Source: https://docs.qlty.sh/cli/developing-plugins Qlty is built on an extensible plugin platform that makes it easy to integrate linters, formatters, and security scanners. We will eventually be opening the plugin system up completely so that you can add plugins yourself if you'd like. For now, while we refine our system, we are happy to handle everything for you. ## Requesting new plugins Our goal is to ensure you can run all of the static analysis you need a single, unified experience with Qlty. If there is a static analysis tool that you use which we do not currently support, please let us know. Typically, we can add support for a new plugin with one week. To ensure a high quality product experience, we avoid adding plugins for static analysis tools that are no longer maintained. ## Customizing existing plugins Existing plugins can be customized via your project configuration file (`.qlty/qlty.toml`). Using this approach, you can modify things like: * File types to analyze * Installing additional packages during setup (e.g. ESLint plugins) * Customizing issue categories or levels * Customizing linter invocations * Caching * Batching Please contact us and we would be happy to help you with this. ## More information * [Available Plugins](/plugins) # Excluding Files and Folders Source: https://docs.qlty.sh/cli/excluding-files Qlty is Git aware and always excludes `.gitignore`'d files. Additionally, we provide multiple ways to exlcude files from analysis. ## Using `exclude_patterns` in qlty.toml Files and path patterns can also be excluded in your project configuration (`.qlty/qlty.toml`) using the `exclude_patterns` key at the top level. For example: ```toml lines theme={"system"} # .. exclude_patterns = ["some/file.py", "**/fixtures/**"] # ... ``` Files that are excluded like this are not processed by any static analysis. `exclude_patterns` applies to static analysis only. To exclude files from **code coverage** reporting, you'll need to configure exclusions within your local coverage tool where coverage data is generated. See [Excluding Files from Coverage](/coverage/excluding-files) for details. ## See Also * [Ignoring Checks and Issues with Qlty CLI](/cli/ignoring-issues) * [Ignoring Checks and Issues with Qlty Cloud](/cloud/triaging-issues) # Frequently Asked Questions (FAQ) Source: https://docs.qlty.sh/cli/faq ## Why is Qlty not showing the specifics of formatting issues? Unlike linters, which are designed to output violations of rules, auto-formatters are instead simply rewrite your code on disk to adhere to match their defined standard. When Qlty analyzes your code, we run the auto-formatters in sandbox directory. This allows us to check if the auto-formatted result matches the current version of the file in you working directory, without overwriting it. If a change is detected in auto-formatters result, Qlty will emit an issue with the following description: > Incorrect formatting, autoformat by running `qlty fmt` No additional information is available so we cannot reference line numbes or specific formatting issues. The solution is to run the auto-formatter by running [`qlty fmt`](https://docs.qlty.sh/cli/commands/fmt) locally and commit the result. Additionally, by [integrating auto-formatters into your workflow](https://docs.qlty.sh/auto-formatting#integrating-auto-formatting-into-your-workflow), you can eliminate formatting issues before they make it to your PRs. # Git Hooks Source: https://docs.qlty.sh/cli/git-hooks Qlty can be integrated into git using git hooks to ensure: 1. code is formatted before committing (pre-commit hook) 2. code meets quality standards before pushes (pre-push hook) ## Installation Installation is easiest using the Qlty CLI. 1. First [Install Qlty](https://docs.qlty.sh/cli/quickstart). 2. Run: ```sh lines theme={"system"} qlty githooks install ``` See the [hook files](https://github.com/qltysh/qlty/tree/main/qlty-cli/src/commands/githooks) to understand what will be installed or to perform manual installation. ## Pre-push The Git pre-push hook will ensure that files are auto-formatted before pushing. If there are files that are formatted incorrectly, it will format them and generate a new commit. Due to the way Git works, when this occurs, you will need to run `git push` again. You can always run `git push --no-verify` to skip the pre-push hook. # Global Options Source: https://docs.qlty.sh/cli/global-options These options are available on every subcommand. ## Arguments Increase the level of detail written to the Qlty logs Disable the upgrade check for new Qlty CLI versions Print help information ## Environment Variables Control logging precisely with a [logging directive](https://docs.rs/tracing-subscriber/latest/tracing_subscriber/filter/struct.EnvFilter.html#directives). Takes precedence over `--debug`. For example, to maximize logging from Qlty code set `QLTY_LOG=qlty=trace`. # Ignoring Issues with Qlty CLI Source: https://docs.qlty.sh/cli/ignoring-issues To fine tune your analysis results, you can ignore issues within your source code or through rules in your `qlty.toml` project configuration file. ## Mute comments Qlty CLI supports using mute comments in your source code files to ignore issues on a line, within a block of code, or for an entire file. This documentation is coming soon. In the meantime, please contact us and we can help! ## Adding `[[exclude]]` rules in qlty.toml Qlty CLI also allows a simple way to exclude certain plugins from running on a set of files in your project configuration file (`.qlty/qlty.toml`). Each `[[exclude]]` block can specify conditions by plugins and file patterns. Qlty will avoid running the given plugins on files that match the given patterns or ignore any issues matching the plugins and file patterns. Examples: ```toml lines theme={"system"} # Exclude eslint from running on files in remix/app/components/ui/ [[exclude]] plugins = ["eslint"] file_patterns = ["remix/app/components/ui/**"] ``` ## Adding `[[triage]]` rules in qlty.toml Qlty CLI also allows a highly flexible way to suppress issues in your project configuration file (`.qlty/qlty.toml`). Each \[\[triage]] block can specify match conditions by plugins, rules, file globs, and levels. If an issue matches all the specified conditions, it will be ignored. Examples: ```toml lines theme={"system"} # Ignore the eslint react/prop-types check only in remix/app/components/ui/ [[triage]] match.rules = ["eslint:react/prop-types"] match.file_patterns = ["remix/app/components/ui/**"] set.ignored = true ``` ```toml lines theme={"system"} # Ignore all rubocop issues at "low" level [[triage]] match.plugins = ["rubocop"] match.levels = ["low"] set.ignored = true ``` ## Reviewing ignored issues Issues that have been ignored in the project configuration file (`.qlty/qlty.toml`) are surpressed at generation time and cannot be viewed in the Qlty web application. ## See Also * [Excluding Files](/cli/excluding-files) * [Triaging Issues with Qlty Cloud](/cloud/triaging-issues) ``` ``` # Integrity Verification Source: https://docs.qlty.sh/cli/integrity-verification Qlty publishes cryptographic attestations for all CLI releases, allowing you to verify that the binary you downloaded was built by Qlty and hasn't been tampered with. These attestations are powered by [Sigstore](https://www.sigstore.dev/) and published as [GitHub artifact attestations](https://docs.github.com/en/actions/security-for-github-actions/using-artifact-attestations/using-artifact-attestations-to-establish-provenance-for-builds). ## How it works When we release a new version of the Qlty CLI, our GitHub Actions workflow: 1. Builds the CLI binaries for each supported platform 2. Generates a cryptographic attestation for each build artifact 3. Publishes the attestations to GitHub's attestation store These attestations cryptographically prove that the binary was built from our official repository using our CI/CD pipeline. ## Verifying the CLI You can verify the integrity of any Qlty CLI release using the GitHub CLI (`gh`). The `gh` CLI must be authenticated to verify attestations, even for public repositories. Run `gh auth login` first if you haven't already. **Example (macOS Apple Silicon):** ```shell lines theme={"system"} # Download the archive from https://github.com/qltysh/qlty/releases curl -LO https://github.com/qltysh/qlty/releases/latest/download/qlty-aarch64-apple-darwin.tar.xz # Verify the attestation gh attestation verify --owner qltysh qlty-aarch64-apple-darwin.tar.xz # Unpack and install tar -xJf qlty-aarch64-apple-darwin.tar.xz sudo mv qlty-aarch64-apple-darwin/qlty /usr/local/bin/ ``` For other platforms, download the appropriate archive from [GitHub releases](https://github.com/qltysh/qlty/releases). ## Successful verification A successful verification will display output similar to: ``` Loaded digest sha256:abc123... for file qlty-aarch64-apple-darwin.tar.xz Loaded 1 attestation from GitHub API ✓ Verification succeeded! ``` This confirms the binary was signed by GitHub Actions and built from the official Qlty repository. ## Learn more * [GitHub artifact attestations documentation](https://docs.github.com/en/actions/security-for-github-actions/using-artifact-attestations/using-artifact-attestations-to-establish-provenance-for-builds) * [Sigstore](https://www.sigstore.dev/) * [Qlty CLI releases](https://github.com/qltysh/qlty/releases) # Qlty CLI Internals Source: https://docs.qlty.sh/cli/internals ## Upstream Analysis This documentation is coming soon. In the meantime, please contact us and we can help! ## Reproducibility This documentation is coming soon. In the meantime, please contact us and we can help! ## Performance ### Caching This documentation is coming soon. In the meantime, please contact us and we can help! ### CPU Utilization This documentation is coming soon. In the meantime, please contact us and we can help! ## Configuration Merging This documentation is coming soon. In the meantime, please contact us and we can help! # Linter Extensions Source: https://docs.qlty.sh/cli/linter-extensions Linter extensions are additional packages or plugins that extend the functionality of base linter tools that Qlty uses. Depending on the linter, extensions can add: * Additional rule sets * Custom rules * Language support * Framework-specific checks * Additional parsers For example, ESLint has numerous plugins like `eslint-plugin-react`, `eslint-plugin-security`, and `eslint-plugin-jest` that add specialized rules for React development, security checks, and Jest testing, respectively. ## Supported Package Managers Qlty supports linter extensions through the following package managers: * **NPM** (Node.js) - For JavaScript/TypeScript tools like ESLint, Stylelint, etc. * **RubyGems** (Ruby) - For Ruby tools like RuboCop, Standard, etc. * **PIP** (Python) - For Python tools like Ruff, Pylint, Bandit, etc. * **Composer** (PHP) - For PHP tools like PHP\_CodeSniffer, PHPStan, etc. ## Managing linter extensions Qlty provides two mutually exclusive ways to configure linter extensions in your `qlty.toml` file: `extra_packages` and `package_file`. ### `extra_packages` The `extra_packages` property allows you to explicitly list additional packages that should be installed alongside the main linter package (including their versions). ```toml qlty.toml lines theme={"system"} [[plugin]] name = "eslint" version = "8.57.0" extra_packages = [ "eslint-plugin-react@7.33.2", "eslint-plugin-jest@27.6.0" ] ``` This works best when your project contains a very limited set of extra packages (1-2), but does not scale well for moderate to complex projects. **Pros:** * Simple, direct specification * Version pinning * Works without existing package files **Cons:** * Duplicates existing dependency management (e.g. package.json) * May diverge from project dependencies * Supports external packages only (not, e.g. in Project packages) ### `package_file` The `package_file` property allows you to reference a package manager file (like `package.json` or `Gemfile`) to manage dependencies. Depending on your use case, you can point the `package_file` either at your project's main package file or at a specific file that contains the linter-related packages. ```toml Project package file lines theme={"system"} [[plugin]] name = "eslint" version = "8.57.0" package_file = "package.json" ``` ```toml Linter package file lines theme={"system"} [[plugin]] name = "eslint" version = "8.57.0" package_file = ".qlty/configs/package.json" ``` **Pros:** * Take advantage of package manager's dependency resolution * Consistent with project dependencies (if pointing to the main package file) **Cons:** * Project's main package file contains many dependencies #### Unified or Linter-Specific Package File When using the `package_file` property, you can specify either the Project's standard package file, or create a new one with just linter-related dependencies. Which should you choose? Some considerations: * In some cases, [limitations](#limitations) may prevent a Project from using the project's primary package file. In these cases, using a separate package file is the only option, but usually works well. * For compatible package files, pointing qlty at your project's main package file results in qlty installing all of your projects dependencies, increasing build time. You can use [package\_filters](#package_filters) to limit these, but package filters cannot honor lock files * Reducing dependency duplication, so that all linter dependencies only exist in this new package file may require additional work. For example, if using standalone linters, in addition to qlty, you may need to update these tools to point at the new package file. #### `package_filters` When using `package_file`, you can use `package_filters` to selectively include only specific packages from the package file. This will cause Qlty to *filter* the packages in the package file and only install the ones that match the filters. This is most useful when you are pointing the `package_file` directive to your project's main package file, and you want to install only the linter-related packages. This can be used to speed up the installation of linters. You can achieve the same goal as package\_filters by using a separate package file which only contains linter dependencies. Because a separate package file's dependencies can be fully resolved using a lock file, we prefer this option. ```toml qlty.toml lines theme={"system"} [[plugin]] name = "eslint" version = "8.57.0" package_file = "package.json" package_filters = ["eslint"] ``` The `package_filters` option can offer a performance speed up or workaround issues installing the app dependencies at the tradeoff of additional complexity. ## Lock files Package lock files (like `package-lock.json`, `Gemfile.lock`, `yarn.lock`) can impact how Qlty installs and manages linter extensions: * When using `package_file`, Qlty respects the locked versions for reliability * When using `package_file` with `package_filters`, the lock files are ignored * For `extra_packages`, lock files are not used and specific versions are installed directly ## Custom RuboCop cops Qlty supports using in-repository Rubocop custom cops - custom rules defined within your codebase, which are referenced in your `.rubocop.yml` config file. Names of any such related files need to be added to plugin config. Otherwise you may get an error like `cannot load such file -- /tmp/qlty/qEYkEfFX-rw/./path/to/local/file` ```qlty.toml lines theme={"system"} [[plugin]] name = rubocop config_files = ["custom_cop.rb"] # files names of custom configuration files, not paths ``` ## Limitations Qlty currently does not support: * **Private linter extensions** - Extensions from private Git repositories or private package registries that require authentication * **Git-based dependencies** - Extensions referenced directly as Git repositories * **Local file dependencies outside the repository** - Extensions referenced from paths outside the repository ## Troubleshooting 1. **Version conflicts** If you see errors like "Dependency conflict" or "Incompatible versions", try: * Aligning versions between your package file and extra\_packages * Using `package_filters` to selectively include compatible packages 2. **Missing extensions** If a linter reports missing plugins or rules: * Verify the extension is correctly specified in `extra_packages` or `package_file`. * Check for typos in package names. * Ensure compatible versions are specified. 3. **Slow performance** If linter installation becomes slow with extensions: * Use either `package_filters` to filter installations, or create a separate package file for linter-related packages. 4. **Configuration issues** If the linter can't find the extension configuration: * Ensure your configuration file correctly references the extensions. * Check that the extension is properly installed. # Project Config (qlty.toml) Source: https://docs.qlty.sh/cli/qlty-toml Project configuration stored in a `qlty.toml` file is used by both Qlty CLI and Qlty Cloud. We strongly recommend that this file is committed into Git version control. This file uses the [TOML](https://toml.io/en/) format and is located at `.qlty/qlty.toml` in your repository: ```text theme={"system"} your-git-repository/ ├── .qlty/ │ ├── ... other qlty files │ └── qlty.toml └── ... rest of your repository files ``` If you do not have a `.qlty/qlty.toml` file checked in to your repository, Qlty Cloud will generate a new, temporary configuration file before running the analysis using `qlty init`. ## `qlty.toml` Specification Each field in the `qlty.toml` file corresponds to a specific configuration setting. Detailed descriptions of these settings are provided below. ### `config_version` The version of the `qlty.toml` configuration file format. Currently, all `config_version`s are `0`. We may use this field in the future to introduce breaking changes to the configuration file format. ### `sources` `sources` are defined at the top-level and specify repositories which contain plugin definitions. By convention, sources are placed at the top of the `qlty.toml` file. The default auto-generated configuration file will include a default source conveniently named `default`. You can add additional sources from other Git repositories and name them as you like. Below are the accepted properties to define a source: | Name | Description | | ------------ | -------------------------------------------------------------- | | `name` | A unique name for this source | | `default` | Set to `true` for the primary source (only one allowed) | | `repository` | The URL of the git repository | | `tag` | The tag to fetch from the repository (conflicts with `branch`) | | `branch` | The branch to fetch from the repository (conflicts with `tag`) | Follow the example below to add a new source: ```toml lines theme={"system"} [[source]] name = "example" repository = "https://github.com/example/example.git" branch = "main" ``` For each source, you can specify either a `tag` or a `branch`, but not both. If you specify both, the `tag` will be used. ### `exclude_patterns` Qlty is Git-aware and honors `.gitignore` files. The `exclude_patterns` setting allows you to specify additional directories and/or files that should be completely excluded from all Qlty activities, both from Qlty Cloud and Qlty CLI. This setting uses [glob syntax](https://en.wikipedia.org/wiki/Glob_\(programming\)) to match file and directory names. This setting is useful for excluding files that are not relevant for Qlty, such as generated code, build artifacts, temporary files, or third-party libraries. Below is an example of how to customize the `exclude_patterns` setting to fit your project: ```toml lines theme={"system"} exclude_patterns = [ "*.log", "**/*.min.js", "**/node_modules/**", "**/*.spec.js" ] ``` ### `test_patterns` The `test_patterns` setting allows you to specify directories and/or files that should considered automated tests run at build time rather than runtime application code. Qlty Cloud uses this information in order to provide higher quality analysis results. This setting uses [glob syntax](https://en.wikipedia.org/wiki/Glob_\(programming\)) to match file and directory names. Below is an example of how to customize the `test_patterns` setting to fit your project: ```toml lines theme={"system"} test_patterns = [ "**/test/**", "**/spec/**", "**/test_*.*", "**/spec_*.*", "**/*_test.*", "**/*_spec.*", ] ``` ### `smells` The `smells` setting defined at the top-level is used to configure the functioning of the `qlty smell` CLI command, which is employed by Qlty Cloud to identify code smells in your project. This allows you to customize the detection and management of various code quality smells. These settings apply for all supported programming languages, and can be customized further for each language using the `languages` setting. #### `smells.mode` The `mode` setting determines how Qlty Cloud handles detected code smells. Four modes are available: | Mode | Description | | ------------------- | ----------------------------------------------------------------------- | | `block` | Code smells may fail the Qlty Gate (post them as pull request comments) | | `comment` (default) | Post comments on pull requests but never fail the Qlty Gate | | `monitor` | Analyze and report smells on Qlty Cloud but never post them to GitHub | | `disabled` | Smell detection will be disabled | #### `smells.[name].enabled` The `enabled` setting allows you to enable or disable the detection of specific code smells. By default, all smells are enabled, but you can selectively disable those that are not relevant to your project. Below is an example of how to enable or disable specific smells: ```toml lines theme={"system"} [smells.boolean_logic] enabled = true [smells.nested_control_flow] enabled = false ``` #### `smells.[name].threshold` The `smells.[name].threshold` setting allows you to fine-tune the parameters for identifying specific types of code smells. Below is a comprehensive list of all available smell settings and their default thresholds: | Smell Name | Threshold | Default | | --------------------- | ---------------------------------------------------------------------------------- | ------- | | `boolean_logic` | Maximum number of boolean operators (such as `and` or `or`) in a single expression | 5 | | `nested_control_flow` | Maximum number of nested control flow statements | 5 | | `function_parameters` | Maximum number of function parameters | 5 | | `return_statements` | Maximum number of return statements in a function | 6 | | `file_complexity` | Maximum allowed complexity for a single file | 50 | | `function_complexity` | Maximum function complexity | 15 | | `identical_code` | Minimum number of duplicated lines for identical code to be flagged | 12 | | `similar_code` | Minimum number of duplicated lines for similar code to be flagged | 12 | #### `smells.duplication` The `smells.duplication` setting configures umbrella settings for duplicated code detection (*copypasta code*) that apply to both the `identical_code` and `similar_code` smells. | Setting Name | Description | Default | | ----------------- | ------------------------------------------------------------------------------------------------------ | ------- | | `nodes_threshold` | The minimum number of AST children nodes for a single node to be included in the duplication detection | 50 | | `filter_patterns` | Glob patterns to exclude from duplication checks | | To control the `enabled` and `threshold` settings for duplication, use `smells.identical_code` and `smells.similar_code` instead: ```toml lines theme={"system"} [smells.identical_code] enabled = true threshold = 20 [smells.similar_code] enabled = true threshold = 20 [smells.duplication] nodes_threshold = 30 ``` These settings apply to all programming languages. You can customize the duplication detection settings for specific languages using the `language` setting. ### `language.[name]` The `language.[name]` setting allows you to customize various settings on a per-language basis, applicable to both Qlty Cloud and Qlty CLI. #### `language.[name].smells` This setting enables you to configure the detection and management of various code quality smells for a specific programming language. Below is an example of how to customize the detection of code smells for a particular language: ```toml lines theme={"system"} [language.rust.smells] duplication.filter_patterns = ["(use_declaration _)"] duplication.nodes_threshold = 40 function_parameters.threshold = 6 function_complexity.threshold = 20 ``` Alternatively, you can use this equally valid [TOML](https://toml.io/en/) syntax: ```toml lines theme={"system"} [language.rust.smells.duplication] filter_patterns = ["(use_declaration _)"] nodes_threshold = 40 [language.rust.smells.function_parameters] threshold = 6 [language.rust.smells.function_complexity] threshold = 20 ``` ### `[[plugin]]` Each `[[plugin]]` entry must be defined at the top-level of the `qlty.toml` file, specifying the configuration for a specific plugin. You will need one `[[plugin]]` entry for each plugin you want to enable in your project. Below are the accepted properties for defining a `[[plugin]]` entry: | Name | Description | | ----------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `name` | The plugin name, e.g., *eslint*, *rubocop*, etc | | `version` | The plugin version, following the version specification used by the plugin (this may vary across plugins) | | `extra_packages` | Some plugins, like the *stylelint* plugin, are usually used in combination with other packages such as `stylelint-config-standard-scss`. This setting allows you to define these additional packages. This is also commonly used by other plugins such as *eslint* and *rubocop* | | `package_file` | This setting is only relevant to some plugins, like *eslint*, that heavily depend on external files. It specifies where a certain package file is located. For *eslint*, you may want to indicate the location of your `package.json` | | `package_filters` | This setting is only relevant when package\_file is specified, it is a list of strings, if a package in the package\_file has a name containing a filter, it is filtered out and the rest are removed from package file, so that only relevant packages can be installed. | | `drivers` | List of drivers to activate for the plugin, if not specified all drivers are activated. | | `config_files` | List of file names (not paths), that contain configuration information needed to run the plugin, for example custom cop files for rubocop. | | `affects_cache` | List of file names (not paths), changing which can affect the cache of existing issues for a plugin. | | `mode` | Enum with the values: `block`, `comment`, `monitor`, `disabled`.
- `block`: sends red statuses on Github
- `comment`: only sends comments
- `monitor`: just records the issues
- `disabled`: disables the plugin | | `triggers` | List of enum values: `manual`, `ide`, `agent`, `pre-commit`, `pre-push`, `build`.
Use to trigger the plugin on specific events only and not all. | | `skip_upstream` | Whether the plugin should run against the upstream or not. The default is `false` | | `prefix` | Run the plugin in a specific subdirectory of the project root, the plugin's targets and config files are limited to that subdirectory only. Useful for monorepo setups, as same plugin can be specified with multiple prefixes. | Follow the example below to customize the execution of a plugin: ```toml lines theme={"system"} [[plugin]] name = "stylelint" version = "15.10.3" extra_packages = ["stylelint-config-standard-scss@11.0.0"] ``` To get started with a new plugin, you can run `qlty plugins enable ` to automatically add the plugin to your `qlty.toml file`. ### `[[exclude]]` The `[[exclude]]` block allows you to declare rules to ignore certain issues in your project, applicable to both Qlty Cloud and Qlty CLI. Each `[[exclude]]` entry can specify conditions based on `plugins`, and `file patterns`. Qlty will avoid running the given plugins on files matching the patterns and ignore any issues that match them. Below are the accepted properties for defining an `[[exclude]]` entry: | Name | Description | | ---------------- | ----------------------------------------------------------------------------------------------------------------- | | `file_patterns ` | A list of glob patterns to match files that should be ignored. The default pattern is `*` which matches all files | | `plugins` | A list of *plugin* names. Issues reported by these plugins will be ignored | Below is an example of how to use the `[[exclude]]` setting: ```toml lines theme={"system"} # Exclude eslint from running on files in remix/app/components/ui/ [[exclude]] plugins = ["eslint"] file_patterns = ["react-app/app/components/ui/**"] ``` `[[exclude]]` blocks are evaluated sequentially, and the first match will be applied. ### `[[triage]]` The `[[triage]]` block allows you to modify certain properties of issues detected by Qlty. Each `[[triage]]` entry is broken down into two parts, `match` and `set`. Match can specify conditions based on `plugins`, `levels`, `rules`, and `file patterns` to determine which issues the triage apply to. If an issue matches all the specified conditions, its properties will be overridden by the values specified in the set part of the `[[triage]]` entry. Below are the properties for defining an `[[triage]]` entry, divided into *match.* and *set.*: #### Match | Name | Description | | --------------- | ------------------------------------------------------------------------------------------------------------------------- | | `plugins` | A list of plugin names. Issues reported by these plugins will be matched | | `rules` | A list of rule names. Issues reported by these rules will be matched. Rules are plugin specific | | `levels` | A list of levels. Issues reported at these levels will be matched. | | `file_patterns` | A list of glob patterns to match files whose issues should be matched. The default pattern is `*` which matches all files | #### Set | Name | Description | | ---------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `level` | The new level for the issues that match the conditions. Possible values are `unspecified`, `fmt`, `low`, `medium`, `high` | | `category` | The new category for the issues that match the conditions. Accepted categories are: `bug`, `vulnerability`, `structure`, `duplication`, `security_hotspot`, `performance`, `documentation`, `type_check`, `style`, `anti_pattern` and `accessibility` | | `mode` | The new mode for the issues that match the conditions. Possible values are `block`, `comment`, `monitor`, `disabled` | | `ignored` | The issues are ignored if set to true. Accepts boolean values true or false | Below are examples of how to use the `[[triage]]` setting: ```toml lines theme={"system"} # Override the level of eslint react/prop-types issues in react-app/components/ui/ to "low" [[triage]] match.rules = ["eslint:react/prop-types"] match.file_patterns = ["react-app/components/ui/**"] set.level = "low" # Override the mode of all rubocop issues to "comment" [[triage]] match.plugins = ["rubocop"] set.mode = "comment" # Override the category of issues in node_modules directory to "dependency" [[triage]] match.file_patterns = ["**/node_modules/**"] set.category = "dependency" ``` `[[triage]]` blocks are evaluated sequentially, and the first match will be applied ## Glob Syntax Reference Following, a table that illustrates the most commonly used glob syntaxes accepted by Qlty: | Example Pattern | Matches | | --------------- | -------------------------------------------------------- | | `foo.rb` | `foo.rb` at the top-level of the repository | | `*.rb` | all files at the top-level that end with `.rb` | | `**/foo.rb` | `foo.rb` anywhere in the repository | | `**/*.rb` | all files that end with `.rb` anywhere in the repository | | `**/test/**` | All folders named `test` at any level | ## Full Example The exact auto generated version of your `.qlty/qlty.toml` file will vary depending on the languages and frameworks used in your project. Below is a general example of how it may look like for a JavaScript project. ```toml lines theme={"system"} config_version = "0" # Required, must be the string "0" exclude_patterns = ["**/node_modules/**","**/vendor/**"] test_patterns = ["**/test/**", "**/spec/**"] [[source]] name = "default" default = true # The default source for plugin definitions [[plugin]] name = "actionlint" [[plugin]] name = "checkov" version = "3.2.49" [[plugin]] name = "markdownlint" version = "0.31.1" [[plugin]] name = "osv-scanner" [[plugin]] name = "prettier" version = "2.8.4" [[plugin]] name = "ripgrep" [[plugin]] name = "shellcheck" version = "0.9.0" [[plugin]] name = "shfmt" [[plugin]] name = "trivy" [[plugin]] name = "trufflehog" [[plugin]] name = "yamllint" ``` The list of auto-enabled plugins provided by the Qlty CLI is a recommended suggestion. You are encouraged to add or remove plugins as needed. # Getting Started with the Qlty CLI Source: https://docs.qlty.sh/cli/quickstart First, install our CLI onto your local machine: ```shell macOS & Linux lines theme={"system"} curl https://qlty.sh | sh ``` ```shell Windows lines theme={"system"} powershell -c "iwr https://qlty.sh | iex" ```