rename-refs
SkillDev tools`$codemap-py:rename-refs`: rename Python names; skip non-Python/unbuilt/local/grep/split/pkg-dir.
Available today. Use it from your connected AI after setup.
No other account needed.
Connect ahel once, and every AI you use reads what you have installed.
Then ask your AI: use the rename-refs skill
What this skill tells your AI
The instructions your AI receives, as published by borda/ai-rig in plugins/codemap-py/codex-skills/rename-refs/SKILL.md and read by ahel’s review.
Before asking, read User Questions.
Rename Refs
Atomically rename one Python symbol/module: definition, __all__ exports, caller imports/calls (fn-rdeps plus line ranges), Sphinx refs in .py/.rst, optional pyDeprecate alias, or hard delete only with exhaustive zero callers.
Interface
symbol <old_qname> <new_qname>: function/class/method. qname is bare (MyClass) or qualified (MyClass.method), matched to symbol-localqualified_name. The module-qualified form (module::symbol) is not accepted byfind-symboland returns zero matches. Build<module>::<qualified_name>only for Step 2fn-rdeps.module <old_module_path> <new_module_path>: dotted paths; rename file and imports.--dry-run: list sites, no edit.--deprecate[=<decorator>]: symbol only; old-name pyDeprecate@deprecatedwrapper to new name; pyDeprecate required.--since <ver>/--removed-in <ver>: decorator versions, default"?".--remove-if-no-callers: symbol only; delete only with exhaustive zero callers.
Reject --deprecate with --remove-if-no-callers before analysis. Static limits: report a getattr(obj, "old_name") search advisory; cross-repo callers require --deprecate plus a SemVer bump for public API.
NOT for: index build ($codemap-py:scan-codebase); query without rename intent ($codemap-py:query-code); non-Python; ABC/Protocol override renames (static imports don't track overrides—review fn-rdeps, then rename overrides explicitly). No --index <path>; use default project index. For monorepo packages, first run $codemap-py:scan-codebase --root <pkg>.
Runtime note
Codex has no bin/ PATH entry or plugin-root variable. Resolve installed root once, substitute PLUGIN_ROOT, retain in reasoning; shell state doesn't persist. Route missing input, stale-index, ambiguous-match, delete/abort, and dry-run/apply/abort questions through User Questions; preserve every feasible choice, wait for valid bound answer before dependent changes.
Workflow
1. Parse and check freshness
Accept only the listed flags; reject other -- tokens, and the incompatible pair. Then run:
PLUGIN_ROOT/bin/codemap-py query find-symbol "<old_ref>" --limit 0
Keep that result for Step 2. index.stale: true means mismatch; index.query_complete: false plus index.completeness_reason: "stale" corroborates. Ask to proceed with possibly incomplete callers or abort and re-run $codemap-py:scan-codebase. If the index block is absent, warn and proceed cautiously; never assume fresh.
2. Resolve targets
For symbol, reuse matches; each has {name, qualified_name, type, module, path, start_line, end_line, source}. Use path/lines for edits and qualified_name for exact filtering. Zero: report Symbol '<old_ref>' not found and stop. Multiple: list name/type/module/path, ask selection, wait. Then query:
PLUGIN_ROOT/bin/codemap-py query fn-rdeps "<module>::<qualified_name>"
It returns {qname, called_by:[{caller, module, path}], count, index:{query_complete,...}}; resolve caller line ranges via query symbol <caller> in Step 4. Read completeness forward-first: index.query_complete, then legacy index.exhaustive only if absent; not complete belongs in the report.
For module, query:
PLUGIN_ROOT/bin/codemap-py query rdeps "<old_module_path>"
Read completeness identically. Honor --remove-if-no-callers only when passed and complete.
3. Report and confirm
Print old→new, type/definition (symbol), static caller count/files, Step 4 doc-ref search, and getattr/cross-repo limits. If incomplete: "index non-exhaustive — some callers may not appear above."
With >50 callers, write full list to .reports/codex/codemap-py/rename-refs-blast-<branch>-<YYYY-MM-DD>.md, print it, edit first 50 only, and call 51–N "skipped callers" in Step 6. <branch> is git branch --show-current | tr '/' '-' (main if empty/detached). Never overwrite: append -2, -3, … until free; this file is the manual-edit record.
For --remove-if-no-callers, before edits: callers found → report count and stop (remove callers first or drop the flag); incomplete/missing completeness → report $codemap-py:scan-codebase required and stop; complete zero → ask delete/abort. Before deletion, verify start_line names the expected symbol; mismatch aborts. Delete definition plus preceding decorators, skip Step 4, and continue at Step 6.
For --dry-run, write would-change sites to .reports/codex/codemap-py/rename-refs-dry-<branch>-<YYYY-MM-DD>.md using the same branch and never-overwrite rule; print path, ask for re-invocation without --dry-run or stop. Otherwise ask apply/abort and stop on abort.
4. Apply symbol edits
- At
start_line, renamedef old_name(/class OldName(...)/class OldName:; for methods, match inside class. Rename@old_name.setter/.deletertoo: an orphaned descriptor raisesAttributeErrorat class definition. Rename@typing.overload def old_name(in the file and sibling.pyi;find-symbolomits these. - In package
__init__.py, rename quoted old names in__all__. - For each
called_by, runPLUGIN_ROOT/bin/codemap-py query symbol "<caller_qname>"; within its range, fix each file's module import once, then qualifiedX.old_name(and bareold_name(. Never bare-replace outside the confirmed range. Warn/skip a caller absent from the index. - Search
.py/.rstSphinx:func:/:class:/:meth:/:mod:/:attr:old-name roles; edit only matching module context. - For
--deprecate, after definition rename runPLUGIN_ROOT/bin/gen_deprecation_wrapper.py; insert after new definition. It maps class to@deprecated_class(target=NewName, ...)(keepsisinstance) and function/method to@deprecated(target=new_fn, ...). Missing pyDeprecate makes target import fail; report advisory in Step 6.
5. Apply module edits
- Refuse non-git, untracked, or uncommitted source; require add/commit/stash.
git mv <old_file_path> <new_file_path>, preferring indexed path over dotted conversion (which can be wrong undersrc/layouts). Package directories (__init__.py) are out of scope: print directgit mv, do not attempt. - Rename direct
import mypackage.old_name(includingas X) andfrom mypackage.old_name import .... - Rename same-package
__init__.pyfrom .old_name import ...after directory check. - Search full dotted path in
pyproject.toml/setup.cfg, editing package/install requirements only; never bare basename. - Rename Sphinx
:mod:full paths; basename fallback needs matching module context.
6. Re-scan and summary
PLUGIN_ROOT/bin/codemap-py index --incremental
PLUGIN_ROOT/bin/codemap-py query find-symbol "<old_ref>" --limit 0 # symbol
PLUGIN_ROOT/bin/codemap-py query rdeps "<old_ref>" # module
If re-scan fails, report it; results are advisory, not authoritative. Expect old name absent except deprecated alias. List other residual files as advisory (dynamic/string/template/out-of-scope refs). Report renamed pair, files, calls, doc refs, alias path/line when used; always flag getattr literal search, external consumers without alias, skipped callers, and residual hits when applicable.
Signals
- GitHub stars
- 27
- Forks
- 4
- Last commit
- Sep 2026
Advanced
- Catalog kind
- skill
- Gateway key
rename-refs- Source
- github.com/borda/ai-rig