Configure modern Python development tooling for any Python project — library, backend, CLI, or otherwise. Invoke this skill whenever a user wants to set up or improve Python tooling, configure pyproject.toml, add pre-commit hooks, set up linting or formatting, configure a type checker or test runner, or any request like "set up my Python project", "configure Python tooling", "add pre-commit to my project", "set up ruff and mypy", or "bootstrap Python dev tools". This skill works on both empty repositories and existing projects with partial configuration. It produces ONLY configuration files — no source code, no test logic.
Configure modern Python development tooling for any Python project. This skill works on both new (empty) repositories and existing projects that already have code and partial configuration. It creates and updates configuration files only — never source code or test logic.
Read references/tools-catalog.md for all supported tool options and their pyproject.toml
config snippets. Read references/pre-commit-catalog.md for all pre-commit hook configurations.
Set up, modernize, or complete the local development tooling for a Python project. The skill is scoped exclusively to developer experience tooling: package management, linting, formatting, type checking, testing, coverage, pre-commit hooks, and security scanning. It does not touch documentation, CI/CD, GitHub Actions, publishing, release automation, or repository hosting.
| Type | Description | Default adjustments |
|---|---|---|
library | Distributable Python package (PyPI) |
build_backend = hatchling, versioning = hatch-vcs |
backend | Web API / server (FastAPI, Django, Flask) | build_backend = none, versioning = none |
cli | Command-line tool | build_backend = hatchling if published, none otherwise |
data-science | Notebooks, data pipelines | build_backend = none, versioning = none |
scripts | Utility scripts, automation | build_backend = none, versioning = none |
The project type influences defaults only. All tool categories work the same regardless of type.
Before asking the user anything, explore the current state of the repository. Use your file reading tools to gather the following information:
Existing configuration files — check which of these exist:
pyproject.toml / setup.py / setup.cfg.pre-commit-config.yaml.python-version.gitignore.editorconfigrequirements.txt / requirements-dev.txt / requirements*.txtPipfile / poetry.lock / uv.lock / pdm.lockProject structure — identify the layout:
src/<name>/ exist? (src layout)<name>/ package directory exist at the root?tests/ or test/ directories?Currently configured tools — if pyproject.toml exists, read it and identify:
[tool.*] sections are already present (ruff, mypy, pytest, etc.)[build-system] backend in use, if anyrequires-python versionProject type signals — look for:
[project] table with name, version, etc.After analysis, present a concise summary to the user:
Project scan complete
- Found:
pyproject.tomlwith ruff and pytest configured,uv.lock(uv), Python 3.12- Missing: mypy, pre-commit,
.editorconfig- Project type looks like: backend web app (fastapi detected)
I'll focus on adding the missing tooling. Continue?
If the repository appears to be empty or brand new, note that and proceed to gather context.
Based on the Phase 0 analysis, ask only for information that could not be determined automatically. Keep it concise — you can ask all at once. Do not re-ask for things already found.
my-project). Skip if already in pyproject.toml.my_project). Skip if determinable from
the project structure. Defaults to project name with hyphens replaced by underscores..python-version or
requires-python. Default: 3.11.pyproject.toml. Skip if already present. Use
YOUR NAME / [email protected] as placeholders if the user wants to skip.library, backend,
cli, data-science, scripts. If unsure or irrelevant, skip — the tooling works the same.| Category | Default | Alternatives |
|---|---|---|
package_manager | uv | pip, poetry, pdm, hatch |
build_backend | hatchling (library) / none (app) | setuptools, flit-core, poetry-core, pdm-backend, none |
linter | ruff | flake8, pylint, none |
formatter | ruff | black, autopep8, none |
import_sorter | none (ruff's I rule covers it) | isort |
static_type_checker | mypy | pyright, basedpyright, none |
test_runner | pytest | unittest, none |
coverage | pytest-cov | coverage, none |
versioning | hatch-vcs (library) / none (app) | bump2version, commitizen, manual, none |
security_scanning | none | bandit, safety |
Notes on project type defaults:
build_backend = hatchling, versioning = hatch-vcsbuild_backend = none,
versioning = none (or manual); pyproject.toml still serves as a tool config hubIf the user says "just use the defaults" or provides no selections, apply the defaults above based on the inferred project type.
Before modifying any files, summarize what will be created or updated and ask the user to confirm. Distinguish clearly between new files, files that will be updated, and files already present with no changes needed. Example:
I'll configure your project with:
- uv · ruff (lint + format) · mypy · pytest + pytest-cov
- pre-commit with ruff, mypy, and hygiene hooks
New files:
.python-version,.editorconfig,.pre-commit-config.yamlUpdate:pyproject.toml(add mypy and coverage sections) Already present, no change:.gitignore, ruff config in pyproject.tomlReady to proceed?
Only proceed after confirmation (or if the user says "just do it").
Work through the files below. For each file: check whether it already exists. If it exists with real content, update or merge rather than overwrite — add missing sections, update stale versions, and preserve existing configuration unless the user explicitly asks to replace it.
For every file the skill touches, apply one of these actions and report it in the final summary:
| Action | When to use |
|---|---|
| Create | File does not exist. Generate from scratch. |
| Update | File exists but is missing sections or has outdated config. Merge new content. |
| Preserve | File exists and its content is already correct. Leave untouched. |
| Skip | File is irrelevant to the selected tools or project type. Do not create. |
Idempotency rule: Running the skill twice with the same inputs must produce the same result. Never duplicate sections, hooks, or dependencies. Always check before appending.
Only create these if they are missing and relevant:
src/<package_name>/ — only for library/package projects with src layout; add .gitkeeptests/ — add .gitkeep if the directory does not existNever create
.pyfiles — only.gitkeepplaceholders. Do not createdocs/or any documentation directory.
pyproject.tomlThis is the primary configuration hub. If it already exists, read it fully first and only add or update the sections relevant to selected tools. Never remove existing sections unless the user explicitly requests it.
[build-system] — include only when build_backend != none. See references/tools-catalog.md § Build Backends.
[project] — if absent, create with:
[project]
name = "<project-name>"
description = "<description>"
readme = "README.md"
license = { text = "MIT" }
authors = [{ name = "<author>", email = "<email>" }]
requires-python = ">= <python-version>"
dynamic = ["version"] # omit if versioning = manual or none; add version = "0.1.0" instead
dependencies = []
If [project] already exists, only add missing fields — do not overwrite existing ones.
[tool.*] sections — append one per selected tool that is not already configured. Pull exact
snippets from references/tools-catalog.md. Key rules:
linter: ruff and formatter: ruff → single [tool.ruff] block covering bothimport_sorter: none when linter: ruff — the I rule handles it; ensure known-first-party
is set in [tool.ruff.lint.isort]import_sorter: isort when ruff is not selected → add [tool.isort] block and isort dev depversioning: hatch-vcs → affects [build-system] and adds [tool.hatch.version]package_manager: uv → add [tool.uv] with dev-dependencies group[project.optional-dependencies] — add dev group when package_manager is not uv:
[project.optional-dependencies]
dev = [] # list dev deps here
If a [tool.*] section for a selected tool already exists, do not add a duplicate — instead
verify it is reasonably configured and note any recommended updates to the user.
.python-versionSingle line: the minimum Python version (e.g. 3.11). Create if missing. Skip if already present
with a valid version.
.gitignoreCopy content from assets/gitignore-python.txt verbatim if .gitignore does not exist.
If .gitignore already exists, append only the lines that are missing from it.
.editorconfigCopy content from assets/editorconfig.txt verbatim. Skip if already present.
.pre-commit-config.yamlAlways create or update this file. Pre-commit is part of every setup regardless of other selections.
If the file does not exist, create it starting with the base hygiene hooks: