charmlint
A charm-aware, model-agnostic linter for Juju charms.
charmlint checks charm source code against Canonical's Juju charm best practices: observability (COS integration, ops-tracing), security (PEP 740 PyPI attestations), testing structure, metadata completeness, configuration quality, and more.
Extracted from tonyandrewmeyer/cantrip,
where charmlint grew as an internal component of the Cantrip AI charm builder.
Installation
uv sync --dev
Usage
uv run charmlint /path/to/charm
uv run charmlint --format json /path/to/charm
uv run charmlint --select COS,META /path/to/charm
uv run charmlint --ignore ATT002 --strict /path/to/charm
Or install and run directly:
uv run pip install -e .
charmlint /path/to/charm
Running tests
uv run pytest tests/ -v
Rule catalogue
Rule IDs follow CATEGORY-### (for example SECURITY-001,
METADATA-003). See docs/id-scheme.md for the full
category catalogue and naming rules.
Configuration
Configure under [tool.charmlint] in pyproject.toml, or in a standalone
charmlint.toml / .charmlint.toml. Discovery walks up from the charm
directory, in the manner of ruff.
[tool.charmlint]
severity = "warning" # minimum severity to report
select = ["OBSERVABILITY", "METADATA"]
ignore = ["ATTESTATION-002"]
[tool.charmlint.per-rule-severity]
"OBSERVABILITY-005" = "error"
Suppressing findings inline
Individual findings can be silenced from within a charm's YAML files with
ruff-style # noqa comments.
An inline # noqa suppresses every finding reported on that line; add a
comma-separated list of codes to suppress only those. A code is a full
rule ID (SECURITY-001) or a category (SECURITY):
config:
options:
admin-password: # noqa: SECURITY-001
type: string
A file-level # charmlint: noqa (on any line) suppresses the whole file;
# charmlint: noqa: SECURITY-001 suppresses only the listed rules across
the file:
# charmlint: noqa: SECURITY-001
Inline # noqa only applies to findings that carry a line number;
findings that anchor to a whole file are silenced with a file-level
directive instead. Only YAML files are scanned.
Versioning
charmlint follows a ruff-style versioning scheme: the minor version carries breaking changes (such as new or sharpened rules being enabled by default) and the patch version carries bug fixes. See docs/versioning.md for the full policy.
License
Apache 2.0 — see LICENSE.
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file charmlint-0.1.1.tar.gz.
File metadata
- Download URL: charmlint-0.1.1.tar.gz
- Upload date:
- Size: 106.6 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via:
twine/7.0.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
6b014955a6d1dee48bba254ff4858401c437674d3f230c3f88896a87dd3d2a5f
|
|
| MD5 |
9d914c9327e2c2b8f7da396526a1da0f
|
|
| BLAKE2b-256 |
d6626402ce7d5b81f5c97d1dd2639cf26a1828ea7851d27b5382e646421413bf
|
Provenance
The following attestation bundles were made for charmlint-0.1.1.tar.gz:
Publisher:
publish.yaml on canonical/charmlint
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
charmlint-0.1.1.tar.gz -
Subject digest:
6b014955a6d1dee48bba254ff4858401c437674d3f230c3f88896a87dd3d2a5f - Sigstore transparency entry: 2684439616
- Sigstore integration time:
-
Permalink:
canonical/charmlint@ae567b42aed105156e6a01be82dfb93ec06a7494 -
Branch / Tag:
refs/tags/v0.1.1 - Owner: https://github.com/canonical
-
Access:
private
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yaml@ae567b42aed105156e6a01be82dfb93ec06a7494 -
Trigger Event:
push
-
Statement type:
File details
Details for the file charmlint-0.1.1-py3-none-any.whl.
File metadata
- Download URL: charmlint-0.1.1-py3-none-any.whl
- Upload date:
- Size: 55.3 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via:
twine/7.0.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
341e7f6fc5ba2b246d98fc820fdbbd600cc3097e57f78ee4af584b4c35feee85
|
|
| MD5 |
efb74d3d4d4212f64872eaaee51e7a90
|
|
| BLAKE2b-256 |
fec3897b17a94dc6741f32342705584082b60be3f86a3cb8e873d6a39ace0b31
|
Provenance
The following attestation bundles were made for charmlint-0.1.1-py3-none-any.whl:
Publisher:
publish.yaml on canonical/charmlint
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
charmlint-0.1.1-py3-none-any.whl -
Subject digest:
341e7f6fc5ba2b246d98fc820fdbbd600cc3097e57f78ee4af584b4c35feee85 - Sigstore transparency entry: 2684439630
- Sigstore integration time:
-
Permalink:
canonical/charmlint@ae567b42aed105156e6a01be82dfb93ec06a7494 -
Branch / Tag:
refs/tags/v0.1.1 - Owner: https://github.com/canonical
-
Access:
private
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yaml@ae567b42aed105156e6a01be82dfb93ec06a7494 -
Trigger Event:
push
-
Statement type: