Python Packaging
Overview
Use this skill when the task is to create, structure, validate, or publish a Python package using the modern PyPA workflow.
This enhanced version preserves the original skill intent while upgrading it into an operator-facing packaging workflow centered on:
pyproject.toml-first configuration
- standardized project metadata
- backend-neutral build guidance
src/ layout decisions
- wheel and source distribution validation
- safer publishing practices for PyPI
Prefer this skill for distributable libraries, reusable internal packages, and Python CLI tools that should be installed through standard packaging workflows.
Do not use it as a substitute for framework-specific deployment guidance, OS packaging, containerization-only workflows, or environment-specific release approvals.
For deeper execution support, use:
references/runtime-practices.md for standards and decision tables
examples/implementation-example.md for concrete package layouts and pyproject.toml examples
scripts/validate-runtime.py for preflight validation of packaging metadata and artifacts
When to Use
Activate this skill when the user needs to:
- create a Python library for distribution
- package a Python CLI tool with console entry points
- migrate from legacy
setup.py-first packaging toward pyproject.toml
- build and inspect wheels and source distributions
- publish to PyPI or TestPyPI
- troubleshoot packaging failures such as missing files, bad metadata, or editable install mismatches
- separate runtime dependencies from optional or development-only dependencies
Do not activate it when the task is mainly about:
- virtual environment management alone
- application deployment without packaging
- Docker image construction
- Conda packaging or Linux distro package maintenance
- framework-specific release automation with no Python packaging decisions involved
Operating Table
| Situation |
Start here |
Why it matters |
| New distributable library |
Prefer src/ layout and a pyproject.toml with [build-system] and [project] |
Reduces accidental imports from the repo root and aligns with current PyPA guidance |
| Unsure which backend to use |
references/runtime-practices.md |
Gives backend-neutral criteria instead of pushing one tool as universally best |
| Building release artifacts |
python -m build |
Produces wheel and sdist through the standard frontend in an isolated build flow |
| Validating metadata before upload |
twine check dist/* and scripts/validate-runtime.py |
Catches broken README rendering, missing metadata, and absent artifacts before publication |
| Packaging a CLI |
examples/implementation-example.md |
Shows a concrete console-script example and expected installed command behavior |
| Publishing from CI |
Prefer PyPI Trusted Publishers |
Avoids long-lived API tokens where supported |
| Debugging package contents |
Inspect dist/ artifacts and compare against project tree |
Many packaging bugs are build-output mismatches, not source-code bugs |
Workflow
Clarify package intent
- Determine whether the target is a library, a library plus CLI, or an internal package.
- Confirm Python version support, target index, and release expectations.
- Ask whether the user needs public PyPI, TestPyPI, or private index publication.
Choose packaging structure deliberately
- For distributable libraries, prefer
src/ layout.
- For very small internal apps, flat layout may be acceptable, but call out the risk of imports succeeding locally while failing after installation.
- Decide whether the package needs only runtime dependencies, optional extras, or separate development groups.
Author pyproject.toml first
- Define
[build-system] with the selected backend requirements.
- Put standardized metadata in
[project] where possible.
- Keep backend-specific configuration in tool-specific sections only when needed.
- Avoid introducing legacy
setup.py configuration unless the task is explicitly legacy maintenance.
Create the package layout
- Ensure importable package directories are present.
- Include
__init__.py where appropriate for regular packages.
- Place tests outside the package tree unless there is a deliberate reason not to.
- If packaging a CLI, declare console entry points instead of relying on ad hoc wrapper scripts.
Install and test in development mode
- Create a clean virtual environment.
- Install editable dependencies if the backend supports editable installs.
- Run the project test suite and basic import checks.
- Confirm that development success is not caused by importing directly from the repository root.
Build distributable artifacts
- Run:
python -m pip install --upgrade build
python -m build
- Expect
dist/ to contain at least a wheel and often an sdist.
- If only one artifact type is produced, verify that this is intentional.
Validate artifacts before publishing
- Run
twine check dist/*.
- Optionally install the built wheel into a fresh environment and run a smoke test.
- Use
python scripts/validate-runtime.py --twine-check for a local preflight report.
- Confirm package data, README rendering, entry points, and metadata fields.
Publish safely
- Prefer TestPyPI or another non-production validation path before a first public release.
- For CI/CD publication, prefer PyPI Trusted Publishers when available.
- Treat long-lived API tokens as a fallback, not the preferred baseline.
- If release integrity is a mature concern, consider attestations as an advanced enhancement.
Hand off with concrete verification
- Report the backend used, project layout, build commands, artifact results, and publishing path.
- Include any warnings from
scripts/validate-runtime.py and the fix applied or deferred.
Examples
Open examples/implementation-example.md when the task needs copy-check-compare examples.
Use those examples for:
- a minimal distributable library using
src/ layout
- a library plus CLI package with a console entry point
- expected
dist/ outputs after build
- validation steps before TestPyPI or PyPI publication
Troubleshooting
1. Tests pass locally but the installed package is broken
Symptoms
- Imports work from the repository root.
- A wheel installs, but runtime imports fail.
Likely causes
- Flat layout is masking missing package discovery or missing files.
- Tests are importing from the working tree instead of the installed package.
Checks
- Confirm whether the project uses
src/ or flat layout.
- Create a fresh environment and install the built wheel.
- Run imports from outside the repository directory.
Fix
- Prefer
src/ layout for distributable libraries.
- Rebuild and retest using the wheel, not only editable install behavior.
2. twine check fails or README rendering is broken
Symptoms
twine check dist/* reports invalid long description content type or rendering issues.
Likely causes
readme metadata is missing or mismatched.
- README content or format declaration is inconsistent.
Checks
- Review the
readme field in [project].
- Confirm the README file exists and matches the declared format.
Fix
- Correct the
readme declaration.
- Rebuild artifacts and rerun
twine check before any upload.
3. Package installs but the CLI command is missing or fails
Symptoms
- Installation succeeds, but the expected command is unavailable.
- The command exists but crashes on startup.
Likely causes
- Missing or incorrect console-script entry point.
- The entry point target does not resolve to a callable.
- The command was installed into a different environment than the one being used.
Checks
- Review entry point configuration in
pyproject.toml.
- Verify the target object exists and is importable.
- Confirm the environment and
PATH are the expected ones.
Fix
- Declare the console entry point correctly.
- Reinstall the built wheel in a fresh environment and test the installed command.
4. Built distribution is missing templates, data files, or other non-code assets
Symptoms
- Source tree contains files that are absent after installation.
- Runtime file lookups fail only in built artifacts.
Likely causes
- Package data was not included in the build configuration.
- The file exists in the repository but is outside the packaged paths.
Checks
- Inspect wheel and sdist contents directly.
- Compare source tree paths with packaged paths.
Fix
- Configure package data explicitly using backend-specific packaging rules.
- Rebuild and inspect artifacts again before upload.
5. Editable install behavior differs from wheel install behavior
Symptoms
- Editable install works, but the built wheel behaves differently.
Likely causes
- The project relies on repository-local paths or undeclared files.
- Backend editable install behavior differs from assumptions.
Checks
- Test both editable install and wheel install in fresh environments.
- Compare import paths and package contents.
Fix
- Treat wheel installation as the release truth.
- Remove assumptions that only hold in editable mode.
6. Dependency specification is rejected or resolves unexpectedly
Symptoms
- Installer errors mention invalid requirement strings.
- Consumers get broader or narrower dependency resolution than intended.
Likely causes
- Invalid version specifier syntax.
- Development-only requirements were placed in runtime dependencies.
Checks
- Review dependency strings against the version-specifier specification.
- Separate mandatory runtime dependencies from optional features and development groups.
Fix
- Correct the requirement syntax.
- Move non-runtime dependencies out of the core runtime dependency list.
Additional Resources
references/runtime-practices.md for backend-neutral decision guidance, metadata reminders, and release checks
examples/implementation-example.md for concrete project trees and packaging examples
scripts/validate-runtime.py for local inspection of pyproject.toml, layout, and dist/ artifacts
External standards and primary references:
- PyPA Packaging tutorial
- PyPA guide to writing
pyproject.toml
- PyPA discussion on
src/ layout vs flat layout
- PyPA discussion of package formats
- PEP 621 for project metadata
- PEP 660 for editable installs
build documentation
- Twine documentation
- PyPI Trusted Publishers documentation
Related Skills
Use a different skill when the task shifts to:
- environment management rather than packaging
- CI/CD workflow authoring beyond package release specifics
- Docker or container image build pipelines
- framework deployment patterns
- repository-wide release engineering outside Python packaging scope
1---2name: python-packaging-23description: Python Packaging workflow skill. Use this skill when the user needs comprehensive guidance for creating, structuring, validating, and distributing Python packages with modern packaging standards, `pyproject.toml`, and PyPI publishing workflows.4---56# Python Packaging78## Overview910Use this skill when the task is to create, structure, validate, or publish a Python package using the modern PyPA workflow.1112This enhanced version preserves the original skill intent while upgrading it into an operator-facing packaging workflow centered on:1314- `pyproject.toml`-first configuration15- standardized project metadata16- backend-neutral build guidance17- `src/` layout decisions18- wheel and source distribution validation19- safer publishing practices for PyPI2021Prefer this skill for distributable libraries, reusable internal packages, and Python CLI tools that should be installed through standard packaging workflows.2223Do **not** use it as a substitute for framework-specific deployment guidance, OS packaging, containerization-only workflows, or environment-specific release approvals.2425For deeper execution support, use:2627- `references/runtime-practices.md` for standards and decision tables28- `examples/implementation-example.md` for concrete package layouts and `pyproject.toml` examples29- `scripts/validate-runtime.py` for preflight validation of packaging metadata and artifacts3031## When to Use3233Activate this skill when the user needs to:3435- create a Python library for distribution36- package a Python CLI tool with console entry points37- migrate from legacy `setup.py`-first packaging toward `pyproject.toml`38- build and inspect wheels and source distributions39- publish to PyPI or TestPyPI40- troubleshoot packaging failures such as missing files, bad metadata, or editable install mismatches41- separate runtime dependencies from optional or development-only dependencies4243Do not activate it when the task is mainly about:4445- virtual environment management alone46- application deployment without packaging47- Docker image construction48- Conda packaging or Linux distro package maintenance49- framework-specific release automation with no Python packaging decisions involved5051## Operating Table5253| Situation | Start here | Why it matters |54| --- | --- | --- |55| New distributable library | Prefer `src/` layout and a `pyproject.toml` with `[build-system]` and `[project]` | Reduces accidental imports from the repo root and aligns with current PyPA guidance |56| Unsure which backend to use | `references/runtime-practices.md` | Gives backend-neutral criteria instead of pushing one tool as universally best |57| Building release artifacts | `python -m build` | Produces wheel and sdist through the standard frontend in an isolated build flow |58| Validating metadata before upload | `twine check dist/*` and `scripts/validate-runtime.py` | Catches broken README rendering, missing metadata, and absent artifacts before publication |59| Packaging a CLI | `examples/implementation-example.md` | Shows a concrete console-script example and expected installed command behavior |60| Publishing from CI | Prefer PyPI Trusted Publishers | Avoids long-lived API tokens where supported |61| Debugging package contents | Inspect `dist/` artifacts and compare against project tree | Many packaging bugs are build-output mismatches, not source-code bugs |6263## Workflow64651. **Clarify package intent**66 - Determine whether the target is a library, a library plus CLI, or an internal package.67 - Confirm Python version support, target index, and release expectations.68 - Ask whether the user needs public PyPI, TestPyPI, or private index publication.69702. **Choose packaging structure deliberately**71 - For distributable libraries, prefer `src/` layout.72 - For very small internal apps, flat layout may be acceptable, but call out the risk of imports succeeding locally while failing after installation.73 - Decide whether the package needs only runtime dependencies, optional extras, or separate development groups.74753. **Author `pyproject.toml` first**76 - Define `[build-system]` with the selected backend requirements.77 - Put standardized metadata in `[project]` where possible.78 - Keep backend-specific configuration in tool-specific sections only when needed.79 - Avoid introducing legacy `setup.py` configuration unless the task is explicitly legacy maintenance.80814. **Create the package layout**82 - Ensure importable package directories are present.83 - Include `__init__.py` where appropriate for regular packages.84 - Place tests outside the package tree unless there is a deliberate reason not to.85 - If packaging a CLI, declare console entry points instead of relying on ad hoc wrapper scripts.86875. **Install and test in development mode**88 - Create a clean virtual environment.89 - Install editable dependencies if the backend supports editable installs.90 - Run the project test suite and basic import checks.91 - Confirm that development success is not caused by importing directly from the repository root.92936. **Build distributable artifacts**94 - Run:95 - `python -m pip install --upgrade build`96 - `python -m build`97 - Expect `dist/` to contain at least a wheel and often an sdist.98 - If only one artifact type is produced, verify that this is intentional.991007. **Validate artifacts before publishing**101 - Run `twine check dist/*`.102 - Optionally install the built wheel into a fresh environment and run a smoke test.103 - Use `python scripts/validate-runtime.py --twine-check` for a local preflight report.104 - Confirm package data, README rendering, entry points, and metadata fields.1051068. **Publish safely**107 - Prefer TestPyPI or another non-production validation path before a first public release.108 - For CI/CD publication, prefer PyPI Trusted Publishers when available.109 - Treat long-lived API tokens as a fallback, not the preferred baseline.110 - If release integrity is a mature concern, consider attestations as an advanced enhancement.1111129. **Hand off with concrete verification**113 - Report the backend used, project layout, build commands, artifact results, and publishing path.114 - Include any warnings from `scripts/validate-runtime.py` and the fix applied or deferred.115116## Examples117118Open `examples/implementation-example.md` when the task needs copy-check-compare examples.119120Use those examples for:121122- a minimal distributable library using `src/` layout123- a library plus CLI package with a console entry point124- expected `dist/` outputs after build125- validation steps before TestPyPI or PyPI publication126127## Troubleshooting128129### 1. Tests pass locally but the installed package is broken130131**Symptoms**132- Imports work from the repository root.133- A wheel installs, but runtime imports fail.134135**Likely causes**136- Flat layout is masking missing package discovery or missing files.137- Tests are importing from the working tree instead of the installed package.138139**Checks**140- Confirm whether the project uses `src/` or flat layout.141- Create a fresh environment and install the built wheel.142- Run imports from outside the repository directory.143144**Fix**145- Prefer `src/` layout for distributable libraries.146- Rebuild and retest using the wheel, not only editable install behavior.147148### 2. `twine check` fails or README rendering is broken149150**Symptoms**151- `twine check dist/*` reports invalid long description content type or rendering issues.152153**Likely causes**154- `readme` metadata is missing or mismatched.155- README content or format declaration is inconsistent.156157**Checks**158- Review the `readme` field in `[project]`.159- Confirm the README file exists and matches the declared format.160161**Fix**162- Correct the `readme` declaration.163- Rebuild artifacts and rerun `twine check` before any upload.164165### 3. Package installs but the CLI command is missing or fails166167**Symptoms**168- Installation succeeds, but the expected command is unavailable.169- The command exists but crashes on startup.170171**Likely causes**172- Missing or incorrect console-script entry point.173- The entry point target does not resolve to a callable.174- The command was installed into a different environment than the one being used.175176**Checks**177- Review entry point configuration in `pyproject.toml`.178- Verify the target object exists and is importable.179- Confirm the environment and `PATH` are the expected ones.180181**Fix**182- Declare the console entry point correctly.183- Reinstall the built wheel in a fresh environment and test the installed command.184185### 4. Built distribution is missing templates, data files, or other non-code assets186187**Symptoms**188- Source tree contains files that are absent after installation.189- Runtime file lookups fail only in built artifacts.190191**Likely causes**192- Package data was not included in the build configuration.193- The file exists in the repository but is outside the packaged paths.194195**Checks**196- Inspect wheel and sdist contents directly.197- Compare source tree paths with packaged paths.198199**Fix**200- Configure package data explicitly using backend-specific packaging rules.201- Rebuild and inspect artifacts again before upload.202203### 5. Editable install behavior differs from wheel install behavior204205**Symptoms**206- Editable install works, but the built wheel behaves differently.207208**Likely causes**209- The project relies on repository-local paths or undeclared files.210- Backend editable install behavior differs from assumptions.211212**Checks**213- Test both editable install and wheel install in fresh environments.214- Compare import paths and package contents.215216**Fix**217- Treat wheel installation as the release truth.218- Remove assumptions that only hold in editable mode.219220### 6. Dependency specification is rejected or resolves unexpectedly221222**Symptoms**223- Installer errors mention invalid requirement strings.224- Consumers get broader or narrower dependency resolution than intended.225226**Likely causes**227- Invalid version specifier syntax.228- Development-only requirements were placed in runtime dependencies.229230**Checks**231- Review dependency strings against the version-specifier specification.232- Separate mandatory runtime dependencies from optional features and development groups.233234**Fix**235- Correct the requirement syntax.236- Move non-runtime dependencies out of the core runtime dependency list.237238## Additional Resources239240- `references/runtime-practices.md` for backend-neutral decision guidance, metadata reminders, and release checks241- `examples/implementation-example.md` for concrete project trees and packaging examples242- `scripts/validate-runtime.py` for local inspection of `pyproject.toml`, layout, and `dist/` artifacts243244External standards and primary references:245246- PyPA Packaging tutorial247- PyPA guide to writing `pyproject.toml`248- PyPA discussion on `src/` layout vs flat layout249- PyPA discussion of package formats250- PEP 621 for project metadata251- PEP 660 for editable installs252- `build` documentation253- Twine documentation254- PyPI Trusted Publishers documentation255256## Related Skills257258Use a different skill when the task shifts to:259260- environment management rather than packaging261- CI/CD workflow authoring beyond package release specifics262- Docker or container image build pipelines263- framework deployment patterns264- repository-wide release engineering outside Python packaging scope