# Improve Codebase

> Architectural review and improvement proposals. Reads the codebase for structural opportunities — shallow modules that should be deepened, leaky abstractions, misplaced complexity — and proposes specific changes with tradeoffs. Uses a four-persona pass (Contrarian, Simplifier, Architect, Hacker) to stress-test proposals before presenting. Not a refactoring bot; it produces proposals, not commits.…

- **Type:** Skill
- **Install:** `agentstack add skill-max4c-skills-improve-codebase`
- **Verified:** Yes — security-reviewed for prompt injection and unsafe behavior
- **Seller:** [max4c](https://agentstack.voostack.com/s/max4c)
- **Installs:** 0
- **Category:** [Agent Skills](https://agentstack.voostack.com/c/agent-skills)
- **Latest version:** 0.1.0
- **License:** MIT
- **Upstream author:** [max4c](https://github.com/max4c)
- **Source:** https://github.com/max4c/skills/tree/main/skills/improve-codebase

## Install

```sh
agentstack add skill-max4c-skills-improve-codebase
```

Requires the [AgentStack CLI](https://agentstack.voostack.com/docs/cli). Works with Claude Code, Cursor, and any MCP-compatible agent.

## About

# Improve Codebase

Architectural review that produces proposals, not commits. Read the codebase, identify structural improvement opportunities, and present them with tradeoffs for the user to decide. The output is a decision document.

Inspired by Matt Pocock's `improve-codebase-architecture`, John Ousterhout's *A Philosophy of Software Design*, and Ouroboros's "Nine Minds" persona system. Synthesizes shallow-module detection with multi-perspective review.

---

## Contract

**Input:** a codebase (or a directory the user points at) + optional focus area.

**Output:** a markdown proposal document with 2-5 specific architectural improvements, each with rationale, tradeoffs, and rough effort estimate. Default destination: `docs/architecture-reviews/-.md`.

**What this skill does NOT do:** refactor code, open PRs, make commits, or "just clean things up". It produces a proposal document. The user decides which proposals to act on and by what mechanism.

---

## Core concept: deep vs shallow modules

From John Ousterhout's *A Philosophy of Software Design*. This is the single most load-bearing concept in this skill.

**Deep module:** small public interface, large internal implementation. A class that exposes 3 methods but internally handles 500 lines of complexity. Users of the module don't need to understand the internals. The interface is stable even as the implementation evolves.

**Shallow module:** wide public interface, thin internal implementation. A class that exposes 20 methods, each of which is a 2-line wrapper around something else. Callers have to understand the module's internals to use it correctly. Changes propagate to every caller.

**The goal of good architecture is to maximize depth.** improve-codebase looks for shallow modules and proposes ways to deepen them, either by (a) absorbing caller logic into the module, (b) narrowing the interface, or (c) merging the module into a bigger one.

### Concrete examples

**Example 1 — A shallow wrapper that should be deepened**

```typescript
// BEFORE (shallow): 8 public methods, each a pass-through
class UserRepository {
  findById(id: string) { return db.users.where({id}).first() }
  findByEmail(email: string) { return db.users.where({email}).first() }
  findAll() { return db.users.toArray() }
  create(user: User) { return db.users.insert(user) }
  update(id: string, patch: Partial) { return db.users.where({id}).update(patch) }
  delete(id: string) { return db.users.where({id}).delete() }
  count() { return db.users.count() }
  exists(id: string) { return db.users.where({id}).count() > 0 }
}
```

The interface is as wide as the query capabilities of the underlying database. Every caller has to decide which method to use, and adding a new query means adding a new method. This is shallow — the repository isn't adding anything beyond routing to the database.

```typescript
// AFTER (deep): 2 methods that capture the actual business concerns
class UserRepository {
  find(criteria: UserCriteria): Promise
  save(user: User): Promise
  // Behind the scenes: caching, denormalization, event emission, soft-delete handling
}
```

The interface is narrower, but the implementation can now do more — cache results, emit events on save, handle soft-deletes uniformly. Callers don't know or care.

**Example 2 — A leaky abstraction**

```swift
// BEFORE: the public interface exposes internal representation
struct MarkdownDocument {
    var tokens: [Token]
    var parseState: ParseState
    var sourcePositions: [SourcePosition]

    func render() -> String { ... }
}
```

Callers can poke at `tokens` and `parseState` directly. Anyone who does becomes coupled to the internal representation. When you want to change how parsing works, you can't — callers depend on the tokens.

```swift
// AFTER: public interface is just what callers actually need
struct MarkdownDocument {
    func render() -> String
    func plainText() -> String
    func outline() -> [Heading]

    private var representation: Representation  // implementation detail
}
```

### Other structural weaknesses

**Leaky abstractions** — interfaces that require callers to know implementation details. Watch for:
- Public types that expose internal data structures
- Methods named for what they do internally rather than what they accomplish
- Return types that force callers to handle intermediate states

**Misplaced complexity** — business logic in the wrong layer. Watch for:
- Data transformations in view code
- UI state management in model code
- Configuration scattered across multiple files with no single source of truth
- State management spread across layers (some in the model, some in the view, some in a singleton)

**Duplication patterns** — the same concept implemented multiple ways. Watch for:
- The same transformation implemented in three places
- Copy-pasted code with small variations (the variations usually indicate a missing parameter or a missing abstraction)
- Multiple ways to do the same thing (two date formatters, three HTTP clients, four error types for the same failure mode)

---

## Phases

### Phase 1: Orient

Before looking for problems, understand what the codebase does.

**Orientation checklist (adapt to codebase type):**

**Web app:**
- Read `package.json` / `pyproject.toml` / equivalent — what framework? what version?
- Read `src/index.*` or equivalent entry point
- Read `README.md` if it exists
- Look at the top-level src/ directories — how is code organized (by feature, by layer, by domain)?
- Look at `routes/` or `pages/` to understand user-facing surface

**macOS/iOS app:**
- Read `Package.swift` or `*.xcodeproj` structure
- Read `App.swift` / `AppDelegate.swift` entry point
- Look at `Sources/` or `[AppName]/` top-level — feature folders, MVVM, VIPER?
- Look at `Views/` vs `Models/` vs `Services/` — is the separation clean?

**CLI tool / library:**
- Read the main entry point
- Read the public API surface (whatever's exported or in `lib/`)
- Read one or two example usages from tests or docs

**Ask the user:** "What area should I focus on?" Options they might pick:
- A specific directory
- "Anywhere" — in which case, look at the directory with the highest recent churn (`git log --format= --name-only | sort | uniq -c | sort -rn | head`)
- "Something that's been bugging me" — follow up with "which thing?"

**Time budget:** 10-15 minutes. Don't read every file. Build a mental model sufficient to identify candidates.

### Phase 2: Identify candidates

Walk the codebase looking for structural weaknesses. For each candidate, capture: file:line, category, what's wrong, why it matters, estimated effort to fix.

**Detection heuristics per category:**

**Shallow module detection:**
- Count public methods per class. 10+ methods is a smell.
- Read each public method's implementation. If it's 

**What:** 

**Where:** 

**Why:** 

**How:** 

**Tradeoffs:**
- Pro: 
- Con: 
- Risk: 

**Effort:**  3 days)>

**Persona notes:**
- Contrarian: 
- Simplifier: 
- Architect: 
- Hacker: 
```

Present 2-5 proposals. If you can't find that many strong candidates, present fewer. Don't pad. A proposal document with 2 strong proposals is better than one with 5 mediocre ones.

### Phase 5: Grill gate

Invoke `max:grill-me` in spec mode against the proposal document. The grill will push on:
- Are the "why" statements concrete, or hand-wavy?
- Do the tradeoffs actually acknowledge costs, or are they marketing?
- Is the effort estimate grounded, or optimistic?
- Have we considered the Contrarian's objection fairly?

Iterate until below the 0.2 threshold or the user overrides.

### Phase 6: Output

Write the proposal to `docs/architecture-reviews/-.md`. Print the path and the number of proposals.

Do not create tickets, open PRs, or make commits. That's the user's call after reading.

---

## Anti-patterns

- **Refactoring is not improvement.** A change that moves code around without reducing complexity isn't an improvement. It's just churn. Every proposal should make the codebase smaller, simpler, or more resilient — not just different.
- **Proposing changes you wouldn't do yourself.** If you wouldn't actually make this change, don't propose it. Proposals should be serious, not speculative.
- **Reviewing from memory.** You have to read the code. Proposals based on "I remember this codebase has problem X" are usually wrong — memory compresses the wrong things.
- **Bigger is better.** A proposal that touches 50 files isn't inherently better than one that touches 5. Often it's worse. Propose the smallest change that produces the benefit.
- **Ignoring the why.** A proposal without a specific pain point is a solution looking for a problem. The best proposals reference actual bug reports, frequent-churn files, or developer complaints.
- **Universal advice.** "This codebase should use dependency injection everywhere" is not a proposal, it's a preference. Good proposals are specific to this codebase and its actual state.
- **Skipping the persona pass.** The personas exist to catch motivated reasoning. If you skip them, your proposals reflect your biases, not the codebase's needs.

---

## Further reading

- John Ousterhout, *A Philosophy of Software Design* — especially chapters on deep modules, information hiding, and complexity
- Martin Fowler, *Refactoring* — when you know the target pattern, this is the playbook
- Matt Pocock's original `improve-codebase-architecture` skill — the starting framing
- Fred Brooks, *No Silver Bullet* — a reminder that architectural improvements are marginal, not transformative

## Source & license

This open-source skill is cataloged on AgentStack and links to its original source — we do not rehost the code.

- **Author:** [max4c](https://github.com/max4c)
- **Source:** [max4c/skills](https://github.com/max4c/skills)
- **License:** MIT

Install and usage instructions live in the source repository linked above.

## Pricing

- **Free** — Free

## Security capabilities

Automated source analysis of v0.1.0 — what this tool can access:

- **Network access:** no
- **Filesystem access:** no
- **Shell / process execution:** no
- **Environment & secrets:** no
- **Dynamic code execution:** no

*"Yes" means the capability is present in the source — more access means more to trust, not that it is unsafe.*


## Versions

- **0.1.0** — security scan: passed — Imported from the upstream source.

## Links

- Listing page: https://agentstack.voostack.com/l/skill-max4c-skills-improve-codebase
- Seller: https://agentstack.voostack.com/s/max4c
- Browse the marketplace: https://agentstack.voostack.com/browse

---
Listed on AgentStack — the marketplace for AI agent skills and MCP servers. Every listing is security-reviewed. Creators keep 70%.
