Metadata-Version: 2.5
Name: conflint
Version: 0.1.1
Summary: Code-aware config linter. Find every env var, config key and secret your app needs - and the drift across .env, CI, Docker, Kubernetes and Terraform before it breaks prod.
Project-URL: Homepage, https://github.com/conflint/conflint
Project-URL: Documentation, https://conflint.readthedocs.io
Project-URL: Repository, https://github.com/conflint/conflint
Project-URL: Issues, https://github.com/conflint/conflint/issues
Project-URL: Changelog, https://github.com/conflint/conflint/blob/main/CHANGELOG.md
Author: conflint contributors
License: MIT License
        
        Copyright (c) 2026 conflint contributors
        
        Permission is hereby granted, free of charge, to any person obtaining a copy
        of this software and associated documentation files (the "Software"), to deal
        in the Software without restriction, including without limitation the rights
        to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
        copies of the Software, and to permit persons to whom the Software is
        furnished to do so, subject to the following conditions:
        
        The above copyright notice and this permission notice shall be included in all
        copies or substantial portions of the Software.
        
        THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
        IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
        FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
        AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
        LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
        OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
        SOFTWARE.
License-File: LICENSE
Keywords: ci,config,dotenv,drift,env,kubernetes,linter,secrets
Classifier: Development Status :: 4 - Beta
Classifier: Environment :: Console
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: MIT License
Classifier: Operating System :: OS Independent
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.9
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Topic :: Software Development :: Quality Assurance
Classifier: Topic :: System :: Systems Administration
Classifier: Typing :: Typed
Requires-Python: >=3.9
Requires-Dist: click>=8.1
Requires-Dist: pathspec>=0.11
Requires-Dist: pyyaml>=6.0
Requires-Dist: rich>=12.0
Requires-Dist: tomli>=2.0; python_version < '3.11'
Provides-Extra: dev
Requires-Dist: build>=1.2; extra == 'dev'
Requires-Dist: mypy>=1.8; extra == 'dev'
Requires-Dist: pytest-cov>=4.1; extra == 'dev'
Requires-Dist: pytest>=7.4; extra == 'dev'
Requires-Dist: ruff>=0.4; extra == 'dev'
Requires-Dist: twine>=5.0; extra == 'dev'
Requires-Dist: types-pyyaml>=6.0; extra == 'dev'
Provides-Extra: docs
Requires-Dist: mkdocs-material>=9.5; extra == 'docs'
Requires-Dist: mkdocs>=1.6; extra == 'docs'
Requires-Dist: mkdocstrings[python]>=0.24; extra == 'docs'
Description-Content-Type: text/markdown

<div align="center">

# conflint

**Code-aware configuration linting.**  
Find every env var, config key and secret your app *actually* reads, then reconcile
it against `.env`, CI, Docker, Kubernetes and Terraform — **before it breaks prod**.

`pip install conflint` · `confl check` · [`conflint` on PyPI](https://pypi.org/project/conflint)

</div>

---

## Why conflint?

Most "works on my machine" disasters are configuration disasters:

- A teammate deleted a key from `.env` that your code still **requires**.
- The CI workflow never defines `DATABASE_URL`, so the app crashes at **deploy**, not at commit.
- `DB_HOST` vs `DBHOST` — the typo that no linter catches because your linter doesn't read your code.
- A real API key sitting in a committed `.env`.

`.env` linters validate a file against a **schema you write by hand**. conflint reads
the **actual source code** to learn the truth about what your app needs, then
reconciles it against **every** place that value should exist.

## Quick start

```bash
pip install conflint
```

```bash
# From your project root:
confl check                  # lint the whole project
confl sync                   # regenerate an accurate .env.example
confl explain DB_HOST        # who reads DB_HOST? where is it defined?
```

Example output:

```text
conflint  checked 42 files (173 config reads, 58 definitions) in 1.24s

app/main.py
  CL001 error: 'DATABASE_URL' is read in code but not defined in any configuration source:12
    hint: Add it to your .env (then run `confl sync` to refresh .env.example)
  CL003 warning: 'DBHOST' is undefined but resembles 'DB_HOST' (distance 1):45
    hint: Did you mean 'DB_HOST'?
docker-compose.yml
  CL004 error: 'POSTGRES_PASSWORD' looks like a committed secret

42 files checked - 2 errors, 1 warning, 0 infos
```

## Commands

| Command               | Purpose                                                            |
| --------------------- | ------------------------------------------------------------------ |
| `confl check`         | Run all rules and exit `1` if anything reaches your fail level.     |
| `confl check --fix`   | Auto-remediate fixable findings (currently: syncs `.env.example`).  |
| `confl sync`          | Regenerate `.env.example` from code + sources (lossless rewrite).   |
| `confl explain KEY`   | Trace one key: every read site and every definition site.           |
| `confl rules`         | List all rules with their default severity.                         |
| `confl init`          | Write a template `conflint.toml`.                                   |
| `confl version`       | Print the installed version.                                        |

## Rules

| Rule  | Name          | Default   | Meaning                                                            |
| ----- | ------------- | --------- | ------------------------------------------------------------------ |
| CL001 | missing       | error     | read in code, defined nowhere                                      |
| CL002 | unused        | warning   | defined for real, never read by code                               |
| CL003 | typo          | warning   | undefined name is one edit away from a known one                   |
| CL004 | secret-leak   | error     | high-entropy secret committed in a config source                   |
| CL005 | drift         | error     | documented in `.env.example`, provided by no real source           |
| CL006 | empty-value   | warning   | required value defined but empty                                   |
| CL007 | duplicate     | warning   | defined twice in one file / conflicting values across sources      |
| CL008 | weak-secret   | warning   | secret value equals a weak/default placeholder                     |
| CL009 | undocumented | info      | used or provided, but missing from the example template            |

### What gets scanned

| Language | Files                    | Recognised reads                                            |
| -------- | ------------------------ | ----------------------------------------------------------- |
| Python   | `.py`, `.pyi` (AST)      | `os.environ[...]`, `os.environ.get`, `os.getenv` (+ aliases) |
| JS/TS    | `.js`, `.ts`, `.jsx`...  | `process.env`, `import.meta.env`, `Bun.env`, `Deno.env.get`, destructuring |
| Go       | `.go`                    | `os.Getenv`, `os.LookupEnv`, `os.Setenv`                     |
| Ruby     | `.rb`                    | `ENV[...]`, `ENV.fetch`                                      |

### Configuration sources (all gitignore-aware in reverse)

| Source          | Finds                                                   |
| --------------- | ------------------------------------------------------- |
| dotenv          | `.env`, `.env.local`, `.env.example`, ...               |
| docker-compose  | `services.*.environment` (list & map styles)            |
| github-actions  | `env:` maps in `.github/workflows/*`                    |
| kubernetes      | container `env`, `ConfigMap.data`, `Secret.data`        |
| terraform       | `variable ""`, `.tfvars`, `environment = {}` blocks     |

## Configuration

Config is optional. When you need it, use `conflint.toml` (or `pyproject.toml`
under `[tool.conflint]`):

```toml
[tool.conflint]
fail-level = "error"              # error | warning | info
require-example = true            # enforce a populated .env.example

enable = { CL003 = "error" }      # raise a rule's severity
disable = ["CL002"]               # turn rules off

ignore-names = ["CI=true", "NODE_ENV=*"]
ignore-paths = ["scripts/**", "vendor/**"]

sources = ["dotenv", "docker-compose", "github-actions", "kubernetes", "terraform"]
scanners = ["python", "javascript"]
reporters = ["text"]
```

Run `confl init` to write a commented template.

## CI integration

### GitHub Actions

```yaml
- name: Lint configuration
  uses: conflint/conflint@v1
  with:
    reporter: github          # inline PR annotations
    fail-level: error
```

or with pip directly:

```yaml
- uses: actions/setup-python@v5
  with: { python-version: "3.12" }
- run: pip install conflint
- run: confl check --github
```

### pre-commit

```yaml
- repo: https://github.com/conflint/conflint
  rev: v0.1.0
  hooks:
    - id: conflint
```

## Output formats

```bash
confl check                       # rich terminal output
confl check --json                # stable JSON schema (v1.0)
confl check --sarif               # SARIF 2.1.0 (CodeQL, Azure Pipelines, GitLab)
confl check --github              # GitHub Actions workflow commands
confl check --report junit        # JUnit XML for Jenkins dashboards
confl check --json --output report.json   # write to a file
```

## Development

```bash
git clone https://github.com/conflint/conflint
cd conflint
pip install -e ".[dev]"
pytest
ruff check .
mypy src
```

## License

MIT. See [LICENSE](LICENSE).

## Similar tools & why conflint is different

| Tool         | What it does                    | What conflint adds                     |
| ------------ | ------------------------------- | -------------------------------------- |
| `dotenv-linter` | validates `.env` against rules | reads your **code**, not a hand-made schema |
| `trufflehog`/`gitleaks` | scans git history for secrets | live per-key **value** + **drift** reconciliation in CI |
| envcheck-style CLIs | compare `.env.example` to `.env` | cross-source graph: code · .env · CI · k8s · terraform |
| `mypy`/`ruff` | static types/lint | the **configuration layer** they ignore |