Rzemiosło · The Craft
What is The CraftLevelsGet startedChapters Search Download PLEN
Level 3 · Codex ~4 min read

In one sentence: When it’s worth building a skill, and when to refactor — and how to do it without breaking working code.

This chapter in plain terms

A chapter about two habits that keep code in check.

Skills are saved “recipes” for repeatable actions that the assistant runs with one command (e.g. /run-tests). You build a skill when you do something at least three times, or when the order of steps is easy to get wrong — then the AI doesn’t guess, it runs a proven procedure. (Mind the difference: a skill is a recipe for the assistant; a hook is an automation run by the tool — “from now on always do X after Y” is a hook, not a skill.)

Refactoring is tidying code without changing what it does — and it has its discipline: write so the code “reads like the code next to it”; don’t mix cleanup with a new feature in one commit (easier to undo then); first check whether the thing already exists somewhere (reuse before rewriting); work in small steps with green tests.

There’s also SOLID — five design principles, but treated not as dogma, rather as five tests: will the change be cheap? Without overdoing it the other way: five layers of abstraction for a simple form is also a mistake.

Example: moving files into new folders? Leave “redirects” (shims) from the old paths, so other people’s calls still work — you don’t break the entry points other code relies on.

Read more: the SOLID principles · refactoring · slash commands in Claude Code.

02 — Skills and refactoring

Commandments I and X: automate the repeatable; refactor so the code reads like its neighbor.

Skills (slash-commands) — when and why

A skill is a repeatable procedure wrapped in a single invocation (/run-projekt, /run-tests, /update-ai-readme, /add-migration). In the reference project, skills proved to be a lever, because they codify “how we do it” — the agent doesn’t guess, it follows a proven recipe. Skills are part of the broader toolkit for operating Claude (models, autopilot, background, agentic work) → 16.

Build a skill when:

  • you repeat the procedure ≥3 times (start server + 22 smoke-checks, run tests, add a Scraping — Automatically gathering data from websites with a program instead of copying by hand. Powerful for acquiring data, but it needs manners: respect others’ rules (robots.txt), don’t overload the server.);
  • the order of steps is easy to get wrong (Migration (database) — A controlled change to the database layout — adding a column, a table or moving data — step by step. Like a renovation to plan: rebuilding data in a set order so nothing “collapses”.: number → SQL — The query language for a database — the way you “ask” the database for data or change it. The universal standard for talking to a database. A badly written query can bog down the whole app.migrate.py → AI_README → commit);
  • there’s a project-specific “gotcha” the agent must remember every time (e.g. “on Windows set PYTHONIOENCODING=utf-8 before the scraper,” “Jest with --runInBand when the server is running”).

A good skill has:

  • one command for the agent + one for the human (fallback);
  • a clear output contract (exit 0 = green; exit 1 = what failed);
  • a list of gotchas specific to the platform/project;
  • a “when it’s NOT needed” section.

Anti-patterns

  • 🚫 A skill for something you do once — that’s pure overhead.
  • 🚫 A skill that hides what it does — when it runs something destructive, it must print it (e.g. “I removed dead code”).
  • 🚫 Confusing a skill (a recipe for the agent) with a hook (automation run by the harness). “From now on always do X after Y” = a hook in the config, not memory/a skill.

Refactoring — the discipline

Golden rule: write code that reads like the code next to it. Match comment density, naming, and idiom to the surroundings. Consistency > your preferences.

Rules

  1. Search for prior art before refactoring (Commandment II). Before you rewrite — git log -S, git blame. Often an “ugly” shape has a reason (compatibility, an edge-case, an old decision).
  2. Refactor separately from a behavior change. One commit = either cleanup or a new feature. Mixing them makes review and Rollback — Reverting a change to the previous, working state — “Ctrl+Z” for a deployment. When a new version breaks production, a rollback restores the previous one in seconds instead of fixing in a panic. harder.
  3. Reuse > rewrite. First check whether a helper already exists (a matcher, a normalizer, upsert_price). Duplicated logic is debt.
  4. Backward-compat on structural changes. In the reference project, moving the scripts into subpackages left shims re-exporting from the old paths — old calls still work. Don’t break others’ entry points.
  5. Small steps, verified. Refactor → tests green → commit. Not “one big rewrite at once,” after which you can’t tell what broke.

Quality without bug-hunting

Separate the two review modes (like /simplify vs /code-review):

  • Simplification/reuse/efficiency — cleanup, without hunting for bugs.
  • Correctness review — adversarial bug-hunting. Don’t mix them — each has a different goal and a different confidence bar.

SOLID — design that doesn’t clog up

Not a dogma, but five tests of whether a change will be cheap. Apply it proportionally to risk (→ 12: don’t over-engineer). SOLID is not a pretext for “just in case” layers of abstraction.

  • S — Single responsibility. One module = one reason to change. It’s the same discipline as “one commit = one thing” (refactor or behavior, not both). A function you have to touch for three unrelated reasons is three functions.
  • O — Open/closed. Extend without cutting into proven code. This is where Feature flag — An internal switch that turns a new feature on for some people, or off, without reworking the code. You roll a novelty out gradually and roll it back in a second — the cheapest insurance with any change. plug in (→ 12): you add the new path behind a flag and ship dark, instead of rewriting the existing branch and risking a regression.
  • L — Liskov. A subtype must honor the supertype’s contract — no “exception that breaks everything.” If an implementation breaks the caller’s assumptions, it’s not a subtype, it’s a trap.
  • I — Interface segregation. Narrow, purposeful interfaces instead of one god-interface. A caller shouldn’t depend on methods it doesn’t use.
  • D — Dependency inversion. Depend on an abstraction, not a concrete. It’s the code-level counterpart of “separate the layers” (→ 12): the logic doesn’t hardcode the database or queue provider — it receives it across a boundary, so it can be swapped (and tested, → 03).

Anti-patterns

  • 🚫 SOLID as a cult — five layers and a factory of factories for a three-field CRUD. Rule D is meant to ease swapping, not multiply files. Measure the need, don’t quote the letters.
  • 🚫 Open/closed without flags — you “extend” by editing a hot path in place with no toggle and no ramp (→ 12: no feature flags).
  • 🚫 Abstraction before there are two cases — an interface extrapolated from a single use guesses the future. Get the second concrete case first, then the shared contract (reuse > rewrite, but not reuse > reality).

In practice

  • Skills to start: /run (server + smoke), /run-tests (unit + e2e), /update-ai-readme, /add-migration (if a relational database). → 08
  • Do a refactor of a critical path (e.g. login) as a separate, tested step: first a test reproducing the current state/bug, then the change. → 03

The canonical doctrine is written in English.