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

# Shared Analysis Configuration

This document outlines the capabilities available in Qlty CLI and Qlty Cloud to support sharing of analysis configuration across multiple repositories within a single workspace.

# Goals

* Simplify the set up and maintenance of static analysis configuration across a large number of GitHub repositories
* Provide partial or full standardization of static analysis configuration for the organization

# Custom Sources

The primary method of sharing analysis configuration across multiple repositories is through defining a custom Source. A Source is a Git repository that stores version controlled static analysis configuration settings which can be re-used by other repositories.

Custom Sources were designed to replace the delegated configuration feature of Code Climate Quality while adding new capabilities.

## Features of Custom Sources

* Create and share new, custom Plugin Definitions
  * *Example:* Define a custom plugin to check that all `package.json` files specify an acceptable `license` value
* Customize out-of-the-box Plugin Definitions
  * *Example*: Override the default definition of the Prettier auto-formatter to avoid rewriting `*.mdx` files
* Share maintainability analysis settings
  * *Example:* Increase the complexity threshold for the "High Function Complexity" code smell
  * *Example:* Add a code filter to exclude common boilerplate from an internally developed framework from duplication detection
* Share file path exclusions
  * *Example:* Exclude all files matching `**/our_generator/**`
* Share issue triage rules
  * *Example:* Downgrade the `level` of issues found by Trivy in the `sandbox/**` folder to `low`
* Automatically enable plugins
  * *Example:* Always run the Shellcheck for any shell scripts in all repositories
* Share linter configuration files
  * *Example:* Provide a base `rubocop.yml` configuration that can be extended for each project

## Advantages of Custom Sources

* Settings provided by the Source can be further customized with the Project's `qlty.toml` configuration file (layered configuration)
* Sources can be declared as pinned (with Git tags) or floating to a branch
* Custom sources work on Qlty CLI and Qlty Cloud

## Example

To use a Custom Source, each repository would declare it from the `.qlty/qlty.toml` file:

```toml lines theme={"system"}
config_version = "0"

# First, use the built-in Qlty source
[[source]]
name = "default"
default = true

# Customize further with the organization's custom source
[[source]]
name = "AcmeCo"
repository = "https://github.com/AcmeCo/qlty-source"
branch = "main"
```

**Why are both sources needed?** The `default` source provides all the built-in Qlty plugin definitions. Your custom source adds overrides and customizations on top. Without the `default` source, Qlty wouldn't know how to run the standard plugins.

To pin your source to a specific version instead of floating to a branch, use `tag`:

```toml lines theme={"system"}
[[source]]
name = "AcmeCo"
repository = "https://github.com/AcmeCo/qlty-source"
tag = "v1.0.0"
```

## Source Repository Structure

The custom Source is a regular Git repository which follows a conventional structure:

```
your-qlty-source/
├── source.toml              # Main configuration file
├── .eslintrc.js             # Linter config files to share (optional)
├── rubocop.yml              #
└── plugins/                 # Custom plugin definitions (optional)
    └── linters/
        └── my-custom-plugin/
            └── plugin.toml
```

* A `source.toml` file at the root of the repository provides settings
* Plugins can be defined or modified in files matching the patterns `plugins/linters/*/plugin.toml`
* Linter configuration files can be placed at the root to be shared with child repos via `exported_config_paths`

## Configuration Merging

Notably, Qlty uses the same TOML configuration syntax in every configuration file. This allows for taking advantage of the same configuration options — from plugin declaration settings to tuning maintainability smells — in any `*.toml` file read by Qlty.

Configuration is applied in the following order from lowest precedence to highest precedence:

1. `plugin.toml` files in Sources
2. `source.toml` file at the root of Sources
3. `qlty.toml` in the project

As the final, merged configuration is assembled, the last setting wins.

The full, merged configuration can be viewed as YAML by running `qlty config show`.

## Sharing Linter Configuration Files

Linter plugins often use their own configuration files (e.g., `.eslintrc.js`, `rubocop.yml`, `.prettierrc`). You can share these files from your custom source repository so that all child repos use the same configuration.

To share a linter configuration file:

1. Commit the linter configuration file to your custom source repository.
2. Within the `source.toml`, use the `exported_config_paths` property to specify which files should be copied to child repos at runtime.

```toml lines theme={"system"}
[plugins.definitions.<plugin-name>]
exported_config_paths = ["<config-file>"]
```

<Warning>
  `exported_config_paths` does not work inside `[[plugin]]`. It must be declared in `[plugins.definitions.<name>]` or it will be silently ignored.
</Warning>

**How it works:** When Qlty runs analysis on a child repo, it copies the files listed in `exported_config_paths` from your source repository into the child repo's working directory. The linter then finds and uses these configuration files as if they were committed directly to the child repo.

**If `exported_config_paths` is not set**, config files in the source repo are NOT shared. The linter will use config files from the child repo if present, otherwise it falls back to its defaults.

### config\_files vs exported\_config\_paths

These two properties work together but serve different purposes:

| Property                | Purpose                                                               |
| ----------------------- | --------------------------------------------------------------------- |
| `config_files`          | Tells the plugin which configuration files to look for when running   |
| `exported_config_paths` | Tells Qlty to copy these files from the source repo to the child repo |

Example in `source.toml`:

```toml lines theme={"system"}
# Enable the plugin and specify which config files it uses
[[plugin]]
name = "<plugin-name>"
config_files = ["<config-file>"]
mode = "monitor"

# Export the config files so child repos receive them
[plugins.definitions.<plugin-name>]
exported_config_paths = ["<config-file>"]
```

You may place plugin configuration files anywhere within your custom source repo. The `exported_config_paths` must be relative to the location of your `source.toml`.

## Sharing Linter Extensions

If a shared plugin configuration file utilizes [linter extensions](https://docs.qlty.sh/cli/linter-extensions), you'll need to define these using the `extra_packages` property within your `source.toml`. For example:

```toml lines theme={"system"}
[[plugin]]
name = "eslint"
version = "8.57.0"
extra_packages = [
  "eslint-config-prettier@10.1.8",
  "eslint-plugin-prettier@5.5.3",
  "prettier@3.6.2"
]
```

## Private Custom Sources

Custom sources can be private repos, provided they are in the same GitHub Org and the user has installed the Qlty GitHub App.

**Qlty Cloud:** HTTPS URLs work automatically. The GitHub App handles authentication.

```toml lines theme={"system"}
[[source]]
name = "AcmeCo"
repository = "https://github.com/AcmeCo/qlty-source"
branch = "main"
```

**Qlty CLI (local):** For private repos, use SSH URLs since the CLI doesn't have access to Qlty Cloud authentication:

```toml lines theme={"system"}
[[source]]
name = "AcmeCo"
repository = "git@github.com:AcmeCo/qlty-source.git"
branch = "main"
```

## Complete Example

Here's a complete working example of sharing configuration between repositories.

### Source Repository

**`source.toml`:**

```toml lines theme={"system"}
config_version = "0"

[[source]]
name = "default"
default = true

# Shared exclusions
exclude_patterns = [
  "**/tmp/**",
  "**/vendor/**",
]

# Enable a plugin with shared config
[[plugin]]
name = "<plugin-name>"
config_files = ["<config-file>"]
mode = "monitor"

# Export the config file to child repos
[plugins.definitions.<plugin-name>]
exported_config_paths = ["<config-file>"]
```

### Child Repository

**`.qlty/qlty.toml`:**

```toml lines theme={"system"}
config_version = "0"

[[source]]
name = "default"
default = true

[[source]]
name = "acme"
repository = "https://github.com/AcmeCo/acme-qlty-source"
branch = "main"
```

The child repository does not need its own linter configuration files — they will be inherited from the source repository when Qlty runs.
