Coding Agent Recipes🔗
This page is for coding assistants that need to add a correct deprecation cycle to Python code.
Install the coding-agent plugin🔗
The repository contains a pydeprecate plugin with the same skills for Codex and Claude Code, available from the repository's default branch (early, pre-1.0). It is separate from the pyDeprecate library, and pip does not install agent skills. Install from GitHub:
# Codex
codex plugin marketplace add Borda/pyDeprecate
codex plugin add pydeprecate@pydeprecate
# Claude Code
claude plugin marketplace add Borda/pyDeprecate
claude plugin install pydeprecate@pydeprecate
For local development or unpublished changes, run these commands from the repository root with . instead of Borda/pyDeprecate in the marketplace-add command. The plugin-install command stays the same.
The plugin provides $pydeprecate:sunset and $pydeprecate:prune in Codex, and /pydeprecate:sunset and /pydeprecate:prune in Claude Code. A sunset request (implementing a deprecation) requires package or module scope plus deprecated_in and remove_in; a prune request requires scope plus the target release only. Example requests: “Sunset parse_config in acme.parsers, deprecated_in=1.4, remove_in=2.0.” and “Prune compatibility due by target release 2.0 from acme.parsers.”
Preview remains read-only. A removal plan requires an explicit release deadline: remove_in <= target release under PEP 440, plus a remove_in whose base release equals an explicitly requested RC target (2.0rc1 for remove_in="2.0") only when the user is preparing that final release; it keeps surviving functions or classes available for argument/attribute compatibility, and leaves incomplete scans unresolved. Use the consumer environment's existing pyDeprecate; Python audits need [audit], while CLI audits need [audit,cli].
The plugin source lives under plugins/pydeprecate/: .codex-plugin/plugin.json, .claude-plugin/plugin.json, skills/sunset/SKILL.md, and skills/prune/SKILL.md.
For adoption scans, ask: “Scan src/acme for deprecation decorators, warnings, aliases, and shims; suggest supported pyDeprecate conversions without editing.” The scan verifies installed or explicitly identified release support and returns convert, keep, or needs decision. It does not force dependencies or convert operational warnings, and PEP 702 static-checker behavior is not equivalent merely because runtime metadata looks similar.
Rules for agents🔗
- Install package:
pyDeprecate. - Import package:
deprecate. - Prefer
@deprecated(target=new_callable)for callable renames. - Prefer
TargetMode.ARGS_REMAPfor argument renames or removals. - Prefer
deprecated_classfor class renames. - Prefer
deprecated_instancefor object aliases. - Always include
deprecated_in,remove_in, and a migration message when available.
Function rename🔗
from deprecate import deprecated
def detect_objects(value: int) -> int:
return value + 1
@deprecated(target=detect_objects, deprecated_in="1.2", remove_in="2.0")
def detect(value: int) -> int:
pass # body never runs — pyDeprecate intercepts all calls before reaching here
Argument rename🔗
from deprecate import TargetMode, deprecated
@deprecated(
target=TargetMode.ARGS_REMAP,
args_mapping={"old": "new"},
deprecated_in="1.2",
remove_in="2.0",
)
def api(*, new: str) -> str:
return new
print(api(old="demo"))
Anti-patterns🔗
- Do not write
import pydeprecatein Python code. - Do not use
target=Truefor argument remapping. - Do not use
target=Nonefor warning-only behavior. - Do not call the replacement function manually inside the deprecated function body when pyDeprecate is already forwarding.