skills/python/create-py-project/SKILL.md
Create, set up, bootstrap, or scaffold modern Python projects with best-in-class tooling. Use when users want to initialize Python projects, create FastAPI apps, build CLI tools, or set up project tooling (poetry, uv, ruff, mypy, pytest, pre-commit).
npx skillsauth add rapid-recovery-agency-inc/agents-skills create-py-projectInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
Create, set up, bootstrap, or scaffold modern Python projects with best-in-class tooling.
ALWAYS use this skill when the user wants to:
Trigger on these phrases and contexts:
Use this skill even if the user:
This skill generates complete, working projects with pyproject.toml, main.py, package structure, router setup (for FastAPI), pre-commit hooks, linting/formatting config, and all starter files. It intelligently extracts requirements from user requests and auto-executes when intent is clear.
All agents must follow these architectural conventions when generating projects:
shared/ - Cross-cutting shared modules and weak models
modules/ - Strong models and domain services
shared/ clientsFollow these principles when generating code and structure:
CRITICAL: Avoid from __future__ import ... statements
Organize projects to be orthogonal and prevent circular imports instead:
modules/ depends on shared/, never the reverseshared/shared/, implement in modules/list[str], dict[str, Any])__future__ importsWhen generating FastAPI projects:
shared/ - Create actual implementation files:
shared/config.py - Settings/configuration using pydantic-settingsshared/{domain}_client.py - API clients for external servicesshared/router.py - FastAPI routers (can be split into multiple files)shared/models.py - DTOs, request/response models (weak models)modules/ - Create domain services that use shared clients:
modules/{domain}_service.py - Business logic that uses clients from shared/modules/models.py - Domain models with business logic (strong models){package_name}/ - Keep minimal (usually just __init__.py)shared/ (for clients, config) and modules/ (for services)When generating CLI projects:
shared/ - Create utilities and helpers:
shared/file_utils.py - File I/O operationsshared/api_client.py - External API clients if neededshared/config.py - Configuration managementmodules/ - Create core business logic:
modules/{domain}_processor.py - Business logic that uses shared utilitiesmodules/models.py - Domain models{package_name}/ - Keep minimal (usually just __init__.py)my-api/
├── main.py # FastAPI app, includes routers
├── pyproject.toml
├── my_api/ # Package (minimal)
│ └── __init__.py
├── shared/ # Infrastructure layer
│ ├── __init__.py
│ ├── config.py # Settings (API keys, URLs, etc.)
│ ├── {domain}_client.py # HTTP client for external API
│ └── router.py # FastAPI routes
└── modules/ # Domain layer
├── __init__.py
├── {domain}_service.py # Business logic using client from shared/
└── models.py # Domain models
Core Files (Always):
pyproject.toml - Full project config with dependencies and tool settingsmain.py - Entry point (CLI or FastAPI with lifespan).pre-commit-config.yaml - Git hooks configured for your type checker choice.gitignore - Python-specific ignores.env.example - Environment template with relevant variables for your projectREADME.md - Complete documentation with accurate commandsJustfile - Task runner with common commands.python-version - Python version (if pyenv detected)Package Structure (Always):
{package_name}/__init__.py - Package initialization (usually minimal/empty)shared/__init__.py - Shared modules directory (cross-cutting concerns, weak models)modules/__init__.py - Modules directory (domain models, business services)Additional Files Based on Project Type:
shared/ (clients, config, routers)shared/ (utilities, helpers) and modules/ (business logic)All files contain working, customized content - not placeholder text or generic templates.
CRITICAL: Directory structure follows company conventions:
shared/ for infrastructure, clients, utilities, weak models - ALWAYS CREATE WITH ACTUAL FILESmodules/ for domain logic, business services, strong models - ALWAYS CREATE, populate based on domain{package_name}/ is typically minimal (just __init__.py) - NOT the main code locationpoetry (default) or uvruff (replaces black, flake8, isort, pydocstyle)mypy (default) or typytestpre-commitUses the proven rule set from production projects:
This skill uses three specialized agents working together:
This skill includes specialized agents for different tasks:
agents/setup-coordinator.md)Purpose: Orchestrate the entire bootstrap process with flexible customization.
Responsibilities:
Key Feature: Understands nuanced user intent and passes it to File Generator for customization.
agents/file-generator.md)Purpose: Dynamically generate all project files with appropriate, working content.
Responsibilities:
Key Feature: Adapts content based on user's specific needs, not rigid templates.
Customization Examples:
agents/project-validator.md)Purpose: Comprehensively validate generated project files.
Validation Checks:
Key Feature: Reports findings only; Setup Coordinator coordinates fixes.
Before asking any questions, analyze the user's request to determine if requirements are explicit.
If the user's request contains explicit project requirements, immediately proceed to file generation. Extract settings from their request and infer reasonable defaults for anything not specified.
When to auto-execute without questions:
When to use ask_user_question for quick clarification (even in auto-execute mode):
ask_user_question with text input)Explicit requirement indicators:
Examples that should auto-execute:
Inferred settings for auto-execute:
is_fastapi=trueis_fastapi=falsepoetry3.13 (unless specified)mypy (unless specified)If the user's request is vague or generic, enter interactive mode and use ask_user_question for all questions. If the user's request don't cover one of the specific questions required for generating a project, then use ask_user_question to ask for that information (one question at a time), if ask_user_question type tooling is not available (check), then ask via chat.
Vague request examples:
Interactive flow:
ask_user_question is available (it should be in Windsurf/Cascade)ask_user_question:
Use default bootstrap settings?["yes", "no"]"yes"ask_user_question for all questions (see section 1.1 below)Default settings:
poetry3.13mypynoA Python projectTool usage:
ask_user_question for requirement gatheringask_user_question is truly unavailable or returns a tool-not-found/errorask_user_question is availableUse ask_user_question in menu/select mode for questions with ≤4 discrete options. This reduces friction and prevents typing errors.
poetry (default) vs uv3.12, 3.13 (default), or Othermypy (default), ty, or noneno (default), yesask_user_question is not availableAsk questions sequentially, one at a time to reduce communication friction. Do not present all questions at once.
Use default bootstrap settings? [Y/n] first.This sequential approach prevents the user from feeling overwhelmed and allows for context-specific follow-ups.
| Question | Default | Options | Input Type |
| ---------------- | ------------------ | -------------------- | ------------ |
| Package manager | poetry | poetry, uv | Menu or text |
| Python version | 3.13 | 3.12, 3.13 | Menu or text |
| Project name | Directory name | Any valid name | Text |
| Description | "A Python project" | Free text | Text |
| Type checker | mypy | mypy, ty, none | Menu or text |
| FastAPI project? | no | yes, no | Menu or text |
| Dependencies | (none) | Comma-separated | Text |
| Dev dependencies | (none) | Comma-separated | Text |
Default dev dependencies always included:
pytestpytest-asyncioruffpre-commitAdditional defaults if type checker selected:
mypy or ty (based on choice)Additional defaults if FastAPI:
fastapi[standard]uvicornpydanticRead the appropriate templates from the skill's templates/ directory based on user choices:
templates/
├── pyproject-poetry.toml
├── pyproject-uv.toml
├── main-simple.py
├── main-fastapi.py
├── package_init.py
├── shared_router.py
├── pre-commit.yaml
├── gitignore
├── env.example
├── readme.md
└── justfile
Substitute these variables into templates using simple string replacement ({{ variable }}):
| Variable | Value | Example |
| ------------------------- | ------------------------------------------- | ----------------------------------------- |
| tool | "poetry" or "uv" | poetry |
| python_version | Python version | 3.13 |
| python_version_nodot | Version without dots | 313 |
| project_name | Package name (kebab-case) | my-project |
| project_name_underscore | Package name (snake_case) | my_project |
| project_description | User's description | A CLI tool |
| tool_name | Tool display name | Poetry or uv |
| dependencies | Formatted dependency lines | "requests",\n "click", |
| dev_dependencies | Formatted dev dependency lines | httpx = "*" (poetry) or "httpx", (uv) |
| fastapi_deps | FastAPI deps if enabled | "fastapi[standard]",\n "uvicorn", |
| type_checker_dep | Type checker dependency line | mypy = "*" or "mypy", |
| mypy_config | mypy config section or empty | [tool.mypy]\nstrict = true |
| mypy_precommit | mypy pre-commit hook or empty | Full yaml block |
| fastapi_env | FastAPI env vars or empty | APP_HOST=127.0.0.1 |
| install_cmd | Install command | poetry install |
| activate_cmd | Activate command | poetry shell |
| run_cmd | Run command | poetry run python main.py |
| ruff_check_cmd | Ruff check command | poetry run ruff check . |
| ruff_format_cmd | Ruff format command | poetry run ruff format . |
| run_verbose_cmd | Run verbose command | poetry run python main.py --verbose |
| ruff_check_fix_cmd | Ruff check with fix | poetry run ruff check --fix . |
| setup_cmd | Setup environment | poetry install |
| update_cmd | Update dependencies | poetry update |
| add_dep_cmd | Add dependency | poetry add |
| add_dev_cmd | Add dev dependency | poetry add --group dev |
| project_structure | Project structure diagram | Directory tree |
| is_fastapi | true or false (for file selection only) | - |
| use_pyenv | true if pyenv detected | true or false |
Write these files to the target directory:
| File | Template | Condition |
| ---------------------------- | ------------------------------------- | ------------------------ |
| pyproject.toml | pyproject-{tool}.toml | Always |
| main.py | main-fastapi.py or main-simple.py | Based on is_fastapi |
| {project_name}/__init__.py | package_init.py | Always |
| shared/__init__.py | Empty | If is_fastapi |
| shared/router.py | shared_router.py | If is_fastapi |
| .pre-commit-config.yaml | pre-commit.yaml | Always |
| .gitignore | gitignore | Always |
| .env.example | env.example | Always |
| README.md | readme.md | Always |
| Justfile | justfile | Always |
| .python-version | Literal | If use_pyenv is true |
Prerequisite:
valid: true.Run the appropriate commands based on tool choice:
poetry install
uv venv
uv pip install -e ".[dev]"
Run initial formatting and linting:
poetry run ruff check --fix .
poetry run ruff format .
uv run ruff check --fix .
uv run ruff format .
Note:
After validation passes, offer to run a live test of the application:
Use ask_user_question to ask:
["yes", "no"]"yes"If user says "yes":
For FastAPI projects:
Start the server in the background: poetry run python main.py or uv run python main.py
Wait for server startup (check for "Application startup complete" or similar)
Test endpoints with curl:
# Test health endpoint
curl -s http://localhost:8000/health || echo "Health check failed"
# Test root endpoint
curl -s http://localhost:8000/ || echo "Root endpoint failed"
# For APIs with specific routes, test those too
# Example: curl -s http://localhost:8000/api/weather/current?city=Seattle&state=WA
Report results to user (success/failure for each endpoint)
Stop the server (send SIGTERM or use process management)
For CLI projects:
--help to verify it works: poetry run python main.py --helpIf user says "no":
Show the user:
✅ Project "{project_name}" bootstrapped successfully!
📁 Files created:
- pyproject.toml (project config)
- main.py (entry point)
{shared/router.py if FastAPI}
- .pre-commit-config.yaml (git hooks)
- .gitignore
- .env.example
- README.md
🚀 Next steps:
1. cd {directory}
2. {poetry shell / source .venv/bin/activate}
3. cp .env.example .env # Edit with your values
4. {poetry run python main.py / uv run python main.py}
📦 To add dependencies:
{poetry add <package> / uv add <package>}
🔧 Tools configured:
- ruff: linting & formatting (run: {poetry run ruff check . / uv run ruff check .})
- {mypy/ty}: type checking (run: {poetry run mypy . / uv run mypy .})
- pytest: testing (run: {poetry run pytest / uv run pytest})
- pre-commit: git hooks (run: pre-commit install)
[project]
name = "{project_name}"
version = "0.1.0"
description = "{project_description}"
readme = "README.md"
requires-python = ">={python_version}"
dependencies = [
# User-specified dependencies
]
[project.scripts]
{project_name} = "{project_name}.main:main"
[tool.poetry]
packages = [{include = "{project_name}"}]
[tool.poetry.group.dev.dependencies]
pytest = "*"
pytest-asyncio = "*"
ruff = "*"
pre-commit = "*"
# Type checker if selected
# User-specified dev dependencies
[tool.ruff]
line-length = 88
target-version = "py{python_version_nodot}"
[tool.ruff.format]
quote-style = "double"
docstring-code-format = true
[tool.ruff.lint]
ignore = [
"E203",
"S110",
"D100",
"D104",
"D107",
"D203",
"D213",
"D105",
]
select = [
"E", "F", "W",
"I",
"UP",
"PL",
"B",
"S",
"C90",
"D"
]
[tool.ruff.lint.per-file-ignores]
"**/tests/**" = ["S101", "PLR2004"]
"**/test_*.py" = ["S101"]
[tool.ruff.lint.pylint]
max-args = 6
[tool.ruff.lint.mccabe]
max-complexity = 13
[tool.mypy]
# If mypy selected
strict = true
warn_return_any = true
warn_unused_ignores = true
[build-system]
requires = ["poetry-core"]
build-backend = "poetry.core.masonry.api"
from contextlib import asynccontextmanager
from collections.abc import AsyncIterator
import uvicorn
from fastapi import FastAPI
from shared.router import router as api_router
@asynccontextmanager
async def lifespan(_app: FastAPI) -> AsyncIterator[None]:
"""Application lifespan handler."""
# Startup
yield
# Shutdown
app = FastAPI(lifespan=lifespan)
@app.get("/")
async def index() -> dict[str, str]:
"""Root endpoint."""
return {"message": "Hello from {project_name}!"}
app.include_router(api_router, prefix="/api")
if __name__ == "__main__":
uvicorn.run("main:app", host="127.0.0.1", port=8000, reload=True)
from fastapi import APIRouter, status
from fastapi.responses import JSONResponse
router = APIRouter()
@router.get("/health")
async def health() -> JSONResponse:
"""Health check endpoint."""
return JSONResponse(content={"status": "healthy"}, status_code=status.HTTP_200_OK)
repos:
- repo: https://github.com/charliermarsh/ruff-pre-commit
rev: v0.14.11
hooks:
- id: ruff
args: [--fix]
- id: ruff-format
- repo: https://github.com/pre-commit/mirrors-mypy
rev: v1.15.0
hooks:
- id: mypy
args: [--strict]
development
How to use the @rapid-recovery-agency-inc/sloth-ui-mobile design system library in a React Native app. Covers theming, styling, components, responsive design, and conventions. Activate for any request involving UI components, styling, theming, text, buttons, modals, cards, or visual presentation when this library is in use.
testing
Create new skills, modify and improve existing skills, and measure skill performance. Use when users want to create a skill from scratch, update or optimize an existing skill, run evals to test a skill, benchmark skill performance with variance analysis, or optimize a skill's description for better triggering accuracy.
development
This skill provides instructions on how to add new environment variables and ensures robust, testable, and maintainable environment variable usage across both TypeScript and Python projects.
development
Create GitHub issues in the appropriate -tickets repository based on source repo family. Performs duplicate detection and produces crystallized, outcome-oriented issue content. Use when a user request implies creating a ticket from code context, discussion, or identified work.