skills/refactor/SKILL.md
Discover architectural friction and propose structural refactors with competing interface options. Focuses on deepening shallow modules, extracting grouped concerns into packages/modules, breaking up god files, reducing duplication, and improving testability. Use when asked to "improve the architecture", "find refactoring opportunities", "deepen modules", "consolidate coupling", "break up god components", "extract this into a package", "make this more testable", or "find architectural friction".
npx skillsauth add howells/arc refactorInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
<tool_restrictions>
EnterPlanMode — BANNED. Do NOT call this tool. This skill has its own structured process.ExitPlanMode — BANNED. You are never in plan mode.
</tool_restrictions><arc_runtime> This workflow requires the full Arc bundle, not a prompts-only install.
Paths in this skill use these conventions:
agents/..., references/..., disciplines/..., templates/..., scripts/..., rules/..., skills/<name>/... are Arc-owned files at the plugin root. Resolve the plugin root from this skill's filesystem location — it's the directory containing agents/ and skills/../... is local to this skill's directory..ruler/..., docs/..., src/..., or any project-relative path refers to the user's project repository.
</arc_runtime><required_reading> Before starting, read these references:
references/architecture-patterns.md — import depth rules, boundary violationsreferences/component-design.md — compound vs simple component patternsreferences/maintainability-review.md — strict god-file, duplication, and structural simplification barreferences/complexity-optimization.md — safe optimization patterns and behavior-preservation checksAlso read, when present in the target project:
CONTEXT.md or the relevant context from CONTEXT-MAP.mddocs/adr/*.md or area-specific ADRs
</required_reading>Discover structural friction, propose deep-module refactors, and create project-local RFCs.
<boundary> This workflow reviews existing code with the explicit goal of creating a refactoring plan or RFC./arc:refactor./arc:audit.Use these terms consistently:
From John Ousterhout's A Philosophy of Software Design:
A deep module has a small interface hiding a large implementation. Deep modules are:
A shallow module has an interface nearly as complex as its implementation. Shallow modules:
Apply the deletion test to suspected shallow modules: if deleting the module makes complexity vanish, it was pass-through indirection; if deleting it spreads complexity across callers, it was earning its keep.
Read the project context before judging architecture:
CONTEXT-MAP.md exists, use it to find the relevant CONTEXT.md.CONTEXT.md if present.docs/adr/ or the relevant area if the candidate touches a documented decision.Use the project's domain vocabulary when naming candidate modules. If a better module name uses a concept not in CONTEXT.md, note that the context should be updated during the grilling loop.
For JavaScript/TypeScript projects, run the Arc-owned god-file and duplication scanner when available:
python3 scripts/find-god-files.py . --max-files 40
Use --include-tests only when the user asks about duplicated tests or test-suite cleanup.
The scanner is heuristic. It ranks likely candidates; it does not decide. Read the highest-ranked files before proposing changes.
Classify confirmed candidates:
god-component — React component doing rendering, data shaping, effects, mutations, validation, and subview control in one file.god-script — CLI/build/migration script mixing argument parsing, I/O, domain logic, formatting, and side effects.god-module — non-UI module with multiple unrelated responsibilities.duplication — repeated functions, schemas, UI fragments, query builders, scripts, or formatting logic.shallow-module — interface nearly as complex as the implementation.package-extraction — grouped behavior that belongs in a discrete package/module because it has a coherent concept, multiple callers, and a stable interface.Use the Agent tool with subagent_type=Explore to navigate the codebase. If the user provided a
path or focus area, start there. Otherwise, explore broadly.
Do NOT follow rigid heuristics. Explore organically and note where you experience friction:
The friction you encounter IS the signal.
Present a numbered list of refactoring opportunities. For each candidate:
| Field | Description | |-------|-------------| | Cluster | Which modules/concepts are involved | | Type | shallow-module, package-extraction, god-component, god-script, god-module, duplication | | Evidence | Line count, responsibility mix, duplicated blocks, import depth, call patterns, shared types | | Problem | Why the current shape causes friction | | Proposed direction | Plain-English description of what would change | | Dependency category | See categories below | | Locality / leverage | What change gets concentrated, and what callers gain | | Test impact | What existing tests would be replaced by boundary tests, or what characterization tests are needed first | | Complexity impact | Current complexity, proposed complexity, and behavior-preservation risk when performance is part of the refactor | | Severity | How much this costs day-to-day |
Ask the user: "Which of these would you like to explore?"
Do NOT propose final interfaces yet. The point is to choose which candidate deserves deeper work.
Use a grilling loop before writing the RFC. Ask one question at a time, with your recommended answer included. Resolve:
CONTEXT.md should gain or sharpen a term.Update project context inline only for durable domain language, not temporary implementation details.
Before spawning interface-option agents, write a user-facing explanation of the chosen candidate:
Show this to the user, then immediately proceed to Step 7.
Spawn 3+ sub-agents in parallel using the Agent tool. Each must produce a radically different interface for the deepened module.
Give each agent a technical brief (file paths, coupling details, dependency category, what's being hidden) plus a different interface constraint:
| Agent | Constraint | |-------|-----------| | Agent 1 | "Minimise the interface — aim for 1-3 entry points max and maximise leverage per entry point" | | Agent 2 | "Maximise flexibility — support many use cases and extension" | | Agent 3 | "Optimise for the most common caller — make the default case trivial" | | Agent 4 (if applicable) | "Use ports & adapters for cross-boundary dependencies" |
Each sub-agent outputs:
Present all options, then compare them in prose. Give your own recommendation — which option is strongest and why. If elements from different options combine well, propose a hybrid. Be opinionated.
Create a refactor RFC in docs/arc/plans/YYYY-MM-DD-[scope]-refactor-rfc.md:
## Problem
[Describe the architectural friction — which modules are shallow and coupled,
what integration risk exists, why this makes the codebase harder to navigate]
## Proposed Interface
[The chosen interface option — signature, usage example, what it hides]
## Package / Module Extraction
[If applicable: where the new package/module lives, what it owns, what remains in callers, and how imports migrate]
## Dependency Strategy
[Which category applies and how dependencies are handled]
## Testing Strategy
- **Characterization tests to write first**: [current behaviours that must be pinned before splitting]
- **New boundary tests to write**: [behaviours to verify at the interface]
- **Old tests to delete**: [shallow module tests that become redundant]
- **Test environment needs**: [local stand-ins or adapters required]
## Decomposition Order
1. [First safe extraction]
2. [Second safe extraction]
3. [Import migration / cleanup]
## Implementation Recommendations
[Durable guidance NOT coupled to current file paths:
- What the module should own (responsibilities)
- What it should hide (implementation details)
- What it should expose (the interface contract)
- How callers should migrate]
Save the RFC and summarize the recommendation. Do not auto-commit it unless the user asks.
When assessing a candidate, classify its dependencies:
Pure computation, in-memory state, no I/O. Always deepenable — merge the modules and test directly.
Dependencies with local test stand-ins (PGLite for Postgres, in-memory filesystem). Deepenable if the stand-in exists. Test with the local stand-in running in the test suite.
Your own services across a network boundary. Define a port (interface) at the module boundary. The deep module owns the logic; the transport is injected. Tests use an in-memory adapter.
Third-party services (Stripe, Twilio) you don't control. Mock at the boundary. The deepened module takes the external dependency as an injected port; tests provide a mock.
The core principle: replace, don't layer.
From the architecture patterns reference:
| Signal | What it means |
|--------|--------------|
| 5+ levels of ../ imports | Code is reaching across boundaries |
| Barrel file re-exporting everything | Hiding the real dependency graph |
| Test file longer than source file | Testing internals, not behaviour |
| "Utils" folder with 20+ files | Shallow modules masquerading as shared code |
| Type file imported by 10+ modules | Hidden coupling through shared types |
| Feature spread across 8+ files | Over-decomposition, shallow modules |
| Mock setup longer than test body | Integration seams are in the wrong place |
| Large component mixes effects, validation, mutation, and rendering | God component |
| Script mixes CLI parsing, I/O, transformation, and output formatting | God script |
| Same schema/query/formatting code appears in several places | Missing shared module |
| Same concept used from multiple apps/packages | Candidate package/module extraction |
development
Go-live and shareability checklist covering the basics needed to make a project visitable, shareable, and ready for a first real audience. Use when asked to "launch", "go live", "make this shareable", "get this ready to show people", or prepare a project for a public URL.
development
Create, review, or revise a concise project vision document that captures what a project is, who it is for, why it exists, success criteria, constraints, non-goals, and decision principles. Use when starting a new project, clarifying product direction, aligning a codebase for future agent work, defining a north star, or turning a vague idea into docs/vision.md.
tools
Use when starting any conversation - establishes Arc's skill routing, instruction priority, and bootstrap rules
development
Characterization testing and safety-net backfill for existing code. Use when legacy, under-tested, or risky code needs tests before a refactor, bug fix, or behavior change. Captures current behavior through public interfaces, identifies coverage gaps, and adds focused unit, integration, or E2E tests without replacing TDD implementation workflows.