Skip to main content

chokkin

日本語

Find unused files, dependencies, and public symbols in Python projects.

chokkin is a reachability analyzer for whole Python projects — a Knip-like experience for Python. It builds a project-wide graph from your manifests, source code, and tool configs, then reports what nothing reaches: run uvx chokkin with zero configuration, and tighten things up with precise settings and CI integration as you go.

[!NOTE] Status: v0.4.0 released. chokkin runs the full analysis pipeline (steps 1–13) by default: unused files, dependencies, and symbols with built-in reporters (default, compact, json, markdown, github, sarif), plus --explain, --trace, --fix, and baseline filtering. Use --probe for steps 1–4 summary only; it reports resolved workspace member counts, and resolver tags member-owned imports while treating cross-member imports as first-party. Strict mode enforces member-local dependency declarations, and reporters expose member ids on workspace findings. v0.4 focuses default CHK003 reporting on runtime imports, keeps conditional missing imports informational, recognizes aliased TYPE_CHECKING guards, adds an offline wheel-metadata harvester, and formalizes safe-autofix and semver contracts. The fixed 20-project corpus dropped from 964 to 131 CHK003 findings with 0 unknown labels while every §17 gate remained green. v0.1.0 through v0.4.0 have been released.

Why chokkin?

Existing tools each cover one slice of the problem:

Ruff     : per-file, syntax-level linting
Vulture  : Python AST-based dead code detection
deptry   : consistency between dependency manifests and imports
chokkin    : unused files, dependencies, and public symbols from the whole project graph

chokkin is not a style/lint tool. It answers a different question: starting from your entry points, what can actually be reached — and what is just sitting there? It reads pyproject.toml (including Poetry/PDM/Hatch dependency sections), requirements files, uv lockfiles, and framework/tool configs (Django, FastAPI, pytest, tox, nox, pre-commit, GitHub Actions, …) to build that picture.

Quick start

uvx chokkin

No configuration needed. On first run, chokkin discovers your manifests (pyproject.toml, setup.cfg, setup.py, requirements*.txt, uv.lock), infers your layout (src/flat, tests, scripts, docs), infers entry points, builds the import graph, and reconciles it against your declared dependencies:

chokkin 0.4.0

Project: acme-api
Config : pyproject.toml
Mode   : auto, production=false

Unused dependencies  3
  boto3          pyproject.toml:18  declared in [project.dependencies], no reachable import found
  rich           pyproject.toml:25  only used by scripts/dev.py; move to dependency-groups.dev
  python-dotenv  pyproject.toml:29  no import/config/binary usage found

Missing dependencies  1
  yaml -> PyYAML  src/acme/config.py:3  imported but not declared

Unused files  2
  src/acme/legacy.py        no path from any entry point
  src/acme/old_handlers.py  no path from any entry point

Unused exports  4
  src/acme/utils.py:12  function legacy_slugify
  src/acme/auth.py:44   class OldTokenBackend

Summary: 10 issues

What it checks

Code Issue Description Default severity
CHK001 unused_file Python file not reachable from any entry point warning
CHK002 unused_dependency declared in a manifest, but no import/config/binary usage found error
CHK003 missing_dependency imported, but not declared directly in any manifest error
CHK004 transitive_dependency imported directly, but only available via another dependency error
CHK005 misplaced_dependency runtime code uses a dev-group dependency, or a test-only dep is in main warning
CHK006 unused_export public symbol not referenced from outside its module warning
CHK007 unused_reexport re-export (e.g. in __init__.py) not referenced internally library: info / app: warning
CHK008 unlisted_binary CLI used by tox/nox/pre-commit/CI without a declared dependency warning
CHK009 duplicate_dependency declared in multiple of main/dev/optional warning
CHK010 unresolved_import import that resolves to neither first-party, third-party, nor stdlib warning

Because any module top-level name is importable in Python, unused_export starts out as a preview rule (info-level in library mode) rather than a hard error.

CLI

uvx chokkin
uvx chokkin --production
uvx chokkin --strict
uvx chokkin --no-exit-code
uvx chokkin --include CHK002,CHK003
uvx chokkin --exclude CHK006
uvx chokkin --reporter json
uvx chokkin --reporter markdown
uvx chokkin --reporter github
uvx chokkin --reporter sarif
uvx chokkin --confidence likely
uvx chokkin --fix
uvx chokkin --fix --dry-run
uvx chokkin --fix --allow-remove-files
uvx chokkin --fix --add-missing
uvx chokkin --baseline chokkin-baseline.json
uvx chokkin --baseline chokkin-baseline.json --update-baseline
uvx chokkin --no-cache
uvx chokkin --explain CHK002:boto3
uvx chokkin --trace src/acme/legacy.py
uvx chokkin --probe              # steps 1–4 summary only
uvx chokkin --init

Key flags:

  • --production — drop dev/test/docs/lint/type contexts and judge reachability from runtime context only. Dev-only files and dependencies are no longer reported, and "unused in production" becomes strict.
  • --strict — direct imports of transitive dependencies always error, workspace members must declare their own dependencies, CHK003 also includes type/test/docs/dev imports, unused environment-marker dependencies error, and maybe-confidence issues are shown.
  • --no-exit-code — exit 0 even when issues are found (config/CLI errors still exit 2, internal errors 3). Useful during adoption and for GitHub Actions summaries.
  • --fix — apply conservative fixes for certain dependency findings; add --allow-remove-files to also remove certain unreachable files. --add-missing adds Certain CHK003 findings to non-Poetry [project].dependencies when the distribution is unambiguous; workspace findings are inserted into the member pyproject.toml when that member manifest was inventoried. Unsupported cases are reported as skipped fixes with details on stderr.
  • --baseline PATH / --update-baseline — freeze current issues in a baseline file and suppress matching issues on later runs so CI fails only on new findings.
  • --no-cache — disable Phase 2 cache reads/writes. Parse, manifest/config scan, and module-index cache units are enabled by default under the project root and are conservative: corrupt or stale entries are treated as misses.
  • --reporter github / --reporter sarif — emit GitHub Actions annotations or a SARIF 2.1.0 subset for code scanning.
  • --probe — include resolved and inventoried workspace member counts when uv or chokkin workspaces are detected.
  • --explain / --trace — show why an issue was reported and how reachability was judged. CHK002 explain includes top-level modules and reachable/unreachable import evidence; --trace prints a positive path for reachable files and a negative trace (reason, entry roots, incoming import chain) for unreachable files. These are the intended path for investigating and reporting false positives.

Exit codes are fixed for CI:

0: no reportable issues
1: issues found
2: CLI/config error
3: internal error

Configuration

Zero config is the default. When you need precision, configure [tool.chokkin] in pyproject.toml (standalone chokkin.toml / .chokkin.toml are also accepted). chokkin --init appends a starter [tool.chokkin] reflecting what auto-discovery found.

[tool.chokkin]
entry = [
  "src/acme/__main__.py",
  "src/acme/asgi.py:application",
  "manage.py",
]
project = [
  "src/**/*.py",
  "tests/**/*.py",
  "scripts/**/*.py",
]
mode = "auto"             # auto | app | library
production = false
target_version = "py311"  # Python version of the analyzed project
respect_gitignore = true
confidence = "likely"     # certain | likely | maybe
exclude = [
  ".venv/**",
  "build/**",
  "dist/**",
  "**/__pycache__/**",
]

[tool.chokkin.dependencies]
dev_groups = ["dev", "test", "tests", "lint", "docs"]
runtime_groups = ["server", "worker"]
type_groups = ["types", "typing", "mypy"]

# distribution name -> import name(s), for cases the bundled map doesn't cover
[tool.chokkin.package_module_map]
"PyYAML" = ["yaml"]
"Pillow" = ["PIL"]

# CLI name -> distribution name, used by CHK008/CHK002 binary-usage checks
[tool.chokkin.binary_map]
"sphinx-build" = "Sphinx"

[tool.chokkin.plugins]
pytest = true
django = true
fastapi = true

# Per-rule severity overrides (off / info / warning / error)
[tool.chokkin.severity]
CHK001 = "off"
CHK006 = "info"
CHK002 = "error"

Modes

mode = "auto" picks one of:

  • app mode — there's a clear entry (console_scripts, manage.py, asgi.py, wsgi.py, app.py). Unused files are reported aggressively.
  • library mode — a [project] name with a package and no clear entry. Public modules may be imported by external users, so unused files/exports are reported at low confidence (or as info). For serious unused-file detection in a library, declare entry explicitly.
  • workspace mode — multiple pyproject.toml files or tool.uv.workspace.members. Each member is analyzed separately (per-member [tool.chokkin.workspaces.<name>] config is supported), sharing the workspace lockfile.

Dependency contexts

Dependencies and files are both assigned contexts (runtime / dev / test / docs / lint / type / optional extras). That's what powers CHK005: import pytest in tests/ with pytest in your dev group is fine; the same import in src/ is a misplaced dependency. Default CHK003 reporting focuses on runtime imports; --strict also reports undeclared type/test/docs/dev imports. TYPE_CHECKING-only imports (including typing aliases) are type-context, while try: import orjson / except ImportError and platform-guarded imports remain informational conditional candidates when undeclared.

Plugins

Frameworks reference modules through strings and decorators, which pure import analysis can't see. Plugins close that gap by adding entry files, string/module references, and binary usage:

  • v0.1: pytest, django, fastapi/uvicorn
  • v0.2+: tox/nox/pre-commit/GitHub Actions binary usage detection, static Flask/Celery route/task references, conventional Sphinx/MkDocs/Alembic config entries, and .ipynb code-cell parsing.

For example, the Django plugin treats INSTALLED_APPS / MIDDLEWARE / ROOT_URLCONF strings as module references and migrations/** as framework-used; the FastAPI plugin treats @router.get-decorated handlers as externally used.

Suppressing issues

Inline and file-level ignores:

from legacy import old_api  # chokkin: ignore[CHK003]

# chokkin: file-ignore[CHK006]   (at the top of a file)

Config ignores, keyed by rule code (globs over distribution names, paths, or path:symbol):

[tool.chokkin.ignore]
CHK001 = ["src/acme/generated/**/*.py"]
CHK002 = ["boto3", "google-cloud-*"]
CHK006 = ["src/acme/public_api.py:*"]

For large existing projects, a baseline freezes current issues so CI only fails on new ones:

uvx chokkin --baseline chokkin-baseline.json --update-baseline
uvx chokkin --baseline chokkin-baseline.json

Baseline and --reporter json output include schema_version: "1". v0.2 baseline files without that field remain readable. Published JSON Schema files live under docs/schema/; migration notes are in docs/dev/schema-migration-notes.md.

CI adoption

For an existing project, generate and review the baseline once:

uvx chokkin --baseline chokkin-baseline.json --update-baseline
git add chokkin-baseline.json

Then wire the baseline into pull request checks. This job emits GitHub annotations, writes SARIF for code scanning, and fails only for findings not already present in the baseline:

name: chokkin

on:
  pull_request:

permissions:
  contents: read
  security-events: write

jobs:
  chokkin:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: astral-sh/setup-uv@v5
      - name: Annotations
        run: uvx chokkin --baseline chokkin-baseline.json --reporter github
      - name: SARIF
        if: always()
        run: uvx chokkin --baseline chokkin-baseline.json --reporter sarif > chokkin.sarif
      - uses: github/codeql-action/upload-sarif@v3
        if: always()
        with:
          sarif_file: chokkin.sarif

Installation

chokkin is a single Rust binary shipped inside a Python wheel (prebuilt for Linux/macOS/Windows), so all of these work without a Rust toolchain:

uvx chokkin        # run without installing
pipx run chokkin
pip install chokkin

chokkin never executes your project's code — analysis is fully static. It also doesn't require your project's virtualenv: if .venv exists it is read for dist-info metadata (METADATA, top_level.txt, RECORD, entry_points.txt), otherwise manifests, lockfiles, and bundled maps are used.

Contributing

See CONTRIBUTING.md. The full design specification (analysis engine, import resolution strategy, roadmap) is in docs/dev/spec.ja.md (Japanese).

License

MIT

Metadata

Release files for chokkin 0.4.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for chokkin 0.4.0
File Size Uploaded
chokkin-0.4.0.tar.gz 492.0 kB Details

Built distributions (wheels)

Table of built distributions (wheels) for chokkin 0.4.0
File
chokkin-0.4.0-py3-none-win_amd64.whl Python 3 none Windows x86-64 Details
chokkin-0.4.0-py3-none-musllinux_1_2_x86_64.whl Python 3 none Linux musl 1.2+ x86-64 Details
chokkin-0.4.0-py3-none-musllinux_1_2_aarch64.whl Python 3 none Linux musl 1.2+ ARM64 Details
chokkin-0.4.0-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl Python 3 none Linux glibc 2.17+ x86-64 Details
chokkin-0.4.0-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl Python 3 none Linux glibc 2.17+ ARM64 Details
chokkin-0.4.0-py3-none-macosx_11_0_arm64.whl Python 3 none macOS 11.0+ ARM64 Details
chokkin-0.4.0-py3-none-macosx_10_12_x86_64.whl Python 3 none macOS 10.12+ x86-64 Details

Total release size: 15.3 MB

Release files / chokkin-0.4.0.tar.gz

Download URL chokkin-0.4.0.tar.gz
Size 492.0 kB
Tags Source
SHA-256 checksum
How to use checksums
10dfe116c6371681d75e0c649ffe5e0adfacaafb9915a6d1a3c9ab1e546e80ef
BLAKE2b-256 checksum
How to use checksums
a575357ab9511d4072f51b7984895772aeaf4418a9c0e6ac5c91d41c03af5fe4
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Aug 18, 2026.

Transparency log

Release files / chokkin-0.4.0-py3-none-win_amd64.whl

Download URL chokkin-0.4.0-py3-none-win_amd64.whl
Size 2.0 MB
Tags Python 3 Windows x86-64
SHA-256 checksum
How to use checksums
7785d072917fd216c1ff4e0b9b4077e5001bed343d14b5117b9b786282a3a775
BLAKE2b-256 checksum
How to use checksums
be1ef3edbaba295a38bb03250180d3cfbec8f48ffc9858ff99f28ebc3f42031d
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Aug 18, 2026.

Transparency log

Release files / chokkin-0.4.0-py3-none-musllinux_1_2_x86_64.whl

Download URL chokkin-0.4.0-py3-none-musllinux_1_2_x86_64.whl
Size 2.3 MB
Tags Linux musl 1.2+ x86-64 Python 3
SHA-256 checksum
How to use checksums
953822f53e0a801685076f465cc04e6ad6b29a077fce82ef26585121bd8848a3
BLAKE2b-256 checksum
How to use checksums
e64b7782acb1c258d4a93474a5a9503f4599e7af6be0a017030590d98e2ba353
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Aug 18, 2026.

Transparency log

Release files / chokkin-0.4.0-py3-none-musllinux_1_2_aarch64.whl

Download URL chokkin-0.4.0-py3-none-musllinux_1_2_aarch64.whl
Size 2.1 MB
Tags Linux musl 1.2+ ARM64 Python 3
SHA-256 checksum
How to use checksums
5f98a699ee544466a9ebc7fac5ff7970ab26eee929962a79e707c6062720bf1e
BLAKE2b-256 checksum
How to use checksums
a0d8ad115efe4fa93faac0d52ef4e887b24aa3e0be8566ceb9dc17ec39dea3aa
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Aug 18, 2026.

Transparency log

Release files / chokkin-0.4.0-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl

Download URL chokkin-0.4.0-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Size 2.2 MB
Tags Linux glibc 2.17+ x86-64 Python 3
SHA-256 checksum
How to use checksums
7fed29bfb0843c3fffab58c8d51a67018d8546578a48a7a238c466e1b5b0ca14
BLAKE2b-256 checksum
How to use checksums
c1f77bd4c693c45e02cc119bf4b52244c225ecec504eba0e2a85b260a5f70ba8
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Aug 18, 2026.

Transparency log

Release files / chokkin-0.4.0-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl

Download URL chokkin-0.4.0-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl
Size 2.1 MB
Tags Linux glibc 2.17+ ARM64 Python 3
SHA-256 checksum
How to use checksums
316a048f39483f1de2c551c45ab5362c3b47b408c5b838d50b2d9f2ea131efb6
BLAKE2b-256 checksum
How to use checksums
ec41d1254c6150c2278591bfe1817a321fc71e39f559857b2ca05d77c79ae5e9
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Aug 18, 2026.

Transparency log

Release files / chokkin-0.4.0-py3-none-macosx_11_0_arm64.whl

Download URL chokkin-0.4.0-py3-none-macosx_11_0_arm64.whl
Size 2.0 MB
Tags Python 3 macOS 11.0+ ARM64
SHA-256 checksum
How to use checksums
c589e2d9ecbf5a6a5cebeea0a21d22a01c0591e7f2e27f7c817d120b3562bf8c
BLAKE2b-256 checksum
How to use checksums
c504d183233e5aeea3205f2f6e93d88b86d3de68e19d1fb30da7ea9d3cdce3d5
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Aug 18, 2026.

Transparency log

Release files / chokkin-0.4.0-py3-none-macosx_10_12_x86_64.whl

Download URL chokkin-0.4.0-py3-none-macosx_10_12_x86_64.whl
Size 2.1 MB
Tags Python 3 macOS 10.12+ x86-64
SHA-256 checksum
How to use checksums
4eb4361af226562e174a935b759b13258e00db3541e28bb6d29d411e08a666cc
BLAKE2b-256 checksum
How to use checksums
2c0dd0ebd009782faf046114c822fcf1038bca825fa1596a8599b007bc096c55
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Aug 18, 2026.

Transparency log

Release history Release notifications | RSS feed

0.5.0

16 release files

This release

0.4.0 This release

8 release files

0.3.0

8 release files

0.2.0

8 release files

0.1.0

8 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page