{"id":13815075,"url":"https://github.com/fredrikaverpil/creosote","last_synced_at":"2026-03-05T23:43:59.795Z","repository":{"id":37008351,"uuid":"456098134","full_name":"fredrikaverpil/creosote","owner":"fredrikaverpil","description":"Identify unused dependencies and avoid a bloated virtual environment.","archived":false,"fork":false,"pushed_at":"2026-02-12T09:16:59.000Z","size":13345,"stargazers_count":365,"open_issues_count":2,"forks_count":8,"subscribers_count":5,"default_branch":"main","last_synced_at":"2026-02-12T16:47:17.884Z","etag":null,"topics":["dependencies","hacktoberfest","python","requirements"],"latest_commit_sha":null,"homepage":"","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/fredrikaverpil.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2022-02-06T08:44:43.000Z","updated_at":"2026-02-12T09:17:01.000Z","dependencies_parsed_at":"2025-12-17T14:14:55.769Z","dependency_job_id":null,"html_url":"https://github.com/fredrikaverpil/creosote","commit_stats":{"total_commits":341,"total_committers":7,"mean_commits":"48.714285714285715","dds":"0.12903225806451613","last_synced_commit":"2008759cc9ae4995e301c1e05f5f74e066832135"},"previous_names":[],"tags_count":44,"template":false,"template_full_name":null,"purl":"pkg:github/fredrikaverpil/creosote","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/fredrikaverpil%2Fcreosote","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/fredrikaverpil%2Fcreosote/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/fredrikaverpil%2Fcreosote/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/fredrikaverpil%2Fcreosote/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/fredrikaverpil","download_url":"https://codeload.github.com/fredrikaverpil/creosote/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/fredrikaverpil%2Fcreosote/sbom","scorecard":{"id":410435,"data":{"date":"2025-08-11","repo":{"name":"github.com/fredrikaverpil/creosote","commit":"329b1193aafa50737dec398cd956067ae7a49f28"},"scorecard":{"version":"v5.2.1-40-gf6ed084d","commit":"f6ed084d17c9236477efd66e5b258b9d4cc7b389"},"score":4.8,"checks":[{"name":"Code-Review","score":0,"reason":"Found 0/23 approved changesets -- score normalized to 0","details":null,"documentation":{"short":"Determines if the project requires human code review before pull requests (aka merge requests) are merged.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#code-review"}},{"name":"Dangerous-Workflow","score":10,"reason":"no dangerous workflow patterns detected","details":null,"documentation":{"short":"Determines if the project's GitHub Action workflows avoid dangerous patterns.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#dangerous-workflow"}},{"name":"Binary-Artifacts","score":10,"reason":"no binaries found in the repo","details":null,"documentation":{"short":"Determines if the project has generated executable (binary) artifacts in the source repository.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#binary-artifacts"}},{"name":"Maintained","score":5,"reason":"6 commit(s) and 1 issue activity found in the last 90 days -- score normalized to 5","details":null,"documentation":{"short":"Determines if the project is \"actively maintained\".","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#maintained"}},{"name":"Pinned-Dependencies","score":0,"reason":"dependency not pinned by hash detected -- score normalized to 0","details":["Warn: third-party GitHubAction not pinned by hash: .github/workflows/managed-opencode.yml:17: update your workflow using https://app.stepsecurity.io/secureworkflow/fredrikaverpil/creosote/managed-opencode.yml/main?enable=pin","Warn: third-party GitHubAction not pinned by hash: .github/workflows/managed-pr.yml:21: update your workflow using https://app.stepsecurity.io/secureworkflow/fredrikaverpil/creosote/managed-pr.yml/main?enable=pin","Warn: third-party GitHubAction not pinned by hash: .github/workflows/managed-releaseplease.yml:15: update your workflow using https://app.stepsecurity.io/secureworkflow/fredrikaverpil/creosote/managed-releaseplease.yml/main?enable=pin","Warn: third-party GitHubAction not pinned by hash: .github/workflows/managed-stale.yml:14: update your workflow using https://app.stepsecurity.io/secureworkflow/fredrikaverpil/creosote/managed-stale.yml/main?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/publish.yml:16: update your workflow using https://app.stepsecurity.io/secureworkflow/fredrikaverpil/creosote/publish.yml/main?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/publish.yml:17: update your workflow using https://app.stepsecurity.io/secureworkflow/fredrikaverpil/creosote/publish.yml/main?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/publish.yml:23: update your workflow using https://app.stepsecurity.io/secureworkflow/fredrikaverpil/creosote/publish.yml/main?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/publish.yml:38: update your workflow using https://app.stepsecurity.io/secureworkflow/fredrikaverpil/creosote/publish.yml/main?enable=pin","Warn: third-party GitHubAction not pinned by hash: .github/workflows/publish.yml:45: update your workflow using https://app.stepsecurity.io/secureworkflow/fredrikaverpil/creosote/publish.yml/main?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/sync.yml:17: update your workflow using https://app.stepsecurity.io/secureworkflow/fredrikaverpil/creosote/sync.yml/main?enable=pin","Warn: third-party GitHubAction not pinned by hash: .github/workflows/sync.yml:20: update your workflow using https://app.stepsecurity.io/secureworkflow/fredrikaverpil/creosote/sync.yml/main?enable=pin","Warn: third-party GitHubAction not pinned by hash: .github/workflows/sync.yml:23: update your workflow using https://app.stepsecurity.io/secureworkflow/fredrikaverpil/creosote/sync.yml/main?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/test.yml:31: update your workflow using https://app.stepsecurity.io/secureworkflow/fredrikaverpil/creosote/test.yml/main?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/test.yml:19: update your workflow using https://app.stepsecurity.io/secureworkflow/fredrikaverpil/creosote/test.yml/main?enable=pin","Warn: third-party GitHubAction not pinned by hash: .github/workflows/test.yml:20: update your workflow using https://app.stepsecurity.io/secureworkflow/fredrikaverpil/creosote/test.yml/main?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/unmanaged-dependabot.yml:22: update your workflow using https://app.stepsecurity.io/secureworkflow/fredrikaverpil/creosote/unmanaged-dependabot.yml/main?enable=pin","Warn: third-party GitHubAction not pinned by hash: .github/workflows/unmanaged-dependabot.yml:24: update your workflow using https://app.stepsecurity.io/secureworkflow/fredrikaverpil/creosote/unmanaged-dependabot.yml/main?enable=pin","Warn: third-party GitHubAction not pinned by hash: .github/workflows/unmanaged-dependabot.yml:43: update your workflow using https://app.stepsecurity.io/secureworkflow/fredrikaverpil/creosote/unmanaged-dependabot.yml/main?enable=pin","Warn: third-party GitHubAction not pinned by hash: .github/workflows/unmanaged-python.yml:15: update your workflow using https://app.stepsecurity.io/secureworkflow/fredrikaverpil/creosote/unmanaged-python.yml/main?enable=pin","Info:   0 out of   8 GitHub-owned GitHubAction dependencies pinned","Info:   0 out of  11 third-party GitHubAction dependencies pinned"],"documentation":{"short":"Determines if the project has declared and pinned the dependencies of its build process.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#pinned-dependencies"}},{"name":"CII-Best-Practices","score":0,"reason":"no effort to earn an OpenSSF best practices badge detected","details":null,"documentation":{"short":"Determines if the project has an OpenSSF (formerly CII) Best Practices Badge.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#cii-best-practices"}},{"name":"Token-Permissions","score":0,"reason":"detected GitHub workflow tokens with excessive permissions","details":["Warn: jobLevel 'contents' permission set to 'write': .github/workflows/unmanaged-dependabot.yml:18","Info: topLevel 'contents' permission set to 'read': .github/workflows/managed-opencode.yml:12","Info: topLevel 'pull-requests' permission set to 'read': .github/workflows/managed-pr.yml:17","Warn: no topLevel permission defined: .github/workflows/managed-releaseplease.yml:1","Warn: no topLevel permission defined: .github/workflows/managed-stale.yml:1","Warn: no topLevel permission defined: .github/workflows/publish.yml:1","Warn: no topLevel permission defined: .github/workflows/sync.yml:1","Warn: no topLevel permission defined: .github/workflows/test.yml:1","Warn: no topLevel permission defined: .github/workflows/unmanaged-dependabot.yml:1","Warn: no topLevel permission defined: .github/workflows/unmanaged-python.yml:1"],"documentation":{"short":"Determines if the project's workflows follow the principle of least privilege.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#token-permissions"}},{"name":"Security-Policy","score":0,"reason":"security policy file not detected","details":["Warn: no security policy file detected","Warn: no security file to analyze","Warn: no security file to analyze","Warn: no security file to analyze"],"documentation":{"short":"Determines if the project has published a security policy.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#security-policy"}},{"name":"Fuzzing","score":0,"reason":"project is not fuzzed","details":["Warn: no fuzzer integrations found"],"documentation":{"short":"Determines if the project uses fuzzing.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#fuzzing"}},{"name":"License","score":10,"reason":"license file detected","details":["Info: project has a license file: LICENSE:0","Info: FSF or OSI recognized license: MIT License: LICENSE:0"],"documentation":{"short":"Determines if the project has defined a license.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#license"}},{"name":"Signed-Releases","score":-1,"reason":"no releases found","details":null,"documentation":{"short":"Determines if the project cryptographically signs release artifacts.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#signed-releases"}},{"name":"Packaging","score":10,"reason":"packaging workflow detected","details":["Info: Project packages its releases by way of GitHub Actions.: .github/workflows/publish.yml:28"],"documentation":{"short":"Determines if the project is published as a package that others can easily download, install, easily update, and uninstall.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#packaging"}},{"name":"Branch-Protection","score":4,"reason":"branch protection is not maximal on development and all release branches","details":["Info: 'allow deletion' disabled on branch 'main'","Info: 'force pushes' disabled on branch 'main'","Info: 'branch protection settings apply to administrators' is required to merge on branch 'main'","Warn: 'stale review dismissal' is disabled on branch 'main'","Warn: branch 'main' does not require approvers","Warn: codeowners review is required - but no codeowners file found in repo","Warn: 'last push approval' is disabled on branch 'main'","Info: 'up-to-date branches' is required to merge on branch 'main'","Info: status check found to merge onto on branch 'main'","Info: PRs are required in order to make changes on branch 'main'"],"documentation":{"short":"Determines if the default and release branches are protected with GitHub's branch protection settings.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#branch-protection"}},{"name":"Vulnerabilities","score":5,"reason":"5 existing vulnerabilities detected","details":["Warn: Project is vulnerable to: PYSEC-2014-14 / GHSA-652x-xj99-gmcc","Warn: Project is vulnerable to: GHSA-9hjg-9r4m-mvj7","Warn: Project is vulnerable to: GHSA-9wx4-h78v-vm56","Warn: Project is vulnerable to: PYSEC-2014-13 / GHSA-cfj3-7x9c-4p3h","Warn: Project is vulnerable to: PYSEC-2018-28 / GHSA-x84v-xcm2-53pg"],"documentation":{"short":"Determines if the project has open, known unfixed vulnerabilities.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#vulnerabilities"}},{"name":"SAST","score":10,"reason":"SAST tool is run on all commits","details":["Info: all commits (30) are checked with a SAST tool"],"documentation":{"short":"Determines if the project uses static code analysis.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#sast"}}]},"last_synced_at":"2025-08-18T22:34:24.646Z","repository_id":37008351,"created_at":"2025-08-18T22:34:24.646Z","updated_at":"2025-08-18T22:34:24.646Z"},"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":30156183,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-03-05T22:39:40.138Z","status":"ssl_error","status_checked_at":"2026-03-05T22:39:24.771Z","response_time":93,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.6:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["dependencies","hacktoberfest","python","requirements"],"created_at":"2024-08-04T04:02:55.084Z","updated_at":"2026-03-05T23:43:59.762Z","avatar_url":"https://github.com/fredrikaverpil.png","language":"Python","funding_links":[],"categories":["Python"],"sub_categories":[],"readme":"# creosote\n\nIdentify unused dependencies and avoid a bloated virtual environment.\n\n## ⚡️ Quickstart\n\nInstall creosote in separate virtual environment, using e.g.\n[`uv tool`](https://docs.astral.sh/uv/concepts/tools/):\n\n```bash\nuv tool install creosote\n```\n\nScan virtual environment for unused dependencies\n([PEP-621](https://peps.python.org/pep-0621/) example below, but\n[Poetry](https://python-poetry.org/), [Pipenv](https://github.com/pypa/pipenv),\n[PDM](https://pdm.fming.dev/latest/) and `requirements.txt` files are also\nsupported,\n[see this table](#which-dependency-specification-toolingstandards-are-supported)):\n\n```\n$ creosote\nFound dependencies in pyproject.toml: dotty-dict, loguru, pip-requirements-parser, requests, toml\nOh no, bloated venv! 🤢 🪣\nUnused dependencies found: requests\n```\n\nAnd after having removed/uninstalled `requests`:\n\n```\n$ creosote\nFound dependencies in pyproject.toml: dotty-dict, loguru, pip-requirements-parser, toml\nNo unused dependencies found! ✨\n```\n\n✋ Note that you will likely not be able to run `creosote` as-is, but will have\nto configure it so it understands your project structure.\n\nGet help:\n\n```bash\ncreosote --help\n```\n\n## ⚙️ Configuration\n\nYou can configure creosote using commandline arguments or in your\n`pyproject.toml`.\n\n### Using commandline arguments\n\n#### Required arguments\n\n| Argument      | Default value                                    | Description                                                                                            |\n| ------------- | ------------------------------------------------ | ------------------------------------------------------------------------------------------------------ |\n| `--venv`      | Path to activated virtual environment or `.venv` | The path(s) to your virtual environment or site-packages folder.                                       |\n| `--path`      | `src`                                            | The path(s) to your source code, one or more files/folders.                                            |\n| `--deps-file` | `pyproject.toml`                                 | The path to the file specifying your dependencies, like `pyproject.toml`, `requirements_*.txt \\| .in`. |\n| `--section`   | `project.dependencies`                           | The toml section(s) to parse, e.g. `project.dependencies`.                                             |\n\n#### Optional arguments\n\n| Argument        | Default value | Description                                                               |\n| --------------- | ------------- | ------------------------------------------------------------------------- |\n| `--exclude-dep` |               | Dependencies you wish to not scan for.                                    |\n| `--format`      | `default`     | The output format, valid values are `default`, `no-color` or `porcelain`. |\n\n### Using `pyproject.toml`\n\n```toml\n[tool.creosote]\nvenvs=[\".venv\"]\npaths=[\"src\"]\ndeps-file=\"pyproject.toml\"\nsections=[\"project.dependencies\"]\nexclude-deps =[\n  \"pyodbc\",\n  \"pg8000\",\n]\n```\n\n## 🤔 How this works\n\nThe creosote tool will first scan the given python file(s) for all its imports.\nThen it fetches all dependency names (from the dependencies spec file). Finally,\nall imports are associated with their corresponding dependency name (requires\nthe virtual environment for resolving and the ability to read the dependency's\n`RECORD` or `top_level.txt` file). If a dependency does not have any imports\nassociated, it is considered unused.\n\nSee the `main` function in\n[`cli.py`](https://github.com/fredrikaverpil/creosote/blob/main/src/creosote/cli.py)\nfor a terse overview of the logic.\n\n### 🌶️ Features\n\nThese optional features enable new/experimental functionality, that may be\nbackward incompatible and may be removed/changed at any time. Some features may\nbecome mandatory for a target release version e.g. the next major release.\nEnable using `--use-feature \u003cFEATURE\u003e`. Use at your own risk!\n\n| Feature                           | Description                                                                                                                                                                                 | Target version |\n| --------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------- |\n| `fail-excluded-and-not-installed` | When excluding a dependency from the scan (using `--exclude-dep`) and if the dependency is removed from the dependency specification file (e.g. `pyproject.toml`), return with exit code 1. | N/A            |\n\n### 😤 Known limitations\n\n- `importlib` imports are not detected by the AST parser (a great first\n  contribution for anyone inclined 😄, reach out or start looking at\n  `parsers.py:get_module_info_from_python_file`.\n\n## 🥧 History and ambition\n\nThis project was inspired by security vulnerability reports about production\ndependencies that were shipped into production but turned out to be unused.\nCreosote aims to help prevent such occurrences and reduce noise from bots like\n[Dependabot](https://github.com/dependabot) or\n[Renovate](https://github.com/renovatebot/renovate) for simply unused\ndependencies.\n\nThe intent is to run Creosote in CI (or with\n[pre-commit](https://pre-commit.com)) to detect cases where developers forget to\nremove unused dependencies, especially during refactorings. Creosote can\nidentify both unused production dependencies and developer dependencies,\ndepending on your objectives.\n\n## 🤨 FAQ\n\n### Which dependency specification tooling/standards are supported?\n\n| Tool/standard                                                                                                               | Supported | `--deps-file` value | Example `--section` values                                                                                          |\n| --------------------------------------------------------------------------------------------------------------------------- | :-------: | ------------------- | ------------------------------------------------------------------------------------------------------------------- |\n| [PDM](https://pdm.fming.dev/latest/) and [PEP-582](https://peps.python.org/pep-0582/)                                       |    ✅     | `pyproject.toml`    | `project.dependencies`,\u003cbr\u003e`project.optional-dependencies.\u003cGROUP\u003e`,\u003cbr\u003e`tool.pdm.dev-dependencies`                  |\n| [Pipenv](https://pipenv.pypa.io/en/latest/)                                                                                 |    ✅     | `pyproject.toml`    | `packages`,\u003cbr\u003e`dev-packages`                                                                                       |\n| [Poetry](https://python-poetry.org/)                                                                                        |    ✅     | `pyproject.toml`    | `tool.poetry.dependencies`,\u003cbr\u003e`tool.poetry.dev-dependencies` (legacy),\u003cbr\u003e`tool.poetry.group.\u003cGROUP\u003e.dependencies` |\n| Legacy Setuptools (`setup.py`)                                                                                              |    ❌     |                     |                                                                                                                     |\n| [PEP-508](https://peps.python.org/pep-0508/) (`requirements.txt`, [pip-tools](https://pip-tools.readthedocs.io/en/latest/)) |    ✅     | `*.[txt\\|in]`       | N/A                                                                                                                 |\n| [PEP-621](https://peps.python.org/pep-0621/)                                                                                |    ✅     | `pyproject.toml`    | `project.dependencies`,\u003cbr\u003e`project.optional-dependencies.\u003cGROUP\u003e`                                                  |\n| [PEP-735](https://peps.python.org/pep-0735/)                                                                                |    ✅     | `pyproject.toml`    | `dependency-groups`                                                                                                 |\n\n#### 📔 Notes on [PEP-508](https://peps.python.org/pep-0508) (`requirements.txt`)\n\nWhen using `requirements.txt` files to specify dependencies, there is no way to\ntell which part of `requirements.txt` specifies production vs developer\ndependencies. Therefore, you have to break your `requirements.txt` file into\ne.g. `requirements-prod.txt` and `requirements-dev.txt` and use any of them as\ninput. When using [pip-tools](https://pip-tools.readthedocs.io/en/latest/), you\nlikely want to point Creosote to scan your `*.in` file(s).\n\n#### 📓 Notes on [PEP-582](https://peps.python.org/pep-0582/) (`__pypackages__`)\n\nCreosote supports the `__pypackages__` folder, although PEP-582 was rejected.\nThere is no reason to remove support for this today, but in case supporting this\nbecomes cumbersome in the future, supporting PEP-582 might be dropped.\n\n```bash\ncreosote --venv __pypackages__\n```\n\n### Can I specify multiple toml sections?\n\nYes, you can specify a list of sections after the `--section` argument. It all\ndepends on what your setup looks like and what you set out to achieve.\n\n```bash\n$ creosote --section project.dependencies --section project.optional-dependencies.lint --section project.optional-dependencies.test\n```\n\n### Can I exclude dependencies from the scan?\n\nYes, you can use the `--exclude-dep` argument to specify one or more\ndependencies you do not wish to get warnings for.\n\nThis feature is intended for dependencies you must specify in your dependencies\nspec file, but which you don't import in your source code. An example of such a\ndependency are database drivers, which are commonly only defined in connection\nstrings and will signal to the ORM which driver to use.\n\n```bash\n$ creosote --exclude-dep pyodbc --exclude-dep pg8000\n```\n\n### Can I run Creosote on Jupyter notebook (\\*.ipynb) files?\n\nYes, any Jupyter notebook files will be temporarily converted to python files\nusing [nbconvert](https://github.com/jupyter/nbconvert) and then Creosote will\nrun on those.\n\n### Can I run Creosote in a GitHub Action workflow?\n\nYes, please see the `action` job example in\n[`.github/workflows/test.yml`](https://github.com/fredrikaverpil/creosote/blob/main/.github/workflows/test.yml).\n\n### Can I run Creosote with [pre-commit](https://pre-commit.com)?\n\nYes, see example in\n[`.pre-commit-config.yaml`](https://github.com/fredrikaverpil/creosote/blob/main/.pre-commit-config.yaml).\n\n\u003cdetails\u003e\n\u003csummary\u003eHere's another example setup, if already have Creosote installed onto $PATH (via e.g. `uv`).\u003c/summary\u003e\n\n```yaml\n# .pre-commit-config.yaml\n\nrepos:\n  - repo: local\n    hooks:\n      - id: system\n        name: creosote\n        entry:\n          creosote --venv .venv --path src --deps-file pyproject.toml --section\n          project.dependencies\n        pass_filenames: false\n        files: \\.(py|toml|txt|in|lock)$\n        language: system\n```\n\n\u003c/details\u003e\n\n### What's with the name \"creosote\"?\n\nThis tool has borrowed its name from the\n[Monty Python scene about Mr. Creosote](https://www.youtube.com/watch?v=aczPDGC3f8U).\n\n## 📰 Creosote in the \"news\"\n\nBecause it makes me happy to see this tool can help others! 🥰\n\n- [Creosote - Identify unused dependencies and avoid a bloated virtual environment](https://www.reddit.com/r/Python/comments/11n717z/creosote_identify_unused_dependencies_and_avoid_a/)\n  — Reddit\n\n## 🌀 Migration guide: creosote 2.x to 3.x\n\n\u003cdetails\u003e\n\u003csummary\u003eExpand me to read the guide.\u003c/summary\u003e\n\n\u003cbr\u003eCreosote was updated to 3.0.0 because the way arguments were supplied has\nnow changed. This also brings `pyproject.toml` configuration support.\n\n### Argument name change\n\nThe argument naming has changed:\n\n| 2.x argument name | 3.x argument name |\n| ----------------- | ----------------- |\n| `--exclude-deps`  | `--exclude-dep`   |\n| `--paths`         | `--path`          |\n| `--sections`      | `--section`       |\n\n### Multiple argument values\n\nWith creosote 2.x, you were able to provide multiple values following some\narguments, example:\n\n```bash\ncreosote -p file1.py file2.py\n```\n\nWith creosote 3.x, you must now provide multiple arguments as a key/value pair:\n\n```bash\ncreosote -p file1.py -p file2.py\n```\n\nThis new creosote 3.x behavior applies to the following 3.x CLI arguments:\n\n- `--venv`\n- `--exclude-dep`\n- `-p` or `--path`\n- `-s` or `--section`\n\n\u003c/details\u003e\n\n## 👩‍🔬 Development/debugging info\n\n### Install in-development builds\n\nYou can run in-development versions of Creosote.\n\n#### uv\n\n```bash\n# Creosote build from main branch\nuv tool install --force git+https://github.com/fredrikaverpil/creosote.git@main\ncreosote --venv .venv\nuv tool uninstall creosote\n\n# Creosote build from PR #123\nuv tool install --force git+https://github.com/fredrikaverpil/creosote.git@refs/pull/123/head\ncreosote --venv .venv\niv tool uninstall creosote\n```\n\n#### pipx\n\n```bash\n# Creosote build from main branch\npipx install --suffix=@main --force git+https://github.com/fredrikaverpil/creosote.git@main\ncreosote@main --venv .venv ...\npipx uninstall creosote@main\n\n# Creosote build from PR #123\npipx install --suffix=@123 --force git+https://github.com/fredrikaverpil/creosote.git@refs/pull/123/head\ncreosote@123 --venv .venv ...\npipx uninstall creosote@123\n```\n\n#### install from source\n\n```bash\ngit clone https://github.com/fredrikaverpil/creosote.git\ncd creosote\nuv sync --all-groups\nsource .venv/bin/activate\ncreosote --venv .venv\n```\n\n### 🚀 Releasing\n\nAfter merging, release-please will open a PR. However, this PR requires changes:\n\n1. Review version string changes made by release-please.\n2. Manually bump version in `.pre-commit-config.yaml`.\n3. GitHub Action will run automatically on creating\n   [a release](https://github.com/fredrikaverpil/creosote/releases) and deploy\n   the release onto PyPi.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ffredrikaverpil%2Fcreosote","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Ffredrikaverpil%2Fcreosote","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ffredrikaverpil%2Fcreosote/lists"}