# Aiclean

> Clean and refactor code with a focus on unnecessary complexity, reducing lines of code, improving readability, and preferring radare2-native portable APIs.

- Skill: `netvar1337/aiclean` (Agent Skill)
- Install (CLI): `npx skillmds@latest add netvar1337/aiclean`
- Raw SKILL.md: https://api.skillmd.com/api/skills/netvar1337/aiclean/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: Coding & Dev Tools
- Author: netvar1337 (https://skillmd.com/u/netvar1337)
- Updated: 2026-09-17
- Page: https://skillmd.com/skills/netvar1337/aiclean

---


When this skill is used:

Read the `AGENTS.md` for project guidelines first.

Workflow:

1. Check uncommitted changes, functions, or URLs given as context or related to the specified task.
2. Analyze the files involved and take a list of common coding practices from the project.
3. Inspect recent cleanup-oriented history in the same subsystem before patching.
   Search for commits using terms like `clean`, `cleanup`, `refactor`, `simplify`, `dedup`, `portable`, `dead code`, `reuse`.
4. Search for an existing API before polishing any new walk, parse, or traversal.
   Grep `libr/include/` for `_foreach`, `_recurse`, `_dfs`, `_iter` and check the `cmd_*.inc.c` help tables; deleting new code in favor of an existing API is the best cleanup.
5. Create a small plan that favors behavior-preserving simplification, LOC reduction, and safer ownership/bounds handling.
   Sweep every new or changed construct (each struct, loop, string test, arithmetic expression, null check, and duplicated block) against the rules below rather than only the obvious spots — maintainer review nitpicks tend to hit the constructs a quick pass skips.
6. Validate with focused tests or builds for the touched area when feasible.

Then improve the code quality following these rules:

- Reduce double dereferences by caching pointers as local variables
- Define and assign variables in the very same line if possible
  Prefer `bool a = true;` instead of `bool a; a = true;`
- Use the correct type for variables and return types. f.ex: use bool instead of int when possible values are 0 or 1.
- Use `R_STR_ISEMPTY (s)` / `R_STR_ISNOTEMPTY (s)` for empty-or-null string tests instead of `!s || !*s` / `s && *s`
- Order struct fields widest-first (pointers and 64-bit types, then 32-bit, then `bool`/`char` last) so the compiler inserts no padding
- Prefer a heap `char *` (`strdup`, `r_str_newf`) over a fixed `char buf[N]` when the string length is unbounded (type, symbol, or user-supplied names); fixed buffers silently truncate
- Parenthesize sub-expressions in mixed-operator arithmetic, e.g. `((ut64)i * stride) + (off / size)`, so precedence is explicit
- Prefer small, surgical patches over broad rewrites
- Preserve behavior first; when cleanup changes behavior, back it with tests or clear bug evidence
- Identify repeated logic that can be unified
- When 2 or more paths perform the same walk, parse, or format, extract a helper/table/callback instead of keeping copy-pasted branches
- Extract the shared tail into one helper when two loops differ only in their up-front filtering
- Fold `if` blocks that differ only in data into one loop over a static table
- Replace parallel candidate fields or fallback branches with a small array plus a loop
- Keep a flat membership test as a `switch` with fallthrough cases; a table plus a scan loop is for branches that carry differing data
- Skip pure style calls; only propose changes with a real LOC or readability win
- Mention code you examined and left alone; some functions are as long as they need to be
- Be positive for if/else the conditionals (if must be the true/valid case)
- Flatten nesting with early returns and continue statements
- Do not use goto statements for retry flow; refactor long functions into shorter ones
- A cleanup label is acceptable only when it clearly centralizes resource release in a complex function
- Main objective is to reduce LOCs and make the code more readable and clean
- Use radare2 APIs for processing strings, arrays, vectors, and hash tables instead of glib/libc
- Identify dead code and eliminate it
- Code must be portable, clean and prefer simpler, shorter logic
- Do surgically well thought patches with the aim of overall LOC reduction with readability in mind
- Static functions should not have `R_RETURN_*` statements
- Public `R_API` entry points should use `R_RETURN_*` for programmer-error precondition checks
- Remove unnecessary null checks when the contract or surrounding guards already guarantee non-null, analyze the codepaths that lead to each case and remove the unnecessary checks.
- Do not route a value through NULL just to test it: `p = p? p + n: NULL;` followed by `if (!p)` should branch on the original condition once, and a second such pair for a fallback case folds into one if/else
- Do not remove runtime checks that protect real allocation, IO, ownership, or bounds failures
- Cache deep dereferences or repeated getters in locals when it reduces noise
  Prefer patterns like `RPanelPos *pos = &p->view->pos;` or `const ut64 bsz = core->blocksize;`
- Clamp or validate sizes, offsets, counts, and radii once before entering loops
- Once bounds are proven, simplify the inner loop instead of repeating the same checks on every iteration
- Replace raw sentinels and magic casts with named constants/macros like `UT64_MAX`, `R_MIN`, `R_MAX`, and `COUNT`
- Prefer radare2-native helpers over ad-hoc code
  Use `r_strbuf_*` or `r_str_newf` instead of repeated append chains or `sprintf`/`strcat`
  Use `r_read_le*` and `r_read_be*` instead of open-coded byte parsing
  Parse user-supplied numbers with `r_num_get`/`r_num_math` (command handlers have `core->num`) instead of `atoi`/`strtol`/`sscanf`, so `0x` forms, negative values, flags and expressions all resolve; `atoi` on a value printed in hex silently yields the wrong number
  When "not a number" has to be told apart from a valid `0`, use `r_num_get_err`/`r_num_math_err` and test the `err` out-param, or `r_num_failed (core->num)` — the plain forms return `0` for garbage, so a bare replacement can turn a typo into a silent hit on whatever lives at offset 0
  Use `r_mem_dup`, `r_list_purge`, `R_NEWS0`, vector/list helpers, `RTable`, `Sdb`, and other existing r2 primitives before inventing new helpers
  Use the `r_str.h` char-scan family (`r_str_rchr`, `r_str_lchr`, `r_str_nchr`, `r_sub_str_rchr`) over `strchr`/`strrchr` chains; `r_str_rchr` takes a start position, so a second backward search resumes from the previous match instead of rescanning
- When output is built in loops, prefer `_tostring` helpers plus one buffered print over many `r_cons_printf` calls
- Avoid multi-line comments, only use single-line comments before the function signature if function name is not clear enough
- Do not use non-portable libc-functions, code must work on Windows too
- Remove hidden global state when a local context/state object can be passed explicitly
- Prefer a single ownership path for allocation/free/reset logic; cleanup patches should often remove leaks at the same time
- Avoid libc patterns that hurt portability or safety
  Avoid `sprintf`, `strcpy`, `strcat`, open-coded endian reads, UB-prone casts, and non-portable format strings
  Use `<r_types.h>` types and `PFMT64` macros

Patterns repeatedly seen in `radare2` cleanup history:

- Replace hand-rolled traversals with existing `*_foreach`/`*_recurse` APIs
  `r_anal_block_recurse_depth_first` already yields post-order via `on_exit`
- Deduplicate nearest-match or traversal logic by extracting a shared helper that accepts a small predicate/callback
- Replace manual string construction with `RStrBuf`, then drain once at the end
- Replace back-to-back `strrchr` calls on one buffer with `r_str_rchr` resuming from the prior match
- Functions used only inside a file with no external references must be `static`
- Convert print-heavy helpers into `*_tostring` style functions to lower `RCons` pressure
- Precompute validated loop invariants once, like clamped slot counts, `slot_off`, or local block size, then keep the loop body simple
- Replace retry `goto` blocks with a bounded `for (;;)` loop and a `retried` flag
- Reduce dependency on ambient state like `core->block` or file-global structs by reading into local buffers and passing explicit state around

