refactor

Discover architectural friction and propose structural refactors with competing interface designs. Focuses on deepening shallow modules, consolidating coupled code, and improving testability. Use when asked to "improve the architecture", "find refactoring opportunities", "deepen modules", "consolidate coupling", "make this more testable", or "find architectural friction".

16 stars

Best use case

refactor is best used when you need a repeatable AI agent workflow instead of a one-off prompt.

Discover architectural friction and propose structural refactors with competing interface designs. Focuses on deepening shallow modules, consolidating coupled code, and improving testability. Use when asked to "improve the architecture", "find refactoring opportunities", "deepen modules", "consolidate coupling", "make this more testable", or "find architectural friction".

Teams using refactor should expect a more consistent output, faster repeated execution, less prompt rewriting.

When to use this skill

  • You want a reusable workflow that can be run more than once with consistent structure.

When not to use this skill

  • You only need a quick one-off answer and do not need a reusable workflow.
  • You cannot install or maintain the underlying files, dependencies, or repository context.

Installation

Claude Code / Cursor / Codex

$curl -o ~/.claude/skills/refactor/SKILL.md --create-dirs "https://raw.githubusercontent.com/howells/arc/main/skills/refactor/SKILL.md"

Manual Installation

  1. Download SKILL.md from GitHub
  2. Place it in .claude/skills/refactor/SKILL.md inside your project
  3. Restart your AI agent — it will auto-discover the skill

How refactor Compares

Feature / AgentrefactorStandard Approach
Platform SupportNot specifiedLimited / Varies
Context Awareness High Baseline
Installation ComplexityUnknownN/A

Frequently Asked Questions

What does this skill do?

Discover architectural friction and propose structural refactors with competing interface designs. Focuses on deepening shallow modules, consolidating coupled code, and improving testability. Use when asked to "improve the architecture", "find refactoring opportunities", "deepen modules", "consolidate coupling", "make this more testable", or "find architectural friction".

Where can I find the source code?

You can find the source code on GitHub using the link provided at the top of the page.

Related Guides

SKILL.md Source

<tool_restrictions>
# MANDATORY Tool Restrictions

## BANNED TOOLS — calling these is a skill violation:
- **`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:
1. `references/architecture-patterns.md` — import depth rules, boundary violations
2. `references/component-design.md` — compound vs simple component patterns
</required_reading>

# Architectural Refactoring

Discover structural friction, propose deep-module refactors, and create RFC issues.

## Core Concept: Deep Modules

From John Ousterhout's *A Philosophy of Software Design*:

A **deep module** has a small interface hiding a large implementation. Deep modules are:
- More testable (test at the boundary, not inside)
- More navigable (fewer files to understand a concept)
- More maintainable (changes stay internal)

A **shallow module** has an interface nearly as complex as its implementation. Shallow modules:
- Force callers to understand implementation details
- Create coupling between files that should be independent
- Make testing harder (you test internals, not behaviour)

## Process

### Step 1 — Explore for friction

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:

- Where does understanding one concept require bouncing between many small files?
- Where are modules so shallow that the interface is nearly as complex as the implementation?
- Where have pure functions been extracted just for testability, but the real bugs hide in how they're called?
- Where do tightly-coupled modules create integration risk in the seams between them?
- Where are there deep relative imports (5+ levels) indicating boundary violations?
- Which parts of the codebase are untested, or hard to test?
- Where do barrel files re-export everything, hiding the real dependency graph?

The friction you encounter IS the signal.

### Step 2 — Present candidates

Present a numbered list of deepening opportunities. For each candidate:

| Field | Description |
|-------|-------------|
| **Cluster** | Which modules/concepts are involved |
| **Why they're coupled** | Shared types, call patterns, co-ownership of a concept |
| **Dependency category** | See categories below |
| **Import depth** | Max relative import depth between coupled modules |
| **Test impact** | What existing tests would be replaced by boundary tests |
| **Severity** | How much this coupling costs day-to-day |

Ask the user: **"Which of these would you like to explore?"**

### Step 3 — Frame the problem space

Before spawning design agents, write a user-facing explanation of the chosen candidate:

- The constraints any new interface would need to satisfy
- The dependencies it would need to rely on
- A rough illustrative code sketch to make the constraints concrete — this is NOT a proposal, just grounding

Show this to the user, then immediately proceed to Step 4.

### Step 4 — Design competing interfaces

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 design constraint:

| Agent | Constraint |
|-------|-----------|
| Agent 1 | "Minimise the interface — aim for 1-3 entry points max" |
| 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) | "Design around ports & adapters for cross-boundary dependencies" |

Each sub-agent outputs:

1. **Interface signature** — types, methods, params
2. **Usage example** — how callers use it
3. **What complexity it hides** — what's internal
4. **Dependency strategy** — how deps are handled (see categories below)
5. **Trade-offs** — what you gain and what you lose

Present all designs, then compare them in prose. **Give your own recommendation** — which design is
strongest and why. If elements from different designs combine well, propose a hybrid. Be opinionated.

### Step 5 — User picks an interface

### Step 6 — Create RFC issue

Create a refactor RFC as a GitHub issue using `gh issue create`:

```markdown
## 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 design — signature, usage example, what it hides]

## Dependency Strategy

[Which category applies and how dependencies are handled]

## Testing Strategy

- **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]

## 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]
```

Do NOT ask the user to review before creating — just create it and share the URL.

## Dependency Categories

When assessing a candidate, classify its dependencies:

### 1. In-process

Pure computation, in-memory state, no I/O. Always deepenable — merge the modules and test directly.

### 2. Local-substitutable

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.

### 3. Remote but owned (Ports & Adapters)

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.

### 4. True external (Mock)

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.

## Testing Strategy

The core principle: **replace, don't layer.**

- Old unit tests on shallow modules are waste once boundary tests exist — delete them
- Write new tests at the deepened module's interface boundary
- Tests assert on observable outcomes through the public interface, not internal state
- Tests should survive internal refactors — they describe behaviour, not implementation

## Signals That Indicate Deepening Opportunities

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 |

Related Skills

vision

16
from howells/arc

Create or review a high-level vision document capturing project goals and purpose. Use when asked to "define the vision", "what is this project", "set goals", or when starting a new project that needs clarity on purpose and direction.

using-arc

16
from howells/arc

Use when starting any conversation - establishes Arc's skill routing, instruction priority, and bootstrap rules

tidy

16
from howells/arc

Clean up completed plans in docs/arc/plans/. Archives or deletes finished plans. Use when asked to "clean up plans", "tidy the docs", "archive old plans", or after completing implementation to remove stale planning documents.

testing

16
from howells/arc

Comprehensive testing strategy. Creates test plans covering unit, integration, and E2E. Uses specialist agents for each test type. Supports vitest and Playwright with auth testing guidance for Clerk and WorkOS.

suggest

16
from howells/arc

Opinionated recommendations for what to work on next based on Linear issues, tasks, and codebase. Use when asked "what should I work on", "what's next", "suggest priorities", or when starting a session and unsure where to begin.

seo

16
from howells/arc

Deep SEO audit for web projects. Analyzes codebase for crawlability, indexability, on-page SEO, structured data, social previews, and technical foundations. Optionally runs Lighthouse and PageSpeed against a live URL. Reports findings with severity, offers direct fixes or /arc:detail plans. Use when asked to "audit SEO", "check SEO", "review SEO", or "is my site SEO-ready".

responsive

16
from howells/arc

Audit and fix responsive/mobile issues across every page of a project, using browser screenshots at two breakpoints (375px mobile, 1440px desktop). Design-aware: reads existing design docs to preserve aesthetic intent, not just "make it fit." Use when asked to "make it responsive", "fix mobile", "responsive audit", or after building a desktop-first UI that needs mobile adaptation.

prune-agents

16
from howells/arc

Kill orphaned Claude subagent processes that didn't exit cleanly. Use when asked to "prune agents", "clean up agents", "kill orphaned processes", or when subagents accumulate from Task tool usage.

progress

16
from howells/arc

Internal skill for progress journal management. Other skills append to docs/arc/progress.md for cross-session context. Not invoked directly by users.

naming

16
from howells/arc

Generate and validate project names. Reads codebase context, produces candidates using tech naming strategies, and checks domain + GitHub availability. Use when naming a new project, renaming, or validating an existing name.

letsgo

16
from howells/arc

Production readiness checklist covering domains, SEO, security, and deployment. Use when asked to "ship it", "deploy to production", "go live", "launch", or when preparing a project for production deployment.

implement

16
from howells/arc

Scope-aware implementation workflow with TDD and continuous quality checks. Use when asked to "implement this", "build this feature", "execute the plan", or after /arc:ideate has created a design doc. For small work it creates a lightweight inline plan; for larger work it creates or loads a full implementation plan and executes task-by-task with build agents.