python-project
Use when creating Python projects, managing dependencies with uv, configuring pyproject.toml, building packages, or publishing to PyPI - covers project initialization, dependency management, and distribution; NOT for testing or performance (plugin:python@dot-claude)
When & Why to Use This Skill
This Claude skill provides a comprehensive framework for modern Python project management, utilizing the 'uv' tool for high-performance dependency handling, environment isolation, and package distribution. It simplifies the entire development lifecycle—from project initialization and pyproject.toml configuration to building and publishing packages to PyPI—ensuring industry best practices like the src/ layout and reproducible lockfiles are maintained.
Use Cases
- Case 1: Rapidly initializing new Python projects with standardized directory structures (src/ layout) and optimized pyproject.toml templates.
- Case 2: Managing complex project dependencies, development tools (ruff, mypy, pytest), and optional extras with high-speed resolution using uv.
- Case 3: Automating the build and publishing workflow to PyPI or TestPyPI, including version management and pre-flight checklist verification.
- Case 4: Ensuring environment reproducibility across different development machines and CI/CD pipelines using pinned Python versions and uv.lock files.
| name | python-project |
|---|---|
| description | Use when creating Python projects, managing dependencies with uv, configuring pyproject.toml, building packages, or publishing to PyPI - covers project initialization, dependency management, and distribution; NOT for testing or performance (plugin:python@dot-claude) |
| allowed-tools | Bash(uv:*), Bash(python:*), Read, Write, Edit |
Python Project Management
Modern Python project setup and dependency management with uv.
Before Writing Code
- Read
references/pythonic-style.mdfor style conventions - Check Python version:
pyproject.toml→.python-version→.claude/python-version - If unknown, ask user once and store in
.claude/python-version
Reference Files
| Topic | When to Load | File |
|---|---|---|
| Pythonic style, conventions | Before generating code | ../references/pythonic-style.md |
| Version-specific features | When adapting to Python version | ../references/version-features.md |
| GitHub Actions, Docker, monorepo | CI/CD and advanced workflows | references/ci-cd-workflows.md |
| Full pyproject.toml templates | Complete configuration examples | references/pyproject-templates.md |
Quick Start
# New project
uv init my-project && cd my-project
uv python pin 3.12
uv add fastapi pydantic
uv add --dev pytest ruff mypy
# Existing project
uv sync # Install from pyproject.toml
uv sync --all-extras # Include optional deps
Project Structure
Source Layout (Recommended)
my-package/
├── pyproject.toml
├── README.md
├── src/
│ └── my_package/
│ ├── __init__.py
│ ├── core.py
│ └── py.typed
├── tests/
│ └── test_core.py
└── .python-version
Why src/ layout: The src/ layout prevents accidental imports from the source tree during
testing. Without it, import my_package might resolve to the local directory instead of the
installed package, masking missing __init__.py files or build configuration errors.
Minimal pyproject.toml
[build-system]
requires = ["setuptools>=61.0"]
build-backend = "setuptools.build_meta"
[project]
name = "my-package"
version = "1.0.0"
requires-python = ">=3.10"
dependencies = ["requests>=2.28"]
[project.optional-dependencies]
dev = ["pytest>=7.0", "ruff>=0.1", "mypy>=1.0"]
[tool.setuptools.packages.find]
where = ["src"]
[tool.ruff]
line-length = 100
target-version = "py310"
[tool.ruff.lint]
select = ["E", "F", "I", "UP"]
Dependency Management
Adding Packages
uv add requests # Add to dependencies
uv add "django>=4.0,<5.0" # With version constraint
uv add --dev pytest ruff # Development dependencies
uv add --optional docs sphinx # Optional group
uv add -e ./local-package # Editable local
Updating Packages
uv add --upgrade requests # Upgrade specific
uv sync --upgrade # Upgrade all
uv tree --outdated # Show outdatable
Locking
uv lock # Generate uv.lock
uv lock --upgrade # Regenerate with latest
uv sync --frozen # Install exact versions (CI)
Python Version Management
uv python install 3.12 # Install Python
uv python pin 3.12 # Create .python-version
uv python list # List installed
Running Code
uv run python app.py # Run script
uv run pytest # Run tests
uv run ruff check . # Run linter
uv run --python 3.11 script.py # Specific version
CLI Entry Points
With Click
# src/my_package/cli.py
import click
@click.group()
@click.version_option()
def cli():
"""My CLI tool."""
@cli.command()
@click.argument("name")
def greet(name: str):
click.echo(f"Hello, {name}!")
def main():
cli()
# pyproject.toml
[project.scripts]
my-tool = "my_package.cli:main"
uv sync && uv run my-tool greet World
Building and Publishing
# Build
uv build # Creates dist/*.whl and dist/*.tar.gz
# Test on TestPyPI first
uv publish --repository testpypi
# Publish to PyPI
uv publish
API Token Setup
# ~/.pypirc
[pypi]
username = __token__
password = pypi-...your-token...
Publishing Checklist
Before publishing:
- Tests passing (
uv run pytest) - Version updated in pyproject.toml
- CHANGELOG updated
- Build succeeds (
uv build) - Install works in clean venv
- Tested on TestPyPI first
Common Issues
# Wrong Python version
uv python pin 3.12 && uv venv --python 3.12
# Dependency conflict
uv lock --verbose
# Cache issues
uv cache clean
# Lockfile out of sync
uv lock --upgrade
Workflow Integration
| Task | Skill |
|---|---|
| Writing tests | python:python-testing |
| Profiling, async | python:python-performance |
| Before claiming done | core:verification |
Best Practices
- Use
src/layout for libraries - Pin Python version with
.python-version - Commit
uv.lockfor reproducibility - Use
uv runinstead of manual activation - Test installation in clean venv before publishing
- Use TestPyPI before real PyPI
- Automate publishing with GitHub Actions
- Keep dependencies minimal
- Use optional groups for dev/docs deps
- Run
uv sync --frozenin CI