Help us improve
Share bugs, ideas, or general feedback.
From python-engineering
Improves Python code quality via static analysis, type refinement, modernization planning/review, and test-driven implementation. Use for technical debt, eliminating Any types, modern patterns, refactoring.
npx claudepluginhub jamie-bitflight/claude_skills --plugin python-engineeringHow this skill is triggered — by the user, by Claude, or both
Slash command
/python-engineering:stinkysnakeThe summary Claude sees in its skill listing — used to decide when to auto-load this skill
<file_paths>$ARGUMENTS</file_paths>
Improves Python code quality with static analysis (ruff/mypy), Any type elimination, modernization plans (Protocols/Generics/Pydantic), plan review, and test-driven refactoring.
Improves Python code quality via structured cleanup: static analysis with ruff/prek, smell investigation, type boundary hardening, modernization within project constraints, pytest verification.
Sets up Python code quality toolchain with ruff linting/formatting, mypy type checking, complexity gating, dead code detection, pre-commit hooks, pyproject.toml config, and Makefile targets.
Share bugs, ideas, or general feedback.
<file_paths>$ARGUMENTS</file_paths>
Systematic Python code quality improvement through static analysis, type refinement, modernization planning with review, and test-driven implementation.
<file_paths/>
┌─────────────────────────────────────────────────────────────────────────────┐
│ STINKYSNAKE WORKFLOW │
├─────────────────────────────────────────────────────────────────────────────┤
│ │
│ Phase 1: STATIC ANALYSIS │
│ ├── Run quality gate (prek) │
│ ├── Auto-fix all resolvable issues │
│ └── Document remaining issues │
│ │ │
│ ▼ │
│ Phase 2: TYPE ANALYSIS │
│ ├── Determine minimum Python version │
│ ├── Inventory all `Any` types │
│ ├── Map type dependencies │
│ └── Identify typing gaps │
│ │ │
│ ▼ │
│ Phase 3: MODERNIZATION PLANNING │
│ ├── Plan Protocol usage for duck typing │
│ ├── Plan Generic type parameters │
│ ├── Plan TypeGuard narrowing │
│ ├── Plan TypeAlias definitions │
│ ├── Plan TypedDict for dict shapes │
│ ├── Plan dataclass/Pydantic models │
│ └── Plan library modernization (httpx, orjson, etc.) │
│ │ │
│ ▼ │
│ Phase 4: PLAN REVIEW (context: fork) │
│ ├── Review against pythonic best practices │
│ ├── Verify against online references │
│ ├── Check feasibility │
│ ├── Identify breaking changes │
│ └── Produce review report │
│ │ │
│ ▼ │
│ Phase 5: PLAN REFINEMENT │
│ └── Update plan based on review feedback │
│ │ │
│ ▼ │
│ Phase 6: DOCUMENTATION DISCOVERY │
│ ├── Find docs requiring updates │
│ └── Note what changes are needed │
│ │ │
│ ▼ │
│ Phase 7: INTERFACE DESIGN │
│ └── Create interfaces/protocols first │
│ │ │
│ ▼ │
│ Phase 8: TEST-FIRST (context: fork, python-pytest-architect) │
│ ├── Write failing tests against interfaces │
│ └── Stop after tests written │
│ │ │
│ ▼ │
│ Phase 9: IMPLEMENTATION (/python-engineering:snakepolish) │
│ ├── context: fork with python-cli-architect │
│ ├── Follow plans and implement functions │
│ └── Run tests until passing │
│ │
└─────────────────────────────────────────────────────────────────────────────┘
This skill integrates with plugins in the same marketplace:
Activation: Skill(skill: "holistic-linting:holistic-linting")
Provides: Linting rules knowledge base, linting-root-cause-resolver agent, automatic linter detection.
Activation: Skill(skill: "python-engineering:python3-tools")
Provides: Git hook automation for quality gates via prek.
Run automated tools to fix all resolvable issues before manual work begins.
uv run prek run --files $ARGUMENTS
# Fallback when no .pre-commit-config.yaml:
# uv run ruff format $ARGUMENTS
# uv run ruff check --fix $ARGUMENTS
Inspect .pre-commit-config.yaml (then CI) first, then pyproject.toml. Default for new work: ty. If hooks or CI invoke mypy: run mypy and do not rip it out. Do not switch to mypy only because [tool.mypy] exists — many repos keep that section while ty is the real gate.
# Default (ty) — when hooks run ty, [tool.ty] is active, or no mypy invocation in hooks/CI
uv run ty check $ARGUMENTS
# Project that actually runs mypy in hooks/CI — respect mypy.ini / [tool.mypy]
uv run mypy $ARGUMENTS
# Project standardizes on pyright / basedpyright
uv run pyright $ARGUMENTS
# uv run basedpyright $ARGUMENTS
Create inventory of issues that cannot be auto-fixed:
## Static Analysis Results
### Auto-Fixed
- [X] Formatting issues: N fixed
- [X] Import sorting: N fixed
- [X] Safe linting fixes: N fixed
### Requires Manual Resolution
| File:Line | Rule | Issue | Complexity |
|-----------|------|-------|------------|
| src/api.py:45 | ANN001 | Missing type annotation | Low |
| src/models.py:120 | B006 | Mutable default | Medium |
Determine Python compatibility and inventory typing gaps.
Check project configuration:
# Check pyproject.toml
grep -E "requires-python|python_requires" pyproject.toml
# Check setup.py if exists
grep -E "python_requires" setup.py
Document the constraint:
## Python Version Constraint
Minimum Version: Python 3.11
Reason: [from pyproject.toml requires-python = ">=3.11"]
Available Language Features:
- Native generics (list[str], dict[str, int])
- Union syntax (str | None)
- Pattern matching (match/case)
- Exception groups
- Self type
- TypeVarTuple
- Required/NotRequired in TypedDict
Any TypesSearch for explicit and implicit Any usage:
# Find explicit Any imports and usage
uv run rg "from typing import.*Any|: Any|-> Any" $ARGUMENTS
# Implicit Any / strict diagnostics — use the same checker the project uses
uv run ty check $ARGUMENTS 2>&1 | grep -iE "Any|implicit" || true
# If project uses mypy instead:
# uv run mypy --strict $ARGUMENTS 2>&1 | grep -E "has type.*Any|Implicit.*Any"
Create inventory:
## Any Type Inventory
### Explicit Any Usage
| Location | Variable | Current Type | Proposed Type |
|----------|----------|--------------|---------------|
| api.py:23 | response | Any | dict[str, JSONValue] |
| utils.py:45 | callback | Any | Callable[[str], None] |
### Implicit Any (from untyped libraries)
| Location | Source | Mitigation |
|----------|--------|------------|
| client.py:12 | third_party.get() | Add type stub or cast |
Understand how types flow through the codebase:
## Type Dependency Map
Entry Points (public API):
- cli.main() -> int
- api.fetch_data(url: str) -> ??? # Needs typing
Internal Flow:
fetch_data() -> parse_response() -> validate() -> Model
Type Gaps:
- parse_response returns Any
- validate accepts Any
Plan how to apply modern Python features to eliminate type gaps and improve design.
Skill(skill: "python-engineering:modernpython")
For each Any in the inventory, plan the replacement using appropriate constructs:
Select the appropriate type construct for each Any replacement:
See references/type-patterns.md for before/after code samples and library modernization reference table.
See the library modernization reference table in references/type-patterns.md#library-modernization-reference.
Resolve the plan directory at runtime: uv run python -c 'from dh_paths import plan_dir; print(plan_dir())' (typically ~/.dh/projects/{slug}/plan/). Create the plan at {plan_dir}/stinkysnake-plan.md using the template in references/plan-templates.md#modernization-plan-template-phase-3-output.
Delegate to a review agent with context fork to critique the plan.
Delegate to code-reviewer using the prompt in references/agent-prompts.md#phase-4-plan-review.
The reviewer produces a report following the template in references/plan-templates.md#plan-review-report-template-phase-4-output.
Update the plan based on review feedback.
For each blocking issue:
For each warning:
For each suggestion:
Update {plan_dir}/stinkysnake-plan.md (resolve plan_dir as in Step 3.4) using the revised plan format in references/plan-templates.md#revised-plan-template-phase-5-output.
Find documentation that needs updating after code changes.
# Find all documentation files
fd -e md -e rst -e txt . docs/ README.md CHANGELOG.md
# Find docstrings in affected files
uv run rg "^\s+\"\"\"" $ARGUMENTS
Create documentation update plan using the template in references/plan-templates.md#documentation-update-plan-template-phase-6-output.
Create interfaces and protocols before implementation.
# src/types.py
from typing import TypeAlias
JSONValue: TypeAlias = str | int | float | bool | None | list["JSONValue"] | dict[str, "JSONValue"]
APIResponse: TypeAlias = dict[str, JSONValue]
# src/protocols.py
from typing import Protocol
class Handler(Protocol):
def handle(self, data: bytes) -> None: ...
class Serializable(Protocol):
def to_dict(self) -> dict[str, Any]: ...
# src/schemas.py
from typing import TypedDict, NotRequired
class UserData(TypedDict):
name: str
email: str
age: NotRequired[int]
# src/models.py
from dataclasses import dataclass
@dataclass
class User:
name: str
email: str
age: int | None = None
Delegate to python-pytest-architect to write failing tests against the interfaces.
Delegate to python-pytest-architect using the prompt in references/agent-prompts.md#phase-8-test-writing-agent.
# Run tests - they should fail
uv run pytest tests/ -v
# Expected output: X failed, 0 passed
Use the /python-engineering:snakepolish skill to implement until tests pass.
/python-engineering:snakepolish $ARGUMENTS
This skill:
context: fork to work in isolationagent: python-cli-architect for implementation# Final verification
uv run prek run --files $ARGUMENTS
# Fallback when no .pre-commit-config.yaml:
# uv run ruff check $ARGUMENTS
uv run pytest -v --cov --cov-report=term-missing
The complete workflow produces:
| Artifact | Location | Purpose |
|---|---|---|
| Static Analysis Results | .claude/reports/static-analysis-{ts}.md | Auto-fix summary |
| Type Inventory | .claude/reports/type-inventory-{ts}.md | Any types found |
| Modernization Plan | {plan_dir}/stinkysnake-plan.md | Implementation plan |
| Plan Review | .claude/reports/plan-review-{ts}.md | Review feedback |
| Revised Plan | {plan_dir}/stinkysnake-plan.md | Updated plan |
| Doc Update Plan | .claude/reports/doc-updates-{ts}.md | Docs to change |
| Test Files | tests/test_*.py | Failing tests |
| Implementation | src/ | Passing code |
Skill(skill: "holistic-linting:holistic-linting") # Linting workflows
Skill(skill: "python-engineering:python3-tools") # Git hooks via prek
Skill(skill: "python-engineering:modernpython") # Python 3.11+ patterns
Skill(skill: "python-engineering:python3-core") # Core patterns
Agent(subagent_type="holistic-linting:linting-root-cause-resolver", ...) # Phase 1 linting
Agent(subagent_type="python-engineering:code-reviewer", ...) # Phase 4 review
Agent(subagent_type="python-engineering:python-pytest-architect", ...) # Phase 8 tests
/python-engineering:snakepolish # Phase 9 implementation (context: fork)
When Phase 4 (quality improvement implementation) involves 3+ independent improvement areas where findings from one area inform or challenge another, consider agent teams instead of sequential subagents.
A quality improvement workflow is a candidate for agent teams when ALL of these are true:
A quality improvement workflow is NOT a candidate for agent teams when:
See ../../../plugin-creator/skills/claude-skills-overview-2026/resources/agent-teams.md for complete criteria, architecture, and usage patterns.
SOURCE: Lines 27-39 of agent-teams.md (accessed 2026-02-06)
references/plan-templates.md — document formats for modernization plan, review report, revised plan, and documentation update planreferences/agent-prompts.md — pre-built delegation prompts for Phase 4 review agent and Phase 8 test writing agent