Load the project-protocol:project-protocol skill for execution preflight, baseline,
candidate gate and recovery. Capture the owned files' exact pre-edit contents,
including preexisting edits and untracked files. Use path-scoped restoration on
failure; hard reset needs an exclusively owned clean isolated workspace and
captured pre_phase_sha. Required remote checks match the candidate snapshot and
command/configuration/job identity. Do not overwrite another writer's later edit.
Use the clean-code-agent to rewrite source code for readability without changing behavior.
Rules
- Validate before and after. Establish a baseline with type checker + tests + linter, then verify no regressions.
- If
--dry-run, preview only. Show proposed changes without modifying files. - Revert on failure. If any validation fails after a change, restore the exact saved pre-edit content through the common protocol; preserve preexisting edits and stop on a foreign-writer conflict.
- Reuse explicit scope authorization. Show the reviewable preview; ask only for choices not already covered by the caller's accepted plan or
--yes. - Block without validation tools. If no tests AND no type checker exist, require
--forceto proceed.
Step 1: Identify Target
From $ARGUMENTS, determine files to clean:
- If a file path: clean that file
- If a directory: clean all source files in it
- Filter out test files (unless they reference renamed symbols)
List the files to be cleaned and their language.
Step 2: Establish Validation Baseline
Detect available validation tools by inspecting project files:
| Tool | How to detect | Command |
|---|---|---|
| Type checker | tsconfig.json |
tsc --noEmit |
mypy.ini, pyrightconfig.json, or mypy/pyright in pyproject.toml |
mypy . or pyright |
|
Cargo.toml |
cargo check |
|
go.mod |
go vet ./... |
|
| Test runner | package.json |
npm test |
pyproject.toml or setup.py |
pytest |
|
Cargo.toml |
cargo test |
|
go.mod |
go test ./... |
|
Makefile with test target |
make test |
|
| Linter | ruff.toml or ruff config in pyproject.toml |
ruff check |
.eslintrc* or eslint.config.* |
eslint |
|
Cargo.toml |
cargo clippy |
Run all detected tools and capture both stdout and stderr. Record the baseline.
Hard gate: if NO tests AND NO type checker are found, stop and tell the user:
No tests or type checker found. Cannot validate that changes are safe.
1. Cancel: set up tests or type checking first (recommended)
2. Proceed with --force: I'll be careful but regressions may go undetected
--yes alone does NOT bypass this gate. Only --force does.
Step 3: Preview Changes (always for --dry-run, ask otherwise)
If --dry-run flag is set, or if the target is a directory with >3 files, show a preview first.
If --yes flag is provided, apply all changes after showing the preview without asking.
For each file, analyze and propose:
- Variable/function renames (vague -> domain-meaningful)
- Boilerplate comments to remove (paraphrase comments, empty docstrings)
- Why-comments to add (non-obvious business logic)
- Structural simplifications (flatten nesting, remove redundant abstractions, consolidate logic)
Present the preview:
Clean Code preview for: [target]
[file1]:
- Rename `data` -> `user_profile` (line 23)
- Rename `proc` -> `process_payment` (line 45)
- Remove boilerplate docstring (line 12-15)
- Flatten nested if/else chain (line 30-50)
- Add comment explaining retry logic (line 67)
[file2]:
- ...
Total changes: [count] across [file count] files
1. Apply all changes
2. Apply to specific files only
3. Cancel
If --dry-run, stop after the preview.
Step 4: Apply Changes
Dispatch the clean-code-agent agent in its own isolated context, with the file list and the approved changes from the preview. The agent has its own safety rules and transformation guidelines: do not repeat them here. Its brief:
Improve the readability of this code. Zero behavior changes.
Files: [list of files]
Approved changes: [from preview, if applicable]
Step 5: Validate & Report
Re-run ALL validation tools detected in Step 2, in this order:
- Type checker: if it fails on a file that passed in baseline, revert that file
- Tests: if any previously-passing test now fails, revert the responsible file
- Linter: if new errors appear, fix or revert
- Non-code grep: for every renamed symbol, search
.json,.yaml,.yml,.toml,.env,.cfg,.ini,.xml,.html,.mdfor the OLD name. Report matches as warnings.
Present summary:
Clean Code complete for: [target]
Files modified: [count]
Changes made:
- Renames: [count]
- Comments removed: [count]
- Comments added: [count]
- Structural simplifications: [count]
Validation:
Type check: [passed / N errors: reverted] or [not available]
Tests: [all passing / X failures: reverted] or [not available]
Linter: [passed / N new warnings] or [not available]
Stale references found in non-code files:
- [config.json:12]: still references old name `data`
- [README.md:45]: documents old function name `proc`
Review the changes with: git diff
If --strict flag is set, also flag any remaining readability concerns that weren't auto-fixable.
What It Does / Does NOT Do
Does: rename vague local variables, remove paraphrase comments, add why-comments, simplify structure (flatten nesting, remove redundant abstractions, consolidate logic).
Does not: reorder code, extract functions, change APIs, remove error handling/validations/imports, modify test files, over-simplify. See the agent's safety rules for the full list.
Return deeper structural changes to the caller's development plan; this method applies readability only.
Clean the following:
$ARGUMENTS