proper
Solve a request strategically and architecturally rather than tactically. Use when the user invokes /proper, asks for "the Proper™ way", wants the long-term design rather than the quickest fix, or wan
SKILL.mdskills/proper/SKILL.md
GitHubThe Proper™ Way
"Make the change easy, then make the easy change." -- Kent Beck
When the user invokes /proper, they are explicitly opting out of the
quickest tactical fix and in to a strategic design pass. The goal is to
reshape the code first so the requested feature becomes a small, natural
follow-up.
When to use this skill
- The user typed
/proper(with or without arguments describing the ask). - The user says things like "do this properly", "the Proper™ way", "solve this strategically", "architecturally", "do it right, not fast".
- A feature feels awkward to fit into the current code shape, and the user wants to step back before implementing it.
What this skill is NOT
- Not a license to refactor the world. The strategic proposal must stay tied to the requested feature. Gold-plating is off-limits -- but if you spot adjacent smells with real leverage, surface them and ask whether to widen the scope. The user decides; never expand silently.
- Not an autonomous implementation step. The output is a diagnosis +
proposal. The user decides whether to proceed, and non-trivial execution
goes through
/mikado. - Not a verdict. Sometimes the tactical fix really is the right call; say so honestly when that's true.
Process
Step 1 -- Restate the immediate ask
Repeat the user's request back in one sentence. Confirm the surface-level
ask before stepping back. If /proper was invoked without an explicit
prompt, ask what the underlying request is.
Step 2 -- Find the friction
Investigate the code as it exists today and answer:
- Where would the tactical fix go? (find the file/function)
- Why isn't this feature already easy? What design choice makes it awkward?
Common friction patterns to look for:
| Smell | What it looks like |
|---|---|
| Missing abstraction | The feature requires touching N similar call sites |
| Leaky boundary | A module knows things it shouldn't, to make this work |
| Conflated concerns | One function would gain a second responsibility |
| Hard-coded assumption | A value/behaviour is baked in that the feature needs to vary |
| Missing seam | There is no clean place to plug new behaviour in |
| Implicit contract | Callers rely on side effects the new feature would break |
| Wrong ownership | The data or logic lives in the wrong layer for this feature |
Name the friction explicitly. If there is no friction (the feature really
does fit cleanly with a small tactical change), say so. /proper is
not an excuse to invent refactorings.
Step 3 -- Propose the strategic shape
Describe, in concrete terms, what the code would need to look like for the requested feature to be a small, obvious change. Typical moves:
- Introduce an abstraction (interface, strategy, registry, adapter)
- Extract a seam (split a function, move a boundary, parameterise a hard-coded value)
- Rename / regroup so the new concept becomes first-class
- Invert a dependency so the new feature doesn't have to reach upward
- Split a module so the new concern has a natural home
- Unify duplicated logic so the feature only has to land in one place
Be specific: name files, types, functions. Sketch before/after when it helps. Keep the scope tight -- the refactoring exists to serve this feature, not to fix every smell you spotted along the way.
If you notice adjacent smells that would be much cheaper to fix while you're already in this area (or that would compound the friction if left alone), list them separately as "Optional scope expansions" with a brief cost/benefit, and ask whether to fold any in. Default to the minimum scope; only widen if the user agrees.
Step 4 -- Compare paths
Present a short, honest comparison so the user can decide with eyes open:
| Tactical | Strategic | |
|---|---|---|
| What it touches | ... | ... |
| Effort | small | medium / large |
| Next similar request | painful again | easy |
| Risk of regression | ... | ... |
| What it teaches the codebase | nothing | a new concept |
Recommend a path, but make the trade-off real. A throwaway script, a soon-to-be-deleted module, or a genuinely one-off request can absolutely deserve the tactical fix.
Step 5 -- Decide with the user
Wait for the user to choose. Do not start implementing until they pick. Possible outcomes:
- Go tactical -- drop
/proper, do the small fix. - Go strategic, small -- the refactoring fits in one or two commits. Implement it directly, then add the feature.
- Go strategic, non-trivial -- hand off to
/mikado(next step).
Step 6 -- Hand off to /mikado for non-trivial work
If the strategic path is non-trivial (multiple prerequisite changes, risk
of breakage along the way, wants safe incremental steps), use /mikado
to manage execution:
- Frame the Mikado goal as the end state of the refactoring, not the
feature itself. Good:
"Extract a
Transportinterface so the WebSocket implementation can be swapped." Bad: "Add SSE support." - Suggest
/mikado goal "<the strategic goal>"to seed the graph. - Let
/mikadodiscover prerequisites by attempting the naive change and observing what breaks. Do not pre-populate the graph with speculative steps. - Track the original feature request as a Mikado follow-up
(
/mikado later "<feature>") or simply implement it after the refactoring goal is reached. It is not part of the refactoring graph itself.
Rules
- Diagnosis before code. Steps 1-4 produce a proposal, not edits.
- Stay tied to the requested feature by default. Prune anything that does not serve it. If widening looks worthwhile, negotiate -- list the option, the cost, the benefit, and let the user pick. Never expand scope silently.
- The user is in control of scope. Always.
- Acknowledge when tactical wins.
/properis a thinking tool, not a verdict. - Defer execution of non-trivial strategic work to
/mikado. Do not try to do Mikado-style incremental work inside this skill. - Never commit autonomously. The user reviews and commits.