Analyze Java project architecture at macro level - package structure, module boundaries, dependency direction, and layering. Use when user asks "review architecture", "check structure", "package organization", or when evaluating if a codebase follows clean architecture principles.
npx skills add https://github.com/decebals/claude-code-java --skill architecture-review
Analyze project structure at the macro level - packages, modules, layers, and boundaries.
| Smell | Symptom | Impact |
|-------|---------|--------|
| Package-by-layer bloat | service/ with 50+ classes | Hard to find related code |
| Domain → Infra dependency | Entity imports @Repository | Core logic tied to framework |
| Circular dependencies | A → B → C → A | Untestable, fragile |
| God package | util/ or common/ growing | Dump for misplaced code |
| Leaky abstractions | Controller knows SQL | Layer boundaries violated |
com.example.app/
├── controller/
│ ├── UserController.java
│ ├── OrderController.java
│ └── ProductController.java
├── service/
│ ├── UserService.java
│ ├── OrderService.java
│ └── ProductService.java
├── repository/
│ ├── UserRepository.java
│ ├── OrderRepository.java
│ └── ProductRepository.java
└── model/
├── User.java
├── Order.java
└── Product.java
Pros: Familiar, simple for small projects
Cons: Scatters related code, doesn't scale, hard to extract modules
com.example.app/
├── user/
│ ├── UserController.java
│ ├── UserService.java
│ ├── UserRepository.java
│ └── User.java
├── order/
│ ├── OrderController.java
│ ├── OrderService.java
│ ├── OrderRepository.java
│ └── Order.java
└── product/
├── ProductController.java
├── ProductService.java
├── ProductRepository.java
└── Product.java
Pros: Related code together, easy to extract, clear boundaries
Cons: May need shared kernel for cross-cutting concerns
com.example.app/
├── domain/ # Pure business logic (no framework imports)
│ ├── model/
│ │ └── User.java
│ ├── port/
│ │ ├── in/ # Use cases (driven)
│ │ │ └── CreateUserUseCase.java
│ │ └── out/ # Repositories (driving)
│ │ └── UserRepository.java
│ └── service/
│ └── UserDomainService.java
├── application/ # Use case implementations
│ └── CreateUserService.java
├── adapter/
│ ├── in/
│ │ └── web/
│ │ └── UserController.java
│ └── out/
│ └── persistence/
│ ├── UserJpaRepository.java
│ └── UserEntity.java
└── config/
└── BeanConfiguration.java
Key rule: Dependencies point inward (adapters → application → domain)
┌─────────────────────────────────────────┐
│ Frameworks │ ← Outer (volatile)
├─────────────────────────────────────────┤
│ Adapters (Web, DB) │
├─────────────────────────────────────────┤
│ Application Services │
├─────────────────────────────────────────┤
│ Domain (Core Logic) │ ← Inner (stable)
└─────────────────────────────────────────┘
Dependencies MUST point inward only.
Inner layers MUST NOT know about outer layers.
// ❌ Domain depends on infrastructure
package com.example.domain.model;
import org.springframework.data.jpa.repository.JpaRepository; // Framework leak!
import javax.persistence.Entity; // JPA in domain!
@Entity
public class User {
// Domain polluted with persistence concerns
}
// ❌ Domain depends on adapter
package com.example.domain.service;
import com.example.adapter.out.persistence.UserJpaRepository; // Wrong direction!
// ✅ Domain defines port, adapter implements
package com.example.domain.port.out;
public interface UserRepository { // Pure interface, no JPA
User findById(UserId id);
void save(User user);
}
util/ or common/ packages growing unboundedsrc/main/java/com/example/
└── app/
├── User.java
├── UserController.java
├── UserService.java
├── UserRepository.java
├── Order.java
├── OrderController.java
├── ... (100+ files in one package)
Fix: Introduce package structure (start with by-feature)
util/
├── StringUtils.java
├── DateUtils.java
├── ValidationUtils.java
├── SecurityUtils.java
├── EmailUtils.java # Should be in notification module
├── OrderCalculator.java # Should be in order domain
└── UserHelper.java # Should be in user domain
Fix: Move domain logic to appropriate modules, keep only truly generic utils
// Domain object is just data
public class Order {
private Long id;
private List<OrderLine> lines;
private BigDecimal total;
// Only getters/setters, no behavior
}
// All logic in "service"
public class OrderService {
public void addLine(Order order, Product product, int qty) { ... }
public void calculateTotal(Order order) { ... }
public void applyDiscount(Order order, Discount discount) { ... }
}
Fix: Move behavior to domain objects (rich domain model)
package com.example.domain;
@Entity // JPA
@Data // Lombok
@JsonIgnoreProperties(ignoreUnknown = true) // Jackson
public class User {
@Id @GeneratedValue
private Long id;
@NotBlank // Validation
private String email;
}
Fix: Separate domain model from persistence/API models
When reviewing architecture, examine:
# Package structure overview
find src/main/java -type d | head -30
# Largest packages (potential god packages)
find src/main/java -name "*.java" | xargs dirname | sort | uniq -c | sort -rn | head -10
# Check for framework imports in domain
grep -r "import org.springframework" src/main/java/*/domain/ 2>/dev/null
grep -r "import javax.persistence" src/main/java/*/domain/ 2>/dev/null
# Find circular dependencies (look for bidirectional imports)
# Check if package A imports from B and B imports from A
When reporting findings:
## Architecture Review: [Project Name]
### Structure Assessment
- **Organization**: Package-by-layer / Package-by-feature / Hexagonal
- **Clarity**: Clear / Mixed / Unclear
### Findings
| Severity | Issue | Location | Recommendation |
|----------|-------|----------|----------------|
| High | Domain imports Spring | `domain/model/User.java` | Extract pure domain model |
| Medium | God package | `util/` (23 classes) | Distribute to feature modules |
| Low | Inconsistent naming | `service/` vs `services/` | Standardize to `service/` |
### Dependency Analysis
[Describe dependency flow, violations found]
### Recommendations
1. [Highest priority fix]
2. [Second priority]
3. [Nice to have]
For large codebases:
find to understand structureGuide for creating high-quality MCP (Model Context Protocol) servers that enable LLMs to interact with external services through well-designed tools. Use when building MCP servers to integrate external APIs or services, whether in Python (FastMCP) or Node/TypeScript (MCP SDK).
Automatically creates user-facing changelogs from git commits by analyzing commit history, categorizing changes, and transforming technical commits into clear, customer-friendly release notes. Turns hours of manual changelog writing into minutes of automated generation.
Use when implementation is complete, all tests pass, and you need to decide how to integrate the work - guides completion of development work by presenting structured options for merge, PR, or cleanup
Guide for creating high-quality MCP (Model Context Protocol) servers that enable LLMs to interact with external services through well-designed tools. Use when building MCP servers to integrate external APIs or services, whether in Python (FastMCP) or Node/TypeScript (MCP SDK).
React Native and Expo best practices for building performant mobile apps. Use when building React Native components, optimizing list performance, implementing animations, or working with native modules. Triggers on tasks involving React Native, Expo, mobile performance, or native platform APIs.
React and Next.js performance optimization guidelines from Vercel Engineering. This skill should be used when writing, reviewing, or refactoring React/Next.js code to ensure optimal performance patterns. Triggers on tasks involving React components, Next.js pages, data fetching, bundle optimization, or performance improvements.
Next.js best practices - file conventions, RSC boundaries, data patterns, async APIs, metadata, error handling, route handlers, image/font optimization, bundling
Use when starting feature work that needs isolation from current workspace or before executing implementation plans - creates isolated git worktrees with smart directory selection and safety verification
Take decebals/architecture-review from the repository into ~/.claude/skills for personal
use, or into .claude/skills inside a project.
The agent identifies a skill by the name field in its header. Two skills with the
same name cannot sit side by side — one of them will be ignored.