
Python Best Practices
Apply type-first, functional Python idioms—frozen dataclasses, discriminated unions, NewType, and Protocol—whenever the agent reads or edits .py and Python project files.
Overview
Python Best Practices is a journey-wide agent skill that enforces type-first, functional Python patterns whenever a solo builder edits .py, pyproject.toml, or requirements.txt.
Install
npx skills add https://github.com/0xbigboss/claude-code --skill python-best-practicesWhat is this skill?
- Make illegal states unrepresentable with frozen dataclasses, Literal unions, and match/case handling
- NewType for domain IDs and Protocol for structural typing without inheritance clutter
- Aligns with CLAUDE.md-style type-first, functional, and error-handling patterns
- Scoped trigger: any read/write of Python sources or dependency manifests
- Language-specific idioms only—complements generic code review, not replaces it
Adoption & trust: 1.6k installs on skills.sh; 49 GitHub stars; 2/3 security scanners passed (skills.sh audits).
What problem does it solve?
Your agent writes mutable, untyped Python that lets invalid states slip through and mixes domain primitives on plain strings.
Who is it for?
Indie developers maintaining typed Python backends, automation scripts, or agent tools who want consistent patterns in every edit session.
Skip if: Pure notebooks-only workflows with no intent to enforce static typing, or teams standardized on a conflicting style guide without adaptation.
When should I use this skill?
Reading or writing Python files (.py, pyproject.toml, requirements.txt).
What do I get? / Deliverables
Python changes follow frozen models, explicit Result-style unions, and structural typing so refactors stay safe across services and scripts.
- Refactored Python modules following repo idioms
- Consistent domain types and error-channel patterns in edited files
Recommended Skills
Journey fit
Useful at every journey phase - explore requirements and options before committing to a direction.
Where it fits
Refactor user/order IDs to NewType while adding a Success|Failure request handler.
Model webhook outcomes as Literal-tagged unions before calling external APIs.
Apply the same dataclass and match patterns when reviewing a PR touching services.
Patch incident fixes without reintroducing mutable shared domain objects.
How it compares
Complements Ship-phase review skills; it is authoring guidance, not a pytest or mypy replacement.
Common Questions / FAQ
Who is python-best-practices for?
Solo builders and small teams using Claude Code or similar agents on Python codebases that already aim for types and clear error handling.
When should I use python-best-practices?
During Build on APIs and CLIs, during Ship review before merge, and during Operate when patching production Python—any time .py or Python manifests change.
Is python-best-practices safe to install?
It is read-only procedural guidance; check the Security Audits panel on this Prism page for the parent repo before install.
SKILL.md
READMESKILL.md - Python Best Practices
# Python Best Practices Follows type-first, functional, and error handling patterns from CLAUDE.md. This skill covers language-specific idioms only. ## Make Illegal States Unrepresentable Use Python's type system to prevent invalid states at type-check time. **Frozen dataclasses for immutable domain models:** ```python from dataclasses import dataclass from datetime import datetime @dataclass(frozen=True) class User: id: str email: str name: str created_at: datetime # Frozen dataclasses are immutable — no accidental mutation ``` **Discriminated unions with Literal:** ```python from dataclasses import dataclass from typing import Literal @dataclass class Success: status: Literal["success"] = "success" data: str @dataclass class Failure: status: Literal["error"] = "error" error: Exception RequestState = Success | Failure def handle_state(state: RequestState) -> None: match state: case Success(data=data): render(data) case Failure(error=err): show_error(err) ``` **NewType for domain primitives:** ```python from typing import NewType UserId = NewType("UserId", str) OrderId = NewType("OrderId", str) def get_user(user_id: UserId) -> User: # Type checker prevents passing OrderId here ... ``` **Protocol for structural typing:** ```python from typing import Protocol class Readable(Protocol): def read(self, n: int = -1) -> bytes: ... def process_input(source: Readable) -> bytes: # Accepts any object with a read() method — no inheritance required return source.read() ``` ## Python-Specific Error Handling Chain exceptions with `from err` to preserve the original traceback: ```python try: data = json.loads(raw) except json.JSONDecodeError as err: raise ValueError(f"invalid JSON payload: {err}") from err ``` ## Structured Logging Use a module-level logger with `%s` formatting (deferred string interpolation): ```python import logging logger = logging.getLogger("myapp.widgets") def create_widget(name: str) -> Widget: logger.debug("creating widget: %s", name) widget = Widget(name=name) logger.debug("created widget id=%s", widget.id) return widget ``` ## Optional: ty For fast type checking, consider [ty](https://docs.astral.sh/ty/) from Astral (creators of ruff and uv). Written in Rust, significantly faster than mypy or pyright. ```bash uvx ty check # run directly, no install needed uvx ty check src/ # check specific path ``` ```toml # pyproject.toml [tool.ty] python-version = "3.12" ``` When to choose: - `ty` — fastest, good for CI and large codebases (early stage, rapidly evolving) - `pyright` — most complete type inference, VS Code integration - `mypy` — mature, extensive plugin ecosystem