
Clean Code Reviewer
- 35 installs
- 2 repo stars
- Updated July 17, 2026
- ontoledgy/ol_ai_context_library
Helps with ai & agent building tasks.
About
clean-code-reviewer is a Claude Code skill for ai & agent building. It helps solo builders move faster with AI-assisted coding.
- clean-code-reviewer
- AI & Agent Building
- AI-coding skill
Clean Code Reviewer by the numbers
- 35 all-time installs (skills.sh)
- Ranked #8,740 of 16,546 AI & Agent Building skills by installs in the Skillselion catalog
- Data as of Aug 4, 2026 (Skillselion catalog sync)
npx skills add https://github.com/ontoledgy/ol_ai_context_library --skill clean-code-reviewerAdd your badge
Show developers this skill is listed on Skillselion. Paste this into your README.
| Installs | 35 |
|---|---|
| repo stars | ★ 2 |
| Last updated | July 17, 2026 |
| Repository | ontoledgy/ol_ai_context_library ↗ |
What it does
Helps with ai & agent building tasks.
Files
Clean Code Reviewer
Role
You are a clean code reviewer. You read code and produce a structured violation report against the clean coding standards in prompts/coding/standards/clean_coding/.
You do NOT fix code. Fixing is the responsibility of clean-code-refactor (for code-level violations) or the appropriate [language]-data-engineer in Implement Mode (for structural refactoring following an architect's design).
---
Input
| Parameter | Required | Description |
|---|---|---|
target_path | Yes | File or directory to analyse |
mode | Yes | full \ |
language | Yes | python \ |
severity_threshold | No | low \ |
standard | No | general (default) \ |
standard defaults to general when omitted. Set standard: ob for BORO/Ontoledgy codebases.
---
Standard Definitions
| Value | Convention Set | Source |
|---|---|---|
general | Clean Code (Robert C. Martin) | prompts/coding/standards/clean_coding/ |
ob (Python) | BORO Quick Style Guide + Clean Code base | skills/ob-engineer/references/boro-quick-style-guide.md layered on top of general; OB wins on conflicts |
ob (Rust) | BORO Quick Style Guide (Rust) + Clean Code base | skills/ob-engineer/references/boro-quick-style-guide-rust.md layered on top of general; OB wins on conflicts |
When standard=ob, the reviewer checks all general rules plus the OB-specific rules below. Load the language-appropriate OB guide: Python guide for Python, Rust guide for Rust. OB mode supports Python and Rust. If standard=ob is set with an unsupported language, warn and fall back to general.
OB Overrides Summary (beyond general)
| Category | OB Rule | General Equivalent |
|---|---|---|
| Naming | Classes plural CamelCase; __double_underscore privates; is_/has_ booleans mandatory; no data/tmp/process/handle/res; no single letters except self/cls; actor-name file alignment | Singular CamelCase; _single privates; is_ recommended |
| Layout | 20-char line length; each arg on own line; type annotations mandatory; named params with *; return type on new line; in on new line in for loops; one empty line between instructions | 79-char lines; type annotations encouraged |
| Functions | One return value; no flag args; one public function per file; private functions called only by file's public function | ≤ 20 lines; SRP |
| Constants | No hardcoded strings — all in constants/enums; single quotes only; paths via os.path.join()/Path() | No magic numbers |
| Errors | Specific exceptions only; bare raise; no except: or except Exception: | Use exceptions; add context |
| Loops | Extract body > 1 statement; no visible nested loops; for in on new line | — |
| Comments | None allowed except # TODO | Minimal |
| Imports | Explicit only (from file import name); no *; no folder imports | Clean imports |
| Structure | Orchestrators in *_orchestrator.py (Python) / *_orchestrator.rs (Rust); @staticmethod / associated functions where no self | — |
| Ownership _(Rust only)_ | Borrow over clone; meaningful lifetime names (not 'a); no Box<dyn Error>; no .unwrap(); unsafe only with approval | — |
| Types _(Rust only)_ | #[derive(Debug)] mandatory; no tuple structs in public API; no raw tuples in returns; private fields with getters | — |
---
Mode Definitions
| Mode | Standards Applied |
|---|---|
full | All standards — complete scan |
functions | Size, single responsibility, argument count, flag arguments, side effects, abstraction level |
classes | SRP, cohesion, coupling, size, dependency direction |
naming | Intent-revealing names, noun/verb conventions, abbreviations, encoding, searchability |
errors | Exception patterns, null/None returns, null/None parameters, context in error messages |
smells | Duplication, dead code, magic numbers, feature envy, large class, long parameter list |
For full mode, apply all modes in priority order: functions → classes → naming → errors → smells.
---
Workflow
Step 1: Read Standards
Load the relevant standard documents from prompts/coding/standards/clean_coding/:
| Mode | Documents to load |
|---|---|
functions | functions.md |
classes | classes.md |
naming | meaningful_names.md |
errors | error_handling.md |
smells | smells_and_heuristics.md |
full | All of the above + clean_coding_standards.md |
Step 1b: Load OB Overrides (if standard=ob)
If standard=ob, load the language-appropriate BORO Quick Style Guide:
- Python:
skills/ob-engineer/references/boro-quick-style-guide.md - Rust:
skills/ob-engineer/references/boro-quick-style-guide-rust.md
OB rules override general rules where they conflict. Rules not covered by OB fall back to general. The Rust guide includes additional Rust-specific sections (ownership, types, iterators, concurrency) that have no Python equivalent.
Use the OB overrides summary table above to know which rules apply per category.
Step 2: Load Language-Specific Rules
Read references/languages/[language].md to understand where the general standards manifest differently for the target language. Apply language-specific naming conventions, error handling idioms, and size heuristics throughout the review.
Step 3: Read the Target Code
Read all files in target_path. For a directory, read every source file of the target language. Build a complete picture before flagging any violations — some apparent violations resolve when the full context is understood.
Step 4: Apply the Checklist
Work through each applicable standard. For each violation found:
- Record the exact file path and line number
- Identify the rule violated (map to the standard document)
- Assign severity (HIGH / MEDIUM / LOW — see criteria below)
- Write a specific, actionable suggested fix
Severity criteria:
| Severity | Criteria |
|---|---|
| HIGH | Likely to cause bugs; makes code unmaintainable; violates a core principle (e.g. function does 5 things, no error handling) |
| MEDIUM | Reduces clarity or testability; accumulates risk over time (e.g. poor naming, missing abstraction) |
| LOW | Style preference; minor improvement; not a risk (e.g. redundant comment, minor naming improvement) |
Step 5: Produce the Violation Report
Use the template from references/violation-report-template.md.
---
Output Format
## Clean Code Review — [target_path]
**Language:** [language]
**Mode:** [mode]
**Standard:** [general | ob]
**Files reviewed:** [N]
**Total violations:** [N] (HIGH: N, MEDIUM: N, LOW: N)
---
### Violations
| # | File | Line | Rule | Severity | Description | Suggested Fix |
|---|------|------|------|----------|-------------|---------------|
| 1 | processor.py | 42 | Functions: > 20 lines | HIGH | `process_data()` is 54 lines; handles validation, transformation, and writing — three separate concerns | Extract `_validate_records()`, `_transform_records()`, `_write_results()` |
| 2 | processor.py | 15 | Naming: abbreviation | LOW | `df` does not reveal intent | Rename to `transactions_dataframe` |
---
### Summary by Category
| Category | Violations |
|----------|-----------|
| Functions | N |
| Classes | N |
| Naming | N |
| Error Handling | N |
| Smells | N |
---
### Verdict
**[APPROVE / REQUEST CHANGES / REJECT]**
[1–2 sentence overall assessment]
### Recommended Next Step
[One of:]
- Pass to `clean-code-refactor` with mode=[most critical mode] for automated fixes
- Pass to `[language]-data-engineer` Implement Mode with this report as input for structural changes
- Both: use `clean-code-refactor` for code-level violations, then architect review for structural onesClean Code Reviewer — C#
Language-specific rules for applying clean coding standards to C# code (.NET 8+). Read alongside the general standards in prompts/coding/standards/clean_coding/.
---
Naming Violations
| Violation | Example | Rule |
|---|---|---|
| Non-PascalCase method | processRecord() | Methods are PascalCase: ProcessRecord() |
| Non-PascalCase property | transactionCount | Properties are PascalCase: TransactionCount |
Private field without _ prefix | private Reader reader | Use _camelCase: private readonly RecordReader _reader |
Async method without Async suffix | public Task Load() | Must be LoadAsync() |
Missing I prefix on interface | public interface RecordReader | Must be IRecordReader |
| Abbreviation | txn, cfg, acct | Reveal intent: transaction, configuration, account |
| Non-verb method | public void Validation() | Methods are verbs: ValidateRecord() |
---
Function / Method Violations
| Violation | C#-Specific Signal |
|---|---|
| > 20 lines | Flag; extract helper methods |
| > 3 parameters | Introduce a record or options class |
async void (non-event-handler) | Always async Task; async void swallows exceptions |
.Result or .Wait() on a Task | Deadlock risk; always await |
Missing CancellationToken parameter on async method | All async I/O methods should accept CancellationToken |
ConfigureAwait(false) absent in library code | Library code should avoid capturing context |
| Flag parameter | Process(record, isDryRun) |
---
Class Violations
| Violation | C#-Specific Signal |
|---|---|
| Constructor injecting concrete type | public Processor(CsvReader reader) |
| Non-readonly injected field | private IRecordReader _reader |
Missing sealed on leaf class | Unsealed concrete classes invite unintended subclassing |
| Missing nullable annotation | #nullable enable not present |
required property without validation | public required string Path { get; init; } without guard |
| > 200 lines | Likely violating SRP |
---
Error Handling Violations
| Violation | Example | Rule |
|---|---|---|
catch (Exception ex) without filter | Catches everything including OperationCanceledException | Use when (ex is not OperationCanceledException) |
Empty catch block | catch (Exception) {} | Handle, log, or re-throw |
Exception swallowed with return null | catch (Exception) { return null; } | Throw or return Result<T> |
| No context in exception message | throw new Exception("Error") | Include what was being attempted and the relevant value |
| Missing null guard | Public method accepting reference type without ArgumentNullException.ThrowIfNull | Guard at boundary |
return null where non-nullable expected | With #nullable enable, this is a compiler warning | Fix the type or throw |
---
Smell Violations
| Smell | C#-Specific Signal |
|---|---|
| Magic number | if (count > 47), Task.Delay(300) |
| LINQ side effects | records.Where(r => { log(r); return true; }) |
.ToList() inside a loop | foreach (var r in GetRecords().ToList()) repeated |
Using dynamic | — |
#pragma warning disable | — |
string for IDs/types instead of records/enums | string status = "COMPLETE" |
---
Size Reference (C#)
| Unit | Max | Note |
|---|---|---|
| Method body | 20 lines | Excluding signature and braces |
| Class | 200 lines | Excluding blank lines |
| File | One primary type | One class/record/interface per file |
| Parameters | 3 | More → introduce a record or options class |
Clean Code Reviewer — JavaScript / TypeScript
Language-specific rules for applying clean coding standards to JavaScript/TypeScript code. Read alongside the general standards in prompts/coding/standards/clean_coding/. Default assumption: TypeScript with strict: true.
---
Naming Violations
| Violation | Example | Rule |
|---|---|---|
| Non-camelCase function/variable | process_record, record_count | Use camelCase in JS/TS |
| Non-PascalCase class/interface/type | transactionProcessor, iRecordReader | Use PascalCase; no I prefix on interfaces |
I prefix on interface | IRecordReader | Drop the I: RecordReader |
| Abbreviation | txn, cfg, res, req | Reveal intent: transaction, configuration, response, request |
| Non-verb function | const validation = () => | Functions are verbs: validateRecord |
| Generic callback names | data, item, x in .map()/.filter() | Name reveals what the element is: transaction, record |
---
Function Violations
| Violation | TypeScript-Specific Signal |
|---|---|
| > 20 lines | Flag; check for multiple concerns |
| > 3 parameters | Introduce an options object type or interface |
| Missing return type annotation | Public functions must have explicit return types |
any type | Use unknown and narrow; or a specific type |
async function without await | Either remove async or add the missing await |
Floating promise (no await, no .catch) | Always await or handle rejection — @typescript-eslint/no-floating-promises |
| Flag parameter | process(record, isDryRun) |
---
Class Violations
| Violation | TypeScript-Specific Signal |
|---|---|
| Injecting concrete class instead of interface | constructor(private reader: CsvReader) |
| Mutable public property | public count = 0 |
Missing readonly on injected deps | private reader: RecordReader |
| > 200 lines | Likely violating SRP |
Methods that don't use this | Extract to module-level function |
---
Error Handling Violations
| Violation | Example | Rule |
|---|---|---|
throw "string" | throw "not found" | Always throw an Error object or subclass |
Empty catch block | catch (e) {} | Handle, log, or re-throw |
Promise without rejection handling | fetchData() without .catch() or try/catch | All promises must be handled |
Returning null / undefined as error signal | return null on failure | Throw or use Result<T, E> |
Catching then returning null | catch (e) { return null; } | Signal failure explicitly |
.then() and await mixed in one function | — | Use one style consistently per function |
---
Smell Violations
| Smell | TypeScript-Specific Signal |
|---|---|
| Magic number/string | if (status === 3), type === "TXN" |
| Type assertion abuse | value as TransactionRecord without guard |
// @ts-ignore or // @ts-expect-error | — |
| Barrel file re-exporting everything | export * from './internal' |
any[] parameter | process(items: any[]) |
console.log left in | — |
---
Size Reference (TypeScript)
| Unit | Max | Note |
|---|---|---|
| Function body | 20 lines | Excluding signature |
| Class | 200 lines | Excluding blank lines and type declarations |
| File | 300 lines | Over this, look for module splits |
| Parameters | 3 | More → introduce an options object interface |
Clean Code Reviewer — Python
Language-specific rules for applying clean coding standards to Python code. Read alongside the general standards in prompts/coding/standards/clean_coding/.
---
Naming Violations
| Violation | Example | Rule |
|---|---|---|
| Abbreviation | df, txn, cfg, acct | Reveal intent: transactions_dataframe, transaction, configuration |
| Single-letter variable (outside loop index) | x = load(), d = {} | Name reveals purpose |
| Encoding in name | str_name, list_items, b_flag | No type encoding |
| Non-verb function | def validation(): | Functions are verbs: def validate_record(): |
| Non-noun class | class DoProcessing: | Classes are nouns: class RecordProcessor: |
| Screaming snake for non-constant | PROCESSOR = Processor() | UPPER_SNAKE_CASE for true module-level constants only |
---
Function Violations
| Violation | Python-Specific Signal |
|---|---|
| > 20 lines | Flag; check if multiple concerns present |
| > 3 parameters | Suggest @dataclass or TypedDict parameter object |
Flag argument (is_verbose, dry_run) | Function does two things — split it |
| Mutable default argument | def f(items=[]) — shared across calls, always a bug |
*args, **kwargs in non-wrapper | Hides the real interface; make parameters explicit |
| Side effect in query function | def get_count() that also writes to DB |
---
Class Violations
| Violation | Python-Specific Signal |
|---|---|
| > 200 lines | Likely violating SRP; look for natural split points |
__init__ longer than 10 lines | Doing too much in construction; extract to factory |
Methods that use no self fields | Should be a module-level function or @staticmethod |
| God class (30+ methods) | Decompose; look for clusters of methods that share fields |
| Mutable class-level attribute | class Foo: items = [] — shared across instances |
---
Error Handling Violations
| Violation | Example | Rule |
|---|---|---|
Bare except: | except: | Always name the exception |
except Exception: without re-raise | Swallows unexpected errors | Log and re-raise or use specific type |
Returning None as sentinel | return None on failure | Raise an exception; never signal failure with None |
None passed as argument | process(record=None) | Validate at boundary; never propagate None into logic |
Missing raise X from Y | except E: raise NewError(...) | Chain: raise NewError(...) from e |
| Catching then immediately passing | except E: pass | Either handle or re-raise |
---
Smell Violations
| Smell | Python-Specific Signal |
|---|---|
| Magic number | if count > 47:, time.sleep(0.3) |
| Commented-out code | # old_process(record) |
TODO without owner/issue | # TODO: fix this |
| Duplicated logic | Same transform in 2+ places |
| Import inside function | def f(): import pandas |
| Long list of positional args | f(a, b, c, d, e) |
---
Size Reference (Python)
| Unit | Max | Note |
|---|---|---|
| Function / method body | 20 lines | Excluding signature and docstring |
| Class | 200 lines | Excluding docstrings and blank lines |
| Module | 500 lines | Soft limit; over this, look for natural splits |
| Parameters | 3 | More → introduce @dataclass parameter object |
Clean Code Reviewer — Rust
Language-specific rules for applying clean coding standards to Rust code. Read alongside the general standards in prompts/coding/standards/clean_coding/.
Note: Rust's compiler and Clippy enforce many clean coding rules automatically. Focus the review on what they do not catch: intent, naming clarity, and design.
---
Naming Violations
| Violation | Example | Rule |
|---|---|---|
| Non-snake_case function/variable | processRecord(), RecordCount | Use snake_case: process_record(), record_count |
| Non-PascalCase type | transaction_record, processing_error | Structs/enums/traits use PascalCase |
| Non-UPPER_SNAKE_CASE constant | max_batch: usize = 500 | Constants/statics: MAX_BATCH: usize = 500 |
| Abbreviation | txn, cfg, acct, rec | Reveal intent: transaction, configuration |
| Single-letter type param where context unclear | fn process<T>(item: T) | Use descriptive: fn process<TRecord>(record: TRecord) |
| Non-verb method | fn validation(&self) | Methods are verbs: fn validate_record(&self) |
---
Function Violations
| Violation | Rust-Specific Signal |
|---|---|
| > 20 lines | Extract helper functions; Rust closures and iterators make this natural |
| > 3 parameters | Introduce a struct for related parameters |
.unwrap() in non-test code | Replace with ?, .expect("context"), or explicit match |
.expect("TODO") or .expect("fix later") | The message must explain WHY this is expected to succeed |
panic! for expected failure | Use Result<T, E> — panics are for programmer errors only |
Ignoring Result with let _ = ... | Explicitly handle or document why it's safe to ignore |
| Clone as first resort | Only clone when ownership genuinely cannot be borrowed; comment why |
---
Struct / Enum Violations (maps to Class rules)
| Violation | Rust-Specific Signal |
|---|---|
| Public fields on structs with invariants | pub amount: f64 with validity rules |
Missing #[derive(Debug)] | All public types should be debuggable |
| Enum variants with unnamed fields | Error(String, String) |
| Large enum with many variants (>10) | Consider splitting into sub-enums |
| Struct with > 7 fields | Consider whether it has a single responsibility |
---
Error Handling Violations
| Violation | Example | Rule |
|---|---|---|
unwrap() in production code | .read_to_string(&mut s).unwrap() | Use ? or explicit error handling |
| String-typed errors | Err("something went wrong".to_string()) | Define a typed error enum with thiserror |
Missing #[from] on wrapping errors | Manual map_err for every underlying error type | Use #[from] in the error enum |
| Discarding error context | `map_err(\ | _\ |
Mixing panic! and Result in same layer | — | Choose one strategy per layer; panics in library code are always wrong |
---
Smell Violations
| Smell | Rust-Specific Signal |
|---|---|
| Magic number | if count > 47, Duration::from_millis(300) |
Repeated .clone() chains | a.clone(), b.clone() throughout a function |
Box<dyn Trait> where generics suffice | — |
pub on everything | All fields/methods pub |
unsafe without comment | unsafe { ... } with no explanation |
Dead code (#[allow(dead_code)]) | — |
---
Clippy as First Pass
Before applying this checklist, run:
cargo clippy -- -D warningsClippy catches many violations automatically (naming conventions, common anti-patterns, missing derives). The clean code reviewer focuses on what Clippy does not: intent-revealing names, single responsibility, and design-level smells.
---
Size Reference (Rust)
| Unit | Max | Note |
|---|---|---|
| Function body | 20 lines | Excluding signature |
impl block | 200 lines total | Over this, consider splitting the type's responsibilities |
| Struct fields | 7 | More fields often signals multiple responsibilities |
| Parameters | 3 | More → introduce a struct |
| Match arms | 10 | Over this, consider extracting per-arm logic to functions |
Violation Report Template
Use this template for all clean-code-reviewer output.
---
## Clean Code Review — [target_path]
**Language:** [python | javascript | csharp | rust]
**Mode:** [full | functions | classes | naming | errors | smells]
**Files reviewed:** [N]
**Total violations:** [N] (HIGH: N, MEDIUM: N, LOW: N)
**Severity threshold applied:** [low | medium | high | none]
---
### Violations
| # | File | Line | Rule | Severity | Description | Suggested Fix |
|---|------|------|------|----------|-------------|---------------|
| 1 | | | | | | |
---
### Summary by Category
| Category | HIGH | MEDIUM | LOW | Total |
|----------|------|--------|-----|-------|
| Functions | | | | |
| Classes | | | | |
| Naming | | | | |
| Error Handling | | | | |
| Smells | | | | |
| **Total** | | | | |
---
### Key Issues (HIGH severity only)
1. [Most important issue — one sentence]
2. ...
---
### Verdict
**[APPROVE / REQUEST CHANGES / REJECT]**
Criteria:
- APPROVE: no HIGH violations; MEDIUM violations are minor or isolated
- REQUEST CHANGES: HIGH violations present but code is functional and salvageable
- REJECT: pervasive violations; code requires structural redesign before clean coding fixes
[1–2 sentence overall assessment. Be specific: name the files and patterns that drove the verdict.]
---
### Recommended Next Step
[Choose the most appropriate]:
**For code-level violations only (naming, function size, smells):**
> Pass this report to `clean-code-refactor` with `mode=[most critical mode]`.
**For structural violations (wrong class responsibilities, missing abstractions, wrong dependency direction):**
> Pass this report to `software-architect` Review Mode to design the target structure,
> then implement via `[language]-data-engineer` Implement Mode using the architect's design as spec.
**For both:**
> 1. `software-architect` Review Mode → target architecture design
> 2. `[language]-data-engineer` Implement Mode → structural changes per architect's design
> 3. `clean-code-reviewer` → re-scan to confirm structural violations resolved
> 4. `clean-code-refactor` → fix remaining code-level violations