
Brewcode:Text Human
- 13 installs
- 29 repo stars
- Updated August 2, 2026
- kochetkov-ma/claude-brewcode
Remove AI artifacts from code and humanize generated text for more natural, human-written appearance.
About
brewcode:text-human removes AI artifacts from code and humanizes generated text. A solo builder uses it when code generated by Claude or other LLMs has distinctive patterns that need smoothing before shipping, making the output feel more hand-written and natural.
- Remove AI-generated artifacts from code
- Humanize text for natural appearance
- Part of brewtools plugin suite
- Token-aware optimization
Brewcode:Text Human by the numbers
- 13 all-time installs (skills.sh)
- Ranked #2,148 of 3,282 Productivity & Planning skills by installs in the Skillselion catalog
- Data as of Aug 5, 2026 (Skillselion catalog sync)
npx skills add https://github.com/kochetkov-ma/claude-brewcode --skill brewcodetext-humanAdd your badge
Show developers this skill is listed on Skillselion. Paste this into your README.
| Installs | 13 |
|---|---|
| repo stars | ★ 29 |
| Last updated | August 2, 2026 |
| Repository | kochetkov-ma/claude-brewcode ↗ |
What it does
Remove AI artifacts from code and humanize generated text for more natural, human-written appearance.
What you get
- polished code
- humanized text
Files
Text Humanizer
Detect and remove AI-generated artifacts from code and documentation. Process commits, files, or folders with parallel sub-agents.
Language References
| Language | Reference | Load When |
|---|---|---|
| Java/Kotlin | @reference/java.md | *.java, *.kt, *.groovy, Spring, Maven/Gradle |
| TypeScript/JS/React | @reference/typescript.md | *.ts, *.tsx, *.js, *.jsx, Node.js, React |
| Python | @reference/python.md | *.py, Django, FastAPI, Flask |
Multi-language projects: Load ALL relevant references.
---
Argument
First token = scope (required):
| Input | Action |
|---|---|
| None | Use AskUserQuestion: "What to humanize?" Options: "Commit hash (git diff)" / "File path" / "Folder path" |
| Commit hash (7+ hex) | Process all text files from commit |
| File path | Process single file |
| Folder path | Process all files in folder |
| "entire project" | Use AskUserQuestion: "Too broad — specify scope." Options: "Specific folder" / "File pattern (e.g. src/*/.java)" |
Everything after first token = custom prompt (optional). Free-form text, no quotes needed. Overrides or extends default humanization rules for this run. Passed to every sub-agent prompt.
Custom Prompt Handling
1. Parse: split args into scope (first token) and customPrompt (rest) 2. If customPrompt is present, prepend it to every sub-agent Task prompt as:
CUSTOM INSTRUCTIONS (highest priority, override defaults):
<customPrompt>3. Custom prompt wins over default rules on conflict
---
Architecture
Orchestrator -> Detect Language -> Load Reference -> Analyze -> Classify -> Split (3-10 blocks) -> Parallel Task agents -> AggregatePhase 1: Scope Analysis
Commit Mode
Process all text files from commit. No extension filtering: git diff --name-only <hash>^..<hash>
File Inclusion Rules
| Include | Exclude |
|---|---|
Source code (*.java, *.kt, *.py, *.ts, *.js, etc.) | Binary files (*.class, *.pyc, *.exe) |
Config (*.xml, *.yaml, *.yml, *.json, *.toml) | Images (*.png, *.jpg, *.gif, *.ico) |
Docs (*.md, *.txt, *.rst) | Archives (*.zip, *.tar, *.gz) |
Build files (pom.xml, package.json, pyproject.toml) | Generated (target/, build/, dist/, node_modules/) |
SQL (*.sql, *.ddl) | Lock files, IDE files |
Path Mode
find <path> -type f \( -name "*.java" -o -name "*.py" -o -name "*.ts" -o -name "*.js" -o -name "*.md" \) | grep -v -E "(target/|node_modules/|\.git/|build/|dist/|__pycache__/)"Block Count
| Files | Lines | Blocks |
|---|---|---|
| 1-2 | <200 | 1 (direct) |
| 3-5 | <500 | 3 |
| 6-10 | 500-1500 | 5 |
| 11-20 | 1500-3000 | 7 |
| 21+ | 3000+ | 10 |
Single file: process directly without Task delegation.
Phase 2: File Classification
Haiku (Simple)
| Type | Patterns |
|---|---|
| Config | *.properties, *.yaml, *.yml, *.toml, *.ini |
| Data | *.json, *.csv |
| Text | *.txt, *.md |
| Simple SQL | Single CREATE/ALTER, no CTEs/subqueries |
| Small files | <50 lines, no logic |
Sonnet (Complex)
| Type | Patterns |
|---|---|
| Source with logic | Business logic, algorithms |
| Tests | Test files for any framework |
| Complex SQL | CTEs, window functions, JOINs, subqueries |
| Config classes | Framework configuration |
Note: See language-specific references for detailed classification rules.
Phase 3: Block Formation
Group files by type, complexity (avoid mixed haiku/sonnet), line count balance. Keep related files together (same package/directory).
Data files block: YAML, JSON, CSV with comments → haiku for unicode fixes
Phase 4: Parallel Execution
Launch all Task calls in single message for true parallelism.
Task(subagent_type="developer", model="haiku", prompt="> **Context:** BC_PLUGIN_ROOT is available in your context (injected by pre-task.mjs hook).\n\n[CUSTOM_INSTRUCTIONS_IF_ANY]\nBlock 1: [files] [rules] Return JSON")
Task(subagent_type="developer", model="sonnet", prompt="> **Context:** BC_PLUGIN_ROOT is available in your context (injected by pre-task.mjs hook).\n\n[CUSTOM_INSTRUCTIONS_IF_ANY]\nBlock 2: [files] [rules] Return JSON")If custom prompt was provided, prepend to EVERY sub-agent prompt (after the Context line):
> **Context:** BC_PLUGIN_ROOT is available in your context (injected by pre-task.mjs hook).
CUSTOM INSTRUCTIONS (highest priority, override defaults):
<user's custom prompt text>
---<output_format> { "files_processed": N, "changes": [{"file": "path", "removed_comments": N, "fixed_unicode": N, "simplified_docs": N}] } </output_format>
Phase 5: Aggregation
Collect JSON results from all agents → merge statistics → generate unified report.
---
<humanization_rules>
AI Artifacts (Universal)
| Pattern | Action |
|---|---|
// Added by AI, // Claude suggestion, // AI-generated, // Generated by | Delete |
# Added by AI, # Claude suggestion | Delete |
/* Suggested by */ | Delete block |
AI-invented issue numbers (BUG-001, FIX-123, ISSUE-1) | Delete |
| Unicode long dash (U+2014) | Replace → -- |
| Unicode arrows (→, ←, ⇒) | Replace → ->, <-, => |
| Unicode bullets (•, ◦) | Replace → - or * |
| Unicode quotes (" " ' ') | Replace → " or ' |
Real vs Fake Issue References
Keep project-specific ticket patterns (INTELDEV-XXXXX, JIRA-XXXXX, GH-XXX). Remove generic AI-invented patterns (BUG-001, FIX-123, ISSUE-42).
Documentation Cleanup (General Principles)
| Remove | Keep |
|---|---|
| Private/internal function docs | Public API documentation |
| Test file documentation | Complex algorithm explanation |
| Obvious classes/functions (name = purpose) | Non-obvious behavior/side effects |
| Trivial parameter docs (restates name) | @throws/Raises with conditions |
| Trivial return docs (restates function) | External API contracts |
Key Rule: Never convert block docs to inline comments. Delete unnecessary docs entirely; for useful descriptions with trivial params, strip params and keep description.
Comments (Universal)
Keep WHY, remove WHAT.
| Remove | Keep |
|---|---|
// Initialize the list | // Retry 3x due to flaky external API |
// Loop through items | // Uses UTC to match database timezone |
// Check if null | // Thread-safe: synchronized on class lock |
Stale // TODO: refactor this | // HACK: workaround for <issue-link> |
Formatting (Universal)
| Issue | Fix |
|---|---|
/* single line */ | // single line or # single line |
| 3+ blank lines | Max 2 |
| Trailing whitespace | Remove |
| Mixed tabs/spaces | Spaces |
</humanization_rules>
---
File Type Rules
| Type | Rules |
|---|---|
| Source code | Full doc cleanup per language reference |
| Test files | Remove all docs, keep test descriptions |
| SQL/XML | Preserve structural comments |
| Markdown | Remove AI disclosures, fix unicode |
| YAML/Properties | Fix unicode, keep config explanations |
| JSON/CSV | Check for comments with unicode, usually skip |
YAML/Data Files
Check for unicode in comments. Section comments are valuable.
| Action | Example |
|---|---|
| FIX | # Lane 90001→10001 → # Lane 90001->10001 |
| KEEP | # ===== VAN loads for test ===== |
| SKIP | Pure data without comments |
SQL/XML Comments
Structural comments are valuable. Analyze neighboring files first.
| Action | Example |
|---|---|
| KEEP | Section headers -- ============ TABLES ============ |
| KEEP | Block separators <!-- ===== Mappers ===== --> |
| KEEP | Column/field documentation |
| REMOVE | Exact duplicates, AI markers |
---
Custom Prompt Mode
Custom prompt overrides or extends default rules. Use for:
- Restricting scope: "only remove AI artifacts, don't touch docs"
- Adding rules: "also remove all @author tags"
- Excluding files: "skip test files"
- Style reference: "use style from src/main/Service.java as reference"
Output Format
## Humanization Report
### Execution Summary
| Metric | Value |
|--------|-------|
| Total files | N |
| Blocks | M |
| Haiku/Sonnet | X/Y |
### Block Results
[Per-block tables with file metrics]
### Totals
| Metric | Count |
|--------|-------|
| Files processed | N |
| Comments removed | X |
| Docs simplified | Y |
| Unicode fixed | Z |Best Practices
- Load language reference first
- Process all commit files (include yaml/data files)
- Check yaml for unicode (comments may have arrows)
- Preserve valuable comments (they add context)
- Skip binaries (avoid corruption)
- Honor style reference if provided
- Keep public API docs
- Group files by complexity
- Launch agents in parallel
Error Handling
| Error | Action |
|---|---|
| Agent timeout | Continue with other blocks |
| File read error | Skip, note in report |
| Binary file | Skip, note in report |
| No changes | Report "No humanization required" |
Examples
/text-human 3be67487 # Commit - all files
/text-human src/main/java/MyService.java # Single file
/text-human src/main/java/services/ # Folder
/text-human 3be67487 don't touch docs on public records # Commit + custom prompt
/text-human src/ only remove AI artifacts and fix unicode # Path + custom prompt
/text-human 3be67487 also remove all @author tags # Commit + extra ruleText Humanizer
Remove AI artifacts and simplify documentation from your code.
What It Does
Cleans up code and documentation by removing AI-generated comments, simplifying excessive docs, and fixing unicode characters. Works with individual files, folders, or entire commits.
How to Use
/brewcode:text-human <commit-hash|path> [custom instructions]Examples
# Process a specific commit
/brewcode:text-human 3be67487
# Process a single file
/brewcode:text-human src/main/java/MyService.java
# Process a folder
/brewcode:text-human src/main/java/services/
# With custom instructions
/brewcode:text-human src/ only remove AI artifacts, don't touch docsWhat Gets Removed
- AI-generated comments:
// Added by AI,// Claude suggestion - Fake issue numbers:
BUG-001,FIX-123 - Unicode artifacts: smart quotes, arrows, dashes
- Trivial documentation that just restates the function name
- Excessive comments that describe obvious code
What Gets Kept
- Real issue references (your project's ticket patterns)
- "Why" comments explaining non-obvious behavior
- Public API documentation
- Structural comments in SQL/YAML files
Speed
Uses parallel processing for large codebases. Simple files processed with Haiku model, complex code with Sonnet for faster results.
Languages Supported
Java, Kotlin, TypeScript, JavaScript, Python, SQL, YAML, Markdown, and more.
Java/Kotlin Reference
Language-specific rules for text-human skill
File Classification
Haiku (Simple)
| Type | Patterns |
|---|---|
| Resources | logback*.xml, pom.xml, build.gradle |
| Small DTOs | *.java <50 lines, no logic |
| Properties | application.properties, bootstrap.yml |
Sonnet (Complex)
| Type | Patterns |
|---|---|
| Business logic | *.java, *.kt with logic |
| Tests | *Test.java, *Spec.kt, *IT.java |
| Config classes | *Configuration.java, *Config.java |
| Controllers | *Controller.java, *RestController.java |
| Services | *Service.java, *ServiceImpl.java |
| Repositories | *Repository.java, *Dao.java |
| Mapper XML | MyBatis/JOOQ dynamic SQL |
Classification Logic
| Extension | Condition | Result |
|---|---|---|
| java, kt | Contains @Test, @Configuration, @Service, @Repository | COMPLEX |
| java, kt | <50 lines, no nested classes | SIMPLE |
| java, kt | Otherwise | COMPLEX |
| groovy | Spock tests, Gradle scripts | COMPLEX |
---
JavaDoc Cleanup
Remove JavaDoc from: private methods, test files, obvious classes. Keep logic description, remove trivial @param/@return.
| Remove | Keep |
|---|---|
| All private/package-private methods | Public API docs with non-obvious behavior |
All test files (*Test.java, *Spec.kt, test helpers) | @DisplayName on test methods |
| Obvious DTOs/Entities (name describes purpose) | Complex business logic explanation |
| All @param (restates param name) | @throws with specific conditions |
| All @return (restates method name) | Non-obvious side effects |
| Class doc when class name is self-explanatory | External API contracts |
Logic vs Parameters Rule
NEVER convert JavaDoc `/ /` to inline `//` comment.* Two rules:
1. JavaDoc is unnecessary (private method, obvious class) → DELETE entirely, no replacement 2. JavaDoc has useful description but trivial @param/@return → strip @param/@return, keep description as single-line /** ... */
// BEFORE - useful description + trivial @param/@return:
/**
* Converts USD to target currency. Returns unchanged if USD.
* @param amount the amount
* @param currency the currency
* @return converted amount
*/
// AFTER - keep description as single-line JavaDoc, strip @param/@return:
/** Converts USD to target currency. Returns unchanged if USD. */
BigDecimal convertCurrency(BigDecimal amount, CurrencyCode currency) { }
// KEEP @param - explains non-obvious behavior:
/**
* @param hasExtraStops true=include ALL loads, false/null=only WITHOUT extra stops
*/Private Methods
// REMOVE - private methods don't need JavaDoc:
/** Validates the filter. */
private boolean isValidFilter(Filter f) { }
/** Builds full condition. */
private Condition buildFullCondition() { }
/** Rounds value to scale. @param value the value @param scale the scale */
private Double roundToScale(double value, int scale) { }Obvious DTOs/Entities
// REMOVE - class name is self-explanatory:
/** Filter DTO for rates history queries. */
@Value @Builder
public class RatesHistoryFilter { }
/** Entity for rate history data. */
@Value @Builder
public class HistoryRateEntity { }
// KEEP - adds non-obvious context:
/** Cached for 1 hour. Thread-safe via copy-on-write. */
public class CompanyCache { }Test Files
Remove all JavaDoc from: test classes (*Test.java, *Spec.kt), test helpers (*Data.java, *Requests.java, *Fixtures.java), any file in src/test/.
// REMOVE - test class:
/** Test class for LoadsHistoryRepository. */
class LoadsHistoryRepositoryTest {
/** Tests filtering by company ID. */
@Test void testFilterByCompanyId() { }
}
// REMOVE - test helper classes:
/** Expected data for rates stats tests. */
@UtilityClass
public class RatesStatsExpectedData {
/** Factory method for expected stats. */
public static Stats expected() { }
}
// CORRECT - no JavaDoc, clear method names:
class LoadsHistoryRepositoryTest {
@Test
@DisplayName("Should filter loads by company ID")
void filterByCompanyId() {
// GIVEN
// WHEN
// THEN
}
}
@UtilityClass
public class RatesStatsExpectedData {
public static Stats expected() { }
}---
Comments
| Remove | Keep |
|---|---|
// Initialize the list | // Retry 3x due to flaky external API |
// Loop through items | // Uses UTC to match database timezone |
// Check if null | // Thread-safe: synchronized on class lock |
Stale // TODO: refactor this | // HACK: workaround for JDK-12345 |
Preserve all BDD comments: // GIVEN, // WHEN, // THEN, // AND
---
Issue References
// REMOVE - AI-invented numbers:
// BUG-001 fix: ...
// FIX-123: ...
// ISSUE-42: ...
// KEEP - real ClickUp/Jira tickets:
// INTELDEV-19207: ...
// Workaround for JIRA-12345Keep project-specific ticket patterns (INTELDEV-XXXXX, JIRA-XXXXX). Remove generic patterns (BUG-001, FIX-123).
---
Pre-Completion Checklist
| Check | Rule |
|---|---|
| [ ] | Private methods: no JavaDoc on private/protected/package-private methods |
| [ ] | Test files: no JavaDoc on *Test.java, *Spec.kt, or any file in src/test/ |
| [ ] | Test helpers: no JavaDoc on *Data.java, *Requests.java, *Fixtures.java |
| [ ] | Obvious DTOs: no JavaDoc if class name is self-explanatory |
| [ ] | Trivial @param: no @param id the id or similar restating param name |
| [ ] | Trivial @return: no @return that restates method name |
| [ ] | Lombok: no docs on @Value, @Data, @Builder classes unless non-obvious |
Scan Pattern
# Semantic search queries for grepai_search:
grepai_search("private methods with javadoc")
grepai_search("trivial param documentation")
grepai_search("test helper classes")
grepai_search("DTO classes with javadoc")
# Fallback grep patterns:
grep -n "^\s*/\*\*" <file> // Find all JavaDoc
grep -n "private.*{" <file> // Find private methodsFiles to Double-Check
Repository classes (private helper methods), Service classes (internal methods), Test helper classes (not ending in Test), DTOs/Entities (redundant class-level JavaDoc).
---
File Inclusion
| Include | Exclude |
|---|---|
*.java, *.kt, *.groovy | *.class, *.jar, *.war |
pom.xml, build.gradle, build.gradle.kts | target/, build/, .gradle/ |
*.xml (Spring, MyBatis) | Generated sources |
*.properties, *.yaml, *.yml | IDE files (.idea/, *.iml) |
Python Reference
Language-specific rules for text-human skill
File Classification
Haiku (Simple)
| Type | Patterns |
|---|---|
| Config | *.toml, pyproject.toml, setup.cfg |
| Requirements | requirements*.txt, constraints.txt |
| Constants | constants.py, config.py (pure values) |
| Init files | __init__.py (imports only) |
| Type stubs | *.pyi |
Sonnet (Complex)
| Type | Patterns |
|---|---|
| Business logic | *.py with classes/functions |
| Tests | test_*.py, *_test.py, conftest.py |
| CLI | cli.py, __main__.py |
| APIs | *_api.py, routes.py, views.py |
| Models | models.py, schemas.py |
| Services | *_service.py, services/*.py |
Classification Logic
| Extension | Condition | Result |
|---|---|---|
| py | Contains def test_, @pytest, class Test | COMPLEX |
| py | <30 lines, only imports/constants | SIMPLE |
| py | Has classes with methods | COMPLEX |
| py | Otherwise | COMPLEX |
| pyi | Type stubs | SIMPLE |
---
Docstring Cleanup
Remove docstrings from: private methods, test files, obvious functions. Keep public API docs.
| Remove | Keep |
|---|---|
Private methods (_method, __method) | Public API |
Test files (test_*.py) | Complex algorithms |
| Obvious functions (name = purpose) | Non-obvious side effects |
| Trivial Args restating name | Raises with conditions |
| Trivial Returns restating function | Examples with edge cases |
| Class docstring when name is clear | Type explanations for Any/Union |
Docstring Styles
Handle all common styles (Google, NumPy, Sphinx):
# REMOVE - trivial Google style:
def get_user(user_id: int) -> User:
"""Get user by ID.
Args:
user_id: The user ID.
Returns:
The user object.
"""
# CORRECT - no docstring needed:
def get_user(user_id: int) -> User:
...
# KEEP - adds context:
def get_user(user_id: int) -> User:
"""Fetches from cache first, falls back to DB. Returns None if not found."""Private Methods
# REMOVE - private methods don't need docstrings:
def _validate_input(self, data: dict) -> bool:
"""Validate the input data."""
def __calculate_hash(self, value: str) -> int:
"""Calculate hash for value."""
# CORRECT - no docstrings:
def _validate_input(self, data: dict) -> bool:
...
def __calculate_hash(self, value: str) -> int:
...Classes
# REMOVE - obvious class:
class UserRepository:
"""Repository for user operations."""
class OrderService:
"""Service for order management."""
# CORRECT - no docstring:
class UserRepository:
...
# KEEP - non-obvious behavior:
class RateLimiter:
"""Token bucket algorithm. Thread-safe. Tokens refill every 100ms."""Dunder Methods
# REMOVE - dunder methods are well-known:
def __init__(self, name: str):
"""Initialize with name."""
def __str__(self) -> str:
"""Return string representation."""
def __len__(self) -> int:
"""Return length."""
# CORRECT - no docstrings on dunders:
def __init__(self, name: str):
self.name = name
# EXCEPTION - keep if non-standard behavior:
def __eq__(self, other) -> bool:
"""Compares by ID only, ignores other fields."""---
Comments
| Remove | Keep |
|---|---|
# Initialize variable | # Workaround for Python 3.9 bug |
# Loop through items | # Must be eager (not lazy) for thread safety |
# Check if None | # noqa: E501 - URL cannot be split |
# TODO: refactor | # HACK: see https://bugs.python.org/12345 |
Type Comments
# REMOVE - use type hints instead:
x = [] # type: List[int]
y = None # type: Optional[str]
# CORRECT - inline type hints:
x: list[int] = []
y: str | None = None
# KEEP - when type hints not possible:
# type: ignore[arg-type] # mypy false positiveNoqa Comments
| Action | Example |
|---|---|
| KEEP | # noqa: E501 - long URL (with reason) |
| KEEP | # type: ignore[override] (mypy) |
| REMOVE | # noqa without code or reason |
| REVIEW | Multiple noqa in one file (code smell) |
---
Test Files
Remove all docstrings from: test files, fixtures, conftest.py.
# REMOVE - test file:
class TestUserService:
"""Tests for UserService."""
def test_create_user(self):
"""Test creating a user."""
# CORRECT - no docstrings:
class TestUserService:
def test_create_user(self):
# Arrange
# Act
# Assert
...
# REMOVE - fixtures:
@pytest.fixture
def mock_user():
"""Create mock user for tests."""
# CORRECT:
@pytest.fixture
def mock_user():
...---
Pre-Completion Checklist
| Check | Rule |
|---|---|
| [ ] | No docstrings on private methods (_method) |
| [ ] | No docstrings on dunder methods (unless non-standard) |
| [ ] | No docstrings on test files |
| [ ] | No trivial Args/Returns in docstrings |
| [ ] | No type comments when type hints work |
| [ ] | # noqa comments have explanations |
Scan Pattern
# Semantic search:
grepai_search("private methods with docstrings")
grepai_search("trivial docstring parameters")
grepai_search("test file documentation")
# Fallback grep:
grep -n '"""' <file> # Find docstrings
grep -n "def _" <file> # Find private methods---
File Inclusion
| Include | Exclude |
|---|---|
*.py, *.pyi | __pycache__/ |
*.toml, *.cfg, *.ini | *.pyc, *.pyo |
*.txt (requirements) | .venv/, venv/, .env/ |
*.md, *.rst | dist/, build/, *.egg-info/ |
Makefile, Dockerfile | .tox/, .pytest_cache/ |
TypeScript/JavaScript/React Reference
Language-specific rules for text-human skill
File Classification
Haiku (Simple)
| Type | Patterns |
|---|---|
| Config | *.json, tsconfig.json, package.json, .eslintrc.* |
| Constants | constants.ts, config.ts (pure exports) |
| Types only | *.d.ts, types.ts, interfaces.ts |
| Styles | *.css, *.scss, *.less |
Sonnet (Complex)
| Type | Patterns |
|---|---|
| Components | *.tsx, *.jsx with logic |
| Hooks | use*.ts, use*.tsx |
| Services | *Service.ts, *Api.ts |
| Tests | *.test.ts, *.spec.ts, *.test.tsx |
| Utilities | utils/*.ts with business logic |
| State | *Slice.ts, *Store.ts, *Context.tsx |
Classification Logic
| Extension | Condition | Result |
|---|---|---|
| ts, tsx | Contains describe(, it(, test( | COMPLEX |
| ts, tsx | <30 lines, only types/interfaces | SIMPLE |
| ts, tsx | React component with hooks/effects | COMPLEX |
| js, jsx | Otherwise | COMPLEX |
| json | Pure data | SIMPLE (often skip) |
---
JSDoc Cleanup
Remove JSDoc from: private functions, test files, obvious components. Keep public API docs.
| Remove | Keep |
|---|---|
| Internal/private functions | Exported public API |
Test files (*.test.ts, *.spec.ts) | Complex utility functions |
| Obvious components (name = purpose) | Non-obvious side effects |
Trivial @param restating name | @throws, @deprecated |
Trivial @returns restating function name | @example with usage |
@type when TypeScript infers | Generic type explanations |
JSDoc vs TypeScript
Prefer TypeScript types over JSDoc when both exist:
// REMOVE - redundant JSDoc with TS types:
/**
* @param {string} name - The user name
* @param {number} age - The user age
* @returns {User} The created user
*/
function createUser(name: string, age: number): User { }
// KEEP - only TS types:
function createUser(name: string, age: number): User { }
// KEEP - adds context beyond types:
/** Creates user and sends welcome email. Throws if email fails. */
function createUser(name: string, age: number): User { }React Components
// REMOVE - obvious component:
/** Button component that renders a button. */
const Button: FC<ButtonProps> = ({ onClick, children }) => { }
/** User profile card component. */
const UserCard: FC<UserCardProps> = ({ user }) => { }
// KEEP - non-obvious behavior:
/** Debounces input by 300ms. Calls onChange only after user stops typing. */
const DebouncedInput: FC<InputProps> = ({ onChange }) => { }
// KEEP - complex props explanation:
/**
* @param renderItem - Custom renderer, receives (item, index, isLast)
* @param onEndReached - Called when scroll reaches 80% of list
*/
const VirtualList: FC<ListProps> = ({ renderItem, onEndReached }) => { }Hooks
// REMOVE - obvious hook:
/** Hook that manages loading state. */
const useLoading = () => { }
/** Hook for user data. */
const useUser = (id: string) => { }
// KEEP - non-obvious behavior:
/** Fetches on mount + refetches every 30s. Pauses when tab inactive. */
const usePolling = (url: string, interval = 30000) => { }
/** Returns memoized callback. Deps auto-tracked via proxy. */
const useAutoCallback = <T extends Function>(fn: T): T => { }---
Comments
| Remove | Keep |
|---|---|
// Initialize state | // Workaround for React 18 strict mode |
// Map over items | // Must be sync for Safari compatibility |
// Check if null | // Intentionally not memoized - cheap to compute |
// TODO: fix later | // HACK: workaround for webpack/webpack#12345 |
ESLint/TSLint Comments
| Action | Example |
|---|---|
| KEEP | // eslint-disable-next-line @typescript-eslint/no-explicit-any |
| KEEP | /* eslint-disable */ at file top with reason |
| REMOVE | // eslint-disable without explanation |
| REVIEW | Multiple disables in one file (code smell) |
Preserve
// @ts-expect-errorwith explanation// @ts-ignore(but prefer @ts-expect-error)- Region comments
// #region,// #endregion
---
Test Files
Remove all JSDoc from: test files, test utilities, mocks, fixtures.
// REMOVE - test file:
/** Tests for UserService. */
describe('UserService', () => {
/** Should create user with valid data. */
it('creates user', () => { })
})
// CORRECT - no JSDoc, clear descriptions:
describe('UserService', () => {
it('creates user with valid data', () => {
// Arrange
// Act
// Assert
})
})
// REMOVE - test utilities:
/** Creates mock user for tests. */
export const createMockUser = () => { }
// CORRECT:
export const createMockUser = () => { }---
Pre-Completion Checklist
| Check | Rule |
|---|---|
| [ ] | No JSDoc on internal/unexported functions |
| [ ] | No JSDoc on test files (*.test.ts, *.spec.ts) |
| [ ] | No redundant JSDoc when TS types exist |
| [ ] | No JSDoc on obvious React components |
| [ ] | ESLint disables have explanations |
| [ ] | No @param/@returns restating obvious info |
Scan Pattern
# Semantic search:
grepai_search("jsdoc on private functions")
grepai_search("redundant type annotations")
grepai_search("test file documentation")
# Fallback grep:
grep -n "/\*\*" <file> // Find JSDoc
grep -n "^const.*=" <file> // Find functions---
File Inclusion
| Include | Exclude |
|---|---|
*.ts, *.tsx, *.js, *.jsx | *.d.ts (generated) |
*.mjs, *.cjs | node_modules/ |
*.json (with comments) | dist/, build/, .next/ |
*.md, *.mdx | coverage/ |
| Config files | Lock files (*.lock, *-lock.json) |