# Improve Codebase Architecture

> Explore a codebase for architectural deepening opportunities: refactors that turn shallow modules into deeper ones with better testability and locality. Use when the user explicitly asks for architecture improvement, refactoring opportunities, or coupled-module analysis. Do not use for pre-merge review (use /sr) or spec gaps (use /ct). Read-only; it does not write code.

- Skill: `alexandrbasis/improve-codebase-architecture-2` (Agent Skill, multi-file: 3 files)
- Install (CLI): `npx skillmds@latest add alexandrbasis/improve-codebase-architecture-2`
- Raw SKILL.md: https://api.skillmd.com/api/skills/alexandrbasis/improve-codebase-architecture-2/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: AI & ML
- Author: alexandrbasis (https://skillmd.com/u/alexandrbasis)
- Updated: 2026-09-21
- Page: https://skillmd.com/skills/alexandrbasis/improve-codebase-architecture-2

---


# Improve Codebase Architecture

> **Upstream**: Adapted from [mattpocock/skills/improve-codebase-architecture](https://github.com/mattpocock/skills/tree/main/improve-codebase-architecture). Vocabulary and principles draw on Ousterhout (*A Philosophy of Software Design*) and Feathers (*Working Effectively with Legacy Code*). Adapted to use this repo's `tasks/` and `product-docs/` conventions instead of upstream's `CONTEXT.md` + `docs/adr/`.

Surface architectural friction and propose **deepening opportunities** — refactors that turn shallow modules into deep ones. The aim is testability and AI-navigability.

For a task-linked review, resolve the repository and active task with
[`../setup/references/task-context.md`](../setup/references/task-context.md), then read only the
linked product/plan context relevant to the target area. This remains read-only; an accepted
candidate is handed to `/ct` rather than mutating the task implicitly.

## Vocabulary

This skill uses the canonical architecture vocabulary in `.claude/skills/architecture-language/LANGUAGE.md`. Load it before suggesting candidates. Use **module**, **interface**, **seam**, **adapter**, **depth**, **leverage**, and **locality** for architectural claims, while retaining established project terms such as `service` or `API` when they carry specific meaning; state the mapping when needed.

Key principles (full list in `architecture-language/LANGUAGE.md`):

- **Deletion test**: imagine deleting the module. If complexity vanishes, it was a pass-through. If complexity reappears across N callers, it was earning its keep.
- **The interface is the test surface.**
- **One adapter = hypothetical seam. Two adapters = real seam.**

## Process

### 1. Explore

Read only the context relevant to the target area:

- If `product-docs/UBIQUITOUS_LANGUAGE.md` exists, use it for candidate names.
- Read PRD, JTBD, or active task decomposition documents only when they cover the target
  area or a decision needed to assess it.
- Read `CLAUDE.md`, `AGENTS.md`, or a project-structure document only when discovered and
  relevant to the architecture under review.

If any of these are missing, proceed silently — don't flag absence or suggest creating them upfront.

Then use the `Explore` agent (subagent_type=Explore) to walk the codebase. Note where you
experience friction rather than scanning unrelated areas:

- Where does understanding one concept require bouncing between many small modules?
- Where are modules **shallow** — interface 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 (no **locality**)?
- Where do tightly-coupled modules leak across their seams?
- Which parts of the codebase are untested, or hard to test through their current interface?

Apply the **deletion test** to anything you suspect is shallow: would deleting it concentrate complexity, or just move it? A "yes, concentrates" is the signal you want.

### 2. Present candidates

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

- **Files** — which files/modules are involved
- **Problem** — why the current architecture is causing friction
- **Solution** — plain English description of what would change
- **Benefits** — explained in terms of locality and leverage, and how tests would improve
- **Dependency category** — see [DEEPENING.md](DEEPENING.md) (in-process / local-substitutable / remote-but-owned / true-external)

**Use `UBIQUITOUS_LANGUAGE.md` vocabulary for the domain, and `architecture-language/LANGUAGE.md` for the architecture.** If `UBIQUITOUS_LANGUAGE.md` defines "Order", talk about "the Order intake module" — not "the FooBarHandler", and not "the Order service".

Do NOT propose interfaces yet. Ask the user: "Which of these would you like to explore?"

### 3. Grilling loop

Once the user picks a candidate, drop into a grilling conversation (invoke `/grill-me`). Walk the design tree with them — constraints, dependencies, the shape of the deepened module, what sits behind the seam, what tests survive.

Side effects happen inline as decisions crystallize:

- **Naming a deepened module after a concept not in `UBIQUITOUS_LANGUAGE.md`?** If the
  caller authorized glossary updates, add the term via `/ubiquitous-language`; otherwise
  report the proposed term for a separately authorized update.
- **Want to explore alternative interfaces for the deepened module?** See [INTERFACE-DESIGN.md](INTERFACE-DESIGN.md).
- **User rejects the candidate with a load-bearing reason?** If the caller authorized a
  durable documentation update, note it in the relevant `tasks/` doc or `product-docs/` so
  future architecture passes don't re-suggest it; otherwise report the reason for a
  separately authorized update. Skip ephemeral reasons ("not worth it right now") and
  self-evident ones.

### 4. Output

This skill READS and REPORTS — it does not write code or commit changes. The output is:

- A list of candidates (Step 2)
- Optionally, a deepened-module design (Step 3, after grilling)

If the user wants to act on a candidate:
- Small refactor → handoff to `/quick`
- Larger refactor → handoff to `/ct` to produce a tech-decomposition

## Scope boundaries

- Does NOT propose interfaces upfront — that comes only after the user picks a candidate
- Does NOT re-litigate decisions already documented in `product-docs/` or active `tasks/` docs
- Does NOT write code or modify files outside its own outputs
- Does NOT expand scope to include unrelated tech debt

