Skip to content

Commit 3bf5456

Browse files
committed
Initial release: Python refactoring skills for Claude Code
A comprehensive collection of 8 Claude Code skills for systematic Python code refactoring and quality improvement. Skills: py-refactor, py-security, py-complexity, py-test-quality, py-code-health, py-modernize, py-quality-setup, py-git-hooks
0 parents  commit 3bf5456

File tree

19 files changed

+3612
-0
lines changed

19 files changed

+3612
-0
lines changed
Lines changed: 205 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,205 @@
1+
name: Validate Skills
2+
3+
on:
4+
push:
5+
branches: [main]
6+
pull_request:
7+
branches: [main]
8+
9+
jobs:
10+
validate:
11+
runs-on: ubuntu-latest
12+
13+
steps:
14+
- name: Checkout repository
15+
uses: actions/checkout@v4
16+
17+
- name: Validate all skill directories have SKILL.md
18+
run: |
19+
echo "Checking that all skill directories contain SKILL.md..."
20+
MISSING=0
21+
SKILL_COUNT=0
22+
23+
# Find all subdirectories under skills/ (excluding hidden dirs)
24+
for skill_dir in skills/*/; do
25+
# Skip if not a directory or if it's a hidden directory
26+
[ -d "$skill_dir" ] || continue
27+
[[ "$(basename "$skill_dir")" == .* ]] && continue
28+
29+
skill_name=$(basename "$skill_dir")
30+
SKILL_COUNT=$((SKILL_COUNT + 1))
31+
32+
if [ ! -f "${skill_dir}SKILL.md" ]; then
33+
echo "✗ Missing SKILL.md in: $skill_name/"
34+
MISSING=1
35+
else
36+
echo "✓ Found SKILL.md in: $skill_name/"
37+
fi
38+
done
39+
40+
if [ $SKILL_COUNT -eq 0 ]; then
41+
echo ""
42+
echo "Error: No skill directories found in skills/"
43+
exit 1
44+
fi
45+
46+
if [ $MISSING -eq 1 ]; then
47+
echo ""
48+
echo "Error: Some skill directories are missing SKILL.md"
49+
exit 1
50+
fi
51+
52+
echo ""
53+
echo "✓ All $SKILL_COUNT skill directories contain SKILL.md"
54+
55+
- name: Validate YAML frontmatter
56+
run: |
57+
echo "Validating YAML frontmatter in SKILL.md files..."
58+
INVALID=0
59+
60+
for file in skills/*/SKILL.md; do
61+
# Check if file starts with ---
62+
if ! head -n 1 "$file" | grep -q "^---$"; then
63+
echo "✗ Invalid frontmatter in $file (missing opening ---)"
64+
INVALID=1
65+
continue
66+
fi
67+
68+
# Check if frontmatter closes with ---
69+
if ! head -n 5 "$file" | tail -n +2 | grep -q "^---$"; then
70+
echo "✗ Invalid frontmatter in $file (missing closing ---)"
71+
INVALID=1
72+
continue
73+
fi
74+
75+
# Check for required fields
76+
if ! head -n 5 "$file" | grep -q "^name:"; then
77+
echo "✗ Missing 'name:' field in $file"
78+
INVALID=1
79+
continue
80+
fi
81+
82+
if ! head -n 5 "$file" | grep -q "^description:"; then
83+
echo "✗ Missing 'description:' field in $file"
84+
INVALID=1
85+
continue
86+
fi
87+
88+
echo "✓ Valid frontmatter: $file"
89+
done
90+
91+
if [ $INVALID -eq 1 ]; then
92+
echo ""
93+
echo "Error: Some SKILL.md files have invalid frontmatter"
94+
exit 1
95+
fi
96+
97+
echo ""
98+
echo "✓ All SKILL.md files have valid frontmatter"
99+
100+
- name: Validate status field
101+
run: |
102+
echo "Validating status field in SKILL.md frontmatter..."
103+
INVALID=0
104+
105+
for file in skills/*/SKILL.md; do
106+
# Extract status field from frontmatter
107+
status=$(sed -n '/^---$/,/^---$/p' "$file" | grep '^status:' | cut -d: -f2 | tr -d ' ' || true)
108+
109+
if [ -z "$status" ]; then
110+
echo "✗ Missing 'status:' field in $file"
111+
INVALID=1
112+
continue
113+
fi
114+
115+
if [ "$status" != "stable" ] && [ "$status" != "wip" ]; then
116+
echo "✗ Invalid status '$status' in $file (must be 'stable' or 'wip')"
117+
INVALID=1
118+
continue
119+
fi
120+
121+
echo "✓ Valid status '$status': $file"
122+
done
123+
124+
if [ $INVALID -eq 1 ]; then
125+
echo ""
126+
echo "Error: Some SKILL.md files have invalid or missing status field"
127+
exit 1
128+
fi
129+
130+
echo ""
131+
echo "✓ All SKILL.md files have valid status field"
132+
133+
- name: Validate script executability
134+
run: |
135+
echo "Checking script permissions..."
136+
INVALID=0
137+
138+
for script in scripts/*.sh; do
139+
if [ ! -x "$script" ]; then
140+
echo "✗ Not executable: $script"
141+
INVALID=1
142+
else
143+
echo "✓ Executable: $script"
144+
fi
145+
done
146+
147+
if [ $INVALID -eq 1 ]; then
148+
echo ""
149+
echo "Error: Some scripts are not executable"
150+
echo "Fix with: chmod +x scripts/*.sh"
151+
exit 1
152+
fi
153+
154+
echo ""
155+
echo "✓ All scripts are executable"
156+
157+
- name: Validate referenced Python scripts exist
158+
run: |
159+
echo "Checking for referenced Python scripts in skills..."
160+
MISSING=0
161+
162+
for skill_dir in skills/*/; do
163+
[ -d "$skill_dir" ] || continue
164+
[[ "$(basename "$skill_dir")" == .* ]] && continue
165+
166+
skill_name=$(basename "$skill_dir")
167+
168+
# Find Python script references in SKILL.md (e.g., hook scripts)
169+
if [ -f "${skill_dir}SKILL.md" ]; then
170+
# Look for references to .py files in the skill directory
171+
# Pattern: references to ./script.py or skill-name/script.py
172+
grep -oE '\./[a-zA-Z0-9_-]+\.py|'"$skill_name"'/[a-zA-Z0-9_-]+\.py' "${skill_dir}SKILL.md" 2>/dev/null | while read -r script_ref; do
173+
# Convert reference to actual path
174+
script_path="${skill_dir}$(basename "$script_ref")"
175+
176+
if [ ! -f "$script_path" ]; then
177+
echo "✗ Referenced script missing: $script_path (referenced in $skill_name/SKILL.md)"
178+
MISSING=1
179+
fi
180+
done
181+
fi
182+
done
183+
184+
if [ $MISSING -eq 1 ]; then
185+
echo ""
186+
echo "Error: Some referenced scripts are missing"
187+
exit 1
188+
fi
189+
190+
echo "✓ All referenced Python scripts exist (or none referenced)"
191+
192+
- name: Summary
193+
if: success()
194+
run: |
195+
echo ""
196+
echo "=========================================="
197+
echo "✓ All validation checks passed!"
198+
echo "=========================================="
199+
echo ""
200+
echo "Validated:"
201+
echo "- All skill directories contain SKILL.md"
202+
echo "- All frontmatter is valid"
203+
echo "- All status fields are valid (stable or wip)"
204+
echo "- All scripts are executable"
205+
echo "- All referenced Python scripts exist"

.gitignore

Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
# Python
2+
__pycache__/
3+
*.py[cod]
4+
*$py.class
5+
*.so
6+
.Python
7+
build/
8+
develop-eggs/
9+
dist/
10+
downloads/
11+
eggs/
12+
.eggs/
13+
lib/
14+
lib64/
15+
parts/
16+
sdist/
17+
var/
18+
wheels/
19+
pip-wheel-metadata/
20+
share/python-wheels/
21+
*.egg-info/
22+
.installed.cfg
23+
*.egg
24+
MANIFEST
25+
26+
# Virtual environments
27+
venv/
28+
ENV/
29+
env/
30+
.venv/
31+
32+
# PyCharm
33+
.idea/
34+
35+
# VSCode
36+
.vscode/
37+
38+
# Vim
39+
*.swp
40+
*.swo
41+
*~
42+
.*.sw[a-z]
43+
44+
# Emacs
45+
\#*\#
46+
.\#*
47+
48+
# macOS
49+
.DS_Store
50+
.AppleDouble
51+
.LSOverride
52+
53+
# Testing
54+
.tox/
55+
.nox/
56+
.coverage
57+
.coverage.*
58+
.cache
59+
nosetests.xml
60+
coverage.xml
61+
*.cover
62+
*.log
63+
.hypothesis/
64+
.pytest_cache/
65+
htmlcov/
66+
67+
# Type checking
68+
.mypy_cache/
69+
.dmypy.json
70+
dmypy.json
71+
.pytype/
72+
73+
# Profiling
74+
*.prof
75+
76+
# Complexity tracking
77+
.wily/
78+
79+
# Ruff
80+
.ruff_cache/
81+
82+
# Editor backups
83+
*.bak
84+
*.orig
85+
86+
tmp/

CHANGELOG.md

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
# Changelog
2+
3+
All notable changes to this project will be documented in this file.
4+
5+
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
6+
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7+
8+
## [1.0.0] - 2025-11-05
9+
10+
### Added
11+
12+
#### Skills
13+
- **py-refactor**: Orchestrator skill for comprehensive refactoring workflows
14+
- **py-security**: Security vulnerability detection and remediation
15+
- **py-complexity**: Complexity reduction (cyclomatic and cognitive)
16+
- **py-test-quality**: Code coverage and mutation testing
17+
- **py-code-health**: Dead code and duplication removal
18+
- **py-modernize**: Codebase modernization (pip→uv, Python 3.13+ syntax)
19+
- **py-quality-setup**: Linter and type checker configuration
20+
- **py-git-hooks**: Pre-commit hook automation
21+
22+
#### Tools Integration
23+
- radon: Cyclomatic complexity and maintainability metrics
24+
- lizard: Cognitive complexity analysis
25+
- vulture: Dead code detection
26+
- bandit: Security vulnerability scanning
27+
- pylint: Duplicate code detection
28+
- pytest-cov: Code coverage measurement
29+
- mutmut: Mutation testing
30+
- wily: Complexity tracking over time
31+
- xenon: CI/CD complexity thresholds
32+
- uv: Fast package management
33+
- pyupgrade: Syntax modernization
34+
35+
#### Refactoring Patterns
36+
- Extract function for complexity reduction
37+
- Guard clauses over nested conditionals
38+
- Lookup tables over if/elif chains
39+
- Polymorphism over type conditionals
40+
- Magic number extraction to configuration
41+
- Repetitive field operations to loops
42+
- Complex type alias extraction
43+
- Coverage-guided refactoring workflow
44+
45+
#### Documentation
46+
- Comprehensive README with quick start
47+
- Detailed installation guide
48+
- Tool comparison and selection guide
49+
- Contributing guidelines
50+
- Skills decision tree
51+
52+
#### Automation
53+
- Installation script for all tools
54+
- GitHub Actions workflow for skill validation
55+
- Symlink installation script
56+
57+
### Success Criteria
58+
59+
Skills enable achieving:
60+
- Zero security vulnerabilities
61+
- 80%+ test coverage
62+
- No functions with complexity ≥C (11+)
63+
- No dead code or duplicates
64+
- Modern Python 3.13+ syntax
65+
- Automated quality enforcement
66+
67+
[1.0.0]: https://github.com/l-mb/python-refactoring-skills/releases/tag/v1.0.0

0 commit comments

Comments
 (0)