{"id":"7d2460a4-d8ae-4b4c-86c3-d1cae71766ba","shortId":"YqQryb","kind":"skill","title":"before-you-refactor","tagline":"Use when considering, evaluating, or performing a refactor, restructure, cross-file rename, or cleanup","description":"# Before You Refactor\n\n## Overview\n\n**Stop. Read the code that already exists. Understand the tests that protect it. Take small steps. Keep the tests green.** This is a **rigid** skill. Run the checklist; don't skip steps. When assessing code (not actively refactoring), steps 1–2 and 6 are the assessment; report findings without editing.\n\n## When to invoke\n\nInvoke when you're about to:\n\n- Refactor existing code (extract function, inline, rename across multiple files, restructure a module)\n- \"Clean up\" code you didn't write\n- Rewrite a function or module because the existing one feels ugly, outdated, or wrong\n- Replace an existing implementation with a \"better\" one\n- Restructure tests, fixtures, or shared helpers used in more than one place\n- Assess whether existing code needs refactoring (reading for smells, coupling, complexity)\n- Review a refactoring proposal or PR that restructures code\n\nIf you're touching ≥3 lines of existing non-trivial logic to change its **shape** (not its behavior), invoke this skill.\n\n### Non-triggers — do NOT invoke for\n\n- Fixing a one-line bug where the change is obvious and the test exists\n- Adding a brand-new function in a brand-new file (use `clean-code` instead)\n- Renaming a single local variable inside one function\n- Fixing a typo in a comment, string, or doc\n- Formatting-only changes (whitespace, import order) handled by a formatter\n- Editing config or data files where there's no logic to refactor\n\nIf you're not sure whether a change counts as a refactor, **invoke anyway** — the checklist is cheap, the consequence of skipping it is not.\n\n## The pre-refactor checklist\n\nRun every step in order. Do not start editing until step 5 is satisfied.\n\n1. **Read the existing code.** Read it through once, then again. Assume it encodes decisions, bug fixes, and edge-case handling you don't yet understand. *(Attapattu, 97/6.)*\n2. **Find the tests that already cover it.** List them. Run them. Confirm they pass on `main` before you change anything. If there are no tests, **stop and add a characterization test that pins down current behavior** before touching the code. *(Attapattu, 97/6 — \"Ensure existing tests pass after each iteration.\")*\n3. **State the goal in one sentence.** \"I am restructuring X so that Y.\" If you can't write that sentence, you don't have a refactor — you have a wish. Stop. Talk to the user.\n4. **Check the goal isn't ego or fashion.** Are you refactoring because the code is genuinely blocking work, or because the style offends you, or because there's a newer framework? *Personal preference, ego, and \"new tech is shiny\" are not valid reasons.* *(Attapattu, 97/6.)* If the answer is fashion, stop and propose the change to the user explicitly with cost and benefit; do not silently rewrite.\n5. **Plan the smallest first step.** Refactor in **many small commits, not one massive change.** Each step must keep the tests green. If your plan starts with \"first I'll rip out X and then over the next hour I'll …\", you're doing it wrong — restart with a smaller first step. *(Attapattu, 97/6; Lewis, 97/24.)*\n6. **Identify coupling and complexity hotspots before you cut.** Skim for high fan-in / fan-out classes, long methods, deep inheritance, and hidden globals — these are the tangled spots that turn a small refactor into a big one. Note them; estimate accordingly; tell the user if the cost is now larger than the original ask. *(Pepperdine, 97/74.)*\n7. **Confirm you have access to break it safely.** Are you on a branch? Can you commit incrementally? Can you revert? You should never refactor directly on a shared branch or in production. *(Evans, 97/31 — generalized: don't touch what you can't safely revert.)*\n\n## Red Flags\n\nThese thoughts mean STOP — restart the checklist:\n\n| Thought | Reality |\n|---|---|\n| \"I'll just rewrite this from scratch — it'll be faster.\" | Throwing away tested, battle-hardened code throws away every bug fix and edge case it absorbed. The rewrite will rediscover those bugs the slow way. (97/6) |\n| \"There are no tests, but the change is obvious.\" | \"Obvious\" is how production breakages are born. Pin behavior with a characterization test first, then refactor. (97/6) |\n| \"I'll do it all in one big PR — easier to review.\" | Big PRs hide bugs and frustrate reviewers. Many small commits keep tests green and changes reviewable. (97/6, 97/24) |\n| \"The old code is ugly and uses outdated patterns — I should modernize it.\" | Style is not a refactor goal. New framework / new language / personal preference are not valid reasons. State the actual user-visible benefit or stop. (97/6) |\n| \"It's just a small cleanup, no need for a checklist.\" | The small cleanups are exactly where the worst tangles hide. Run the checklist. (97/74) |\n| \"I'll fix everything I see while I'm in there.\" | Boy Scout rule says *a little better*, not *perfect*. Bounded improvement only. Write the rest down for later. (97/8) |\n| \"I can patch it directly on the staging/production server, just this once.\" | No. Refactors flow through your normal commit → test → review → deploy path. \"Just this once\" is how outages happen. (97/31) |\n| \"The tests are failing but it's just flaky — I'll keep going.\" | Failing tests during a refactor mean the refactor changed behavior. Stop, investigate, fix or revert. Don't push through. (97/6) |\n| \"Estimating is too hard — I'll figure it out as I go.\" | Open-ended refactors balloon. Identify the coupling hotspots up front and re-estimate. If it's now bigger than the ask, escalate. (97/74) |\n| \"I'll just rename some variables — the function isn't *that* long.\" | If the function scrolls, renaming alone won't help. Extract helpers whose names explain the *why*; the body shrinks to a sequence of named steps. (`Fowler/LongMethod`) |\n| \"The function does X *and also* Y, but they're related.\" | If you needed \"and also\" to describe the unit, it has more than one reason to change — the SRP refactoring trigger. State the unit's responsibility in one sentence; if you can't without \"and also,\" split. See `clean-code` decision 4 for the discipline of writing the result. (97/76) |\n| \"The same change keeps forcing me to edit the same eight files.\" | Shotgun surgery: the behavior is conceptually one thing, physically scattered. Move related fields and methods together until the next instance of the change is one file. (`Fowler/ShotgunSurgery`) |\n| \"This function already takes seven primitives — I'll just add an eighth.\" | Data clump. The fields are a missing type. Extract a class / dataclass / parameter object before adding the eighth. (`Fowler/DataClumps`) |\n| \"Everything lives in one file — it's easier to find when it's all together.\" | Co-location by import convenience is not a single responsibility. If the pieces change for different reasons, split the module along the axes of change. (97/76) |\n\n## What \"done\" looks like\n\nYou are done when **all** of the following are true:\n\n- [ ] The goal sentence from checklist step 3 is satisfied.\n- [ ] All tests that passed before the refactor still pass.\n- [ ] Any new behavior or new edge case has a new test (write it under TDD per `superpowers/test-driven-development`).\n- [ ] No file you touched is left in a half-refactored state — no dead code, no commented-out blocks, no `TODO: finish this`.\n- [ ] Each commit on the branch keeps the tests green (you can revert any single commit and the project still builds).\n- [ ] If you found tangled spots outside your scope, they are written down (issue, todo, note to the user) — not silently expanded into the PR.\n- [ ] You can describe the change to the user in two sentences without saying \"and also.\"\n\nIf any box is unchecked, you are not done. Either finish, or revert and re-plan.\n\n## Principles in this skill\n\n| # | Principle | Author |\n|---|---|---|\n| 97/6 | Before You Refactor | Rajith Attapattu |\n| 97/8 | The Boy Scout Rule | Robert C. Martin |\n| 97/24 | Don't Be Afraid to Break Things | Mike Lewis |\n| 97/31 | Don't Touch That Code! | Cal Evans |\n| 97/74 | The Road to Performance Is Littered with Dirty Code Bombs | Kirk Pepperdine |\n| 97/76 | The Single Responsibility Principle / SRP (refactoring trigger) | Robert C. Martin |\n| `Fowler/LongMethod` | Long Method → Extract Function | Martin Fowler |\n| `Fowler/FeatureEnvy` | Feature Envy → Move Method | Martin Fowler |\n| `Fowler/ShotgunSurgery` | Shotgun Surgery → Move Field / Inline Class | Martin Fowler |\n| `Fowler/DataClumps` | Data Clumps → Extract Class / Introduce Parameter Object | Martin Fowler |\n\nSee `principles.md` for the long-form distillations, citations, and source links.","tags":["before","you","refactor","oribarilan","agent-skills","ai-agents","best-practices","claude-code","claude-code-plugin","claude-code-skills","coding-agents","copilot-cli"],"capabilities":["skill","source-oribarilan","skill-before-you-refactor","topic-agent-skills","topic-ai-agents","topic-best-practices","topic-claude-code","topic-claude-code-plugin","topic-claude-code-skills","topic-coding-agents","topic-copilot-cli","topic-copilot-cli-plugin","topic-opencode","topic-opencode-plugin","topic-programming-principles"],"categories":["97"],"synonyms":[],"warnings":[],"endpointUrl":"https://skills.sh/oribarilan/97/before-you-refactor","protocol":"skill","transport":"skills-sh","auth":{"type":"none","details":{"cli":"npx skills add oribarilan/97","source_repo":"https://github.com/oribarilan/97","install_from":"skills.sh"}},"qualityScore":"0.460","qualityRationale":"deterministic score 0.46 from registry signals: · indexed on github topic:agent-skills · 21 github stars · SKILL.md body (8,596 chars)","verified":false,"liveness":"unknown","lastLivenessCheck":null,"agentReviews":{"count":0,"score_avg":null,"cost_usd_avg":null,"success_rate":null,"latency_p50_ms":null,"narrative_summary":null,"summary_updated_at":null},"enrichmentModel":"deterministic:skill-github:v1","enrichmentVersion":1,"enrichedAt":"2026-05-18T19:05:32.437Z","embedding":null,"createdAt":"2026-05-08T13:06:23.426Z","updatedAt":"2026-05-18T19:05:32.437Z","lastSeenAt":"2026-05-18T19:05:32.437Z","tsv":"'1':63,302 '2':64,331 '3':161,381,1177 '4':417,1036 '5':299,485 '6':66,541 '7':600 '97/24':540,749,1326 '97/31':634,874,1336 '97/6':330,373,462,538,693,719,748,788,907,1312 '97/74':599,813,944,1344 '97/76':1044,1156,1357 '97/8':843,1318 'absorb':683 'access':604 'accord':584 'across':90 'activ':60 'actual':781 'ad':201,1111 'add':359,1093 'afraid':1330 'alon':962 'along':1151 'alreadi':29,336,1086 'also':988,998,1029,1288 'answer':465 'anyth':351 'anyway':271 'ask':597,942 'assess':57,69,137 'assum':313 'attapattu':329,372,461,537,1317 'author':1311 'away':668,675 'axe':1153 'balloon':924 'battl':671 'battle-harden':670 'before-you-refactor':1 'behavior':175,367,711,897,1060,1191 'benefit':480,785 'better':123,831 'big':579,727,732 'bigger':939 'block':434,1225 'bodi':974 'bomb':1354 'born':709 'bound':834 'box':1291 'boy':825,1320 'branch':613,629,1234 'brand':204,210 'brand-new':203,209 'break':606,1332 'breakag':707 'bug':191,317,677,689,735 'build':1249 'c':1324,1366 'cal':1342 'case':322,681,1195 'chang':170,194,238,265,350,472,499,700,746,896,1010,1047,1079,1144,1155,1278 'character':361,714 'cheap':275 'check':418 'checklist':51,273,287,653,799,812,1175 'citat':1409 'class':559,1106,1388,1395 'clean':96,215,1033 'clean-cod':214,1032 'cleanup':19,794,802 'clump':1097,1393 'co':1131 'co-loc':1130 'code':27,58,85,98,140,156,216,306,371,431,673,752,1034,1220,1341,1353 'comment':231,1223 'commented-out':1222 'commit':495,616,741,862,1231,1244 'complex':147,545 'conceptu':1062 'config':247 'confirm':343,601 'consequ':277 'consid':7 'conveni':1135 'cost':478,590 'count':266 'coupl':146,543,927 'cover':337 'cross':15 'cross-fil':14 'current':366 'cut':549 'data':249,1096,1392 'dataclass':1107 'dead':1219 'decis':316,1035 'deep':562 'deploy':865 'describ':1000,1276 'didn':100 'differ':1146 'direct':625,848 'dirti':1352 'disciplin':1039 'distil':1408 'doc':234 'done':1158,1163,1297 'easier':729,1122 'edg':321,680,1194 'edge-cas':320 'edit':73,246,296,1052 'ego':423,451 'eight':1055 'eighth':1095,1113 'either':1298 'encod':315 'end':922 'ensur':374 'envi':1377 'escal':943 'estim':583,908,934 'evalu':8 'evan':633,1343 'everi':289,676 'everyth':817,1115 'exact':804 'exist':30,84,110,119,139,164,200,305,375 'expand':1270 'explain':970 'explicit':476 'extract':86,966,1104,1371,1394 'fail':878,888 'fan':554,557 'fan-in':553 'fan-out':556 'fashion':425,467 'faster':666 'featur':1376 'feel':112 'field':1069,1099,1386 'figur':914 'file':16,92,212,250,1056,1082,1119,1207 'find':71,332,1124 'finish':1228,1299 'first':489,512,535,716 'fix':186,226,318,678,816,900 'fixtur':127 'flag':646 'flaki':883 'flow':858 'follow':1168 'forc':1049 'form':1407 'format':236 'formatt':245 'formatting-on':235 'found':1252 'fowler':1374,1381,1390,1400 'fowler/dataclumps':1114,1391 'fowler/featureenvy':1375 'fowler/longmethod':982,1368 'fowler/shotgunsurgery':1083,1382 'framework':448,770 'front':930 'frustrat':737 'function':87,105,206,225,952,959,984,1085,1372 'general':635 'genuin':433 'global':566 'go':887,919 'goal':384,420,768,1172 'green':43,506,744,1238 'half':1215 'half-refactor':1214 'handl':242,323 'happen':873 'hard':911 'harden':672 'help':965 'helper':130,967 'hidden':565 'hide':734,809 'high':552 'hotspot':546,928 'hour':523 'identifi':542,925 'implement':120 'import':240,1134 'improv':835 'increment':617 'inherit':563 'inlin':88,1387 'insid':223 'instanc':1076 'instead':217 'introduc':1396 'investig':899 'invok':76,77,176,184,270 'isn':421,953 'issu':1262 'iter':380 'keep':40,503,742,886,1048,1235 'kirk':1355 'languag':772 'larger':593 'later':842 'left':1211 'lewi':539,1335 'like':1160 'line':162,190 'link':1412 'list':339 'litter':1350 'littl':830 'live':1116 'll':514,525,657,664,721,815,885,913,946,1091 'local':221 'locat':1132 'logic':168,255 'long':560,956,1369,1406 'long-form':1405 'look':1159 'm':822 'main':347 'mani':493,739 'martin':1325,1367,1373,1380,1389,1399 'massiv':498 'mean':649,893 'method':561,1071,1370,1379 'mike':1334 'miss':1102 'modern':761 'modul':95,107,1150 'move':1067,1378,1385 'multipl':91 'must':502 'name':969,980 'need':141,796,996 'never':623 'new':205,211,453,769,771,1190,1193,1198 'newer':447 'next':522,1075 'non':166,180 'non-trigg':179 'non-trivi':165 'normal':861 'note':581,1264 'object':1109,1398 'obvious':196,702,703 'offend':440 'old':751 'one':111,124,135,189,224,386,497,580,726,1007,1021,1063,1081,1118 'one-lin':188 'open':921 'open-end':920 'order':241,292 'origin':596 'outag':872 'outdat':114,757 'outsid':1255 'overview':23 'paramet':1108,1397 'pass':345,377,1183,1188 'patch':846 'path':866 'pattern':758 'pepperdin':598,1356 'per':1204 'perfect':833 'perform':10,1348 'person':449,773 'physic':1065 'piec':1143 'pin':364,710 'place':136 'plan':486,509,1305 'pr':153,728,1273 'pre':285 'pre-refactor':284 'prefer':450,774 'primit':1089 'principl':1306,1310,1361 'principles.md':1402 'product':632,706 'project':1247 'propos':151,470 'protect':35 'prs':733 'push':905 'rajith':1316 're':80,159,260,527,933,992,1304 're-estim':932 're-plan':1303 'read':25,143,303,307 'realiti':655 'reason':460,778,1008,1147 'red':645 'rediscov':687 'refactor':4,12,22,61,83,142,150,257,269,286,407,428,491,576,624,718,767,857,892,895,923,1013,1186,1216,1315,1363 'relat':993,1068 'renam':17,89,218,948,961 'replac':117 'report':70 'respons':1019,1140,1360 'rest':839 'restart':531,651 'restructur':13,93,125,155,390 'result':1043 'revert':620,644,902,1241,1301 'review':148,731,738,747,864 'rewrit':103,484,659,685 'rigid':47 'rip':515 'road':1346 'robert':1323,1365 'rule':827,1322 'run':49,288,341,810 'safe':608,643 'satisfi':301,1179 'say':828,1286 'scatter':1066 'scope':1257 'scout':826,1321 'scratch':662 'scroll':960 'see':819,1031,1401 'sentenc':387,401,1022,1173,1284 'sequenc':978 'server':852 'seven':1088 'shape':172 'share':129,628 'shini':456 'shotgun':1057,1383 'shrink':975 'silent':483,1269 'singl':220,1139,1243,1359 'skill':48,178,1309 'skill-before-you-refactor' 'skim':550 'skip':54,279 'slow':691 'small':38,494,575,740,793,801 'smaller':534 'smallest':488 'smell':145 'sourc':1411 'source-oribarilan' 'split':1030,1148 'spot':571,1254 'srp':1012,1362 'staging/production':851 'start':295,510 'state':382,779,1015,1217 'step':39,55,62,290,298,490,501,536,981,1176 'still':1187,1248 'stop':24,357,412,468,650,787,898 'string':232 'style':439,763 'superpowers/test-driven-development':1205 'sure':262 'surgeri':1058,1384 'take':37,1087 'talk':413 'tangl':570,808,1253 'tdd':1203 'tech':454 'tell':585 'test':33,42,126,199,334,356,362,376,505,669,697,715,743,863,876,889,1181,1199,1237 'thing':1064,1333 'thought':648,654 'throw':667,674 'todo':1227,1263 'togeth':1072,1129 'topic-agent-skills' 'topic-ai-agents' 'topic-best-practices' 'topic-claude-code' 'topic-claude-code-plugin' 'topic-claude-code-skills' 'topic-coding-agents' 'topic-copilot-cli' 'topic-copilot-cli-plugin' 'topic-opencode' 'topic-opencode-plugin' 'topic-programming-principles' 'touch':160,369,638,1209,1339 'trigger':181,1014,1364 'trivial':167 'true':1170 'turn':573 'two':1283 'type':1103 'typo':228 'ugli':113,754 'uncheck':1293 'understand':31,328 'unit':1002,1017 'use':5,131,213,756 'user':416,475,587,783,1267,1281 'user-vis':782 'valid':459,777 'variabl':222,950 'visibl':784 'way':692 'whether':138,263 'whitespac':239 'whose':968 'wish':411 'without':72,1027,1285 'won':963 'work':435 'worst':807 'write':102,399,837,1041,1200 'written':1260 'wrong':116,530 'x':391,517,986 'y':394,989 'yet':327","prices":[{"id":"6dba8dc8-8165-4539-878c-43694f96562b","listingId":"7d2460a4-d8ae-4b4c-86c3-d1cae71766ba","amountUsd":"0","unit":"free","nativeCurrency":null,"nativeAmount":null,"chain":null,"payTo":null,"paymentMethod":"skill-free","isPrimary":true,"details":{"org":"oribarilan","category":"97","install_from":"skills.sh"},"createdAt":"2026-05-08T13:06:23.426Z"}],"sources":[{"listingId":"7d2460a4-d8ae-4b4c-86c3-d1cae71766ba","source":"github","sourceId":"oribarilan/97/before-you-refactor","sourceUrl":"https://github.com/oribarilan/97/tree/main/skills/before-you-refactor","isPrimary":false,"firstSeenAt":"2026-05-08T13:06:23.426Z","lastSeenAt":"2026-05-18T19:05:32.437Z"}],"details":{"listingId":"7d2460a4-d8ae-4b4c-86c3-d1cae71766ba","quickStartSnippet":null,"exampleRequest":null,"exampleResponse":null,"schema":null,"openapiUrl":null,"agentsTxtUrl":null,"citations":[],"useCases":[],"bestFor":[],"notFor":[],"kindDetails":{"org":"oribarilan","slug":"before-you-refactor","github":{"repo":"oribarilan/97","stars":21,"topics":["agent-skills","ai-agents","best-practices","claude-code","claude-code-plugin","claude-code-skills","coding-agents","copilot-cli","copilot-cli-plugin","opencode","opencode-plugin","programming-principles"],"license":"other","html_url":"https://github.com/oribarilan/97","pushed_at":"2026-05-15T21:32:54Z","description":"Agent skills distilled from the hard-won lessons of world-renowned programmers, in the spirit of \"97 Things Every Programmer Should Know\"","skill_md_sha":"91fbb947b8d2b02f58abbbf0ba400438051ae236","skill_md_path":"skills/before-you-refactor/SKILL.md","default_branch":"main","skill_tree_url":"https://github.com/oribarilan/97/tree/main/skills/before-you-refactor"},"layout":"multi","source":"github","category":"97","frontmatter":{"name":"before-you-refactor","description":"Use when considering, evaluating, or performing a refactor, restructure, cross-file rename, or cleanup"},"skills_sh_url":"https://skills.sh/oribarilan/97/before-you-refactor"},"updatedAt":"2026-05-18T19:05:32.437Z"}}