How the improve-codebase-architecture Skill Identifies Shallow Modules

The improve-codebase-architecture skill identifies shallow modules by running an exploratory sub-agent that traverses the codebase and flags architectural friction points—such as interfaces nearly as complex as their implementations or logic fragmented across excessive files—as candidates for deepening.

The mattpocock/skills repository contains a specialized agent skill that detects shallow modules through systematic exploration rather than static metrics. Unlike traditional analysis tools that rely solely on code complexity scores, this skill uses an organic traversal approach to surface friction points that indicate insufficient abstraction boundaries. Understanding how the skill identifies these shallow modules helps developers architect code with proper encapsulation before technical debt accumulates.

The Exploration Phase: Detecting Architectural Friction

According to SKILL.md (lines 14-22), the improve-codebase-architecture skill begins its detection process with an Explore sub-agent that walks the codebase organically. This traversal does not follow rigid parsing rules but instead treats architectural friction as the primary signal—specifically, the principle that "the friction you encounter is the signal" (lines 24-25). When the agent struggles to understand a concept without bouncing between files or encounters interfaces that leak implementation details, it records these points as indicators of shallow architecture.

Five Warning Signs of Shallow Modules

During the exploration phase, the skill documents specific patterns that expose shallow modules—units where the public interface provides minimal abstraction over internal complexity. As implemented in SKILL.md, the skill watches for five critical warning signs:

Fragmented Concepts Across Many Files

When "understanding one concept requires bouncing between many small files" (lines 18-19), the logic splits across excessive modules. This fragmentation prevents any single file from offering a meaningful abstraction layer, forcing developers to mentally assemble functionality from scattered pieces.

Interface Complexity Mirrors Implementation

Modules where "the interface is nearly as complex as the implementation" (lines 19-20) lack proper encapsulation. The skill flags these when public APIs expose internal details rather than hiding complexity behind simple contracts, indicating the module cannot be used without understanding its internals.

Test-Driven Fragmentation

The presence of "pure functions extracted just for testability, but the real bugs hide in how they're called" reveals shallow boundaries. This anti-pattern shows that test scaffolding masks deeper coupling issues, proving the surrounding module fails to provide a clean isolation boundary between units.

Tight Coupling at Module Seams

When modules create "integration risk in the seams between them" through mutual dependencies on each other's internals, neither can be deepened independently. The skill identifies these coupling points as friction that prevents independent evolution of components.

Untestable or Untested Code

Segments that are "untested or hard to test" often signal responsibilities too thin to isolate properly. Shallow modules frequently resist testing because they lack the depth to be meaningfully verified in isolation without extensive mocking of their dependencies.

From Detection to Deepening

After aggregating these friction points, the skill compiles a numbered list of candidates for "deepening"—transforming shallow modules into deep modules with small interfaces hiding large implementations (lines 26-30). This prioritization process cross-references guidance from REFERENCE.md regarding dependency categories and testing strategies to determine which shallow modules would provide the highest architectural value when refactored.

Practical Implementation: Detecting Shallow Modules Programmatically

While the mattpocock skill runs inside the Opencode agent framework, the detection logic can be replicated in custom tooling. The following pseudo-code illustrates how to programmatically identify shallow module candidates using heuristics that mirror the skill's exploratory approach:


# Pseudo-code: detecting shallow modules

def is_shallow(module):
    # 1. Count files a concept spans

    if len(module.related_files) > 3:
        return True
    # 2. Compare interface size vs implementation size

    if module.interface_complexity >= 0.8 * module.impl_complexity:
        return True
    # 3. Look for tightly-coupled imports

    if any(dep in module.imports for dep in module.coupled_modules):
        return True
    return False

def explore_and_flag(root_path):
    for mod in traverse_modules(root_path):
        if is_shallow(mod):
            print(f"Shallow candidate: {mod.name} ({mod.path})")

Running this detection routine surfaces the same categories of friction points that the improve-codebase-architecture skill identifies during its organic exploration phase.

Summary

  • The improve-codebase-architecture skill uses an Explore sub-agent to organically traverse repositories and treat architectural friction as the detection signal
  • Five warning signs identify shallow modules: fragmented concepts spanning many files, interface complexity matching implementation, test-driven fragmentation, tight coupling at seams, and untestable code
  • Flagged modules are candidates for deepening, transforming them into units with small public interfaces that hide large implementations
  • Detection logic references SKILL.md (lines 14-30) for the exploration process and REFERENCE.md for architectural prioritization guidance

Frequently Asked Questions

What distinguishes a shallow module from a deep module?

A shallow module provides a public interface that is nearly as complex as its underlying implementation, offering minimal abstraction value. A deep module, conversely, maintains a simple interface that hides significant internal complexity, allowing developers to use the functionality without understanding its implementation details.

Why does the skill use exploratory traversal instead of static analysis?

According to SKILL.md (lines 24-25), the skill treats "the friction you encounter is the signal" because organic traversal mimics how developers actually experience the codebase. Static metrics might miss the cognitive load of navigating between fragmented files or the integration risks that only appear when tracing how functions are actually called.

How does the skill prioritize which shallow modules to refactor first?

After aggregating friction points during the exploration phase, the skill creates a numbered list of deepening candidates (lines 26-30). This prioritization considers the severity of architectural friction detected and cross-references dependency categories from REFERENCE.md to identify which modules would provide the highest value when transformed from shallow to deep architecture.

Can this detection logic be implemented outside the Opencode framework?

Yes, the core heuristics—such as checking if interface complexity approaches implementation complexity or if concepts span excessive files—can be implemented in custom linting tools or CI pipelines. The pseudo-code example provides a template for programmatically identifying shallow module candidates using the same principles that guide the improve-codebase-architecture skill's exploratory detection.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →