{"id":13468817,"url":"https://github.com/scientific-python/cookie","last_synced_at":"2026-03-04T13:32:27.064Z","repository":{"id":37830693,"uuid":"326477608","full_name":"scientific-python/cookie","owner":"scientific-python","description":"Scientific Python Library Development Guide and Cookiecutter","archived":false,"fork":false,"pushed_at":"2026-02-28T23:13:12.000Z","size":1743,"stargazers_count":384,"open_issues_count":26,"forks_count":72,"subscribers_count":11,"default_branch":"main","last_synced_at":"2026-03-01T02:10:23.774Z","etag":null,"topics":["cookiecutter","cookiecutter-python","cookiecutter-python3","pypi-package","python","scikit-hep"],"latest_commit_sha":null,"homepage":"https://learn.scientific-python.org/development","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"bsd-3-clause","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/scientific-python.png","metadata":{"files":{"readme":"README.md","changelog":null,"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":"2021-01-03T18:46:50.000Z","updated_at":"2026-02-28T23:13:14.000Z","dependencies_parsed_at":"2026-01-05T21:09:35.767Z","dependency_job_id":null,"html_url":"https://github.com/scientific-python/cookie","commit_stats":{"total_commits":520,"total_committers":41,"mean_commits":"12.682926829268293","dds":0.4403846153846154,"last_synced_commit":"dafbd9333143b811be7d8f6304b1e4d1c618ee4d"},"previous_names":["scikit-hep/cookie"],"tags_count":23,"template":false,"template_full_name":null,"purl":"pkg:github/scientific-python/cookie","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/scientific-python%2Fcookie","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/scientific-python%2Fcookie/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/scientific-python%2Fcookie/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/scientific-python%2Fcookie/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/scientific-python","download_url":"https://codeload.github.com/scientific-python/cookie/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/scientific-python%2Fcookie/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":30081440,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-03-04T13:22:36.021Z","status":"ssl_error","status_checked_at":"2026-03-04T13:20:45.750Z","response_time":59,"last_error":"SSL_read: 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":["cookiecutter","cookiecutter-python","cookiecutter-python3","pypi-package","python","scikit-hep"],"created_at":"2024-07-31T15:01:19.702Z","updated_at":"2026-03-04T13:32:27.043Z","avatar_url":"https://github.com/scientific-python.png","language":"Python","readme":"# Scientific Python: guide, cookie, \u0026 sp-repo-review\n\n## Cookie\n\n[![Actions Status][actions-badge]][actions-link]\n[![GitHub Discussion][github-discussions-badge]][github-discussions-link]\n[![Live ReadTheDocs][rtd-badge]][rtd-link]\n\n[![PyPI version][pypi-version]][pypi-link]\n[![PyPI platforms][pypi-platforms]][pypi-link]\n\nA [copier][]/[cookiecutter][] template for new Python projects based on the\nScientific Python Developer Guide. What makes this different from other\ntemplates for Python packages?\n\n- Lives with the [Scientific-Python Development Guide][]: Every decision is\n  clearly documented and every tool described, and everything is kept in sync.\n- Nine different backends to choose from for building packages.\n- Optional VCS versioning for most backends.\n- Template generation tested in GitHub Actions using nox.\n- Supports generation with [copier][], [cookiecutter][], and [cruft][].\n- Supports GitHub Actions if targeting a `github.com` url (the default), and\n  adds experimental GitLab CI support otherwise.\n- Includes several compiled backends using [pybind11][], with wheels produced\n  for all platforms using [cibuildwheel][].\n- Provides [`sp-repo-review`][pypi-link] to evaluate existing repos against the\n  guidelines, with a WebAssembly version integrated with the guide. All checks\n  cross-linked.\n- Follows [PyPA][] best practices and regularly updated.\n\nBe sure you have read the [Scientific-Python Development Guide][] first, and\npossibly used them on a project or two. This is _not_ a minimal example or\ntutorial. It is a collection of useful tooling for starting a new project using\ncookiecutter, or for copying in individual files for an existing project (by\nhand, from `{{cookiecutter.project_name}}/`).\n\nDuring generation you can select from the following backends for your package:\n\n1. [hatch][]: This uses hatchling, a modern builder with nice file inclusion,\n   extendable via plugins, and good error messages. **(Recommended for pure\n   Python projects)**\n2. [flit][]: A modern, lightweight [PEP 621][] build system for pure Python\n   projects. Replaces setuptools, no MANIFEST.in, setup.py, or setup.cfg. Low\n   learning curve. Easy to bootstrap into new distributions. Difficult to get\n   the right files included, little dynamic metadata support.\n3. [pdm][]: A modern, less opinionated all-in-one solution to pure Python\n   projects supporting standards. Replaces setuptools, venv/pipenv, pip, wheel,\n   and twine. Supports [PEP 621][].\n4. [poetry][]: An all-in-one solution to pure Python projects. Replaces\n   setuptools, venv/pipenv, pip, wheel, and twine. Higher learning curve, but is\n   all-in-one. Makes some bad default assumptions for libraries.\n5. [setuptools][]: The classic build system, but with the new standardized\n   configuration.\n6. [pybind11][]: This is setuptools but with an C++ extension written in\n   [pybind11][] and wheels generated by [cibuildwheel][].\n7. [scikit-build][]: A scikit-build (CMake) project also using pybind11, using\n   scikit-build-core. **(Recommended for C++ projects)**\n8. [meson-python][]: A Meson project also using pybind11. (No VCS versioning)\n9. [maturin][]: A [PEP 621][] builder for Rust binary extensions. (No VCS\n   versioning) **(Recommended for Rust projects)**\n\nCurrently, the best choice is probably hatch for pure Python projects, and\nscikit-build (such as the scikit-build-core + pybind11 choice) for binary\nprojects.\n\n#### To use (copier version)\n\nInstall `copier` and `copier-templates-extensions`. Using [uv][], that's:\n\n```bash\nuv tool install copier!=9.5.0 --with copier-templates-extensions\n```\n\n(Copier 9.5.0 [has a bug](https://github.com/copier-org/copier/issues/1977))\nNow, run copier to generate your project:\n\n```bash\ncopier copy gh:scientific-python/cookie \u003cpkg\u003e --trust --vcs-ref=HEAD\n```\n\n(`\u003cpkg\u003e` is the path to put the new project. `--vcs-ref=HEAD` gets the current\nversion instead of the last tag, matching cookiecutter's behavior.)\n\nYou will get a nicer CLI experience with answer validation. You will also get a\n`.copier-answers.yml` file, which will allow you to perform updates in the\nfuture.\n\n\u003e Note: Add `--vcs-ref=HEAD` to get the latest version instead of the last\n\u003e tagged version; HEAD always passes tests (and is what cookiecutter uses).\n\n#### To use (cookiecutter version)\n\nInstall cookiecutter, ideally with `brew install cookiecutter` if you use brew,\notherwise with `uv tool install cookiecutter` (or prepend `uvx` to the command\nbelow, and skip installation). Then run:\n\n```bash\ncookiecutter gh:scientific-python/cookie\n```\n\nIf you are using cookiecutter 2.2.3+, you will get nice descriptions for the\noptions like copier!\n\n#### To use (cruft version)\n\nYou can also use [cruft][], which adds the ability update to cookiecutter\nprojects. Install with `uv tool install cruft` (or prepend `uvx` to the command\nbelow, and skip installation). Then run:\n\n```bash\ncruft create https://github.com/scientific-python/cookie\n```\n\n#### Post generation\n\nCheck the key setup files, `pyproject.toml`, and possibly `setup.cfg` and\n`setup.py` (pybind11 example). Update `README.md`. Also update and add docs to\n`docs/`.\n\nThere are a few example dependencies and a minimum Python version of 3.9, feel\nfree to change it to whatever you actually need/want. There is also a basic\nbackports structure with a small typing example.\n\n#### Contained components:\n\n- GitHub Actions runs testing for the generation itself\n  - Uses nox so cookie development can be checked locally\n- GitHub actions deploy\n  - C++ backends include cibuildwheel for wheel builds\n  - Uses PyPI trusted publisher deployment\n- Dependabot keeps actions up to date periodically, through useful pull requests\n- Formatting handled by pre-commit\n  - No reason not to be strict on a new project; remove what you don't want.\n  - Includes MyPy - static typing\n  - Includes Ruff - standard formatting, linting and autofixes\n    - Replaces Flake8, isort, pyupgrade, yesqa, pycln, and dozens of plugins\n  - Includes spell checking\n- An pylint nox target can be used to run pylint, which integrated GHA\n  annotations\n- A ReadTheDocs-ready Sphinx docs folder and `[docs]` extra\n- A test folder and pytest `[test]` extra\n- A noxfile is included with a few common targets\n\n#### For developers:\n\nYou can test locally with [nox][]:\n\n```console\n# See all commands\nnox -l\n\n# Run a specific check\nnox -s \"lint(scikit-build)\"\n\n# Run a noxfile command on the project noxfile\nnox -s \"nox(hatch)\" -- docs\n```\n\nIf you don't have `nox` locally, you can use [uv][], such as `uvx nox` instead.\n\n#### Other similar projects\n\n[Hypermodern-Python][hypermodern] is another project worth checking out with\nmany similarities, like great documentation for each feature and many of the\nsame tools used. It has a slightly different set of features, and has a stronger\nfocus on GitHub Actions - most our guide could be adapted to a different CI\nsystem fairly easily if you don't want to use GHA. It also forces the use of\nPoetry (instead of having a backend selection), and doesn't support compiled\nprojects. It currently dumps all development dependencies into a shared\nenvironment, causing long solve times and high chance of conflicts. It also does\nnot use pre-commit the way it was intended to be used. It also has quite a bit\nof custom code.\n\n#### History\n\nA lot of the guide, cookiecutter, and repo-review started out as part of\n[Scikit-HEP][]. These projects were merged, generalized, and combined with the\n[NSLS-II][] guide during the 2023 Scientific-Python Developers Summit.\n\n\u003c!-- prettier-ignore-start --\u003e\n\n[actions-badge]: https://github.com/scientific-python/cookie/workflows/CI/badge.svg\n[actions-link]: https://github.com/scientific-python/cookie/actions\n[cibuildwheel]: https://cibuildwheel.readthedocs.io\n[cookiecutter]: https://cookiecutter.readthedocs.io\n[copier]: https://copier.readthedocs.io\n[cruft]: https://cruft.github.io/cruft\n[flit]: https://flit.readthedocs.io/en/latest/\n[github-discussions-badge]: https://img.shields.io/static/v1?label=Discussions\u0026message=Ask\u0026color=blue\u0026logo=github\n[github-discussions-link]: https://github.com/scientific-python/cookie/discussions\n[hatch]: https://github.com/ofek/hatch\n[hypermodern]: https://github.com/cjolowicz/cookiecutter-hypermodern-python\n[maturin]: https://maturin.rs\n[meson-python]: https://meson-python.readthedocs.io\n[nox]: https://nox.thea.codes/en/stable/\n[nsls-ii]: https://nsls-ii.github.io/scientific-python-cookiecutter/\n[pdm]: https://pdm.fming.dev\n[pep 621]: https://www.python.org/dev/peps/pep-0621\n[poetry]: https://python-poetry.org\n[pybind11]: https://pybind11.readthedocs.io\n[pypa]: https://www.pypa.io\n[pypi-link]: https://pypi.org/project/sp-repo-review/\n[pypi-platforms]: https://img.shields.io/pypi/pyversions/sp-repo-review\n[pypi-version]: https://badge.fury.io/py/sp-repo-review.svg\n[rtd-badge]: https://readthedocs.org/projects/scientific-python-cookie/badge/?version=latest\n[rtd-link]: https://scientific-python-cookie.readthedocs.io/en/latest/?badge=latest\n[scikit-build]: https://scikit-build.readthedocs.io\n[setuptools]: https://setuptools.readthedocs.io\n[uv]: https://docs.astral.sh/uv\n\n\u003c!-- prettier-ignore-end --\u003e\n\n---\n\n## sp-repo-review\n\n\u003c!-- sp-repo-review --\u003e\n\n`sp-repo-review` provides checks based on the [Scientific-Python Development\nGuide][] at [scientific-python/cookie][] for [repo-review][].\n\nThis tool can check the style of a repository. Use like this:\n\n```bash\nuv run --extra=cli sp-repo-review \u003cpath to repository\u003e\n```\n\nThis will produce a list of results - green checkmarks mean this rule is\nfollowed, red x’s mean the rule is not. A yellow warning sign means that the\ncheck was skipped because a previous required check failed. Some checks will\nfail, that’s okay - the goal is bring all possible issues to your attention, not\nto force compliance with arbitrary checks. Eventually there might be a way to\nmark checks as ignored.\n\nFor example, `GH101` expects all your action files to have a nice `name:` field.\nIf you are happy with the file-based names you see in CI, you should feel free\nto simply ignore this check (you can specify ignored checks in pyproject.toml or\nby passing args to repo-review, see the [repo-review\ndocs][repo-review configuring]).\n\nAll checks are mentioned at least in some way in the [Scientific-Python\nDevelopment Guide][]. You should read that first - if you are not attempting to\nfollow them, some of the checks might not work. For example, the guidelines\nspecify pytest configuration be placed in `pyproject.toml`. If you place it\nsomewhere else, then all the pytest checks will be skipped.\n\nThis was originally developed for [Scikit-HEP][] before moving to Scientific\nPython.\n\n## Other ways to use\n\nYou can also use GitHub Actions:\n\n```yaml\n- uses: scientific-python/cookie@\u003cversion\u003e\n```\n\nOr pre-commit:\n\n```yaml\n- repo: https://github.com/scientific-python/cookie\n  rev: \u003cversion\u003e\n  hooks:\n    - id: sp-repo-review\n```\n\nIf you use `additional_dependencies` to add more plugins, like\n`validate-pyproject`, you should also include `\"repo-review[cli]\"` to ensure the\nCLI requirements are included.\n\n## List of checks\n\n\u003c!-- prettier-ignore-start --\u003e\n\n\u003c!-- [[[cog\nimport itertools\n\nfrom repo_review.processor import collect_all\nfrom repo_review.checks import get_check_url, get_check_description\nfrom repo_review.families import get_family_name\n\ncollected = collect_all()\nprint()\nfor family, grp in itertools.groupby(collected.checks.items(), key=lambda x: x[1].family):\n    print(f'### {get_family_name(collected.families, family)}')\n    for code, check in grp:\n        url = get_check_url(code, check)\n        link = f\"[`{code}`]({url})\" if url else f\"`{code}`\"\n        print(f\"- {link}: {get_check_description(code, check)}\")\n    print()\n]]] --\u003e\n\n### General\n- [`PY001`](https://learn.scientific-python.org/development/guides/packaging-simple#PY001): Has a pyproject.toml\n- [`PY002`](https://learn.scientific-python.org/development/guides/packaging-simple#PY002): Has a README.(md|rst) file\n- [`PY003`](https://learn.scientific-python.org/development/guides/packaging-simple#PY003): Has a LICENSE* file\n- [`PY004`](https://learn.scientific-python.org/development/guides/packaging-simple#PY004): Has docs folder\n- [`PY005`](https://learn.scientific-python.org/development/guides/packaging-simple#PY005): Has tests folder\n- [`PY006`](https://learn.scientific-python.org/development/guides/style#PY006): Has pre-commit config\n- [`PY007`](https://learn.scientific-python.org/development/guides/tasks#PY007): Supports an easy task runner (nox, tox, pixi, etc.)\n\n### PyProject\n- [`PP002`](https://learn.scientific-python.org/development/guides/packaging-simple#PP002): Has a proper build-system table\n- [`PP003`](https://learn.scientific-python.org/development/guides/packaging-classic#PP003): Does not list wheel as a build-dep\n- [`PP004`](https://learn.scientific-python.org/development/guides/packaging-simple#PP004): Does not upper cap Python requires\n- [`PP005`](https://learn.scientific-python.org/development/guides/packaging-simple#PP005): Using SPDX project.license should not use deprecated trove classifiers\n- [`PP301`](https://learn.scientific-python.org/development/guides/pytest#PP301): Has pytest in pyproject\n- [`PP302`](https://learn.scientific-python.org/development/guides/pytest#PP302): Sets a minimum pytest to at least 6\n- [`PP303`](https://learn.scientific-python.org/development/guides/pytest#PP303): Sets the test paths\n- [`PP304`](https://learn.scientific-python.org/development/guides/pytest#PP304): Sets the log level in pytest\n- [`PP305`](https://learn.scientific-python.org/development/guides/pytest#PP305): Specifies xfail_strict\n- [`PP306`](https://learn.scientific-python.org/development/guides/pytest#PP306): Specifies strict config\n- [`PP307`](https://learn.scientific-python.org/development/guides/pytest#PP307): Specifies strict markers\n- [`PP308`](https://learn.scientific-python.org/development/guides/pytest#PP308): Specifies useful pytest summary\n- [`PP309`](https://learn.scientific-python.org/development/guides/pytest#PP309): Filter warnings specified\n\n### Documentation\n- [`RTD100`](https://learn.scientific-python.org/development/guides/docs#RTD100): Uses ReadTheDocs (pyproject config)\n- [`RTD101`](https://learn.scientific-python.org/development/guides/docs#RTD101): You have to set the RTD version number to 2\n- [`RTD102`](https://learn.scientific-python.org/development/guides/docs#RTD102): You have to set the RTD build image\n- [`RTD103`](https://learn.scientific-python.org/development/guides/docs#RTD103): You have to set the RTD python version\n- [`RTD104`](https://learn.scientific-python.org/development/guides/docs#RTD104): You have to specify a build configuration now for readthedocs.\n\n### GitHub Actions\n- [`GH100`](https://learn.scientific-python.org/development/guides/gha-basic#GH100): Has GitHub Actions config\n- [`GH101`](https://learn.scientific-python.org/development/guides/gha-basic#GH101): Has nice names\n- [`GH102`](https://learn.scientific-python.org/development/guides/gha-basic#GH102): Auto-cancel on repeated PRs\n- [`GH103`](https://learn.scientific-python.org/development/guides/gha-basic#GH103): At least one workflow with manual dispatch trigger\n- [`GH104`](https://learn.scientific-python.org/development/guides/gha-wheels#GH104): Use unique names for upload-artifact\n- [`GH200`](https://learn.scientific-python.org/development/guides/gha-basic#GH200): Maintained by Dependabot\n- [`GH210`](https://learn.scientific-python.org/development/guides/gha-basic#GH210): Maintains the GitHub action versions with Dependabot\n- [`GH211`](https://learn.scientific-python.org/development/guides/gha-basic#GH211): Do not pin core actions as major versions\n- [`GH212`](https://learn.scientific-python.org/development/guides/gha-basic#GH212): Require GHA update grouping\n\n### MyPy\n- [`MY100`](https://learn.scientific-python.org/development/guides/style#MY100): Uses MyPy (pyproject config)\n- [`MY101`](https://learn.scientific-python.org/development/guides/style#MY101): MyPy strict mode\n- `MY102`: MyPy show_error_codes deprecated\n- [`MY103`](https://learn.scientific-python.org/development/guides/style#MY103): MyPy warn unreachable\n- [`MY104`](https://learn.scientific-python.org/development/guides/style#MY104): MyPy enables ignore-without-code\n- [`MY105`](https://learn.scientific-python.org/development/guides/style#MY105): MyPy enables redundant-expr\n- [`MY106`](https://learn.scientific-python.org/development/guides/style#MY106): MyPy enables truthy-bool\n\n### Pre-commit\n- [`PC100`](https://learn.scientific-python.org/development/guides/style#PC100): Has pre-commit-hooks\n- [`PC110`](https://learn.scientific-python.org/development/guides/style#PC110): Uses black or ruff-format\n- [`PC111`](https://learn.scientific-python.org/development/guides/style#PC111): Uses blacken-docs\n- [`PC140`](https://learn.scientific-python.org/development/guides/style#PC140): Uses a type checker\n- [`PC160`](https://learn.scientific-python.org/development/guides/style#PC160): Uses a spell checker\n- [`PC170`](https://learn.scientific-python.org/development/guides/style#PC170): Uses PyGrep hooks (only needed if rST present)\n- [`PC180`](https://learn.scientific-python.org/development/guides/style#PC180): Uses a markdown formatter\n- [`PC190`](https://learn.scientific-python.org/development/guides/style#PC190): Uses Ruff\n- [`PC191`](https://learn.scientific-python.org/development/guides/style#PC191): Ruff show fixes if fixes enabled\n- [`PC901`](https://learn.scientific-python.org/development/guides/style#PC901): Custom pre-commit CI message\n\n### Ruff\n- [`RF001`](https://learn.scientific-python.org/development/guides/style#RF001): Has Ruff config\n- [`RF002`](https://learn.scientific-python.org/development/guides/style#RF002): Target version must be set\n- [`RF003`](https://learn.scientific-python.org/development/guides/style#RF003): src directory doesn't need to be specified anymore (0.6+)\n- [`RF101`](https://learn.scientific-python.org/development/guides/style#RF101): Bugbear must be selected\n- [`RF102`](https://learn.scientific-python.org/development/guides/style#RF102): isort must be selected\n- [`RF103`](https://learn.scientific-python.org/development/guides/style#RF103): pyupgrade must be selected\n- `RF201`: Avoid using deprecated config settings\n- `RF202`: Use (new) lint config section\n\n\u003c!-- [[[end]]] --\u003e\n\n[repo-review]: https://repo-review.readthedocs.io\n[repo-review configuring]: https://repo-review.readthedocs.io/en/latest/intro.html#configuring\n[scientific-python development guide]: https://learn.scientific-python.org/development\n[scientific-python/cookie]: https://github.com/scientific-python/cookie\n[scikit-hep]: https://scikit-hep.org\n\n\u003c!-- prettier-ignore-end --\u003e\n","funding_links":[],"categories":["Python"],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fscientific-python%2Fcookie","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fscientific-python%2Fcookie","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fscientific-python%2Fcookie/lists"}