Modern Python
Ruff is the rule database and the project's target Python version is the gate. The bundled tool
lists only the modernization rules whose own Ruff examples diagnose under that target, so nobody
curates a rule table and the guidance tracks Ruff. It corrects two things at once: training-data
lag (a feature newer than the model) and frequency bias (the older pattern the model reaches for
out of habit).
Tool: python <skill-dir>/scripts/modern_python.py, where <skill-dir> is this folder.
Subcommands: list, explain, check, fix, probe.
Step 0: the project's answers
Read .claude/modern-python.md at the repo root. It holds the interview answers: codebase,
convention, enforcement, target, target-source, ruff-fallback, profile.
- Present: continue with its values.
- Absent: run the interview in
references/interview.md once, write
the file, continue. If the user declines the interview, proceed with enforcement: advisory,
convention: preserve, no target override, say so once, and do not ask again this session.
- The repo's
CLAUDE.md carries modern-python: off: proceed as declined without asking. That
is the line for a repo whose .claude/ is not yours to write (onboard-light territory).
/modern-python setup re-runs the interview and rewrites the file.
Before editing Python
List the guidance that applies to the file you are about to touch:
python <skill-dir>/scripts/modern_python.py list --file path/to/file.py --target-version <target> --profile <profile>
Omit --target-version when target-source: declared. For a file that does not exist yet,
pass --target-version from the answers file.
Exit 3 means the project's Ruff is too old to report rule metadata. Ask whether to update Ruff
through the project's own manager (uv, Poetry, PDM, pre-commit). On yes, update and rerun. On
no, rerun with --allow-stale and rely on the post-edit check.
Read the complete output. Do not pipe it through head, tail, grep, sed, or any other truncating
or filtering command: a rule dropped there is a rule you will violate. Baseline rules diagnose
under the target now; conditional ones need from __future__ import annotations.
For every listed rule that may touch the code you plan to write, read its explanation before
editing:
python <skill-dir>/scripts/modern_python.py explain --file path/to/file.py UP045 FURB123
Skipping a relevant rule costs the same call: explain it first, then skip with the reason
stated.
Apply the convention the answers file sets:
convention: override: follow a returned rule even when nearby code or repository
convention uses the older pattern. Four exits only: it would not run on the target, it
would change behaviour, it clearly does not match the edited code, or a fix-scoped skill is
active (surgical-patch, a cavecrew builder), in which case rules apply only to the lines the
fix already touches.
convention: preserve: inside existing files, match the surrounding pattern. Use the modern
idiom in new files and new functions, and everywhere when the task is a modernization pass.
Write the code. The target version is the compatibility boundary: no syntax or stdlib API newer
than it. When the tool reports Ruff default (no project configuration found) and the answers
file carries no target, the target is unknown: avoid version-gated syntax and say so.
After editing Python
enforcement: advisory: done after the edit. Report which rules you applied.
enforcement: verified or enforced:
Check the files you touched (exit 1 means findings remain). Add --target-version <target>
when the answers file says target-source: chosen, since Ruff otherwise checks at its own
default; --concise prints one line per finding instead of JSON:
python <skill-dir>/scripts/modern_python.py check --concise path/to/file.py
explain each finding you do not already understand. Fix by hand, or apply Ruff's safe fixes
with the same flags:
python <skill-dir>/scripts/modern_python.py fix --concise path/to/file.py
check again until it exits 0, or name the remaining findings and the documented caveat that
applies to each.
Run the project's own formatter, type checker and tests for the changed code. This check
supplements them.
enforced additionally means a PostToolUse hook runs the same check on every edited .py file
and returns findings as context. That hook is installed only by onboard-repo Phase 4b, with its
HARNESS.md entry and a tested fire case; this skill never writes settings.json. Asked for
enforcement outside onboarding: say to run onboard-repo and re-run Phase 4b alone.
Profiles
core is UP, FURB, F401. modern (default) adds SIM, C4, PIE, PTH, FLY, PERF. Preview
rules stay off unless the project opts in.
Done when
The listed rules were read in full, every relevant one was applied or explained away, the edit
respects the target, and under verified or enforced the check exits 0 or the remaining findings
are named with their caveat.
1---2name: modern-python3description: Version-gated modern Python guidance backed by Ruff. Use before writing, editing, fixing or refactoring any Python file: list the rules the project's target version allows, apply them, verify. /modern-python setup runs the per-project interview.4license: MIT5---67# Modern Python89Ruff is the rule database and the project's target Python version is the gate. The bundled tool10lists only the modernization rules whose own Ruff examples diagnose under that target, so nobody11curates a rule table and the guidance tracks Ruff. It corrects two things at once: training-data12lag (a feature newer than the model) and frequency bias (the older pattern the model reaches for13out of habit).1415Tool: `python <skill-dir>/scripts/modern_python.py`, where `<skill-dir>` is this folder.16Subcommands: `list`, `explain`, `check`, `fix`, `probe`.1718## Step 0: the project's answers1920Read `.claude/modern-python.md` at the repo root. It holds the interview answers: `codebase`,21`convention`, `enforcement`, `target`, `target-source`, `ruff-fallback`, `profile`.2223- Present: continue with its values.24- Absent: run the interview in [`references/interview.md`](references/interview.md) once, write25 the file, continue. If the user declines the interview, proceed with `enforcement: advisory`,26 `convention: preserve`, no target override, say so once, and do not ask again this session.27- The repo's `CLAUDE.md` carries `modern-python: off`: proceed as declined without asking. That28 is the line for a repo whose `.claude/` is not yours to write (onboard-light territory).29- `/modern-python setup` re-runs the interview and rewrites the file.3031## Before editing Python32331. List the guidance that applies to the file you are about to touch:3435 ```sh36 python <skill-dir>/scripts/modern_python.py list --file path/to/file.py --target-version <target> --profile <profile>37 ```3839 Omit `--target-version` when `target-source: declared`. For a file that does not exist yet,40 pass `--target-version` from the answers file.41422. Exit 3 means the project's Ruff is too old to report rule metadata. Ask whether to update Ruff43 through the project's own manager (uv, Poetry, PDM, pre-commit). On yes, update and rerun. On44 no, rerun with `--allow-stale` and rely on the post-edit check.45463. Read the complete output. Do not pipe it through head, tail, grep, sed, or any other truncating47 or filtering command: a rule dropped there is a rule you will violate. Baseline rules diagnose48 under the target now; conditional ones need `from __future__ import annotations`.49504. For every listed rule that may touch the code you plan to write, read its explanation before51 editing:5253 ```sh54 python <skill-dir>/scripts/modern_python.py explain --file path/to/file.py UP045 FURB12355 ```5657 Skipping a relevant rule costs the same call: explain it first, then skip with the reason58 stated.59605. Apply the convention the answers file sets:61 - `convention: override`: follow a returned rule even when nearby code or repository62 convention uses the older pattern. Four exits only: it would not run on the target, it63 would change behaviour, it clearly does not match the edited code, or a fix-scoped skill is64 active (surgical-patch, a cavecrew builder), in which case rules apply only to the lines the65 fix already touches.66 - `convention: preserve`: inside existing files, match the surrounding pattern. Use the modern67 idiom in new files and new functions, and everywhere when the task is a modernization pass.68696. Write the code. The target version is the compatibility boundary: no syntax or stdlib API newer70 than it. When the tool reports `Ruff default (no project configuration found)` and the answers71 file carries no target, the target is unknown: avoid version-gated syntax and say so.7273## After editing Python7475`enforcement: advisory`: done after the edit. Report which rules you applied.7677`enforcement: verified` or `enforced`:78791. Check the files you touched (exit 1 means findings remain). Add `--target-version <target>`80 when the answers file says `target-source: chosen`, since Ruff otherwise checks at its own81 default; `--concise` prints one line per finding instead of JSON:8283 ```sh84 python <skill-dir>/scripts/modern_python.py check --concise path/to/file.py85 ```86872. `explain` each finding you do not already understand. Fix by hand, or apply Ruff's safe fixes88 with the same flags:8990 ```sh91 python <skill-dir>/scripts/modern_python.py fix --concise path/to/file.py92 ```93943. `check` again until it exits 0, or name the remaining findings and the documented caveat that95 applies to each.96974. Run the project's own formatter, type checker and tests for the changed code. This check98 supplements them.99100`enforced` additionally means a PostToolUse hook runs the same check on every edited `.py` file101and returns findings as context. That hook is installed only by onboard-repo Phase 4b, with its102`HARNESS.md` entry and a tested fire case; this skill never writes `settings.json`. Asked for103enforcement outside onboarding: say to run onboard-repo and re-run Phase 4b alone.104105## Profiles106107`core` is `UP, FURB, F401`. `modern` (default) adds `SIM, C4, PIE, PTH, FLY, PERF`. Preview108rules stay off unless the project opts in.109110## Done when111112The listed rules were read in full, every relevant one was applied or explained away, the edit113respects the target, and under verified or enforced the check exits 0 or the remaining findings114are named with their caveat.