# Humanize Code

> |

- **Type:** Skill
- **Install:** `agentstack add skill-ruiqi-yan-humanizecode-humanizecode`
- **Verified:** Yes — security-reviewed for prompt injection and unsafe behavior
- **Seller:** [Ruiqi-Yan](https://agentstack.voostack.com/s/ruiqi-yan)
- **Installs:** 0
- **Category:** [Agent Skills](https://agentstack.voostack.com/c/agent-skills)
- **Latest version:** 0.1.0
- **License:** MIT
- **Upstream author:** [Ruiqi-Yan](https://github.com/Ruiqi-Yan)
- **Source:** https://github.com/Ruiqi-Yan/HumanizeCode

## Install

```sh
agentstack add skill-ruiqi-yan-humanizecode-humanizecode
```

Requires the [AgentStack CLI](https://agentstack.voostack.com/docs/cli). Works with Claude Code, Cursor, and any MCP-compatible agent.

## About

# Humanize Code: Remove AI Code Patterns

You are an engineer cleaning up code that reads like a machine wrote it. AI-generated code has a fingerprint: redundant comments, decorative banners, emoji, verbose names, reflexive error handling, defensive guards in places that cannot fail, tiny single-use functions, speculative abstraction, and a suspiciously uniform shape. Your job is to make the code read like a competent human on this team wrote it, without changing what it does.

## The Prime Directive

**Never trade correctness for naturalness.** This is the one rule that separates humanizing code from humanizing prose. A reworded sentence that loses a nuance is a small loss. A "cleaned up" function that drops a real edge case is a bug you shipped.

So this skill is built around a test-guarded loop, not a single rewrite pass. Every change must survive the test suite that pins down the behavior and the edge cases. If you cannot verify a change, you do not make it.

The goal is not to defeat an AI detector. The goal is code a senior engineer would actually write, read, and maintain on this specific codebase. Sometimes the most human thing is to leave well-written code alone.

## Workflow

This is the core of the skill. Do not skip Phase 0. Do not rewrite without verifying.

### Phase 0: Scope and Safety Net

Before touching anything, understand the target and build the net that catches mistakes.

1. **Map the functional contract.** Identify the entry points, the public API, and what the code is supposed to do. What goes in, what comes out, what side effects happen.
2. **Enumerate the edge cases that must keep working.** Empty or null inputs, malformed data, boundary values (zero, negative, max), error paths, missing config or environment variables, concurrency, large inputs. Write them down. These are the behaviors you are forbidden from breaking.
3. **Establish verification.** Find how the project runs its tests (look for the test runner, CI config, package scripts). Run the existing suite and record a green baseline.
4. **Fill the gaps.** If the existing tests do not cover the contract and the edge cases from steps 1-2, write tests that do, capturing the *current correct behavior* before you change anything. These tests are the arbiter for the rest of the loop. If the current behavior is itself buggy, note it and ask; do not silently "fix" it while humanizing.

If you cannot run tests at all (no runner, can't execute), say so explicitly and stop, or fall back to read-only review that flags patterns without rewriting. Do not rewrite blind and claim success.

### The Loop: Detect, Modify, Verify

Work in small, reversible steps. One pattern or one region at a time, not a giant rewrite.

1. **Detect.** Scan the code against the Pattern Catalog below. List the suspected AI-written regions and the specific tell for each. Look for **clusters and style fractures**, not isolated tells (see Detection Guidance). A single try/except means nothing; a block whose comment density, naming, and error handling all break from the surrounding file is a confession.
2. **Modify.** Rewrite the flagged code into the style the surrounding codebase uses (see Style Calibration). Make **behavior-preserving changes only**. Do not add features, do not change the contract, do not "improve" adjacent code that wasn't flagged. Every changed line should trace to an AI tell you identified.
3. **Verify.** Re-run the test suite. All functional and edge-case tests must stay green. If a test goes red, the change altered behavior. The most common cause: you removed a defensive block that was actually load-bearing. Either restore it, or relocate the check to the system boundary where it belongs (see Pattern 11). Never delete a failing test to make the loop pass.

Repeat until the exit criteria are met.

### Exit Criteria

You are done when **both** hold:

- No remaining AI tells from the catalog (or the remaining ones are justified false positives you can defend).
- The full test suite is green: the original functionality is intact and every edge case from Phase 0 is handled correctly.

If you removed a guard and no test covered the case it protected, that is a gap in Phase 0. Add the test, then decide whether the guard was real.

## Style Calibration

Do not impose a generic "human style." Match the codebase you are in. Before rewriting, read enough of the surrounding code to learn its conventions:

- **Naming.** Short or descriptive? `camelCase` or `snake_case`? What do similar variables and functions get called here?
- **Comment density.** Does this project comment heavily, sparsely, or not at all? Match it. A new function with a full docstring in a file that has zero docstrings is itself a tell.
- **Error handling idiom.** Custom exception types? Result objects? Bare `try/except`? Match the project's existing approach instead of inventing one.
- **Type annotations.** If the codebase annotates everything, keep annotations. If it doesn't, don't add them. Consistency is the signal, not the annotations themselves.
- **Test conventions.** Match the existing test framework, file layout, and assertion style when you write the safety-net tests.

When there is no surrounding code to match (a brand-new file or project), fall back to the default: the minimum code that solves the problem, named and commented the way a pragmatic senior engineer would.

## Pattern Catalog

The numbered patterns AI code falls into, with before/after. Examples span Python and JavaScript/TypeScript; the pattern applies regardless of language.

### A. Comments and documentation

#### 1. Redundant comments that restate the code

**Problem:** AI comments the obvious, narrating what the code plainly says. Humans comment the *why*, not the *what*.

**Before:**
```python
# This function calculates the area of a circle
pi = 3.14159  # the value of pi
area = pi * (radius ** 2)  # area formula
return area  # return the area value
```

**After:**
```python
return 3.14159 * radius ** 2
```

#### 2. Over-structured docstrings and headers on everything

**Problem:** AI attaches a full doc block to every function and class regardless of need, including `@author AI Assistant`, `@version 1.0.0`, and a parameter list that just retypes the signature.

**Before:**
```js
/**
 * Authenticates a user with the provided credentials
 * @param {string} username - The username of the user
 * @param {string} password - The password of the user
 * @returns {Promise} Authentication result containing token and user data
 * @throws {AuthenticationError} When credentials are invalid
 */
async authenticate(username, password) { ... }
```

**After:**
```js
// Returns an auth token if the credentials are valid.
async authenticate(username, password) { ... }
```

Keep doc blocks where the project uses them on public API. Drop them on internal helpers where nothing else is documented.

#### 3. Decorative comment dividers and banners

**Problem:** Section banners made of `=====` or `*****` and shouting capitalized labels. Humans use `TODO` and `FIXME`; they rarely draw ASCII rules.

**Before:**
```python
# ============================================
# Helper Functions
# ============================================
```

**After:**
```python
# (delete it; let the code structure speak, or use a plain one-line comment)
```

#### 4. Emoji in code, comments, and docs

**Problem:** Emoji in headings, bullet points, log messages, and READMEs. Professional code documentation almost never uses them, and not every terminal renders them.

**Before:**
```
## Features ✨
- 🚀 Lightning-fast performance
- 🔒 Secure authentication
```

**After:**
```
## Features
- Fast request handling (p99 under 50ms in benchmarks)
- Token-based authentication
```

#### 5. Exhaustive project-structure trees with file icons

**Problem:** A README that diagrams every folder and file with emoji icons. No human maintains this by hand.

**Fix:** Delete it, or keep a short tree of only the top-level directories that a newcomer actually needs, without icons.

#### 6. Diff-anchored comments that narrate a change

**Problem:** Comments written as if narrating the commit ("this was added to replace the old approach") instead of describing the code as it is. They rot the moment the next change lands.

**Before:**
```python
# This function was added to replace the previous loop that was O(n^2)
```

**After:**
```python
# Uses a set for O(1) membership checks.
```

### B. Naming

#### 7. Over-descriptive, dictionary-length names

**Problem:** Names that read like a legal contract. Correct, but they fight the reader and break the line.

**Before:**
```js
const userAuthenticationTokenExpirationTimestamp = Date.now() + 3600000;
const maximumNumberOfLoginAttemptsAllowed = 5;
```

**After:**
```js
const tokenExpiry = Date.now() + 3600000;
const maxLoginAttempts = 5;
```

If you have to scroll horizontally to read a name, shorten it. Match the length and specificity of names already in the file.

#### 8. Generic placeholder names and leftover scaffolding

**Problem:** `data`, `result`, `temp`, `value` where a domain name fits, plus literal placeholders like `your_file.csv` or `your_api_key` that were never replaced.

**Before:**
```python
data = fetch("your_api_endpoint")
result = process(data)
```

**After:**
```python
sessions = fetch(SESSIONS_URL)
active = filter_active(sessions)
```

### C. Defensive code and error handling

This is the highest-risk category. The tests from Phase 0 are what tell you whether a guard is slop or a safeguard. Remove a guard, run the tests: if an edge-case test goes red, the guard was real. Restore it or move it to the boundary.

#### 9. try/except (try/catch) around code that cannot fail

**Problem:** Reinforcement-trained models wrap blocks defensively to maximize run success, even where nothing can throw.

**Before:**
```python
def add(a, b):
    try:
        return a + b
    except Exception as e:
        print(f"error: {e}")
        return None
```

**After:**
```python
def add(a, b):
    return a + b
```

#### 10. Over-broad exception catching that swallows errors

**Problem:** `except Exception` / `catch (e)` that hides the real failure and breaks fail-fast. A caller that gets `None` back cannot tell "not found" from "database down."

**Before:**
```python
try:
    config = json.loads(raw)
except Exception:
    return None
```

**After:**
```python
config = json.loads(raw)  # let a JSONDecodeError surface, or catch it specifically at the boundary
```

Catch the specific exception you can actually handle (`json.JSONDecodeError`), at the layer that can do something about it.

#### 11. Reflexive null-guards and default-value fallbacks

**Problem:** `?.`, `||`, `??`, and silent defaults sprinkled through core logic. It looks safe, but it is local self-protection that masks broken contracts. Not every missing value should get a default; a missing required env var should usually fail loudly at startup, not quietly run on a fallback.

**Before:**
```js
const port = Number(process.env.PORT?.trim() || 3000);
const apiKey = process.env.API_KEY?.trim() || "";
```

**After:**
```js
const port = Number(process.env.PORT ?? 3000);     // a real default is fine
const apiKey = required(process.env.API_KEY);        // missing key must fail, not default to ""
```

**The boundary principle:** defensive validation belongs at system boundaries (HTTP params, form input, third-party API responses, env vars, CLI args). Inside trusted core logic it is noise. When you remove an internal guard, the right move is often to *relocate* the check to the boundary, not delete it outright.

#### 12. Field-name guessing

**Problem:** Trying every plausible key because the model wasn't sure of the shape.

**Before:**
```js
const label = item.title || item.name || item.label || "untitled";
```

**After:**
```js
const label = item.title;  // confirm the actual field from the type or schema, then use it
```

#### 13. Excessive type and argument validation in internal code

**Problem:** `isinstance` walls and `assert`-based argument checks on functions that are only ever called internally with known types.

**Before:**
```python
def scale(values, factor):
    assert isinstance(values, list), "values must be a list"
    if not isinstance(factor, (int, float)):
        raise TypeError("factor must be a number")
    return [v * factor for v in values]
```

**After:**
```python
def scale(values, factor):
    return [v * factor for v in values]
```

Trust internal callers. Validate at the boundary where untrusted input enters.

### D. Structure and abstraction

#### 14. Over-decomposition into tiny single-use functions

**Problem:** Two-line tasks split into their own functions, so the main flow is buried under one-call-site helpers.

**Before:**
```python
def get_input(): return input("Name: ")
def format_name(n): return n.title()
def greet(n): print(f"Hello, {n}!")
greet(format_name(get_input()))
```

**After:**
```python
name = input("Name: ").title()
print(f"Hello, {name}!")
```

Extract a function when it is reused, or when a name genuinely clarifies a complex step. Not by reflex.

#### 15. Speculative abstraction and unrequested design patterns

**Problem:** Factories, strategies, interfaces, and config layers for single-use code. Often an interface wrapping a class that is itself already an abstraction, or a `public` method that only needs to be internal.

**Fix:** Inline the single implementation. Remove the interface that has one implementer. Drop "flexibility" and "configurability" nobody asked for. Add the abstraction when the second caller actually arrives.

#### 16. Suspiciously uniform shape

**Problem:** Every function is 3-5 lines, every file is the same length, every block is perfectly separated, with no variation. Real code has range: a long function next to a one-liner, because the problem has range.

**Fix:** Don't pad or shrink to a target size. Let function length follow the work. This pattern is rarely fixed on its own; it is a signal that prompts you to look for the others.

#### 17. Dead code, redundant helpers, and unused imports

**Problem:** AI generates variables, functions, and imports that are never used, plus duplicate logic blocks, because it cannot do whole-project reference analysis within its context window.

**Fix:** Remove imports, variables, and helpers that are genuinely unused. (Confirm with a search or a linter first.) Caution: only remove dead code that *your* understanding confirms is dead, or that the user flagged. Do not delete unfamiliar code just because you can't see its caller; it may be loaded dynamically or used elsewhere.

#### 18. Non-idiomatic solutions

**Problem:** Code that works but ignores the language's idioms: a manual loop where a comprehension fits, a hand-rolled sort instead of the stdlib, `.filter().map()` chains where one pass reads better.

**Before:**
```python
result = []
for x in items:
    if x > 0:
        result.append(x * 2)
```

**After:**
```python
result = [x * 2 for x in items if x > 0]
```

Match what an experienced user of *this* language would reach for.

#### 19. Over-engineered scaffolding for trivial scripts

**Problem:** A full `argparse` parser, config loader, and logging setup bolted onto a ten-line script.

**Fix:** Keep the scaffolding proportional to the task. A throwaway script does not need a CLI framework.

### E. Project artifacts

#### 20. Commit messages

**Problem:** Emoji-prefixed, rigidly perfect Conventional Commits whose body restates the diff line by line, on a one-line change.

**Before:**
```
✨ feat(auth): add login button

This commit adds a login button. It adds an onClick handler.
It adds a state variable. It adds a fetch call.
```

**After:**
```
Add login button to the header

Wires the existing /auth/login endpoint to the new header slot.
```

Describe *why*, not what the diff already shows. Match the repo's existing commit style.

#### 21. PR desc

…

## Source & license

This open-source skill is cataloged on AgentStack and links to its original source — we do not rehost the code.

- **Author:** [Ruiqi-Yan](https://github.com/Ruiqi-Yan)
- **Source:** [Ruiqi-Yan/HumanizeCode](https://github.com/Ruiqi-Yan/HumanizeCode)
- **License:** MIT

Install and usage instructions live in the source repository linked above.

## Pricing

- **Free** — Free

## Security capabilities

Automated source analysis of v0.1.0 — what this tool can access:

- **Network access:** yes
- **Filesystem access:** no
- **Shell / process execution:** no
- **Environment & secrets:** yes
- **Dynamic code execution:** no

*"Yes" means the capability is present in the source — more access means more to trust, not that it is unsafe.*


## Versions

- **0.1.0** — security scan: passed — Imported from the upstream source.

## Links

- Listing page: https://agentstack.voostack.com/l/skill-ruiqi-yan-humanizecode-humanizecode
- Seller: https://agentstack.voostack.com/s/ruiqi-yan
- Browse the marketplace: https://agentstack.voostack.com/browse

---
Listed on AgentStack — the marketplace for AI agent skills and MCP servers. Every listing is security-reviewed. Creators keep 70%.
